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_2D_H michael@0: #define _MOZILLA_GFX_2D_H michael@0: michael@0: #include "Types.h" michael@0: #include "Point.h" michael@0: #include "Rect.h" michael@0: #include "Matrix.h" michael@0: #include "UserData.h" michael@0: michael@0: // GenericRefCountedBase allows us to hold on to refcounted objects of any type michael@0: // (contrary to RefCounted which requires knowing the type T) and, in particular, michael@0: // without having a dependency on that type. This is used for DrawTargetSkia michael@0: // to be able to hold on to a GLContext. michael@0: #include "mozilla/GenericRefCounted.h" michael@0: michael@0: // This RefPtr class isn't ideal for usage in Azure, as it doesn't allow T** michael@0: // outparams using the &-operator. But it will have to do as there's no easy michael@0: // solution. michael@0: #include "mozilla/RefPtr.h" michael@0: michael@0: #include "mozilla/DebugOnly.h" michael@0: michael@0: #ifdef MOZ_ENABLE_FREETYPE michael@0: #include michael@0: #endif michael@0: michael@0: struct _cairo_surface; michael@0: typedef _cairo_surface cairo_surface_t; michael@0: michael@0: struct _cairo_scaled_font; michael@0: typedef _cairo_scaled_font cairo_scaled_font_t; michael@0: michael@0: struct ID3D10Device1; michael@0: struct ID3D10Texture2D; michael@0: struct ID3D11Device; michael@0: struct ID2D1Device; michael@0: struct IDWriteRenderingParams; michael@0: michael@0: class GrContext; michael@0: struct GrGLInterface; michael@0: michael@0: struct CGContext; michael@0: typedef struct CGContext *CGContextRef; michael@0: michael@0: namespace mozilla { michael@0: michael@0: namespace gfx { michael@0: michael@0: class SourceSurface; michael@0: class DataSourceSurface; michael@0: class DrawTarget; michael@0: class DrawEventRecorder; michael@0: class FilterNode; michael@0: michael@0: struct NativeSurface { michael@0: NativeSurfaceType mType; michael@0: SurfaceFormat mFormat; michael@0: gfx::IntSize mSize; michael@0: void *mSurface; michael@0: }; michael@0: michael@0: struct NativeFont { michael@0: NativeFontType mType; michael@0: void *mFont; michael@0: }; michael@0: michael@0: /* michael@0: * This structure is used to send draw options that are universal to all drawing michael@0: * operations. It consists of the following: michael@0: * michael@0: * mAlpha - Alpha value by which the mask generated by this operation is michael@0: * multiplied. michael@0: * mCompositionOp - The operator that indicates how the source and destination michael@0: * patterns are blended. michael@0: * mAntiAliasMode - The AntiAlias mode used for this drawing operation. michael@0: */ michael@0: struct DrawOptions { michael@0: DrawOptions(Float aAlpha = 1.0f, michael@0: CompositionOp aCompositionOp = CompositionOp::OP_OVER, michael@0: AntialiasMode aAntialiasMode = AntialiasMode::DEFAULT) michael@0: : mAlpha(aAlpha) michael@0: , mCompositionOp(aCompositionOp) michael@0: , mAntialiasMode(aAntialiasMode) michael@0: {} michael@0: michael@0: Float mAlpha; michael@0: CompositionOp mCompositionOp; michael@0: AntialiasMode mAntialiasMode; michael@0: }; michael@0: michael@0: /* michael@0: * This structure is used to send stroke options that are used in stroking michael@0: * operations. It consists of the following: michael@0: * michael@0: * mLineWidth - Width of the stroke in userspace. michael@0: * mLineJoin - Join style used for joining lines. michael@0: * mLineCap - Cap style used for capping lines. michael@0: * mMiterLimit - Miter limit in units of linewidth michael@0: * mDashPattern - Series of on/off userspace lengths defining dash. michael@0: * Owned by the caller; must live at least as long as michael@0: * this StrokeOptions. michael@0: * mDashPattern != null <=> mDashLength > 0. michael@0: * mDashLength - Number of on/off lengths in mDashPattern. michael@0: * mDashOffset - Userspace offset within mDashPattern at which stroking michael@0: * begins. michael@0: */ michael@0: struct StrokeOptions { michael@0: StrokeOptions(Float aLineWidth = 1.0f, michael@0: JoinStyle aLineJoin = JoinStyle::MITER_OR_BEVEL, michael@0: CapStyle aLineCap = CapStyle::BUTT, michael@0: Float aMiterLimit = 10.0f, michael@0: size_t aDashLength = 0, michael@0: const Float* aDashPattern = 0, michael@0: Float aDashOffset = 0.f) michael@0: : mLineWidth(aLineWidth) michael@0: , mMiterLimit(aMiterLimit) michael@0: , mDashPattern(aDashLength > 0 ? aDashPattern : 0) michael@0: , mDashLength(aDashLength) michael@0: , mDashOffset(aDashOffset) michael@0: , mLineJoin(aLineJoin) michael@0: , mLineCap(aLineCap) michael@0: { michael@0: MOZ_ASSERT(aDashLength == 0 || aDashPattern); michael@0: } michael@0: michael@0: Float mLineWidth; michael@0: Float mMiterLimit; michael@0: const Float* mDashPattern; michael@0: size_t mDashLength; michael@0: Float mDashOffset; michael@0: JoinStyle mLineJoin; michael@0: CapStyle mLineCap; michael@0: }; michael@0: michael@0: /* michael@0: * This structure supplies additional options for calls to DrawSurface. michael@0: * michael@0: * mFilter - Filter used when resampling source surface region to the michael@0: * destination region. michael@0: * aSamplingBounds - This indicates whether the implementation is allowed michael@0: * to sample pixels outside the source rectangle as michael@0: * specified in DrawSurface on the surface. michael@0: */ michael@0: struct DrawSurfaceOptions { michael@0: DrawSurfaceOptions(Filter aFilter = Filter::LINEAR, michael@0: SamplingBounds aSamplingBounds = SamplingBounds::UNBOUNDED) michael@0: : mFilter(aFilter) michael@0: , mSamplingBounds(aSamplingBounds) michael@0: { } michael@0: michael@0: Filter mFilter; michael@0: SamplingBounds mSamplingBounds; michael@0: }; michael@0: michael@0: /* michael@0: * This class is used to store gradient stops, it can only be used with a michael@0: * matching DrawTarget. Not adhering to this condition will make a draw call michael@0: * fail. michael@0: */ michael@0: class GradientStops : public RefCounted michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStops) michael@0: virtual ~GradientStops() {} michael@0: michael@0: virtual BackendType GetBackendType() const = 0; michael@0: michael@0: protected: michael@0: GradientStops() {} michael@0: }; michael@0: michael@0: /* michael@0: * This is the base class for 'patterns'. Patterns describe the pixels used as michael@0: * the source for a masked composition operation that is done by the different michael@0: * drawing commands. These objects are not backend specific, however for michael@0: * example the gradient stops on a gradient pattern can be backend specific. michael@0: */ michael@0: class Pattern michael@0: { michael@0: public: michael@0: virtual ~Pattern() {} michael@0: michael@0: virtual PatternType GetType() const = 0; michael@0: michael@0: protected: michael@0: Pattern() {} michael@0: }; michael@0: michael@0: class ColorPattern : public Pattern michael@0: { michael@0: public: michael@0: ColorPattern(const Color &aColor) michael@0: : mColor(aColor) michael@0: {} michael@0: michael@0: virtual PatternType GetType() const { return PatternType::COLOR; } michael@0: michael@0: Color mColor; michael@0: }; michael@0: michael@0: /* michael@0: * This class is used for Linear Gradient Patterns, the gradient stops are michael@0: * stored in a separate object and are backend dependent. This class itself michael@0: * may be used on the stack. michael@0: */ michael@0: class LinearGradientPattern : public Pattern michael@0: { michael@0: public: michael@0: /* michael@0: * aBegin Start of the linear gradient michael@0: * aEnd End of the linear gradient - NOTE: In the case of a zero length michael@0: * gradient it will act as the color of the last stop. michael@0: * aStops GradientStops object for this gradient, this should match the michael@0: * backend type of the draw target this pattern will be used with. michael@0: * aMatrix A matrix that transforms the pattern into user space michael@0: */ michael@0: LinearGradientPattern(const Point &aBegin, michael@0: const Point &aEnd, michael@0: GradientStops *aStops, michael@0: const Matrix &aMatrix = Matrix()) michael@0: : mBegin(aBegin) michael@0: , mEnd(aEnd) michael@0: , mStops(aStops) michael@0: , mMatrix(aMatrix) michael@0: { michael@0: } michael@0: michael@0: virtual PatternType GetType() const { return PatternType::LINEAR_GRADIENT; } michael@0: michael@0: Point mBegin; michael@0: Point mEnd; michael@0: RefPtr mStops; michael@0: Matrix mMatrix; michael@0: }; michael@0: michael@0: /* michael@0: * This class is used for Radial Gradient Patterns, the gradient stops are michael@0: * stored in a separate object and are backend dependent. This class itself michael@0: * may be used on the stack. michael@0: */ michael@0: class RadialGradientPattern : public Pattern michael@0: { michael@0: public: michael@0: /* michael@0: * aCenter1 Center of the inner (focal) circle. michael@0: * aCenter2 Center of the outer circle. michael@0: * aRadius1 Radius of the inner (focal) circle. michael@0: * aRadius2 Radius of the outer circle. michael@0: * aStops GradientStops object for this gradient, this should match the michael@0: * backend type of the draw target this pattern will be used with. michael@0: * aMatrix A matrix that transforms the pattern into user space michael@0: */ michael@0: RadialGradientPattern(const Point &aCenter1, michael@0: const Point &aCenter2, michael@0: Float aRadius1, michael@0: Float aRadius2, michael@0: GradientStops *aStops, michael@0: const Matrix &aMatrix = Matrix()) michael@0: : mCenter1(aCenter1) michael@0: , mCenter2(aCenter2) michael@0: , mRadius1(aRadius1) michael@0: , mRadius2(aRadius2) michael@0: , mStops(aStops) michael@0: , mMatrix(aMatrix) michael@0: { michael@0: } michael@0: michael@0: virtual PatternType GetType() const { return PatternType::RADIAL_GRADIENT; } michael@0: michael@0: Point mCenter1; michael@0: Point mCenter2; michael@0: Float mRadius1; michael@0: Float mRadius2; michael@0: RefPtr mStops; michael@0: Matrix mMatrix; michael@0: }; michael@0: michael@0: /* michael@0: * This class is used for Surface Patterns, they wrap a surface and a michael@0: * repetition mode for the surface. This may be used on the stack. michael@0: */ michael@0: class SurfacePattern : public Pattern michael@0: { michael@0: public: michael@0: /* michael@0: * aSourceSurface Surface to use for drawing michael@0: * aExtendMode This determines how the image is extended outside the bounds michael@0: * of the image. michael@0: * aMatrix A matrix that transforms the pattern into user space michael@0: * aFilter Resampling filter used for resampling the image. michael@0: */ michael@0: SurfacePattern(SourceSurface *aSourceSurface, ExtendMode aExtendMode, michael@0: const Matrix &aMatrix = Matrix(), Filter aFilter = Filter::GOOD) michael@0: : mSurface(aSourceSurface) michael@0: , mExtendMode(aExtendMode) michael@0: , mFilter(aFilter) michael@0: , mMatrix(aMatrix) michael@0: {} michael@0: michael@0: virtual PatternType GetType() const { return PatternType::SURFACE; } michael@0: michael@0: RefPtr mSurface; michael@0: ExtendMode mExtendMode; michael@0: Filter mFilter; michael@0: Matrix mMatrix; michael@0: }; michael@0: michael@0: /* michael@0: * This is the base class for source surfaces. These objects are surfaces michael@0: * which may be used as a source in a SurfacePattern or a DrawSurface call. michael@0: * They cannot be drawn to directly. michael@0: */ michael@0: class SourceSurface : public RefCounted michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurface) michael@0: virtual ~SourceSurface() {} michael@0: michael@0: virtual SurfaceType GetType() const = 0; michael@0: virtual IntSize GetSize() const = 0; michael@0: virtual SurfaceFormat GetFormat() const = 0; michael@0: michael@0: /* This returns false if some event has made this source surface invalid for michael@0: * usage with current DrawTargets. For example in the case of Direct2D this michael@0: * could return false if we have switched devices since this surface was michael@0: * created. michael@0: */ michael@0: virtual bool IsValid() const { return true; } michael@0: michael@0: /* michael@0: * This function will get a DataSourceSurface for this surface, a michael@0: * DataSourceSurface's data can be accessed directly. michael@0: */ michael@0: virtual TemporaryRef GetDataSurface() = 0; michael@0: michael@0: /* Tries to get this SourceSurface's native surface. This will fail if aType michael@0: * is not the type of this SourceSurface's native surface. michael@0: */ michael@0: virtual void *GetNativeSurface(NativeSurfaceType aType) { michael@0: return nullptr; michael@0: } michael@0: michael@0: void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) { michael@0: mUserData.Add(key, userData, destroy); michael@0: } michael@0: void *GetUserData(UserDataKey *key) { michael@0: return mUserData.Get(key); michael@0: } michael@0: michael@0: protected: michael@0: UserData mUserData; michael@0: }; michael@0: michael@0: class DataSourceSurface : public SourceSurface michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurface) michael@0: DataSourceSurface() michael@0: : mIsMapped(false) michael@0: { michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: virtual ~DataSourceSurface() michael@0: { michael@0: MOZ_ASSERT(!mIsMapped, "Someone forgot to call Unmap()"); michael@0: } michael@0: #endif michael@0: michael@0: struct MappedSurface { michael@0: uint8_t *mData; michael@0: int32_t mStride; michael@0: }; michael@0: michael@0: enum MapType { michael@0: READ, michael@0: WRITE, michael@0: READ_WRITE michael@0: }; michael@0: michael@0: virtual SurfaceType GetType() const { return SurfaceType::DATA; } michael@0: /* [DEPRECATED] michael@0: * Get the raw bitmap data of the surface. michael@0: * Can return null if there was OOM allocating surface data. michael@0: */ michael@0: virtual uint8_t *GetData() = 0; michael@0: michael@0: /* [DEPRECATED] michael@0: * Stride of the surface, distance in bytes between the start of the image michael@0: * data belonging to row y and row y+1. This may be negative. michael@0: * Can return 0 if there was OOM allocating surface data. michael@0: */ michael@0: virtual int32_t Stride() = 0; michael@0: michael@0: virtual bool Map(MapType, MappedSurface *aMappedSurface) michael@0: { michael@0: aMappedSurface->mData = GetData(); michael@0: aMappedSurface->mStride = Stride(); michael@0: mIsMapped = true; michael@0: return true; michael@0: } michael@0: michael@0: virtual void Unmap() michael@0: { michael@0: MOZ_ASSERT(mIsMapped); michael@0: mIsMapped = false; michael@0: } michael@0: michael@0: /* michael@0: * Returns a DataSourceSurface with the same data as this one, but michael@0: * guaranteed to have surface->GetType() == SurfaceType::DATA. michael@0: */ michael@0: virtual TemporaryRef GetDataSurface(); michael@0: michael@0: bool mIsMapped; michael@0: }; michael@0: michael@0: /* This is an abstract object that accepts path segments. */ michael@0: class PathSink : public RefCounted michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathSink) michael@0: virtual ~PathSink() {} michael@0: michael@0: /* Move the current point in the path, any figure currently being drawn will michael@0: * be considered closed during fill operations, however when stroking the michael@0: * closing line segment will not be drawn. michael@0: */ michael@0: virtual void MoveTo(const Point &aPoint) = 0; michael@0: /* Add a linesegment to the current figure */ michael@0: virtual void LineTo(const Point &aPoint) = 0; michael@0: /* Add a cubic bezier curve to the current figure */ michael@0: virtual void BezierTo(const Point &aCP1, michael@0: const Point &aCP2, michael@0: const Point &aCP3) = 0; michael@0: /* Add a quadratic bezier curve to the current figure */ michael@0: virtual void QuadraticBezierTo(const Point &aCP1, michael@0: const Point &aCP2) = 0; michael@0: /* Close the current figure, this will essentially generate a line segment michael@0: * from the current point to the starting point for the current figure michael@0: */ michael@0: virtual void Close() = 0; michael@0: /* Add an arc to the current figure */ michael@0: virtual void Arc(const Point &aOrigin, float aRadius, float aStartAngle, michael@0: float aEndAngle, bool aAntiClockwise = false) = 0; michael@0: /* Point the current subpath is at - or where the next subpath will start michael@0: * if there is no active subpath. michael@0: */ michael@0: virtual Point CurrentPoint() const = 0; michael@0: }; michael@0: michael@0: class PathBuilder; michael@0: class FlattenedPath; michael@0: michael@0: /* The path class is used to create (sets of) figures of any shape that can be michael@0: * filled or stroked to a DrawTarget michael@0: */ michael@0: class Path : public RefCounted michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(Path) michael@0: virtual ~Path(); michael@0: michael@0: virtual BackendType GetBackendType() const = 0; michael@0: michael@0: /* This returns a PathBuilder object that contains a copy of the contents of michael@0: * this path and is still writable. michael@0: */ michael@0: virtual TemporaryRef CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const = 0; michael@0: virtual TemporaryRef TransformedCopyToBuilder(const Matrix &aTransform, michael@0: FillRule aFillRule = FillRule::FILL_WINDING) const = 0; michael@0: michael@0: /* This function checks if a point lies within a path. It allows passing a michael@0: * transform that will transform the path to the coordinate space in which michael@0: * aPoint is given. michael@0: */ michael@0: virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const = 0; michael@0: michael@0: michael@0: /* This function checks if a point lies within the stroke of a path using the michael@0: * specified strokeoptions. It allows passing a transform that will transform michael@0: * the path to the coordinate space in which aPoint is given. michael@0: */ michael@0: virtual bool StrokeContainsPoint(const StrokeOptions &aStrokeOptions, michael@0: const Point &aPoint, michael@0: const Matrix &aTransform) const = 0; michael@0: michael@0: /* This functions gets the bounds of this path. These bounds are not michael@0: * guaranteed to be tight. A transform may be specified that gives the bounds michael@0: * after application of the transform. michael@0: */ michael@0: virtual Rect GetBounds(const Matrix &aTransform = Matrix()) const = 0; michael@0: michael@0: /* This function gets the bounds of the stroke of this path using the michael@0: * specified strokeoptions. These bounds are not guaranteed to be tight. michael@0: * A transform may be specified that gives the bounds after application of michael@0: * the transform. michael@0: */ michael@0: virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions, michael@0: const Matrix &aTransform = Matrix()) const = 0; michael@0: michael@0: /* Take the contents of this path and stream it to another sink, this works michael@0: * regardless of the backend that might be used for the destination sink. michael@0: */ michael@0: virtual void StreamToSink(PathSink *aSink) const = 0; michael@0: michael@0: /* This gets the fillrule this path's builder was created with. This is not michael@0: * mutable. michael@0: */ michael@0: virtual FillRule GetFillRule() const = 0; michael@0: michael@0: virtual Float ComputeLength(); michael@0: michael@0: virtual Point ComputePointAtLength(Float aLength, michael@0: Point* aTangent = nullptr); michael@0: michael@0: protected: michael@0: Path(); michael@0: void EnsureFlattenedPath(); michael@0: michael@0: RefPtr mFlattenedPath; michael@0: }; michael@0: michael@0: /* The PathBuilder class allows path creation. Once finish is called on the michael@0: * pathbuilder it may no longer be written to. michael@0: */ michael@0: class PathBuilder : public PathSink michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilder) michael@0: /* Finish writing to the path and return a Path object that can be used for michael@0: * drawing. Future use of the builder results in a crash! michael@0: */ michael@0: virtual TemporaryRef Finish() = 0; michael@0: }; michael@0: michael@0: struct Glyph michael@0: { michael@0: uint32_t mIndex; michael@0: Point mPosition; michael@0: }; michael@0: michael@0: /* This class functions as a glyph buffer that can be drawn to a DrawTarget. michael@0: * XXX - This should probably contain the guts of gfxTextRun in the future as michael@0: * roc suggested. But for now it's a simple container for a glyph vector. michael@0: */ michael@0: struct GlyphBuffer michael@0: { michael@0: // A pointer to a buffer of glyphs. Managed by the caller. michael@0: const Glyph *mGlyphs; michael@0: // Number of glyphs mGlyphs points to. michael@0: uint32_t mNumGlyphs; michael@0: }; michael@0: michael@0: /* This class is an abstraction of a backend/platform specific font object michael@0: * at a particular size. It is passed into text drawing calls to describe michael@0: * the font used for the drawing call. michael@0: */ michael@0: class ScaledFont : public RefCounted michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont) michael@0: virtual ~ScaledFont() {} michael@0: michael@0: typedef void (*FontFileDataOutput)(const uint8_t *aData, uint32_t aLength, uint32_t aIndex, Float aGlyphSize, void *aBaton); michael@0: michael@0: virtual FontType GetType() const = 0; michael@0: michael@0: /* This allows getting a path that describes the outline of a set of glyphs. michael@0: * A target is passed in so that the guarantee is made the returned path michael@0: * can be used with any DrawTarget that has the same backend as the one michael@0: * passed in. michael@0: */ michael@0: virtual TemporaryRef GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) = 0; michael@0: michael@0: /* This copies the path describing the glyphs into a PathBuilder. We use this michael@0: * API rather than a generic API to append paths because it allows easier michael@0: * implementation in some backends, and more efficient implementation in michael@0: * others. michael@0: */ michael@0: virtual void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint = nullptr) = 0; michael@0: michael@0: virtual bool GetFontFileData(FontFileDataOutput, void *) { return false; } michael@0: michael@0: void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) { michael@0: mUserData.Add(key, userData, destroy); michael@0: } michael@0: void *GetUserData(UserDataKey *key) { michael@0: return mUserData.Get(key); michael@0: } michael@0: michael@0: protected: michael@0: ScaledFont() {} michael@0: michael@0: UserData mUserData; michael@0: }; michael@0: michael@0: #ifdef MOZ_ENABLE_FREETYPE michael@0: /** michael@0: * Describes a font michael@0: * Used to pass the key informatin from a gfxFont into Azure michael@0: * XXX Should be replaced by a more long term solution, perhaps Bug 738014 michael@0: */ michael@0: struct FontOptions michael@0: { michael@0: std::string mName; michael@0: FontStyle mStyle; michael@0: }; michael@0: #endif michael@0: michael@0: michael@0: /* This class is designed to allow passing additional glyph rendering michael@0: * parameters to the glyph drawing functions. This is an empty wrapper class michael@0: * merely used to allow holding on to and passing around platform specific michael@0: * parameters. This is because different platforms have unique rendering michael@0: * parameters. michael@0: */ michael@0: class GlyphRenderingOptions : public RefCounted michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptions) michael@0: virtual ~GlyphRenderingOptions() {} michael@0: michael@0: virtual FontType GetType() const = 0; michael@0: michael@0: protected: michael@0: GlyphRenderingOptions() {} michael@0: }; michael@0: michael@0: /* This is the main class used for all the drawing. It is created through the michael@0: * factory and accepts drawing commands. The results of drawing to a target michael@0: * may be used either through a Snapshot or by flushing the target and directly michael@0: * accessing the backing store a DrawTarget was created with. michael@0: */ michael@0: class DrawTarget : public RefCounted michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTarget) michael@0: DrawTarget() : mTransformDirty(false), mPermitSubpixelAA(false) {} michael@0: virtual ~DrawTarget() {} michael@0: michael@0: virtual BackendType GetType() const = 0; michael@0: /** michael@0: * Returns a SourceSurface which is a snapshot of the current contents of the DrawTarget. michael@0: * Multiple calls to Snapshot() without any drawing operations in between will michael@0: * normally return the same SourceSurface object. michael@0: */ michael@0: virtual TemporaryRef Snapshot() = 0; michael@0: virtual IntSize GetSize() = 0; michael@0: michael@0: /** michael@0: * If possible returns the bits to this DrawTarget for direct manipulation. While michael@0: * the bits is locked any modifications to this DrawTarget is forbidden. michael@0: * Release takes the original data pointer for safety. michael@0: */ michael@0: virtual bool LockBits(uint8_t** aData, IntSize* aSize, michael@0: int32_t* aStride, SurfaceFormat* aFormat) { return false; } michael@0: virtual void ReleaseBits(uint8_t* aData) {} michael@0: michael@0: /* Ensure that the DrawTarget backend has flushed all drawing operations to michael@0: * this draw target. This must be called before using the backing surface of michael@0: * this draw target outside of GFX 2D code. michael@0: */ michael@0: virtual void Flush() = 0; michael@0: michael@0: /* michael@0: * Draw a surface to the draw target. Possibly doing partial drawing or michael@0: * applying scaling. No sampling happens outside the source. michael@0: * michael@0: * aSurface Source surface to draw michael@0: * aDest Destination rectangle that this drawing operation should draw to michael@0: * aSource Source rectangle in aSurface coordinates, this area of aSurface michael@0: * will be stretched to the size of aDest. michael@0: * aOptions General draw options that are applied to the operation michael@0: * aSurfOptions DrawSurface options that are applied michael@0: */ michael@0: virtual void DrawSurface(SourceSurface *aSurface, michael@0: const Rect &aDest, michael@0: const Rect &aSource, michael@0: const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(), michael@0: const DrawOptions &aOptions = DrawOptions()) = 0; michael@0: michael@0: /* michael@0: * Draw the output of a FilterNode to the DrawTarget. michael@0: * michael@0: * aNode FilterNode to draw michael@0: * aSourceRect Source rectangle in FilterNode space to draw michael@0: * aDestPoint Destination point on the DrawTarget to draw the michael@0: * SourceRectangle of the filter output to michael@0: */ michael@0: virtual void DrawFilter(FilterNode *aNode, michael@0: const Rect &aSourceRect, michael@0: const Point &aDestPoint, michael@0: const DrawOptions &aOptions = DrawOptions()) = 0; michael@0: michael@0: /* michael@0: * Blend a surface to the draw target with a shadow. The shadow is drawn as a michael@0: * gaussian blur using a specified sigma. The shadow is clipped to the size michael@0: * of the input surface, so the input surface should contain a transparent michael@0: * border the size of the approximate coverage of the blur (3 * aSigma). michael@0: * NOTE: This function works in device space! michael@0: * michael@0: * aSurface Source surface to draw. michael@0: * aDest Destination point that this drawing operation should draw to. michael@0: * aColor Color of the drawn shadow michael@0: * aOffset Offset of the shadow michael@0: * aSigma Sigma used for the guassian filter kernel michael@0: * aOperator Composition operator used michael@0: */ michael@0: virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, michael@0: const Point &aDest, michael@0: const Color &aColor, michael@0: const Point &aOffset, michael@0: Float aSigma, michael@0: CompositionOp aOperator) = 0; michael@0: michael@0: /* michael@0: * Clear a rectangle on the draw target to transparent black. This will michael@0: * respect the clipping region and transform. michael@0: * michael@0: * aRect Rectangle to clear michael@0: */ michael@0: virtual void ClearRect(const Rect &aRect) = 0; michael@0: michael@0: /* michael@0: * This is essentially a 'memcpy' between two surfaces. It moves a pixel michael@0: * aligned area from the source surface unscaled directly onto the michael@0: * drawtarget. This ignores both transform and clip. michael@0: * michael@0: * aSurface Surface to copy from michael@0: * aSourceRect Source rectangle to be copied michael@0: * aDest Destination point to copy the surface to michael@0: */ michael@0: virtual void CopySurface(SourceSurface *aSurface, michael@0: const IntRect &aSourceRect, michael@0: const IntPoint &aDestination) = 0; michael@0: michael@0: /* michael@0: * Same as CopySurface, except uses itself as the source. michael@0: * michael@0: * Some backends may be able to optimize this better michael@0: * than just taking a snapshot and using CopySurface. michael@0: */ michael@0: virtual void CopyRect(const IntRect &aSourceRect, michael@0: const IntPoint &aDestination) michael@0: { michael@0: RefPtr source = Snapshot(); michael@0: CopySurface(source, aSourceRect, aDestination); michael@0: } michael@0: michael@0: /* michael@0: * Fill a rectangle on the DrawTarget with a certain source pattern. michael@0: * michael@0: * aRect Rectangle that forms the mask of this filling operation michael@0: * aPattern Pattern that forms the source of this filling operation michael@0: * aOptions Options that are applied to this operation michael@0: */ michael@0: virtual void FillRect(const Rect &aRect, michael@0: const Pattern &aPattern, michael@0: const DrawOptions &aOptions = DrawOptions()) = 0; michael@0: michael@0: /* michael@0: * Stroke a rectangle on the DrawTarget with a certain source pattern. michael@0: * michael@0: * aRect Rectangle that forms the mask of this stroking operation michael@0: * aPattern Pattern that forms the source of this stroking operation michael@0: * aOptions Options that are applied to this operation michael@0: */ michael@0: virtual void StrokeRect(const Rect &aRect, michael@0: const Pattern &aPattern, michael@0: const StrokeOptions &aStrokeOptions = StrokeOptions(), michael@0: const DrawOptions &aOptions = DrawOptions()) = 0; michael@0: michael@0: /* michael@0: * Stroke a line on the DrawTarget with a certain source pattern. michael@0: * michael@0: * aStart Starting point of the line michael@0: * aEnd End point of the line michael@0: * aPattern Pattern that forms the source of this stroking operation michael@0: * aOptions Options that are applied to this operation michael@0: */ michael@0: virtual void StrokeLine(const Point &aStart, michael@0: const Point &aEnd, michael@0: const Pattern &aPattern, michael@0: const StrokeOptions &aStrokeOptions = StrokeOptions(), michael@0: const DrawOptions &aOptions = DrawOptions()) = 0; michael@0: michael@0: /* michael@0: * Stroke a path on the draw target with a certain source pattern. michael@0: * michael@0: * aPath Path that is to be stroked michael@0: * aPattern Pattern that should be used for the stroke michael@0: * aStrokeOptions Stroke options used for this operation michael@0: * aOptions Draw options used for this operation michael@0: */ michael@0: virtual void Stroke(const Path *aPath, michael@0: const Pattern &aPattern, michael@0: const StrokeOptions &aStrokeOptions = StrokeOptions(), michael@0: const DrawOptions &aOptions = DrawOptions()) = 0; michael@0: michael@0: /* michael@0: * Fill a path on the draw target with a certain source pattern. michael@0: * michael@0: * aPath Path that is to be filled michael@0: * aPattern Pattern that should be used for the fill michael@0: * aOptions Draw options used for this operation michael@0: */ michael@0: virtual void Fill(const Path *aPath, michael@0: const Pattern &aPattern, michael@0: const DrawOptions &aOptions = DrawOptions()) = 0; michael@0: michael@0: /* michael@0: * Fill a series of clyphs on the draw target with a certain source pattern. michael@0: */ michael@0: virtual void FillGlyphs(ScaledFont *aFont, michael@0: const GlyphBuffer &aBuffer, michael@0: const Pattern &aPattern, michael@0: const DrawOptions &aOptions = DrawOptions(), michael@0: const GlyphRenderingOptions *aRenderingOptions = nullptr) = 0; michael@0: michael@0: /* michael@0: * This takes a source pattern and a mask, and composites the source pattern michael@0: * onto the destination surface using the alpha channel of the mask pattern michael@0: * as a mask for the operation. michael@0: * michael@0: * aSource Source pattern michael@0: * aMask Mask pattern michael@0: * aOptions Drawing options michael@0: */ michael@0: virtual void Mask(const Pattern &aSource, michael@0: const Pattern &aMask, michael@0: const DrawOptions &aOptions = DrawOptions()) = 0; michael@0: michael@0: /* michael@0: * This takes a source pattern and a mask, and composites the source pattern michael@0: * onto the destination surface using the alpha channel of the mask source. michael@0: * The operation is bound by the extents of the mask. michael@0: * michael@0: * aSource Source pattern michael@0: * aMask Mask surface michael@0: * aOffset a transformed offset that the surface is masked at michael@0: * aOptions Drawing options michael@0: */ michael@0: virtual void MaskSurface(const Pattern &aSource, michael@0: SourceSurface *aMask, michael@0: Point aOffset, michael@0: const DrawOptions &aOptions = DrawOptions()) = 0; michael@0: michael@0: /* michael@0: * Push a clip to the DrawTarget. michael@0: * michael@0: * aPath The path to clip to michael@0: */ michael@0: virtual void PushClip(const Path *aPath) = 0; michael@0: michael@0: /* michael@0: * Push an axis-aligned rectangular clip to the DrawTarget. This rectangle michael@0: * is specified in user space. michael@0: * michael@0: * aRect The rect to clip to michael@0: */ michael@0: virtual void PushClipRect(const Rect &aRect) = 0; michael@0: michael@0: /* Pop a clip from the DrawTarget. A pop without a corresponding push will michael@0: * be ignored. michael@0: */ michael@0: virtual void PopClip() = 0; michael@0: michael@0: /* michael@0: * Create a SourceSurface optimized for use with this DrawTarget from michael@0: * existing bitmap data in memory. michael@0: * michael@0: * The SourceSurface does not take ownership of aData, and may be freed at any time. michael@0: */ michael@0: virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, michael@0: const IntSize &aSize, michael@0: int32_t aStride, michael@0: SurfaceFormat aFormat) const = 0; michael@0: michael@0: /* michael@0: * Create a SourceSurface optimized for use with this DrawTarget from an michael@0: * arbitrary SourceSurface type supported by this backend. This may return michael@0: * aSourceSurface or some other existing surface. michael@0: */ michael@0: virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const = 0; michael@0: michael@0: /* michael@0: * Create a SourceSurface for a type of NativeSurface. This may fail if the michael@0: * draw target does not know how to deal with the type of NativeSurface passed michael@0: * in. michael@0: */ michael@0: virtual TemporaryRef michael@0: CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const = 0; michael@0: michael@0: /* michael@0: * Create a DrawTarget whose snapshot is optimized for use with this DrawTarget. michael@0: */ michael@0: virtual TemporaryRef michael@0: CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const = 0; michael@0: michael@0: /* michael@0: * Create a draw target optimized for drawing a shadow. michael@0: * michael@0: * Note that aSigma is the blur radius that must be used when we draw the michael@0: * shadow. Also note that this doesn't affect the size of the allocated michael@0: * surface, the caller is still responsible for including the shadow area in michael@0: * its size. michael@0: */ michael@0: virtual TemporaryRef michael@0: CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, michael@0: float aSigma) const michael@0: { michael@0: return CreateSimilarDrawTarget(aSize, aFormat); michael@0: } michael@0: michael@0: /* michael@0: * Create a path builder with the specified fillmode. michael@0: * michael@0: * We need the fill mode up front because of Direct2D. michael@0: * ID2D1SimplifiedGeometrySink requires the fill mode michael@0: * to be set before calling BeginFigure(). michael@0: */ michael@0: virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const = 0; michael@0: michael@0: /* michael@0: * Create a GradientStops object that holds information about a set of michael@0: * gradient stops, this object is required for linear or radial gradient michael@0: * patterns to represent the color stops in the gradient. michael@0: * michael@0: * aStops An array of gradient stops michael@0: * aNumStops Number of stops in the array aStops michael@0: * aExtendNone This describes how to extend the stop color outside of the michael@0: * gradient area. michael@0: */ michael@0: virtual TemporaryRef michael@0: CreateGradientStops(GradientStop *aStops, michael@0: uint32_t aNumStops, michael@0: ExtendMode aExtendMode = ExtendMode::CLAMP) const = 0; michael@0: michael@0: /* michael@0: * Create a FilterNode object that can be used to apply a filter to various michael@0: * inputs. michael@0: * michael@0: * aType Type of filter node to be created. michael@0: */ michael@0: virtual TemporaryRef CreateFilter(FilterType aType) = 0; michael@0: michael@0: const Matrix &GetTransform() const { return mTransform; } michael@0: michael@0: /* michael@0: * Set a transform on the surface, this transform is applied at drawing time michael@0: * to both the mask and source of the operation. michael@0: */ michael@0: virtual void SetTransform(const Matrix &aTransform) michael@0: { mTransform = aTransform; mTransformDirty = true; } michael@0: michael@0: SurfaceFormat GetFormat() { return mFormat; } michael@0: michael@0: /* Tries to get a native surface for a DrawTarget, this may fail if the michael@0: * draw target cannot convert to this surface type. michael@0: */ michael@0: virtual void *GetNativeSurface(NativeSurfaceType aType) { return nullptr; } michael@0: michael@0: virtual bool IsDualDrawTarget() { return false; } michael@0: michael@0: void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) { michael@0: mUserData.Add(key, userData, destroy); michael@0: } michael@0: void *GetUserData(UserDataKey *key) { michael@0: return mUserData.Get(key); michael@0: } michael@0: michael@0: /* Within this rectangle all pixels will be opaque by the time the result of michael@0: * this DrawTarget is first used for drawing. Either by the underlying surface michael@0: * being used as an input to external drawing, or Snapshot() being called. michael@0: * This rectangle is specified in device space. michael@0: */ michael@0: void SetOpaqueRect(const IntRect &aRect) { michael@0: mOpaqueRect = aRect; michael@0: } michael@0: michael@0: const IntRect &GetOpaqueRect() const { michael@0: return mOpaqueRect; michael@0: } michael@0: michael@0: virtual void SetPermitSubpixelAA(bool aPermitSubpixelAA) { michael@0: mPermitSubpixelAA = aPermitSubpixelAA; michael@0: } michael@0: michael@0: bool GetPermitSubpixelAA() { michael@0: return mPermitSubpixelAA; michael@0: } michael@0: michael@0: #ifdef USE_SKIA_GPU michael@0: virtual bool InitWithGrContext(GrContext* aGrContext, michael@0: const IntSize &aSize, michael@0: SurfaceFormat aFormat) michael@0: { michael@0: MOZ_CRASH(); michael@0: } michael@0: #endif michael@0: michael@0: protected: michael@0: UserData mUserData; michael@0: Matrix mTransform; michael@0: IntRect mOpaqueRect; michael@0: bool mTransformDirty : 1; michael@0: bool mPermitSubpixelAA : 1; michael@0: michael@0: SurfaceFormat mFormat; michael@0: }; michael@0: michael@0: class DrawEventRecorder : public RefCounted michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorder) michael@0: virtual ~DrawEventRecorder() { } michael@0: }; michael@0: michael@0: class GFX2D_API Factory michael@0: { michael@0: public: michael@0: static bool HasSSE2(); 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 IntSize &sz, int32_t limit = 0); michael@0: michael@0: static TemporaryRef CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat = nullptr); michael@0: michael@0: static TemporaryRef michael@0: CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat); michael@0: michael@0: static TemporaryRef michael@0: CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT); michael@0: michael@0: static TemporaryRef michael@0: CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat); michael@0: michael@0: static TemporaryRef michael@0: CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize); michael@0: michael@0: /** michael@0: * This creates a ScaledFont from TrueType data. michael@0: * michael@0: * aData - Pointer to the data michael@0: * aSize - Size of the TrueType data michael@0: * aFaceIndex - Index of the font face in the truetype data this ScaledFont needs to represent. michael@0: * aGlyphSize - Size of the glyphs in this ScaledFont michael@0: * aType - Type of ScaledFont that should be created. michael@0: */ michael@0: static TemporaryRef michael@0: CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize, uint32_t aFaceIndex, Float aGlyphSize, FontType aType); michael@0: michael@0: /* michael@0: * This creates a scaled font with an associated cairo_scaled_font_t, and michael@0: * must be used when using the Cairo backend. The NativeFont and michael@0: * cairo_scaled_font_t* parameters must correspond to the same font. michael@0: */ michael@0: static TemporaryRef michael@0: CreateScaledFontWithCairo(const NativeFont &aNativeFont, Float aSize, cairo_scaled_font_t* aScaledFont); michael@0: michael@0: /* michael@0: * This creates a simple data source surface for a certain size. It allocates michael@0: * new memory for the surface. This memory is freed when the surface is michael@0: * destroyed. michael@0: */ michael@0: static TemporaryRef michael@0: CreateDataSourceSurface(const IntSize &aSize, SurfaceFormat aFormat); michael@0: michael@0: /* michael@0: * This creates a simple data source surface for a certain size with a michael@0: * specific stride, which must be large enough to fit all pixels. michael@0: * It allocates new memory for the surface. This memory is freed when michael@0: * the surface is destroyed. michael@0: */ michael@0: static TemporaryRef michael@0: CreateDataSourceSurfaceWithStride(const IntSize &aSize, SurfaceFormat aFormat, int32_t aStride); michael@0: michael@0: /* michael@0: * This creates a simple data source surface for some existing data. It will michael@0: * wrap this data and the data for this source surface. The caller is michael@0: * responsible for deallocating the memory only after destruction of the michael@0: * surface. michael@0: */ michael@0: static TemporaryRef michael@0: CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride, michael@0: const IntSize &aSize, SurfaceFormat aFormat); michael@0: michael@0: static TemporaryRef michael@0: CreateEventRecorderForFile(const char *aFilename); michael@0: michael@0: static void SetGlobalEventRecorder(DrawEventRecorder *aRecorder); michael@0: michael@0: #ifdef USE_SKIA_GPU michael@0: static TemporaryRef michael@0: CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext, michael@0: const IntSize &aSize, michael@0: SurfaceFormat aFormat); michael@0: #endif michael@0: michael@0: static void PurgeAllCaches(); michael@0: michael@0: #if defined(USE_SKIA) && defined(MOZ_ENABLE_FREETYPE) michael@0: static TemporaryRef michael@0: CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting); michael@0: #endif michael@0: static TemporaryRef michael@0: CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB); michael@0: michael@0: #ifdef XP_MACOSX michael@0: static TemporaryRef CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize); michael@0: #endif michael@0: michael@0: #ifdef WIN32 michael@0: static TemporaryRef CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); michael@0: static TemporaryRef michael@0: CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA, michael@0: ID3D10Texture2D *aTextureB, michael@0: SurfaceFormat aFormat); michael@0: michael@0: static void SetDirect3D10Device(ID3D10Device1 *aDevice); michael@0: static ID3D10Device1 *GetDirect3D10Device(); michael@0: #ifdef USE_D2D1_1 michael@0: static void SetDirect3D11Device(ID3D11Device *aDevice); michael@0: static ID3D11Device *GetDirect3D11Device(); michael@0: static ID2D1Device *GetD2D1Device(); michael@0: #endif michael@0: michael@0: static TemporaryRef michael@0: CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams); michael@0: michael@0: static uint64_t GetD2DVRAMUsageDrawTarget(); michael@0: static uint64_t GetD2DVRAMUsageSourceSurface(); michael@0: static void D2DCleanup(); michael@0: michael@0: private: michael@0: static ID3D10Device1 *mD3D10Device; michael@0: #ifdef USE_D2D1_1 michael@0: static ID3D11Device *mD3D11Device; michael@0: static ID2D1Device *mD2D1Device; michael@0: #endif michael@0: #endif michael@0: michael@0: static DrawEventRecorder *mRecorder; michael@0: }; michael@0: michael@0: } michael@0: } michael@0: michael@0: #endif // _MOZILLA_GFX_2D_H