michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef GFX_ASURFACE_H michael@0: #define GFX_ASURFACE_H michael@0: michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "gfxTypes.h" michael@0: #include "mozilla/Scoped.h" michael@0: #include "nscore.h" michael@0: #include "nsSize.h" michael@0: michael@0: #ifdef MOZILLA_INTERNAL_API michael@0: #include "nsStringFwd.h" michael@0: #else michael@0: #include "nsStringAPI.h" michael@0: #endif michael@0: michael@0: class gfxImageSurface; michael@0: struct nsIntPoint; michael@0: struct nsIntRect; michael@0: struct gfxRect; michael@0: struct gfxPoint; michael@0: michael@0: template michael@0: struct already_AddRefed; michael@0: michael@0: /** michael@0: * A surface is something you can draw on. Instantiate a subclass of this michael@0: * abstract class, and use gfxContext to draw on this surface. michael@0: */ michael@0: class gfxASurface { michael@0: public: michael@0: #ifdef MOZILLA_INTERNAL_API michael@0: nsrefcnt AddRef(void); michael@0: nsrefcnt Release(void); michael@0: michael@0: // These functions exist so that browsercomps can refcount a gfxASurface michael@0: virtual nsrefcnt AddRefExternal(void); michael@0: virtual nsrefcnt ReleaseExternal(void); michael@0: #else michael@0: virtual nsrefcnt AddRef(void); michael@0: virtual nsrefcnt Release(void); michael@0: #endif michael@0: michael@0: public: michael@0: michael@0: /** Wrap the given cairo surface and return a gfxASurface for it. michael@0: * This adds a reference to csurf (owned by the returned gfxASurface). michael@0: */ michael@0: static already_AddRefed Wrap(cairo_surface_t *csurf, const gfxIntSize& aSize = gfxIntSize(-1, -1)); michael@0: michael@0: /*** this DOES NOT addref the surface */ michael@0: cairo_surface_t *CairoSurface() { michael@0: return mSurface; michael@0: } michael@0: michael@0: gfxSurfaceType GetType() const; michael@0: michael@0: gfxContentType GetContentType() const; michael@0: michael@0: void SetDeviceOffset(const gfxPoint& offset); michael@0: gfxPoint GetDeviceOffset() const; michael@0: michael@0: virtual bool GetRotateForLandscape() { return false; } michael@0: michael@0: void Flush() const; michael@0: void MarkDirty(); michael@0: void MarkDirty(const gfxRect& r); michael@0: michael@0: /* Printing backend functions */ michael@0: virtual nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName); michael@0: virtual nsresult EndPrinting(); michael@0: virtual nsresult AbortPrinting(); michael@0: virtual nsresult BeginPage(); michael@0: virtual nsresult EndPage(); michael@0: michael@0: void SetData(const cairo_user_data_key_t *key, michael@0: void *user_data, michael@0: thebes_destroy_func_t destroy); michael@0: void *GetData(const cairo_user_data_key_t *key); michael@0: michael@0: virtual void Finish(); michael@0: michael@0: /** michael@0: * Create an offscreen surface that can be efficiently copied into michael@0: * this surface (at least if tiling is not involved). michael@0: * Returns null on error. michael@0: */ michael@0: virtual already_AddRefed CreateSimilarSurface(gfxContentType aType, michael@0: const nsIntSize& aSize); michael@0: michael@0: /** michael@0: * Returns an image surface for this surface, or nullptr if not supported. michael@0: * This will not copy image data, just wraps an image surface around michael@0: * pixel data already available in memory. michael@0: */ michael@0: virtual already_AddRefed GetAsImageSurface(); michael@0: michael@0: /** michael@0: * Returns a read-only ARGB32 image surface for this surface. If this is an michael@0: * optimized surface this may require a copy. michael@0: * Returns null on error. michael@0: */ michael@0: virtual already_AddRefed GetAsReadableARGB32ImageSurface(); michael@0: michael@0: /** michael@0: * Creates a new ARGB32 image surface with the same contents as this surface. michael@0: * Returns null on error. michael@0: */ michael@0: already_AddRefed CopyToARGB32ImageSurface(); michael@0: michael@0: int CairoStatus(); michael@0: michael@0: /* Make sure that the given dimensions don't overflow a 32-bit signed int michael@0: * using 4 bytes per pixel; optionally, make sure that either dimension michael@0: * doesn't exceed the given limit. michael@0: */ michael@0: static bool CheckSurfaceSize(const nsIntSize& sz, int32_t limit = 0); michael@0: michael@0: /* Provide a stride value that will respect all alignment requirements of michael@0: * the accelerated image-rendering code. michael@0: */ michael@0: static int32_t FormatStrideForWidth(gfxImageFormat format, int32_t width); michael@0: michael@0: /* Return the default set of context flags for this surface; these are michael@0: * hints to the context about any special rendering considerations. See michael@0: * gfxContext::SetFlag for documentation. michael@0: */ michael@0: virtual int32_t GetDefaultContextFlags() const { return 0; } michael@0: michael@0: static gfxContentType ContentFromFormat(gfxImageFormat format); michael@0: michael@0: void SetSubpixelAntialiasingEnabled(bool aEnabled); michael@0: bool GetSubpixelAntialiasingEnabled(); michael@0: michael@0: /** michael@0: * Record number of bytes for given surface type. Use positive bytes michael@0: * for allocations and negative bytes for deallocations. michael@0: */ michael@0: static void RecordMemoryUsedForSurfaceType(gfxSurfaceType aType, michael@0: int32_t aBytes); michael@0: michael@0: /** michael@0: * Same as above, but use current surface type as returned by GetType(). michael@0: * The bytes will be accumulated until RecordMemoryFreed is called, michael@0: * in which case the value that was recorded for this surface will michael@0: * be freed. michael@0: */ michael@0: void RecordMemoryUsed(int32_t aBytes); michael@0: void RecordMemoryFreed(); michael@0: michael@0: virtual int32_t KnownMemoryUsed() { return mBytesRecorded; } michael@0: michael@0: virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; michael@0: virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; michael@0: // gfxASurface has many sub-classes. This method indicates if a sub-class michael@0: // is capable of measuring its own size accurately. If not, the caller michael@0: // must fall back to a computed size. (Note that gfxASurface can actually michael@0: // measure itself, but we must |return false| here because it serves as the michael@0: // (conservative) default for all the sub-classes. Therefore, this michael@0: // function should only be called on a |gfxASurface*| that actually points michael@0: // to a sub-class of gfxASurface.) michael@0: virtual bool SizeOfIsMeasured() const { return false; } michael@0: michael@0: /** michael@0: * Where does this surface's memory live? By default, we say it's in this michael@0: * process's heap. michael@0: */ michael@0: virtual gfxMemoryLocation GetMemoryLocation() const; michael@0: michael@0: static int32_t BytePerPixelFromFormat(gfxImageFormat format); michael@0: michael@0: virtual const nsIntSize GetSize() const; michael@0: michael@0: /** michael@0: * Debug functions to encode the current image as a PNG and export it. michael@0: */ michael@0: michael@0: /** michael@0: * Writes a binary PNG file. michael@0: */ michael@0: void WriteAsPNG(const char* aFile); michael@0: michael@0: /** michael@0: * Write as a PNG encoded Data URL to a file. michael@0: */ michael@0: void DumpAsDataURL(FILE* aOutput = stdout); michael@0: michael@0: /** michael@0: * Write as a PNG encoded Data URL to stdout. michael@0: */ michael@0: void PrintAsDataURL(); michael@0: michael@0: /** michael@0: * Copy a PNG encoded Data URL to the clipboard. michael@0: */ michael@0: void CopyAsDataURL(); michael@0: michael@0: void WriteAsPNG_internal(FILE* aFile, bool aBinary); michael@0: michael@0: void SetOpaqueRect(const gfxRect& aRect); michael@0: michael@0: const gfxRect& GetOpaqueRect() { michael@0: if (!!mOpaqueRect) michael@0: return *mOpaqueRect; michael@0: return GetEmptyOpaqueRect(); michael@0: } michael@0: michael@0: /** michael@0: * Move the pixels in |aSourceRect| to |aDestTopLeft|. Like with michael@0: * memmove(), |aSourceRect| and the rectangle defined by michael@0: * |aDestTopLeft| are allowed to overlap, and the effect is michael@0: * equivalent to copying |aSourceRect| to a scratch surface and michael@0: * then back to |aDestTopLeft|. michael@0: * michael@0: * |aSourceRect| and the destination rectangle defined by michael@0: * |aDestTopLeft| are clipped to this surface's bounds. michael@0: */ michael@0: virtual void MovePixels(const nsIntRect& aSourceRect, michael@0: const nsIntPoint& aDestTopLeft); michael@0: michael@0: /** michael@0: * Mark the surface as being allowed/not allowed to be used as a source. michael@0: */ michael@0: void SetAllowUseAsSource(bool aAllow) { mAllowUseAsSource = aAllow; } michael@0: bool GetAllowUseAsSource() { return mAllowUseAsSource; } michael@0: michael@0: static uint8_t BytesPerPixel(gfxImageFormat aImageFormat); michael@0: michael@0: protected: michael@0: gfxASurface(); michael@0: michael@0: static gfxASurface* GetSurfaceWrapper(cairo_surface_t *csurf); michael@0: static void SetSurfaceWrapper(cairo_surface_t *csurf, gfxASurface *asurf); michael@0: michael@0: /** michael@0: * An implementation of MovePixels that assumes the backend can michael@0: * internally handle this operation and doesn't allocate any michael@0: * temporary surfaces. michael@0: */ michael@0: void FastMovePixels(const nsIntRect& aSourceRect, michael@0: const nsIntPoint& aDestTopLeft); michael@0: michael@0: // NB: Init() *must* be called from within subclass's michael@0: // constructors. It's unsafe to call it after the ctor finishes; michael@0: // leaks and use-after-frees are possible. michael@0: void Init(cairo_surface_t *surface, bool existingSurface = false); michael@0: michael@0: // out-of-line helper to allow GetOpaqueRect() to be inlined michael@0: // without including gfxRect.h here michael@0: static const gfxRect& GetEmptyOpaqueRect(); michael@0: michael@0: virtual ~gfxASurface(); michael@0: michael@0: cairo_surface_t *mSurface; michael@0: mozilla::ScopedDeletePtr mOpaqueRect; michael@0: michael@0: private: michael@0: static void SurfaceDestroyFunc(void *data); michael@0: michael@0: int32_t mFloatingRefs; michael@0: int32_t mBytesRecorded; michael@0: michael@0: protected: michael@0: bool mSurfaceValid; michael@0: bool mAllowUseAsSource; michael@0: }; michael@0: michael@0: /** michael@0: * An Unknown surface; used to wrap unknown cairo_surface_t returns from cairo michael@0: */ michael@0: class gfxUnknownSurface : public gfxASurface { michael@0: public: michael@0: gfxUnknownSurface(cairo_surface_t *surf, const gfxIntSize& aSize) michael@0: : mSize(aSize) michael@0: { michael@0: Init(surf, true); michael@0: } michael@0: michael@0: virtual ~gfxUnknownSurface() { } michael@0: virtual const nsIntSize GetSize() const { return mSize; } michael@0: michael@0: private: michael@0: nsIntSize mSize; michael@0: }; michael@0: michael@0: #endif /* GFX_ASURFACE_H */