|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef GFX_ASURFACE_H |
|
7 #define GFX_ASURFACE_H |
|
8 |
|
9 #include "mozilla/MemoryReporting.h" |
|
10 #include "gfxTypes.h" |
|
11 #include "mozilla/Scoped.h" |
|
12 #include "nscore.h" |
|
13 #include "nsSize.h" |
|
14 |
|
15 #ifdef MOZILLA_INTERNAL_API |
|
16 #include "nsStringFwd.h" |
|
17 #else |
|
18 #include "nsStringAPI.h" |
|
19 #endif |
|
20 |
|
21 class gfxImageSurface; |
|
22 struct nsIntPoint; |
|
23 struct nsIntRect; |
|
24 struct gfxRect; |
|
25 struct gfxPoint; |
|
26 |
|
27 template <typename T> |
|
28 struct already_AddRefed; |
|
29 |
|
30 /** |
|
31 * A surface is something you can draw on. Instantiate a subclass of this |
|
32 * abstract class, and use gfxContext to draw on this surface. |
|
33 */ |
|
34 class gfxASurface { |
|
35 public: |
|
36 #ifdef MOZILLA_INTERNAL_API |
|
37 nsrefcnt AddRef(void); |
|
38 nsrefcnt Release(void); |
|
39 |
|
40 // These functions exist so that browsercomps can refcount a gfxASurface |
|
41 virtual nsrefcnt AddRefExternal(void); |
|
42 virtual nsrefcnt ReleaseExternal(void); |
|
43 #else |
|
44 virtual nsrefcnt AddRef(void); |
|
45 virtual nsrefcnt Release(void); |
|
46 #endif |
|
47 |
|
48 public: |
|
49 |
|
50 /** Wrap the given cairo surface and return a gfxASurface for it. |
|
51 * This adds a reference to csurf (owned by the returned gfxASurface). |
|
52 */ |
|
53 static already_AddRefed<gfxASurface> Wrap(cairo_surface_t *csurf, const gfxIntSize& aSize = gfxIntSize(-1, -1)); |
|
54 |
|
55 /*** this DOES NOT addref the surface */ |
|
56 cairo_surface_t *CairoSurface() { |
|
57 return mSurface; |
|
58 } |
|
59 |
|
60 gfxSurfaceType GetType() const; |
|
61 |
|
62 gfxContentType GetContentType() const; |
|
63 |
|
64 void SetDeviceOffset(const gfxPoint& offset); |
|
65 gfxPoint GetDeviceOffset() const; |
|
66 |
|
67 virtual bool GetRotateForLandscape() { return false; } |
|
68 |
|
69 void Flush() const; |
|
70 void MarkDirty(); |
|
71 void MarkDirty(const gfxRect& r); |
|
72 |
|
73 /* Printing backend functions */ |
|
74 virtual nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName); |
|
75 virtual nsresult EndPrinting(); |
|
76 virtual nsresult AbortPrinting(); |
|
77 virtual nsresult BeginPage(); |
|
78 virtual nsresult EndPage(); |
|
79 |
|
80 void SetData(const cairo_user_data_key_t *key, |
|
81 void *user_data, |
|
82 thebes_destroy_func_t destroy); |
|
83 void *GetData(const cairo_user_data_key_t *key); |
|
84 |
|
85 virtual void Finish(); |
|
86 |
|
87 /** |
|
88 * Create an offscreen surface that can be efficiently copied into |
|
89 * this surface (at least if tiling is not involved). |
|
90 * Returns null on error. |
|
91 */ |
|
92 virtual already_AddRefed<gfxASurface> CreateSimilarSurface(gfxContentType aType, |
|
93 const nsIntSize& aSize); |
|
94 |
|
95 /** |
|
96 * Returns an image surface for this surface, or nullptr if not supported. |
|
97 * This will not copy image data, just wraps an image surface around |
|
98 * pixel data already available in memory. |
|
99 */ |
|
100 virtual already_AddRefed<gfxImageSurface> GetAsImageSurface(); |
|
101 |
|
102 /** |
|
103 * Returns a read-only ARGB32 image surface for this surface. If this is an |
|
104 * optimized surface this may require a copy. |
|
105 * Returns null on error. |
|
106 */ |
|
107 virtual already_AddRefed<gfxImageSurface> GetAsReadableARGB32ImageSurface(); |
|
108 |
|
109 /** |
|
110 * Creates a new ARGB32 image surface with the same contents as this surface. |
|
111 * Returns null on error. |
|
112 */ |
|
113 already_AddRefed<gfxImageSurface> CopyToARGB32ImageSurface(); |
|
114 |
|
115 int CairoStatus(); |
|
116 |
|
117 /* Make sure that the given dimensions don't overflow a 32-bit signed int |
|
118 * using 4 bytes per pixel; optionally, make sure that either dimension |
|
119 * doesn't exceed the given limit. |
|
120 */ |
|
121 static bool CheckSurfaceSize(const nsIntSize& sz, int32_t limit = 0); |
|
122 |
|
123 /* Provide a stride value that will respect all alignment requirements of |
|
124 * the accelerated image-rendering code. |
|
125 */ |
|
126 static int32_t FormatStrideForWidth(gfxImageFormat format, int32_t width); |
|
127 |
|
128 /* Return the default set of context flags for this surface; these are |
|
129 * hints to the context about any special rendering considerations. See |
|
130 * gfxContext::SetFlag for documentation. |
|
131 */ |
|
132 virtual int32_t GetDefaultContextFlags() const { return 0; } |
|
133 |
|
134 static gfxContentType ContentFromFormat(gfxImageFormat format); |
|
135 |
|
136 void SetSubpixelAntialiasingEnabled(bool aEnabled); |
|
137 bool GetSubpixelAntialiasingEnabled(); |
|
138 |
|
139 /** |
|
140 * Record number of bytes for given surface type. Use positive bytes |
|
141 * for allocations and negative bytes for deallocations. |
|
142 */ |
|
143 static void RecordMemoryUsedForSurfaceType(gfxSurfaceType aType, |
|
144 int32_t aBytes); |
|
145 |
|
146 /** |
|
147 * Same as above, but use current surface type as returned by GetType(). |
|
148 * The bytes will be accumulated until RecordMemoryFreed is called, |
|
149 * in which case the value that was recorded for this surface will |
|
150 * be freed. |
|
151 */ |
|
152 void RecordMemoryUsed(int32_t aBytes); |
|
153 void RecordMemoryFreed(); |
|
154 |
|
155 virtual int32_t KnownMemoryUsed() { return mBytesRecorded; } |
|
156 |
|
157 virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
|
158 virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
|
159 // gfxASurface has many sub-classes. This method indicates if a sub-class |
|
160 // is capable of measuring its own size accurately. If not, the caller |
|
161 // must fall back to a computed size. (Note that gfxASurface can actually |
|
162 // measure itself, but we must |return false| here because it serves as the |
|
163 // (conservative) default for all the sub-classes. Therefore, this |
|
164 // function should only be called on a |gfxASurface*| that actually points |
|
165 // to a sub-class of gfxASurface.) |
|
166 virtual bool SizeOfIsMeasured() const { return false; } |
|
167 |
|
168 /** |
|
169 * Where does this surface's memory live? By default, we say it's in this |
|
170 * process's heap. |
|
171 */ |
|
172 virtual gfxMemoryLocation GetMemoryLocation() const; |
|
173 |
|
174 static int32_t BytePerPixelFromFormat(gfxImageFormat format); |
|
175 |
|
176 virtual const nsIntSize GetSize() const; |
|
177 |
|
178 /** |
|
179 * Debug functions to encode the current image as a PNG and export it. |
|
180 */ |
|
181 |
|
182 /** |
|
183 * Writes a binary PNG file. |
|
184 */ |
|
185 void WriteAsPNG(const char* aFile); |
|
186 |
|
187 /** |
|
188 * Write as a PNG encoded Data URL to a file. |
|
189 */ |
|
190 void DumpAsDataURL(FILE* aOutput = stdout); |
|
191 |
|
192 /** |
|
193 * Write as a PNG encoded Data URL to stdout. |
|
194 */ |
|
195 void PrintAsDataURL(); |
|
196 |
|
197 /** |
|
198 * Copy a PNG encoded Data URL to the clipboard. |
|
199 */ |
|
200 void CopyAsDataURL(); |
|
201 |
|
202 void WriteAsPNG_internal(FILE* aFile, bool aBinary); |
|
203 |
|
204 void SetOpaqueRect(const gfxRect& aRect); |
|
205 |
|
206 const gfxRect& GetOpaqueRect() { |
|
207 if (!!mOpaqueRect) |
|
208 return *mOpaqueRect; |
|
209 return GetEmptyOpaqueRect(); |
|
210 } |
|
211 |
|
212 /** |
|
213 * Move the pixels in |aSourceRect| to |aDestTopLeft|. Like with |
|
214 * memmove(), |aSourceRect| and the rectangle defined by |
|
215 * |aDestTopLeft| are allowed to overlap, and the effect is |
|
216 * equivalent to copying |aSourceRect| to a scratch surface and |
|
217 * then back to |aDestTopLeft|. |
|
218 * |
|
219 * |aSourceRect| and the destination rectangle defined by |
|
220 * |aDestTopLeft| are clipped to this surface's bounds. |
|
221 */ |
|
222 virtual void MovePixels(const nsIntRect& aSourceRect, |
|
223 const nsIntPoint& aDestTopLeft); |
|
224 |
|
225 /** |
|
226 * Mark the surface as being allowed/not allowed to be used as a source. |
|
227 */ |
|
228 void SetAllowUseAsSource(bool aAllow) { mAllowUseAsSource = aAllow; } |
|
229 bool GetAllowUseAsSource() { return mAllowUseAsSource; } |
|
230 |
|
231 static uint8_t BytesPerPixel(gfxImageFormat aImageFormat); |
|
232 |
|
233 protected: |
|
234 gfxASurface(); |
|
235 |
|
236 static gfxASurface* GetSurfaceWrapper(cairo_surface_t *csurf); |
|
237 static void SetSurfaceWrapper(cairo_surface_t *csurf, gfxASurface *asurf); |
|
238 |
|
239 /** |
|
240 * An implementation of MovePixels that assumes the backend can |
|
241 * internally handle this operation and doesn't allocate any |
|
242 * temporary surfaces. |
|
243 */ |
|
244 void FastMovePixels(const nsIntRect& aSourceRect, |
|
245 const nsIntPoint& aDestTopLeft); |
|
246 |
|
247 // NB: Init() *must* be called from within subclass's |
|
248 // constructors. It's unsafe to call it after the ctor finishes; |
|
249 // leaks and use-after-frees are possible. |
|
250 void Init(cairo_surface_t *surface, bool existingSurface = false); |
|
251 |
|
252 // out-of-line helper to allow GetOpaqueRect() to be inlined |
|
253 // without including gfxRect.h here |
|
254 static const gfxRect& GetEmptyOpaqueRect(); |
|
255 |
|
256 virtual ~gfxASurface(); |
|
257 |
|
258 cairo_surface_t *mSurface; |
|
259 mozilla::ScopedDeletePtr<gfxRect> mOpaqueRect; |
|
260 |
|
261 private: |
|
262 static void SurfaceDestroyFunc(void *data); |
|
263 |
|
264 int32_t mFloatingRefs; |
|
265 int32_t mBytesRecorded; |
|
266 |
|
267 protected: |
|
268 bool mSurfaceValid; |
|
269 bool mAllowUseAsSource; |
|
270 }; |
|
271 |
|
272 /** |
|
273 * An Unknown surface; used to wrap unknown cairo_surface_t returns from cairo |
|
274 */ |
|
275 class gfxUnknownSurface : public gfxASurface { |
|
276 public: |
|
277 gfxUnknownSurface(cairo_surface_t *surf, const gfxIntSize& aSize) |
|
278 : mSize(aSize) |
|
279 { |
|
280 Init(surf, true); |
|
281 } |
|
282 |
|
283 virtual ~gfxUnknownSurface() { } |
|
284 virtual const nsIntSize GetSize() const { return mSize; } |
|
285 |
|
286 private: |
|
287 nsIntSize mSize; |
|
288 }; |
|
289 |
|
290 #endif /* GFX_ASURFACE_H */ |