1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Oracle Corporation code.
16 : *
17 : * The Initial Developer of the Original Code is Oracle Corporation.
18 : * Portions created by the Initial Developer are Copyright (C) 2005
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Stuart Parmenter <pavlov@pavlov.net>
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #ifndef GFX_ASURFACE_H
39 : #define GFX_ASURFACE_H
40 :
41 : #include "gfxTypes.h"
42 : #include "gfxRect.h"
43 : #include "nsAutoPtr.h"
44 : #include "nsAutoRef.h"
45 : #include "nsThreadUtils.h"
46 :
47 :
48 : typedef struct _cairo_surface cairo_surface_t;
49 : typedef struct _cairo_user_data_key cairo_user_data_key_t;
50 :
51 : typedef void (*thebes_destroy_func_t) (void *data);
52 :
53 : class gfxImageSurface;
54 : struct nsIntPoint;
55 : struct nsIntRect;
56 :
57 : /**
58 : * A surface is something you can draw on. Instantiate a subclass of this
59 : * abstract class, and use gfxContext to draw on this surface.
60 : */
61 : class THEBES_API gfxASurface {
62 : public:
63 : #ifdef MOZILLA_INTERNAL_API
64 : nsrefcnt AddRef(void);
65 : nsrefcnt Release(void);
66 :
67 : // These functions exist so that browsercomps can refcount a gfxASurface
68 0 : virtual nsresult AddRefExternal(void)
69 : {
70 0 : return AddRef();
71 : }
72 0 : virtual nsresult ReleaseExternal(void)
73 : {
74 0 : return Release();
75 : }
76 : #else
77 : virtual nsresult AddRef(void);
78 : virtual nsresult Release(void);
79 : #endif
80 :
81 : public:
82 : /**
83 : * The format for an image surface. For all formats with alpha data, 0
84 : * means transparent, 1 or 255 means fully opaque.
85 : */
86 : typedef enum {
87 : ImageFormatARGB32, ///< ARGB data in native endianness, using premultiplied alpha
88 : ImageFormatRGB24, ///< xRGB data in native endianness
89 : ImageFormatA8, ///< Only an alpha channel
90 : ImageFormatA1, ///< Packed transparency information (one byte refers to 8 pixels)
91 : ImageFormatRGB16_565, ///< RGB_565 data in native endianness
92 : ImageFormatUnknown
93 : } gfxImageFormat;
94 :
95 : typedef enum {
96 : SurfaceTypeImage,
97 : SurfaceTypePDF,
98 : SurfaceTypePS,
99 : SurfaceTypeXlib,
100 : SurfaceTypeXcb,
101 : SurfaceTypeGlitz, // unused, but needed for cairo parity
102 : SurfaceTypeQuartz,
103 : SurfaceTypeWin32,
104 : SurfaceTypeBeOS,
105 : SurfaceTypeDirectFB, // unused, but needed for cairo parity
106 : SurfaceTypeSVG,
107 : SurfaceTypeOS2,
108 : SurfaceTypeWin32Printing,
109 : SurfaceTypeQuartzImage,
110 : SurfaceTypeScript,
111 : SurfaceTypeQPainter,
112 : SurfaceTypeRecording,
113 : SurfaceTypeVG,
114 : SurfaceTypeGL,
115 : SurfaceTypeDRM,
116 : SurfaceTypeTee,
117 : SurfaceTypeXML,
118 : SurfaceTypeSkia,
119 : SurfaceTypeSubsurface,
120 : SurfaceTypeD2D,
121 : SurfaceTypeMax
122 : } gfxSurfaceType;
123 :
124 : typedef enum {
125 : CONTENT_COLOR = 0x1000,
126 : CONTENT_ALPHA = 0x2000,
127 : CONTENT_COLOR_ALPHA = 0x3000
128 : } gfxContentType;
129 :
130 : /** Wrap the given cairo surface and return a gfxASurface for it.
131 : * This adds a reference to csurf (owned by the returned gfxASurface).
132 : */
133 : static already_AddRefed<gfxASurface> Wrap(cairo_surface_t *csurf);
134 :
135 : /*** this DOES NOT addref the surface */
136 0 : cairo_surface_t *CairoSurface() {
137 0 : NS_ASSERTION(mSurface != nsnull, "gfxASurface::CairoSurface called with mSurface == nsnull!");
138 0 : return mSurface;
139 : }
140 :
141 : gfxSurfaceType GetType() const;
142 :
143 : gfxContentType GetContentType() const;
144 :
145 : void SetDeviceOffset(const gfxPoint& offset);
146 : gfxPoint GetDeviceOffset() const;
147 :
148 64 : virtual bool GetRotateForLandscape() { return false; }
149 :
150 : void Flush() const;
151 : void MarkDirty();
152 : void MarkDirty(const gfxRect& r);
153 :
154 : /* Printing backend functions */
155 : virtual nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName);
156 : virtual nsresult EndPrinting();
157 : virtual nsresult AbortPrinting();
158 : virtual nsresult BeginPage();
159 : virtual nsresult EndPage();
160 :
161 : void SetData(const cairo_user_data_key_t *key,
162 : void *user_data,
163 : thebes_destroy_func_t destroy);
164 : void *GetData(const cairo_user_data_key_t *key);
165 :
166 : virtual void Finish();
167 :
168 : /**
169 : * Create an offscreen surface that can be efficiently copied into
170 : * this surface (at least if tiling is not involved).
171 : * Returns null on error.
172 : */
173 : virtual already_AddRefed<gfxASurface> CreateSimilarSurface(gfxContentType aType,
174 : const gfxIntSize& aSize);
175 :
176 : /**
177 : * Returns an image surface for this surface, or nsnull if not supported.
178 : * This will not copy image data, just wraps an image surface around
179 : * pixel data already available in memory.
180 : */
181 0 : virtual already_AddRefed<gfxImageSurface> GetAsImageSurface()
182 : {
183 0 : return nsnull;
184 : }
185 :
186 : int CairoStatus();
187 :
188 : /* Make sure that the given dimensions don't overflow a 32-bit signed int
189 : * using 4 bytes per pixel; optionally, make sure that either dimension
190 : * doesn't exceed the given limit.
191 : */
192 : static bool CheckSurfaceSize(const gfxIntSize& sz, PRInt32 limit = 0);
193 :
194 : /* Provide a stride value that will respect all alignment requirements of
195 : * the accelerated image-rendering code.
196 : */
197 : static PRInt32 FormatStrideForWidth(gfxImageFormat format, PRInt32 width);
198 :
199 : /* Return the default set of context flags for this surface; these are
200 : * hints to the context about any special rendering considerations. See
201 : * gfxContext::SetFlag for documentation.
202 : */
203 64 : virtual PRInt32 GetDefaultContextFlags() const { return 0; }
204 :
205 : static gfxContentType ContentFromFormat(gfxImageFormat format);
206 : static gfxImageFormat FormatFromContent(gfxContentType format);
207 :
208 : void SetSubpixelAntialiasingEnabled(bool aEnabled);
209 : bool GetSubpixelAntialiasingEnabled();
210 :
211 : /**
212 : * Record number of bytes for given surface type. Use positive bytes
213 : * for allocations and negative bytes for deallocations.
214 : */
215 : static void RecordMemoryUsedForSurfaceType(gfxASurface::gfxSurfaceType aType,
216 : PRInt32 aBytes);
217 :
218 : /**
219 : * Same as above, but use current surface type as returned by GetType().
220 : * The bytes will be accumulated until RecordMemoryFreed is called,
221 : * in which case the value that was recorded for this surface will
222 : * be freed.
223 : */
224 : void RecordMemoryUsed(PRInt32 aBytes);
225 : void RecordMemoryFreed();
226 :
227 2 : virtual PRInt32 KnownMemoryUsed() { return mBytesRecorded; }
228 :
229 : /**
230 : * The memory used by this surface (as reported by KnownMemoryUsed()) can
231 : * either live in this process's heap, in this process but outside the
232 : * heap, or in another process altogether.
233 : */
234 : enum MemoryLocation {
235 : MEMORY_IN_PROCESS_HEAP,
236 : MEMORY_IN_PROCESS_NONHEAP,
237 : MEMORY_OUT_OF_PROCESS
238 : };
239 :
240 : /**
241 : * Where does this surface's memory live? By default, we say it's in this
242 : * process's heap.
243 : */
244 : virtual MemoryLocation GetMemoryLocation() const;
245 :
246 : static PRInt32 BytePerPixelFromFormat(gfxImageFormat format);
247 :
248 0 : virtual const gfxIntSize GetSize() const { return gfxIntSize(-1, -1); }
249 :
250 : #ifdef MOZ_DUMP_PAINTING
251 : /**
252 : * Debug functions to encode the current image as a PNG and export it.
253 : */
254 :
255 : /**
256 : * Writes a binary PNG file.
257 : */
258 : void WriteAsPNG(const char* aFile);
259 :
260 : /**
261 : * Write as a PNG encoded Data URL to a file.
262 : */
263 : void DumpAsDataURL(FILE* aOutput = stdout);
264 :
265 : /**
266 : * Write as a PNG encoded Data URL to stdout.
267 : */
268 : void PrintAsDataURL();
269 :
270 : /**
271 : * Copy a PNG encoded Data URL to the clipboard.
272 : */
273 : void CopyAsDataURL();
274 :
275 : void WriteAsPNG_internal(FILE* aFile, bool aBinary);
276 : #endif
277 :
278 0 : void SetOpaqueRect(const gfxRect& aRect) {
279 0 : if (aRect.IsEmpty()) {
280 0 : mOpaqueRect = nsnull;
281 0 : } else if (mOpaqueRect) {
282 0 : *mOpaqueRect = aRect;
283 : } else {
284 0 : mOpaqueRect = new gfxRect(aRect);
285 : }
286 0 : }
287 0 : const gfxRect& GetOpaqueRect() {
288 0 : if (mOpaqueRect)
289 0 : return *mOpaqueRect;
290 0 : static const gfxRect empty(0, 0, 0, 0);
291 0 : return empty;
292 : }
293 :
294 : /**
295 : * Move the pixels in |aSourceRect| to |aDestTopLeft|. Like with
296 : * memmove(), |aSourceRect| and the rectangle defined by
297 : * |aDestTopLeft| are allowed to overlap, and the effect is
298 : * equivalent to copying |aSourceRect| to a scratch surface and
299 : * then back to |aDestTopLeft|.
300 : *
301 : * |aSourceRect| and the destination rectangle defined by
302 : * |aDestTopLeft| are clipped to this surface's bounds.
303 : */
304 : virtual void MovePixels(const nsIntRect& aSourceRect,
305 : const nsIntPoint& aDestTopLeft);
306 :
307 : /**
308 : * Mark the surface as being allowed/not allowed to be used as a source.
309 : */
310 : void SetAllowUseAsSource(bool aAllow) { mAllowUseAsSource = aAllow; }
311 28 : bool GetAllowUseAsSource() { return mAllowUseAsSource; }
312 :
313 : protected:
314 65 : gfxASurface() : mSurface(nsnull), mFloatingRefs(0), mBytesRecorded(0),
315 65 : mSurfaceValid(false), mAllowUseAsSource(true)
316 : {
317 65 : MOZ_COUNT_CTOR(gfxASurface);
318 65 : }
319 :
320 : static gfxASurface* GetSurfaceWrapper(cairo_surface_t *csurf);
321 : static void SetSurfaceWrapper(cairo_surface_t *csurf, gfxASurface *asurf);
322 :
323 : /**
324 : * An implementation of MovePixels that assumes the backend can
325 : * internally handle this operation and doesn't allocate any
326 : * temporary surfaces.
327 : */
328 : void FastMovePixels(const nsIntRect& aSourceRect,
329 : const nsIntPoint& aDestTopLeft);
330 :
331 : // NB: Init() *must* be called from within subclass's
332 : // constructors. It's unsafe to call it after the ctor finishes;
333 : // leaks and use-after-frees are possible.
334 : void Init(cairo_surface_t *surface, bool existingSurface = false);
335 :
336 65 : virtual ~gfxASurface()
337 130 : {
338 65 : RecordMemoryFreed();
339 :
340 65 : MOZ_COUNT_DTOR(gfxASurface);
341 130 : }
342 :
343 : cairo_surface_t *mSurface;
344 : nsAutoPtr<gfxRect> mOpaqueRect;
345 :
346 : private:
347 : static void SurfaceDestroyFunc(void *data);
348 :
349 : PRInt32 mFloatingRefs;
350 : PRInt32 mBytesRecorded;
351 :
352 : protected:
353 : bool mSurfaceValid;
354 : bool mAllowUseAsSource;
355 : };
356 :
357 : /**
358 : * An Unknown surface; used to wrap unknown cairo_surface_t returns from cairo
359 : */
360 : class THEBES_API gfxUnknownSurface : public gfxASurface {
361 : public:
362 0 : gfxUnknownSurface(cairo_surface_t *surf) {
363 0 : Init(surf, true);
364 0 : }
365 :
366 0 : virtual ~gfxUnknownSurface() { }
367 : };
368 :
369 : #ifndef XPCOM_GLUE_AVOID_NSPR
370 : /**
371 : * We need to be able to hold a reference to a gfxASurface from Image
372 : * subclasses. This is potentially a problem since Images can be addrefed
373 : * or released off the main thread. We can ensure that we never AddRef
374 : * a gfxASurface off the main thread, but we might want to Release due
375 : * to an Image being destroyed off the main thread.
376 : *
377 : * We use nsCountedRef<nsMainThreadSurfaceRef> to reference the
378 : * gfxASurface. When AddRefing, we assert that we're on the main thread.
379 : * When Releasing, if we're not on the main thread, we post an event to
380 : * the main thread to do the actual release.
381 : */
382 : class nsMainThreadSurfaceRef;
383 :
384 : template <>
385 : class nsAutoRefTraits<nsMainThreadSurfaceRef> {
386 : public:
387 : typedef gfxASurface* RawRef;
388 :
389 : /**
390 : * The XPCOM event that will do the actual release on the main thread.
391 : */
392 : class SurfaceReleaser : public nsRunnable {
393 : public:
394 : SurfaceReleaser(RawRef aRef) : mRef(aRef) {}
395 : NS_IMETHOD Run() {
396 : mRef->Release();
397 : return NS_OK;
398 : }
399 : RawRef mRef;
400 : };
401 :
402 : static RawRef Void() { return nsnull; }
403 : static void Release(RawRef aRawRef)
404 : {
405 : if (NS_IsMainThread()) {
406 : aRawRef->Release();
407 : return;
408 : }
409 : nsCOMPtr<nsIRunnable> runnable = new SurfaceReleaser(aRawRef);
410 : NS_DispatchToMainThread(runnable);
411 : }
412 : static void AddRef(RawRef aRawRef)
413 : {
414 : NS_ASSERTION(NS_IsMainThread(),
415 : "Can only add a reference on the main thread");
416 : aRawRef->AddRef();
417 : }
418 : };
419 :
420 : #endif
421 : #endif /* GFX_ASURFACE_H */
|