Source code
Revision control
Copy as Markdown
Other Tools
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
#ifndef _MOZILLA_GFX_2D_H
#define _MOZILLA_GFX_2D_H
#include "Types.h"
#include "Point.h"
#include "Rect.h"
#include "Matrix.h"
#include "Quaternion.h"
#include "UserData.h"
#include "FontVariation.h"
#include <vector>
// GenericRefCountedBase allows us to hold on to refcounted objects of any type
// (contrary to RefCounted<T> which requires knowing the type T) and, in
// particular, without having a dependency on that type. This is used for
// DrawTargetSkia to be able to hold on to a GLContext.
#include "mozilla/GenericRefCounted.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Path.h"
// This RefPtr class isn't ideal for usage in Azure, as it doesn't allow T**
// outparams using the &-operator. But it will have to do as there's no easy
// solution.
#include "mozilla/RefPtr.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/ThreadSafeWeakPtr.h"
#include "mozilla/Atomics.h"
#include "mozilla/DebugOnly.h"
#include "nsRegionFwd.h"
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK)
# ifndef MOZ_ENABLE_FREETYPE
# define MOZ_ENABLE_FREETYPE
# endif
#endif
struct _cairo_surface;
typedef _cairo_surface cairo_surface_t;
struct _cairo_scaled_font;
typedef _cairo_scaled_font cairo_scaled_font_t;
struct FT_LibraryRec_;
typedef FT_LibraryRec_* FT_Library;
struct FT_FaceRec_;
typedef FT_FaceRec_* FT_Face;
typedef int FT_Error;
struct _FcPattern;
typedef _FcPattern FcPattern;
struct ID3D11Texture2D;
struct ID3D11Device;
struct ID2D1Device;
struct ID2D1DeviceContext;
struct ID2D1Multithread;
struct IDWriteFactory;
struct IDWriteRenderingParams;
struct IDWriteFontFace;
struct IDWriteFontCollection;
class SkCanvas;
struct gfxFontStyle;
struct CGContext;
typedef struct CGContext* CGContextRef;
struct CGFont;
typedef CGFont* CGFontRef;
namespace mozilla {
class Mutex;
namespace layers {
class TextureData;
}
namespace wr {
struct FontInstanceOptions;
struct FontInstancePlatformOptions;
} // namespace wr
namespace gfx {
class UnscaledFont;
class ScaledFont;
} // namespace gfx
namespace gfx {
class AlphaBoxBlur;
class ScaledFont;
class SourceSurface;
class DataSourceSurface;
class DrawTarget;
class DrawEventRecorder;
class FilterNode;
class LogForwarder;
struct NativeSurface {
NativeSurfaceType mType;
SurfaceFormat mFormat;
gfx::IntSize mSize;
void* mSurface;
};
/**
* This structure is used to send draw options that are universal to all drawing
* operations.
*/
struct DrawOptions {
/// For constructor parameter description, see member data documentation.
explicit DrawOptions(Float aAlpha = 1.0f,
CompositionOp aCompositionOp = CompositionOp::OP_OVER,
AntialiasMode aAntialiasMode = AntialiasMode::DEFAULT)
: mAlpha(aAlpha),
mCompositionOp(aCompositionOp),
mAntialiasMode(aAntialiasMode) {}
Float mAlpha; /**< Alpha value by which the mask generated by this
operation is multiplied. */
CompositionOp mCompositionOp; /**< The operator that indicates how the source
and destination patterns are blended. */
AntialiasMode mAntialiasMode; /**< The AntiAlias mode used for this drawing
operation. */
};
struct StoredStrokeOptions;
/**
* This structure is used to send stroke options that are used in stroking
* operations.
*/
struct StrokeOptions {
/// For constructor parameter description, see member data documentation.
explicit StrokeOptions(Float aLineWidth = 1.0f,
JoinStyle aLineJoin = JoinStyle::MITER_OR_BEVEL,
CapStyle aLineCap = CapStyle::BUTT,
Float aMiterLimit = 10.0f, size_t aDashLength = 0,
const Float* aDashPattern = 0, Float aDashOffset = 0.f)
: mLineWidth(aLineWidth),
mMiterLimit(aMiterLimit),
mDashPattern(aDashLength > 0 ? aDashPattern : 0),
mDashLength(aDashLength),
mDashOffset(aDashOffset),
mLineJoin(aLineJoin),
mLineCap(aLineCap) {
MOZ_ASSERT(aDashLength == 0 || aDashPattern);
}
Float mLineWidth; //!< Width of the stroke in userspace.
Float mMiterLimit; //!< Miter limit in units of linewidth
const Float* mDashPattern; /**< Series of on/off userspace lengths defining
dash. Owned by the caller; must live at least as
long as this StrokeOptions.
mDashPattern != null <=> mDashLength > 0. */
size_t mDashLength; //!< Number of on/off lengths in mDashPattern.
Float mDashOffset; /**< Userspace offset within mDashPattern at which
stroking begins. */
JoinStyle mLineJoin; //!< Join style used for joining lines.
CapStyle mLineCap; //!< Cap style used for capping lines.
StoredStrokeOptions* Clone() const;
bool operator==(const StrokeOptions& aOther) const {
return mLineWidth == aOther.mLineWidth &&
mMiterLimit == aOther.mMiterLimit &&
mDashLength == aOther.mDashLength &&
(!mDashLength || (mDashPattern && aOther.mDashPattern &&
!memcmp(mDashPattern, aOther.mDashPattern,
mDashLength * sizeof(Float)))) &&
mDashOffset == aOther.mDashOffset && mLineJoin == aOther.mLineJoin &&
mLineCap == aOther.mLineCap;
}
};
/**
* Heap-allocated variation of StrokeOptions that ensures dash patterns are
* properly allocated and destroyed even if the source was stack-allocated.
*/
struct StoredStrokeOptions : public StrokeOptions {
explicit StoredStrokeOptions(const StrokeOptions& aOptions)
: StrokeOptions(aOptions) {
if (mDashLength) {
Float* pattern = new Float[mDashLength];
memcpy(pattern, mDashPattern, mDashLength * sizeof(Float));
mDashPattern = pattern;
}
}
~StoredStrokeOptions() {
if (mDashPattern) {
delete[] mDashPattern;
}
}
};
inline StoredStrokeOptions* StrokeOptions::Clone() const {
return new StoredStrokeOptions(*this);
}
/**
* This structure supplies additional options for calls to DrawSurface.
*/
struct DrawSurfaceOptions {
/// For constructor parameter description, see member data documentation.
explicit DrawSurfaceOptions(
SamplingFilter aSamplingFilter = SamplingFilter::LINEAR,
SamplingBounds aSamplingBounds = SamplingBounds::UNBOUNDED)
: mSamplingFilter(aSamplingFilter), mSamplingBounds(aSamplingBounds) {}
SamplingFilter
mSamplingFilter; /**< SamplingFilter used when resampling source surface
region to the destination region. */
SamplingBounds mSamplingBounds; /**< This indicates whether the implementation
is allowed to sample pixels outside the
source rectangle as specified in
DrawSurface on the surface. */
};
/**
* ShadowOptions supplies options necessary for describing the appearance of a
* a shadow in draw calls that use shadowing.
*/
struct ShadowOptions {
explicit ShadowOptions(const DeviceColor& aColor = DeviceColor(0.0f, 0.0f,
0.0f),
const Point& aOffset = Point(), Float aSigma = 0.0f)
: mColor(aColor), mOffset(aOffset), mSigma(aSigma) {}
DeviceColor mColor; /**< Color of the drawn shadow. */
Point mOffset; /**< Offset of the shadow. */
Float mSigma; /**< Sigma used for the Gaussian filter kernel. */
int32_t BlurRadius() const;
};
/**
* This class is used to store gradient stops, it can only be used with a
* matching DrawTarget. Not adhering to this condition will make a draw call
* fail.
*/
class GradientStops : public SupportsThreadSafeWeakPtr<GradientStops> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStops)
virtual ~GradientStops() = default;
virtual BackendType GetBackendType() const = 0;
virtual bool IsValid() const { return true; }
protected:
GradientStops() = default;
};
/**
* This is the base class for 'patterns'. Patterns describe the pixels used as
* the source for a masked composition operation that is done by the different
* drawing commands. These objects are not backend specific, however for
* example the gradient stops on a gradient pattern can be backend specific.
*/
class Pattern {
public:
virtual ~Pattern() = default;
virtual PatternType GetType() const = 0;
/** Instantiate a new clone with the same pattern type and values. Any
* internal strong references will be converted to weak references. */
virtual Pattern* CloneWeak() const { return nullptr; }
/** Whether the pattern holds an internal weak reference. */
virtual bool IsWeak() const { return false; }
/** Whether any internal weak references still point to a target. */
virtual bool IsValid() const { return true; }
/** Determine if the pattern type and values exactly match. */
virtual bool operator==(const Pattern& aOther) const = 0;
bool operator!=(const Pattern& aOther) const { return !(*this == aOther); }
protected:
Pattern() = default;
// Utility functions to check if a weak reference is still valid.
template <typename T>
static inline bool IsRefValid(const RefPtr<T>& aPtr) {
// RefPtrs are always valid.
return true;
}
template <typename T>
static inline bool IsRefValid(const ThreadSafeWeakPtr<T>& aPtr) {
// Weak refs are only valid if they aren't dead.
return !aPtr.IsDead();
}
};
class ColorPattern : public Pattern {
public:
// Explicit because consumers should generally use ToDeviceColor when
// creating a ColorPattern.
explicit ColorPattern(const DeviceColor& aColor) : mColor(aColor) {}
PatternType GetType() const override { return PatternType::COLOR; }
Pattern* CloneWeak() const override { return new ColorPattern(mColor); }
bool operator==(const Pattern& aOther) const override {
if (aOther.GetType() != PatternType::COLOR) {
return false;
}
const ColorPattern& other = static_cast<const ColorPattern&>(aOther);
return mColor == other.mColor;
}
DeviceColor mColor;
};
/**
* This class is used for Linear Gradient Patterns, the gradient stops are
* stored in a separate object and are backend dependent. This class itself
* may be used on the stack.
*/
template <template <typename> typename REF = RefPtr>
class LinearGradientPatternT : public Pattern {
typedef LinearGradientPatternT<ThreadSafeWeakPtr> Weak;
public:
/// For constructor parameter description, see member data documentation.
LinearGradientPatternT(const Point& aBegin, const Point& aEnd,
RefPtr<GradientStops> aStops,
const Matrix& aMatrix = Matrix())
: mBegin(aBegin),
mEnd(aEnd),
mStops(std::move(aStops)),
mMatrix(aMatrix) {}
PatternType GetType() const override { return PatternType::LINEAR_GRADIENT; }
Pattern* CloneWeak() const override {
return new Weak(mBegin, mEnd, do_AddRef(mStops), mMatrix);
}
bool IsWeak() const override {
return std::is_same<decltype(*this), Weak>::value;
}
bool IsValid() const override { return IsRefValid(mStops); }
template <template <typename> typename T>
bool operator==(const LinearGradientPatternT<T>& aOther) const {
return mBegin == aOther.mBegin && mEnd == aOther.mEnd &&
mStops == aOther.mStops && mMatrix.ExactlyEquals(aOther.mMatrix);
}
bool operator==(const Pattern& aOther) const override {
if (aOther.GetType() != PatternType::LINEAR_GRADIENT) {
return false;
}
return aOther.IsWeak()
? *this == static_cast<const Weak&>(aOther)
: *this == static_cast<const LinearGradientPatternT<>&>(aOther);
}
Point mBegin; //!< Start of the linear gradient
Point mEnd; /**< End of the linear gradient - NOTE: In the case
of a zero length gradient it will act as the
color of the last stop. */
REF<GradientStops> mStops; /**< GradientStops object for this gradient, this
should match the backend type of the draw
target this pattern will be used with. */
Matrix mMatrix; /**< A matrix that transforms the pattern into
user space */
};
typedef LinearGradientPatternT<> LinearGradientPattern;
/**
* This class is used for Radial Gradient Patterns, the gradient stops are
* stored in a separate object and are backend dependent. This class itself
* may be used on the stack.
*/
template <template <typename> typename REF = RefPtr>
class RadialGradientPatternT : public Pattern {
typedef RadialGradientPatternT<ThreadSafeWeakPtr> Weak;
public:
/// For constructor parameter description, see member data documentation.
RadialGradientPatternT(const Point& aCenter1, const Point& aCenter2,
Float aRadius1, Float aRadius2,
RefPtr<GradientStops> aStops,
const Matrix& aMatrix = Matrix())
: mCenter1(aCenter1),
mCenter2(aCenter2),
mRadius1(aRadius1),
mRadius2(aRadius2),
mStops(std::move(aStops)),
mMatrix(aMatrix) {}
PatternType GetType() const override { return PatternType::RADIAL_GRADIENT; }
Pattern* CloneWeak() const override {
return new Weak(mCenter1, mCenter2, mRadius1, mRadius2, do_AddRef(mStops),
mMatrix);
}
bool IsWeak() const override {
return std::is_same<decltype(*this), Weak>::value;
}
bool IsValid() const override { return IsRefValid(mStops); }
template <template <typename> typename T>
bool operator==(const RadialGradientPatternT<T>& aOther) const {
return mCenter1 == aOther.mCenter1 && mCenter2 == aOther.mCenter2 &&
mRadius1 == aOther.mRadius1 && mRadius2 == aOther.mRadius2 &&
mStops == aOther.mStops && mMatrix.ExactlyEquals(aOther.mMatrix);
}
bool operator==(const Pattern& aOther) const override {
if (aOther.GetType() != PatternType::RADIAL_GRADIENT) {
return false;
}
return aOther.IsWeak()
? *this == static_cast<const Weak&>(aOther)
: *this == static_cast<const RadialGradientPatternT<>&>(aOther);
}
Point mCenter1; //!< Center of the inner (focal) circle.
Point mCenter2; //!< Center of the outer circle.
Float mRadius1; //!< Radius of the inner (focal) circle.
Float mRadius2; //!< Radius of the outer circle.
REF<GradientStops> mStops; /**< GradientStops object for this gradient, this
should match the backend type of the draw
target this pattern will be used with. */
Matrix mMatrix; //!< A matrix that transforms the pattern into user space
};
typedef RadialGradientPatternT<> RadialGradientPattern;
/**
* This class is used for Conic Gradient Patterns, the gradient stops are
* stored in a separate object and are backend dependent. This class itself
* may be used on the stack.
*/
template <template <typename> typename REF = RefPtr>
class ConicGradientPatternT : public Pattern {
typedef ConicGradientPatternT<ThreadSafeWeakPtr> Weak;
public:
/// For constructor parameter description, see member data documentation.
ConicGradientPatternT(const Point& aCenter, Float aAngle, Float aStartOffset,
Float aEndOffset, RefPtr<GradientStops> aStops,
const Matrix& aMatrix = Matrix())
: mCenter(aCenter),
mAngle(aAngle),
mStartOffset(aStartOffset),
mEndOffset(aEndOffset),
mStops(std::move(aStops)),
mMatrix(aMatrix) {}
PatternType GetType() const override { return PatternType::CONIC_GRADIENT; }
Pattern* CloneWeak() const override {
return new Weak(mCenter, mAngle, mStartOffset, mEndOffset,
do_AddRef(mStops), mMatrix);
}
bool IsWeak() const override {
return std::is_same<decltype(*this), Weak>::value;
}
bool IsValid() const override { return IsRefValid(mStops); }
template <template <typename> typename T>
bool operator==(const ConicGradientPatternT<T>& aOther) const {
return mCenter == aOther.mCenter && mAngle == aOther.mAngle &&
mStartOffset == aOther.mStartOffset &&
mEndOffset == aOther.mEndOffset && mStops == aOther.mStops &&
mMatrix.ExactlyEquals(aOther.mMatrix);
}
bool operator==(const Pattern& aOther) const override {
if (aOther.GetType() != PatternType::CONIC_GRADIENT) {
return false;
}
return aOther.IsWeak()
? *this == static_cast<const Weak&>(aOther)
: *this == static_cast<const ConicGradientPatternT<>&>(aOther);
}
Point mCenter; //!< Center of the gradient
Float mAngle; //!< Start angle of gradient
Float mStartOffset; // Offset of first stop
Float mEndOffset; // Offset of last stop
REF<GradientStops> mStops; /**< GradientStops object for this gradient, this
should match the backend type of the draw
target this pattern will be used with. */
Matrix mMatrix; //!< A matrix that transforms the pattern into user space
};
typedef ConicGradientPatternT<> ConicGradientPattern;
/**
* This class is used for Surface Patterns, they wrap a surface and a
* repetition mode for the surface. This may be used on the stack.
*/
template <template <typename> typename REF = RefPtr>
class SurfacePatternT : public Pattern {
typedef SurfacePatternT<ThreadSafeWeakPtr> Weak;
public:
/// For constructor parameter description, see member data documentation.
SurfacePatternT(RefPtr<SourceSurface> aSourceSurface, ExtendMode aExtendMode,
const Matrix& aMatrix = Matrix(),
SamplingFilter aSamplingFilter = SamplingFilter::GOOD,
const IntRect& aSamplingRect = IntRect())
: mSurface(std::move(aSourceSurface)),
mExtendMode(aExtendMode),
mSamplingFilter(aSamplingFilter),
mMatrix(aMatrix),
mSamplingRect(aSamplingRect) {}
PatternType GetType() const override { return PatternType::SURFACE; }
Pattern* CloneWeak() const override {
return new Weak(do_AddRef(mSurface), mExtendMode, mMatrix, mSamplingFilter,
mSamplingRect);
}
bool IsWeak() const override {
return std::is_same<decltype(*this), Weak>::value;
}
bool IsValid() const override { return IsRefValid(mSurface); }
template <template <typename> typename T>
bool operator==(const SurfacePatternT<T>& aOther) const {
return mSurface == aOther.mSurface && mExtendMode == aOther.mExtendMode &&
mSamplingFilter == aOther.mSamplingFilter &&
mMatrix.ExactlyEquals(aOther.mMatrix) &&
mSamplingRect.IsEqualEdges(aOther.mSamplingRect);
}
bool operator==(const Pattern& aOther) const override {
if (aOther.GetType() != PatternType::SURFACE) {
return false;
}
return aOther.IsWeak()
? *this == static_cast<const Weak&>(aOther)
: *this == static_cast<const SurfacePatternT<>&>(aOther);
}
REF<SourceSurface> mSurface; //!< Surface to use for drawing
ExtendMode mExtendMode; /**< This determines how the image is extended
outside the bounds of the image */
SamplingFilter
mSamplingFilter; //!< Resampling filter for resampling the image.
Matrix mMatrix; //!< Transforms the pattern into user space
IntRect mSamplingRect; /**< Rect that must not be sampled outside of,
or an empty rect if none has been
specified. */
};
typedef SurfacePatternT<> SurfacePattern;
class StoredPattern;
static const int32_t kReasonableSurfaceSize = 8192;
/**
* This is the base class for source surfaces. These objects are surfaces
* which may be used as a source in a SurfacePattern or a DrawSurface call.
* They cannot be drawn to directly.
*
* Although SourceSurface has thread-safe refcount, some SourceSurface cannot
* be used on random threads at the same time. Only DataSourceSurface can be
* used on random threads now. This will be fixed in the future. Eventually
* all SourceSurface should be thread-safe.
*/
class SourceSurface : public SupportsThreadSafeWeakPtr<SourceSurface> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurface)
virtual ~SourceSurface() = default;
virtual SurfaceType GetType() const = 0;
virtual IntSize GetSize() const = 0;
/* GetRect is useful for when the underlying surface doesn't actually
* have a backing store starting at 0, 0. e.g. SourceSurfaceOffset */
virtual IntRect GetRect() const { return IntRect(IntPoint(0, 0), GetSize()); }
virtual SurfaceFormat GetFormat() const = 0;
/**
* Structure containing memory size information for the surface.
*/
struct SizeOfInfo {
SizeOfInfo()
: mHeapBytes(0),
mNonHeapBytes(0),
mUnknownBytes(0),
mExternalHandles(0),
mExternalId(0),
mTypes(0) {}
void Accumulate(const SizeOfInfo& aOther) {
mHeapBytes += aOther.mHeapBytes;
mNonHeapBytes += aOther.mNonHeapBytes;
mUnknownBytes += aOther.mUnknownBytes;
mExternalHandles += aOther.mExternalHandles;
if (aOther.mExternalId) {
mExternalId = aOther.mExternalId;
}
mTypes |= aOther.mTypes;
}
void AddType(SurfaceType aType) { mTypes |= 1 << uint32_t(aType); }
size_t mHeapBytes; // Bytes allocated on the heap.
size_t mNonHeapBytes; // Bytes allocated off the heap.
size_t mUnknownBytes; // Bytes allocated to either, but unknown.
size_t mExternalHandles; // Open handles for the surface.
uint64_t mExternalId; // External ID for WebRender, if available.
uint32_t mTypes; // Bit shifted values representing SurfaceType.
};
/**
* Get the size information of the underlying data buffer.
*/
virtual void SizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
SizeOfInfo& aInfo) const {
// Default is to estimate the footprint based on its size/format.
auto size = GetSize();
auto format = GetFormat();
aInfo.AddType(GetType());
aInfo.mUnknownBytes = size.width * size.height * BytesPerPixel(format);
}
/** This returns false if some event has made this source surface invalid for
* usage with current DrawTargets. For example in the case of Direct2D this
* could return false if we have switched devices since this surface was
* created.
*/
virtual bool IsValid() const { return true; }
/**
* This returns true if it is the same underlying surface data, even if
* the objects are different (e.g. indirection due to
* DataSourceSurfaceWrapper).
*/
virtual bool Equals(SourceSurface* aOther, bool aSymmetric = true) {
return this == aOther ||
(aSymmetric && aOther && aOther->Equals(this, false));
}
/**
* This function will return true if the surface type matches that of a
* DataSourceSurface and if GetDataSurface will return the same object.
*/
bool IsDataSourceSurface() const {
switch (GetType()) {
case SurfaceType::DATA:
case SurfaceType::DATA_SHARED:
case SurfaceType::DATA_RECYCLING_SHARED:
case SurfaceType::DATA_ALIGNED:
case SurfaceType::DATA_SHARED_WRAPPER:
case SurfaceType::DATA_MAPPED:
case SurfaceType::SKIA:
case SurfaceType::WEBGL:
return true;
default:
return false;
}
}
/**
* This function will get a DataSourceSurface for this surface, a
* DataSourceSurface's data can be accessed directly.
*/
virtual already_AddRefed<DataSourceSurface> GetDataSurface() = 0;
/** This function will return a SourceSurface without any offset. */
virtual already_AddRefed<SourceSurface> GetUnderlyingSurface() {
RefPtr<SourceSurface> surface = this;
return surface.forget();
}
/** Tries to get this SourceSurface's native surface. This will fail if aType
* is not the type of this SourceSurface's native surface.
*/
virtual void* GetNativeSurface(NativeSurfaceType aType) { return nullptr; }
void AddUserData(UserDataKey* key, void* userData, void (*destroy)(void*)) {
mUserData.Add(key, userData, destroy);
}
void* GetUserData(UserDataKey* key) const { return mUserData.Get(key); }
void RemoveUserData(UserDataKey* key) { mUserData.RemoveAndDestroy(key); }
/** Tries to extract an optimal subrect for the surface. This may fail if the
* request can't be satisfied.
*/
virtual already_AddRefed<SourceSurface> ExtractSubrect(const IntRect& aRect) {
return nullptr;
}
protected:
friend class StoredPattern;
ThreadSafeUserData mUserData;
};
class DataSourceSurface : public SourceSurface {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurface, override)
DataSourceSurface() : mMapCount(0) {}
#ifdef DEBUG
virtual ~DataSourceSurface() { MOZ_ASSERT(mMapCount == 0); }
#endif
struct MappedSurface {
uint8_t* mData = nullptr;
int32_t mStride = 0;
};
enum MapType { READ, WRITE, READ_WRITE };
/**
* This is a scoped version of Map(). Map() is called in the constructor and
* Unmap() in the destructor. Use this for automatic unmapping of your data
* surfaces.
*
* Use IsMapped() to verify whether Map() succeeded or not.
*/
class ScopedMap final {
public:
ScopedMap(DataSourceSurface* aSurface, MapType aType)
: mSurface(aSurface), mIsMapped(aSurface->Map(aType, &mMap)) {}
ScopedMap(ScopedMap&& aOther)
: mSurface(std::move(aOther.mSurface)),
mMap(aOther.mMap),
mIsMapped(aOther.mIsMapped) {
aOther.mMap.mData = nullptr;
aOther.mIsMapped = false;
}
ScopedMap& operator=(ScopedMap&& aOther) {
if (mIsMapped) {
mSurface->Unmap();
}
mSurface = std::move(aOther.mSurface);
mMap = aOther.mMap;
mIsMapped = aOther.mIsMapped;
aOther.mMap.mData = nullptr;
aOther.mIsMapped = false;
return *this;
}
~ScopedMap() {
if (mIsMapped) {
mSurface->Unmap();
}
}
uint8_t* GetData() const {
MOZ_ASSERT(mIsMapped);
return mMap.mData;
}
int32_t GetStride() const {
MOZ_ASSERT(mIsMapped);
return mMap.mStride;
}
const MappedSurface* GetMappedSurface() const {
MOZ_ASSERT(mIsMapped);
return &mMap;
}
const DataSourceSurface* GetSurface() const {
MOZ_ASSERT(mIsMapped);
return mSurface;
}
bool IsMapped() const { return mIsMapped; }
private:
ScopedMap(const ScopedMap& aOther) = delete;
ScopedMap& operator=(const ScopedMap& aOther) = delete;
RefPtr<DataSourceSurface> mSurface;
MappedSurface mMap;
bool mIsMapped;
};
SurfaceType GetType() const override { return SurfaceType::DATA; }
/** @deprecated
* Get the raw bitmap data of the surface.
* Can return null if there was OOM allocating surface data.
*
* Deprecated means you shouldn't be using this!! Use Map instead.
* Please deny any reviews which add calls to this!
*/
virtual uint8_t* GetData() = 0;
/** @deprecated
* Stride of the surface, distance in bytes between the start of the image
* data belonging to row y and row y+1. This may be negative.
* Can return 0 if there was OOM allocating surface data.
*/
virtual int32_t Stride() = 0;
/**
* The caller is responsible for ensuring aMappedSurface is not null.
// Althought Map (and Moz2D in general) isn't normally threadsafe,
// we want to allow it for SourceSurfaceRawData since it should
// always be fine (for reading at least).
//
// This is the same as the base class implementation except using
// mMapCount instead of mIsMapped since that breaks for multithread.
//
// Once mfbt supports Monitors we should implement proper read/write
// locking to prevent write races.
*/
virtual bool Map(MapType, MappedSurface* aMappedSurface) {
aMappedSurface->mData = GetData();
aMappedSurface->mStride = Stride();
bool success = !!aMappedSurface->mData;
if (success) {
mMapCount++;
}
return success;
}
virtual void Unmap() {
mMapCount--;
MOZ_ASSERT(mMapCount >= 0);
}
/**
* Returns a DataSourceSurface with the same data as this one, but
* guaranteed to have surface->GetType() == SurfaceType::DATA.
*
* The returning surface might be null, because of OOM or gfx device reset.
* The caller needs to do null-check before using it.
*/
already_AddRefed<DataSourceSurface> GetDataSurface() override;
/**
* Returns whether or not the data was allocated on the heap. This should
* be used to determine if the memory needs to be cleared to 0.
*/
virtual bool OnHeap() const { return true; }
/**
* Yields a dirty rect of what has changed since it was last called.
*/
virtual Maybe<IntRect> TakeDirtyRect() { return Nothing(); }
/**
* Indicate a region which has changed in the surface.
*/
virtual void Invalidate(const IntRect& aDirtyRect) {}
protected:
Atomic<int32_t> mMapCount;
};
/** This is an abstract object that accepts path segments. */
class PathSink : public RefCounted<PathSink> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathSink)
virtual ~PathSink() = default;
/** Move the current point in the path, any figure currently being drawn will
* be considered closed during fill operations, however when stroking the
* closing line segment will not be drawn.
*/
virtual void MoveTo(const Point& aPoint) = 0;
/** Add a linesegment to the current figure */
virtual void LineTo(const Point& aPoint) = 0;
/** Add a cubic bezier curve to the current figure */
virtual void BezierTo(const Point& aCP1, const Point& aCP2,
const Point& aCP3) = 0;
/** Add a quadratic bezier curve to the current figure */
virtual void QuadraticBezierTo(const Point& aCP1, const Point& aCP2) = 0;
/** Close the current figure, this will essentially generate a line segment
* from the current point to the starting point for the current figure
*/
virtual void Close() = 0;
/** Add an arc to the current figure */
virtual void Arc(const Point& aOrigin, float aRadius, float aStartAngle,
float aEndAngle, bool aAntiClockwise = false) = 0;
virtual Point CurrentPoint() const { return mCurrentPoint; }
virtual Point BeginPoint() const { return mBeginPoint; }
virtual void SetCurrentPoint(const Point& aPoint) { mCurrentPoint = aPoint; }
virtual void SetBeginPoint(const Point& aPoint) { mBeginPoint = aPoint; }
protected:
/** Point the current subpath is at - or where the next subpath will start
* if there is no active subpath.
*/
Point mCurrentPoint;
/** Position of the previous MoveTo operation. */
Point mBeginPoint;
};
class PathBuilder;
class FlattenedPath;
/** The path class is used to create (sets of) figures of any shape that can be
* filled or stroked to a DrawTarget
*/
class Path : public external::AtomicRefCounted<Path> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(Path)
virtual ~Path();
virtual BackendType GetBackendType() const = 0;
/** This returns a PathBuilder object that contains a copy of the contents of
* this path and is still writable.
*/
inline already_AddRefed<PathBuilder> CopyToBuilder() const {
return CopyToBuilder(GetFillRule());
}
inline already_AddRefed<PathBuilder> TransformedCopyToBuilder(
const Matrix& aTransform) const {
return TransformedCopyToBuilder(aTransform, GetFillRule());
}
/** This returns a PathBuilder object that contains a copy of the contents of
* this path, converted to use the specified FillRule, and still writable.
*/
virtual already_AddRefed<PathBuilder> CopyToBuilder(
FillRule aFillRule) const = 0;
virtual already_AddRefed<PathBuilder> TransformedCopyToBuilder(
const Matrix& aTransform, FillRule aFillRule) const = 0;
/** This function checks if a point lies within a path. It allows passing a
* transform that will transform the path to the coordinate space in which
* aPoint is given.
*/
virtual bool ContainsPoint(const Point& aPoint,
const Matrix& aTransform) const = 0;
/** This function checks if a point lies within the stroke of a path using the
* specified strokeoptions. It allows passing a transform that will transform
* the path to the coordinate space in which aPoint is given.
*/
virtual bool StrokeContainsPoint(const StrokeOptions& aStrokeOptions,
const Point& aPoint,
const Matrix& aTransform) const = 0;
/** This functions gets the bounds of this path. These bounds are not
* guaranteed to be tight. A transform may be specified that gives the bounds
* after application of the transform.
*/
virtual Rect GetBounds(const Matrix& aTransform = Matrix()) const = 0;
/** This function gets the bounds of the stroke of this path using the
* specified strokeoptions. These bounds are not guaranteed to be tight.
* A transform may be specified that gives the bounds after application of
* the transform.
*/
virtual Rect GetStrokedBounds(const StrokeOptions& aStrokeOptions,
const Matrix& aTransform = Matrix()) const = 0;
/** Gets conservative bounds for the path, optionally stroked or transformed.
* This function will prioritize speed of computation over tightness of the
* computed bounds if the backend supports the distinction.
*/
virtual Rect GetFastBounds(
const Matrix& aTransform = Matrix(),
const StrokeOptions* aStrokeOptions = nullptr) const;
/** Take the contents of this path and stream it to another sink, this works
* regardless of the backend that might be used for the destination sink.
*/
virtual void StreamToSink(PathSink* aSink) const = 0;
/** This gets the fillrule this path's builder was created with. This is not
* mutable.
*/
virtual FillRule GetFillRule() const = 0;
virtual Float ComputeLength();
virtual Maybe<Rect> AsRect() const { return Nothing(); }
virtual Point ComputePointAtLength(Float aLength, Point* aTangent = nullptr);
virtual bool IsEmpty() const { return false; }
protected:
Path();
void EnsureFlattenedPath();
RefPtr<FlattenedPath> mFlattenedPath;
};
/** The PathBuilder class allows path creation. Once finish is called on the
* pathbuilder it may no longer be written to.
*/
class PathBuilder : public PathSink {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilder, override)
/** Finish writing to the path and return a Path object that can be used for
* drawing. Future use of the builder results in a crash!
*/
virtual already_AddRefed<Path> Finish() = 0;
virtual BackendType GetBackendType() const = 0;
};
struct Glyph {
uint32_t mIndex;
Point mPosition;
};
static inline bool operator==(const Glyph& aOne, const Glyph& aOther) {
return aOne.mIndex == aOther.mIndex && aOne.mPosition == aOther.mPosition;
}
/** This class functions as a glyph buffer that can be drawn to a DrawTarget.
* @todo XXX - This should probably contain the guts of gfxTextRun in the future
* as roc suggested. But for now it's a simple container for a glyph vector.
*/
struct GlyphBuffer {
const Glyph*
mGlyphs; //!< A pointer to a buffer of glyphs. Managed by the caller.
uint32_t mNumGlyphs; //!< Number of glyphs mGlyphs points to.
};
#ifdef MOZ_ENABLE_FREETYPE
class SharedFTFace;
/** SharedFTFaceData abstracts data that may be used to back a SharedFTFace.
* Its main function is to manage the lifetime of the data and ensure that it
* lasts as long as the face.
*/
class SharedFTFaceData {
public:
/** Utility for creating a new face from this data. */
virtual already_AddRefed<SharedFTFace> CloneFace(int aFaceIndex = 0) {
return nullptr;
}
/** Binds the data's lifetime to the face. */
virtual void BindData() = 0;
/** Signals that the data is no longer needed by a face. */
virtual void ReleaseData() = 0;
};
/** Wrapper class for ref-counted SharedFTFaceData that handles calling the
* appropriate ref-counting methods
*/
template <class T>
class SharedFTFaceRefCountedData : public SharedFTFaceData {
public:
void BindData() { static_cast<T*>(this)->AddRef(); }
void ReleaseData() { static_cast<T*>(this)->Release(); }
};
// Helper class used for clearing out user font data when FT font
// face is destroyed. Since multiple faces may use the same data, be
// careful to assure that the data is only cleared out when all uses
// expire. The font entry object contains a refptr to FTUserFontData and
// each FT face created from that font entry contains a refptr to that
// same FTUserFontData object.
// This is also attached to FT faces for installed fonts (recording the
// filename, rather than storing the font data) if variations are present.
class FTUserFontData final
: public mozilla::gfx::SharedFTFaceRefCountedData<FTUserFontData> {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FTUserFontData)
FTUserFontData(const uint8_t* aData, uint32_t aLength)
: mFontData(aData), mLength(aLength) {}
explicit FTUserFontData(const char* aFilename) : mFilename(aFilename) {}
const uint8_t* FontData() const { return mFontData; }
already_AddRefed<mozilla::gfx::SharedFTFace> CloneFace(
int aFaceIndex = 0) override;
private:
~FTUserFontData() {
if (mFontData) {
free((void*)mFontData);
}
}
std::string mFilename;
const uint8_t* mFontData = nullptr;
uint32_t mLength = 0;
};
/** SharedFTFace is a shared wrapper around an FT_Face. It is ref-counted,
* unlike FT_Face itself, so that it may be shared among many users with
* RefPtr. Users should take care to lock SharedFTFace before accessing any
* FT_Face fields that may change to ensure exclusive access to it. It also
* allows backing data's lifetime to be bound to it via SharedFTFaceData so
* that the data will not disappear before the face does.
*/
class SharedFTFace : public external::AtomicRefCounted<SharedFTFace> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SharedFTFace)
explicit SharedFTFace(FT_Face aFace, SharedFTFaceData* aData);
virtual ~SharedFTFace();
FT_Face GetFace() const { return mFace; }
SharedFTFaceData* GetData() const { return mData; }
/** Locks the face for exclusive access by a given owner. Returns false if
* the given owner is acquiring the lock for the first time, and true if
* the owner was the prior owner of the lock. Thus the return value can be
* used to do owner-specific initialization of the FT face such as setting
* a size or transform that may have been invalidated by a previous owner.
* If no owner is given, then the user should avoid modifying any state on
* the face so as not to invalidate the prior owner's modification.
*/
bool Lock(const void* aOwner = nullptr) MOZ_CAPABILITY_ACQUIRE(mLock) {
mLock.Lock();
return !aOwner || mLastLockOwner.exchange(aOwner) == aOwner;
}
void Unlock() MOZ_CAPABILITY_RELEASE(mLock) { mLock.Unlock(); }
/** Should be called when a lock owner is destroyed so that we don't have
* a dangling pointer to a destroyed owner.
*/
void ForgetLockOwner(const void* aOwner) {
if (aOwner) {
mLastLockOwner.compareExchange(aOwner, nullptr);
}
}
private:
FT_Face mFace;
SharedFTFaceData* mData;
Mutex mLock;
// Remember the last owner of the lock, even after unlocking, to allow users
// to avoid reinitializing state on the FT face if the last owner hasn't
// changed by the next time it is locked with the same owner.
Atomic<const void*> mLastLockOwner;
};
#endif
class UnscaledFont : public SupportsThreadSafeWeakPtr<UnscaledFont> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFont)
virtual ~UnscaledFont();
virtual FontType GetType() const = 0;
static uint32_t DeletionCounter() { return sDeletionCounter; }
typedef void (*FontFileDataOutput)(const uint8_t* aData, uint32_t aLength,
uint32_t aIndex, void* aBaton);
typedef void (*FontInstanceDataOutput)(const uint8_t* aData, uint32_t aLength,
void* aBaton);
typedef void (*FontDescriptorOutput)(const uint8_t* aData, uint32_t aLength,
uint32_t aIndex, void* aBaton);
virtual bool GetFontFileData(FontFileDataOutput, void*) { return false; }
virtual bool GetFontInstanceData(FontInstanceDataOutput, void*) {
return false;
}
virtual bool GetFontDescriptor(FontDescriptorOutput, void*) { return false; }
virtual already_AddRefed<ScaledFont> CreateScaledFont(
Float aGlyphSize, const uint8_t* aInstanceData,
uint32_t aInstanceDataLength, const FontVariation* aVariations,
uint32_t aNumVariations) {
return nullptr;
}
virtual already_AddRefed<ScaledFont> CreateScaledFontFromWRFont(
Float aGlyphSize, const wr::FontInstanceOptions* aOptions,
const wr::FontInstancePlatformOptions* aPlatformOptions,
const FontVariation* aVariations, uint32_t aNumVariations) {
return CreateScaledFont(aGlyphSize, nullptr, 0, aVariations,
aNumVariations);
}
protected:
UnscaledFont() = default;
private:
static Atomic<uint32_t> sDeletionCounter;
};
/** This class is an abstraction of a backend/platform specific font object
* at a particular size. It is passed into text drawing calls to describe
* the font used for the drawing call.
*/
class ScaledFont : public SupportsThreadSafeWeakPtr<ScaledFont> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont)
virtual ~ScaledFont();
virtual FontType GetType() const = 0;
virtual Float GetSize() const = 0;
virtual AntialiasMode GetDefaultAAMode() { return AntialiasMode::DEFAULT; }
static uint32_t DeletionCounter() { return sDeletionCounter; }
/** This allows getting a path that describes the outline of a set of glyphs.
* A target is passed in so that the guarantee is made the returned path
* can be used with any DrawTarget that has the same backend as the one
* passed in.
*/
virtual already_AddRefed<Path> GetPathForGlyphs(
const GlyphBuffer& aBuffer, const DrawTarget* aTarget) = 0;
/** This copies the path describing the glyphs into a PathBuilder. We use this
* API rather than a generic API to append paths because it allows easier
* implementation in some backends, and more efficient implementation in
* others.
*/
virtual void CopyGlyphsToBuilder(const GlyphBuffer& aBuffer,
PathBuilder* aBuilder,
const Matrix* aTransformHint = nullptr) = 0;
typedef void (*FontInstanceDataOutput)(const uint8_t* aData, uint32_t aLength,
const FontVariation* aVariations,
uint32_t aNumVariations, void* aBaton);
virtual bool GetFontInstanceData(FontInstanceDataOutput, void*) {
return false;
}
virtual bool GetWRFontInstanceOptions(
Maybe<wr::FontInstanceOptions>* aOutOptions,
Maybe<wr::FontInstancePlatformOptions>* aOutPlatformOptions,
std::vector<FontVariation>* aOutVariations) {
return false;
}
virtual bool CanSerialize() { return false; }
virtual bool HasVariationSettings() { return false; }
virtual bool MayUseBitmaps() { return false; }
virtual bool UseSubpixelPosition() const { return false; }
void AddUserData(UserDataKey* key, void* userData, void (*destroy)(void*)) {
mUserData.Add(key, userData, destroy);
}
void* GetUserData(UserDataKey* key) { return mUserData.Get(key); }
void RemoveUserData(UserDataKey* key) { mUserData.RemoveAndDestroy(key); }
const RefPtr<UnscaledFont>& GetUnscaledFont() const { return mUnscaledFont; }
virtual cairo_scaled_font_t* GetCairoScaledFont() { return nullptr; }
Float GetSyntheticObliqueAngle() const { return mSyntheticObliqueAngle; }
void SetSyntheticObliqueAngle(Float aAngle) {
mSyntheticObliqueAngle = aAngle;
}
protected:
explicit ScaledFont(const RefPtr<UnscaledFont>& aUnscaledFont)
: mUnscaledFont(aUnscaledFont), mSyntheticObliqueAngle(0.0f) {}
ThreadSafeUserData mUserData;
RefPtr<UnscaledFont> mUnscaledFont;
Float mSyntheticObliqueAngle;
private:
static Atomic<uint32_t> sDeletionCounter;
};
/**
* Derived classes hold a native font resource from which to create
* ScaledFonts.
*/
class NativeFontResource
: public external::AtomicRefCounted<NativeFontResource> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResource)
/**
* Creates a UnscaledFont using the font corresponding to the index.
*
* @param aIndex index for the font within the resource.
* @param aInstanceData pointer to read-only buffer of any available instance
* data.
* @param aInstanceDataLength the size of the instance data.
* @return an already_addrefed UnscaledFont, containing nullptr if failed.
*/
virtual already_AddRefed<UnscaledFont> CreateUnscaledFont(
uint32_t aIndex, const uint8_t* aInstanceData,
uint32_t aInstanceDataLength) = 0;
NativeFontResource(size_t aDataLength);
virtual ~NativeFontResource();
static void RegisterMemoryReporter();
private:
size_t mDataLength;
};
/** This is the main class used for all the drawing. It is created through the
* factory and accepts drawing commands. The results of drawing to a target
* may be used either through a Snapshot or by flushing the target and directly
* accessing the backing store a DrawTarget was created with.
*/
class DrawTarget : public external::AtomicRefCounted<DrawTarget> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTarget)
DrawTarget()
: mTransformDirty(false),
mPermitSubpixelAA(false),
mFormat(SurfaceFormat::UNKNOWN) {}
virtual ~DrawTarget() = default;
virtual bool IsValid() const { return true; };
virtual DrawTargetType GetType() const = 0;
virtual BackendType GetBackendType() const = 0;
virtual bool IsRecording() const { return false; }
/**
* Method to generate hyperlink in PDF output (with appropriate backend).
*/
virtual void Link(const char* aDestination, const Rect& aRect) {}
virtual void Destination(const char* aDestination, const Point& aPoint) {}
/**
* Returns a SourceSurface which is a snapshot of the current contents of the
* DrawTarget. Multiple calls to Snapshot() without any drawing operations in
* between will normally return the same SourceSurface object.
*/
virtual already_AddRefed<SourceSurface> Snapshot() = 0;
/**
* Returns a SourceSurface which wraps the buffer backing the DrawTarget. The
* contents of the buffer may change if there are drawing operations after
* calling but only guarantees that it reflects the state at the time it was
* called.
*/
virtual already_AddRefed<SourceSurface> GetBackingSurface() {
return Snapshot();
}
// Snapshots the contents and returns an alpha mask
// based on the RGB values.
virtual already_AddRefed<SourceSurface> IntoLuminanceSource(
LuminanceType aLuminanceType, float aOpacity);
virtual IntSize GetSize() const = 0;
virtual IntRect GetRect() const { return IntRect(IntPoint(0, 0), GetSize()); }
/**
* If possible returns the bits to this DrawTarget for direct manipulation.
* While the bits is locked any modifications to this DrawTarget is forbidden.
* Release takes the original data pointer for safety.
*/
virtual bool LockBits(uint8_t** aData, IntSize* aSize, int32_t* aStride,
SurfaceFormat* aFormat, IntPoint* aOrigin = nullptr) {
return false;
}
virtual void ReleaseBits(uint8_t* aData) {}
/** Ensure that the DrawTarget backend has flushed all drawing operations to
* this draw target. This must be called before using the backing surface of
* this draw target outside of GFX 2D code.
*/
virtual void Flush() = 0;
/**
* Draw a surface to the draw target. Possibly doing partial drawing or
* applying scaling. No sampling happens outside the source.
*
* @param aSurface Source surface to draw
* @param aDest Destination rectangle that this drawing operation should draw
* to
* @param aSource Source rectangle in aSurface coordinates, this area of
* aSurface
* will be stretched to the size of aDest.
* @param aOptions General draw options that are applied to the operation
* @param aSurfOptions DrawSurface options that are applied
*/
virtual void DrawSurface(
SourceSurface* aSurface, const Rect& aDest, const Rect& aSource,
const DrawSurfaceOptions& aSurfOptions = DrawSurfaceOptions(),
const DrawOptions& aOptions = DrawOptions()) = 0;
/**
* Draw a surface to the draw target, when the surface will be available
* at a later time. This is only valid for recording DrawTargets.
*
* This is considered fallible, and replaying this without making the surface
* available to the replay will just skip the draw.
*/
virtual void DrawDependentSurface(uint64_t aId, const Rect& aDest) {
MOZ_CRASH("GFX: DrawDependentSurface");
}
/**
* Draw the output of a FilterNode to the DrawTarget.
*
* @param aNode FilterNode to draw
* @param aSourceRect Source rectangle in FilterNode space to draw
* @param aDestPoint Destination point on the DrawTarget to draw the
* SourceRectangle of the filter output to
*/
virtual void DrawFilter(FilterNode* aNode, const Rect& aSourceRect,
const Point& aDestPoint,
const DrawOptions& aOptions = DrawOptions()) = 0;
/**
* Blend a surface to the draw target with a shadow. The shadow is drawn as a
* gaussian blur using a specified sigma. The shadow is clipped to the size
* of the input surface, so the input surface should contain a transparent
* border the size of the approximate coverage of the blur (3 * aSigma).
* NOTE: This function works in device space!
*
* @param aSurface Source surface to draw.
* @param aDest Destination point that this drawing operation should draw to.
* @param aShadow Description of shadow to be drawn.
* @param aOperator Composition operator used
*/
virtual void DrawSurfaceWithShadow(SourceSurface* aSurface,
const Point& aDest,
const ShadowOptions& aShadow,
CompositionOp aOperator) = 0;
/**
* Draws a shadow for the specified path, which may be optionally stroked.
*
* @param aPath The path to use for the shadow geometry.
* @param aPattern The pattern to use for filling the path.
* @param aShadow Description of shadow to be drawn.
* @param aOptions General drawing options to apply to drawing the path.
* @param aStrokeOptions Stroking parameters that control stroking of path
* geometry, if supplied.
*/
virtual void DrawShadow(const Path* aPath, const Pattern& aPattern,
const ShadowOptions& aShadow,
const DrawOptions& aOptions = DrawOptions(),
const StrokeOptions* aStrokeOptions = nullptr);
/**
* Clear a rectangle on the draw target to transparent black. This will
* respect the clipping region and transform.
*
* @param aRect Rectangle to clear
*/
virtual void ClearRect(const Rect& aRect) = 0;
/**
* This is essentially a 'memcpy' between two surfaces. It moves a pixel
* aligned area from the source surface unscaled directly onto the
* drawtarget. This ignores both transform and clip.
*
* @param aSurface Surface to copy from
* @param aSourceRect Source rectangle to be copied
* @param aDest Destination point to copy the surface to
*/
virtual void CopySurface(SourceSurface* aSurface, const IntRect& aSourceRect,
const IntPoint& aDestination) = 0;
/** @see CopySurface
* Same as CopySurface, except uses itself as the source.
*
* Some backends may be able to optimize this better
* than just taking a snapshot and using CopySurface.
*/
virtual void CopyRect(const IntRect& aSourceRect,
const IntPoint& aDestination) {
RefPtr<SourceSurface> source = Snapshot();
CopySurface(source, aSourceRect, aDestination);
}
/**
* Fill a rectangle on the DrawTarget with a certain source pattern.
*
* @param aRect Rectangle that forms the mask of this filling operation
* @param aPattern Pattern that forms the source of this filling operation
* @param aOptions Options that are applied to this operation
*/
virtual void FillRect(const Rect& aRect, const Pattern& aPattern,
const DrawOptions& aOptions = DrawOptions()) = 0;
/**
* Fill a rounded rectangle on the DrawTarget with a certain source pattern.
*
* @param aRect Rounded rectangle that forms the mask of this filling
* operation
* @param aPattern Pattern that forms the source of this filling operation
* @param aOptions Options that are applied to this operation
*/
virtual void FillRoundedRect(const RoundedRect& aRect,
const Pattern& aPattern,
const DrawOptions& aOptions = DrawOptions());
/**
* Stroke a rectangle on the DrawTarget with a certain source pattern.
*
* @param aRect Rectangle that forms the mask of this stroking operation
* @param aPattern Pattern that forms the source of this stroking operation
* @param aOptions Options that are applied to this operation
*/
virtual void StrokeRect(const Rect& aRect, const Pattern& aPattern,
const StrokeOptions& aStrokeOptions = StrokeOptions(),
const DrawOptions& aOptions = DrawOptions()) = 0;
/**
* Stroke a line on the DrawTarget with a certain source pattern.
*
* @param aStart Starting point of the line
* @param aEnd End point of the line
* @param aPattern Pattern that forms the source of this stroking operation
* @param aOptions Options that are applied to this operation
*/
virtual void StrokeLine(const Point& aStart, const Point& aEnd,
const Pattern& aPattern,
const StrokeOptions& aStrokeOptions = StrokeOptions(),
const DrawOptions& aOptions = DrawOptions()) = 0;
/**
* Stroke a path on the draw target with a certain source pattern.
*
* @param aPath Path that is to be stroked
* @param aPattern Pattern that should be used for the stroke
* @param aStrokeOptions Stroke options used for this operation
* @param aOptions Draw options used for this operation
*/
virtual void Stroke(const Path* aPath, const Pattern& aPattern,
const StrokeOptions& aStrokeOptions = StrokeOptions(),
const DrawOptions& aOptions = DrawOptions()) = 0;
/**
* Fill a path on the draw target with a certain source pattern.
*
* @param aPath Path that is to be filled
* @param aPattern Pattern that should be used for the fill
* @param aOptions Draw options used for this operation
*/
virtual void Fill(const Path* aPath, const Pattern& aPattern,
const DrawOptions& aOptions = DrawOptions()) = 0;
/**
* Fill a series of glyphs on the draw target with a certain source pattern.
*/
virtual void FillGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
const Pattern& aPattern,
const DrawOptions& aOptions = DrawOptions()) = 0;
/**
* Stroke a series of glyphs on the draw target with a certain source pattern.
*/
virtual void StrokeGlyphs(
ScaledFont* aFont, const GlyphBuffer& aBuffer, const Pattern& aPattern,
const StrokeOptions& aStrokeOptions = StrokeOptions(),
const DrawOptions& aOptions = DrawOptions());
/**
* This takes a source pattern and a mask, and composites the source pattern
* onto the destination surface using the alpha channel of the mask pattern
* as a mask for the operation.