1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef _MOZILLA_GFX_BORROWED_CONTEXT_H
8 #define _MOZILLA_GFX_BORROWED_CONTEXT_H
9 
10 #include "2D.h"
11 
12 #ifdef MOZ_X11
13 #  include <X11/extensions/Xrender.h>
14 #  include <X11/Xlib.h>
15 #  include "X11UndefineNone.h"
16 #endif
17 
18 struct _cairo;
19 typedef struct _cairo cairo_t;
20 
21 namespace mozilla {
22 
23 namespace gfx {
24 
25 /* This is a helper class that let's you borrow a cairo_t from a
26  * DrawTargetCairo. This is used for drawing themed widgets.
27  *
28  * Callers should check the cr member after constructing the object
29  * to see if it succeeded. The DrawTarget should not be used while
30  * the context is borrowed. */
31 class BorrowedCairoContext {
32  public:
BorrowedCairoContext()33   BorrowedCairoContext() : mCairo(nullptr), mDT(nullptr) {}
34 
BorrowedCairoContext(DrawTarget * aDT)35   explicit BorrowedCairoContext(DrawTarget* aDT) : mDT(aDT) {
36     mCairo = BorrowCairoContextFromDrawTarget(aDT);
37   }
38 
39   // We can optionally Init after construction in
40   // case we don't know what the DT will be at construction
41   // time.
Init(DrawTarget * aDT)42   cairo_t* Init(DrawTarget* aDT) {
43     MOZ_ASSERT(!mDT, "Can't initialize twice!");
44     mDT = aDT;
45     return mCairo = BorrowCairoContextFromDrawTarget(aDT);
46   }
47 
48   // The caller needs to call Finish if cr is non-null when
49   // they are done with the context. This is currently explicit
50   // instead of happening implicitly in the destructor to make
51   // what's happening in the caller more clear. It also
52   // let's you resume using the DrawTarget in the same scope.
Finish()53   void Finish() {
54     if (mCairo) {
55       ReturnCairoContextToDrawTarget(mDT, mCairo);
56       mCairo = nullptr;
57     }
58   }
59 
~BorrowedCairoContext()60   ~BorrowedCairoContext() { MOZ_ASSERT(!mCairo); }
61 
62   cairo_t* mCairo;
63 
64  private:
65   static cairo_t* BorrowCairoContextFromDrawTarget(DrawTarget* aDT);
66   static void ReturnCairoContextToDrawTarget(DrawTarget* aDT, cairo_t* aCairo);
67   DrawTarget* mDT;
68 };
69 
70 #ifdef MOZ_X11
71 /* This is a helper class that let's you borrow an Xlib drawable from
72  * a DrawTarget. This is used for drawing themed widgets.
73  *
74  * Callers should check the Xlib drawable after constructing the object
75  * to see if it succeeded. The DrawTarget should not be used while
76  * the drawable is borrowed. */
77 class BorrowedXlibDrawable {
78  public:
BorrowedXlibDrawable()79   BorrowedXlibDrawable()
80       : mDT(nullptr),
81         mDisplay(nullptr),
82         mDrawable(X11None),
83         mScreen(nullptr),
84         mVisual(nullptr),
85         mXRenderFormat(nullptr) {}
86 
BorrowedXlibDrawable(DrawTarget * aDT)87   explicit BorrowedXlibDrawable(DrawTarget* aDT)
88       : mDT(nullptr),
89         mDisplay(nullptr),
90         mDrawable(X11None),
91         mScreen(nullptr),
92         mVisual(nullptr),
93         mXRenderFormat(nullptr) {
94     Init(aDT);
95   }
96 
97   // We can optionally Init after construction in
98   // case we don't know what the DT will be at construction
99   // time.
100   bool Init(DrawTarget* aDT);
101 
102   // The caller needs to call Finish if drawable is non-zero when
103   // they are done with the context. This is currently explicit
104   // instead of happening implicitly in the destructor to make
105   // what's happening in the caller more clear. It also
106   // let's you resume using the DrawTarget in the same scope.
107   void Finish();
108 
~BorrowedXlibDrawable()109   ~BorrowedXlibDrawable() { MOZ_ASSERT(!mDrawable); }
110 
GetDisplay()111   Display* GetDisplay() const { return mDisplay; }
GetDrawable()112   Drawable GetDrawable() const { return mDrawable; }
GetScreen()113   Screen* GetScreen() const { return mScreen; }
GetVisual()114   Visual* GetVisual() const { return mVisual; }
GetSize()115   IntSize GetSize() const { return mSize; }
GetOffset()116   Point GetOffset() const { return mOffset; }
117 
GetXRenderFormat()118   XRenderPictFormat* GetXRenderFormat() const { return mXRenderFormat; }
119 
120  private:
121   DrawTarget* mDT;
122   Display* mDisplay;
123   Drawable mDrawable;
124   Screen* mScreen;
125   Visual* mVisual;
126   XRenderPictFormat* mXRenderFormat;
127   IntSize mSize;
128   Point mOffset;
129 };
130 #endif
131 
132 #ifdef XP_DARWIN
133 /* This is a helper class that let's you borrow a CGContextRef from a
134  * DrawTargetCG. This is used for drawing themed widgets.
135  *
136  * Callers should check the cg member after constructing the object
137  * to see if it succeeded. The DrawTarget should not be used while
138  * the context is borrowed. */
139 class BorrowedCGContext {
140  public:
BorrowedCGContext()141   BorrowedCGContext() : cg(nullptr), mDT(nullptr) {}
142 
BorrowedCGContext(DrawTarget * aDT)143   explicit BorrowedCGContext(DrawTarget* aDT) : mDT(aDT) {
144     MOZ_ASSERT(aDT, "Caller should check for nullptr");
145     cg = BorrowCGContextFromDrawTarget(aDT);
146   }
147 
148   // We can optionally Init after construction in
149   // case we don't know what the DT will be at construction
150   // time.
Init(DrawTarget * aDT)151   CGContextRef Init(DrawTarget* aDT) {
152     MOZ_ASSERT(aDT, "Caller should check for nullptr");
153     MOZ_ASSERT(!mDT, "Can't initialize twice!");
154     mDT = aDT;
155     cg = BorrowCGContextFromDrawTarget(aDT);
156     return cg;
157   }
158 
159   // The caller needs to call Finish if cg is non-null when
160   // they are done with the context. This is currently explicit
161   // instead of happening implicitly in the destructor to make
162   // what's happening in the caller more clear. It also
163   // let's you resume using the DrawTarget in the same scope.
Finish()164   void Finish() {
165     if (cg) {
166       ReturnCGContextToDrawTarget(mDT, cg);
167       cg = nullptr;
168     }
169   }
170 
~BorrowedCGContext()171   ~BorrowedCGContext() { MOZ_ASSERT(!cg); }
172 
173   CGContextRef cg;
174 
175  private:
176 #  ifdef USE_SKIA
177   static CGContextRef BorrowCGContextFromDrawTarget(DrawTarget* aDT);
178   static void ReturnCGContextToDrawTarget(DrawTarget* aDT, CGContextRef cg);
179 #  else
180   static CGContextRef BorrowCGContextFromDrawTarget(DrawTarget* aDT) {
181     MOZ_CRASH("Not supported without Skia");
182   }
183 
184   static void ReturnCGContextToDrawTarget(DrawTarget* aDT, CGContextRef cg) {
185     MOZ_CRASH("not supported without Skia");
186   }
187 #  endif
188   DrawTarget* mDT;
189 };
190 #endif
191 
192 }  // namespace gfx
193 }  // namespace mozilla
194 
195 #endif  // _MOZILLA_GFX_BORROWED_CONTEXT_H
196