michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 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 _MOZILLA_GFX_SOURCESURFACECG_H michael@0: #define _MOZILLA_GFX_SOURCESURFACECG_H michael@0: michael@0: #include michael@0: michael@0: #include "2D.h" michael@0: michael@0: class MacIOSurface; michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: michael@0: CGImageRef michael@0: CreateCGImage(void *aInfo, michael@0: const void *aData, michael@0: const IntSize &aSize, michael@0: int32_t aStride, michael@0: SurfaceFormat aFormat); michael@0: michael@0: class DrawTargetCG; michael@0: michael@0: class SourceSurfaceCG : public SourceSurface michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceCG) michael@0: SourceSurfaceCG() {} michael@0: SourceSurfaceCG(CGImageRef aImage) : mImage(aImage) {} michael@0: ~SourceSurfaceCG(); michael@0: michael@0: virtual SurfaceType GetType() const { return SurfaceType::COREGRAPHICS_IMAGE; } michael@0: virtual IntSize GetSize() const; michael@0: virtual SurfaceFormat GetFormat() const; michael@0: virtual TemporaryRef GetDataSurface(); michael@0: michael@0: CGImageRef GetImage() { return mImage; } michael@0: michael@0: bool InitFromData(unsigned char *aData, michael@0: const IntSize &aSize, michael@0: int32_t aStride, michael@0: SurfaceFormat aFormat); michael@0: michael@0: private: michael@0: CGImageRef mImage; michael@0: michael@0: /* It might be better to just use the bitmap info from the CGImageRef to michael@0: * deduce the format to save space in SourceSurfaceCG, michael@0: * for now we just store it in mFormat */ michael@0: SurfaceFormat mFormat; michael@0: }; michael@0: michael@0: class DataSourceSurfaceCG : public DataSourceSurface michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCG) michael@0: DataSourceSurfaceCG() {} michael@0: DataSourceSurfaceCG(CGImageRef aImage); michael@0: ~DataSourceSurfaceCG(); michael@0: michael@0: virtual SurfaceType GetType() const { return SurfaceType::DATA; } michael@0: virtual IntSize GetSize() const; michael@0: virtual SurfaceFormat GetFormat() const { return mFormat; } michael@0: michael@0: CGImageRef GetImage() { return mImage; } michael@0: michael@0: bool InitFromData(unsigned char *aData, michael@0: const IntSize &aSize, michael@0: int32_t aStride, michael@0: SurfaceFormat aFormat); michael@0: michael@0: virtual unsigned char *GetData(); michael@0: michael@0: virtual int32_t Stride() { return CGImageGetBytesPerRow(mImage); } michael@0: michael@0: michael@0: private: michael@0: CGContextRef mCg; michael@0: CGImageRef mImage; michael@0: SurfaceFormat mFormat; michael@0: //XXX: we don't need to store mData we can just get it from the CGContext michael@0: void *mData; michael@0: /* It might be better to just use the bitmap info from the CGImageRef to michael@0: * deduce the format to save space in SourceSurfaceCG, michael@0: * for now we just store it in mFormat */ michael@0: }; michael@0: michael@0: class SourceSurfaceCGContext : public DataSourceSurface michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCGContext) michael@0: virtual void DrawTargetWillChange() = 0; michael@0: virtual CGImageRef GetImage() = 0; michael@0: }; michael@0: michael@0: class SourceSurfaceCGBitmapContext : public SourceSurfaceCGContext michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCGBitmapContext) michael@0: SourceSurfaceCGBitmapContext(DrawTargetCG *); michael@0: ~SourceSurfaceCGBitmapContext(); michael@0: michael@0: virtual SurfaceType GetType() const { return SurfaceType::COREGRAPHICS_CGCONTEXT; } michael@0: virtual IntSize GetSize() const; michael@0: virtual SurfaceFormat GetFormat() const { return mFormat; } michael@0: virtual TemporaryRef GetDataSurface() michael@0: { michael@0: // This call to DrawTargetWillChange() is needed to make a local copy of michael@0: // the data from mDrawTarget. If we don't do that, the data can end up michael@0: // getting deleted before the CGImageRef it belongs to. michael@0: // michael@0: // Another reason we need a local copy of the data is that the data in michael@0: // mDrawTarget could change when someone touches the original DrawTargetCG michael@0: // object. But a SourceSurface object should be immutable. michael@0: // michael@0: // For more information see bug 925448. michael@0: DrawTargetWillChange(); michael@0: return this; michael@0: } michael@0: michael@0: CGImageRef GetImage() { EnsureImage(); return mImage; } michael@0: michael@0: virtual unsigned char *GetData() { return static_cast(mData); } michael@0: michael@0: virtual int32_t Stride() { return mStride; } michael@0: michael@0: private: michael@0: //XXX: do the other backends friend their DrawTarget? michael@0: friend class DrawTargetCG; michael@0: virtual void DrawTargetWillChange(); michael@0: void EnsureImage() const; michael@0: michael@0: // We hold a weak reference to these two objects. michael@0: // The cycle is broken by DrawTargetWillChange michael@0: DrawTargetCG *mDrawTarget; michael@0: CGContextRef mCg; michael@0: SurfaceFormat mFormat; michael@0: michael@0: mutable CGImageRef mImage; michael@0: michael@0: // mData can be owned by three different things: michael@0: // mImage, mCg or SourceSurfaceCGBitmapContext michael@0: void *mData; michael@0: michael@0: // The image buffer, if the buffer is owned by this class. michael@0: AlignedArray mDataHolder; michael@0: michael@0: int32_t mStride; michael@0: IntSize mSize; michael@0: }; michael@0: michael@0: class SourceSurfaceCGIOSurfaceContext : public SourceSurfaceCGContext michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCGIOSurfaceContext) michael@0: SourceSurfaceCGIOSurfaceContext(DrawTargetCG *); michael@0: ~SourceSurfaceCGIOSurfaceContext(); michael@0: michael@0: virtual SurfaceType GetType() const { return SurfaceType::COREGRAPHICS_CGCONTEXT; } michael@0: virtual IntSize GetSize() const; michael@0: virtual SurfaceFormat GetFormat() const { return mFormat; } michael@0: michael@0: CGImageRef GetImage() { EnsureImage(); return mImage; } michael@0: michael@0: virtual unsigned char *GetData(); michael@0: michael@0: virtual int32_t Stride() { return mStride; } michael@0: michael@0: private: michael@0: //XXX: do the other backends friend their DrawTarget? michael@0: friend class DrawTargetCG; michael@0: virtual void DrawTargetWillChange(); michael@0: void EnsureImage() const; michael@0: michael@0: SurfaceFormat mFormat; michael@0: mutable CGImageRef mImage; michael@0: MacIOSurface* mIOSurface; michael@0: michael@0: void *mData; michael@0: int32_t mStride; michael@0: michael@0: IntSize mSize; michael@0: }; michael@0: michael@0: michael@0: } michael@0: } michael@0: michael@0: #endif // _MOZILLA_GFX_SOURCESURFACECG_H