diff options
Diffstat (limited to '')
-rw-r--r-- | gfx/2d/DrawTargetDual.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/gfx/2d/DrawTargetDual.cpp b/gfx/2d/DrawTargetDual.cpp new file mode 100644 index 0000000000..6f09ce7a8c --- /dev/null +++ b/gfx/2d/DrawTargetDual.cpp @@ -0,0 +1,215 @@ +/* -*- 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 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DrawTargetDual.h" +#include "Tools.h" +#include "Logging.h" + +namespace mozilla { +namespace gfx { + +class DualSurface { + public: + inline explicit DualSurface(SourceSurface* aSurface) { + if (!aSurface) { + mA = mB = nullptr; + return; + } + + if (aSurface->GetType() != SurfaceType::DUAL_DT) { + mA = mB = aSurface; + return; + } + + SourceSurfaceDual* ssDual = static_cast<SourceSurfaceDual*>(aSurface); + mA = ssDual->mA; + mB = ssDual->mB; + } + + SourceSurface* mA; + SourceSurface* mB; +}; + +/* This only needs to split patterns up for SurfacePatterns. Only in that + * case can we be dealing with a 'dual' source (SourceSurfaceDual) and do + * we need to pass separate patterns into our destination DrawTargets. + */ +class DualPattern final { + public: + inline explicit DualPattern(const Pattern& aPattern) + : mPatternsInitialized(false) { + if (aPattern.GetType() != PatternType::SURFACE) { + mA = mB = &aPattern; + return; + } + + const SurfacePattern* surfPat = + static_cast<const SurfacePattern*>(&aPattern); + + if (surfPat->mSurface->GetType() != SurfaceType::DUAL_DT) { + mA = mB = &aPattern; + return; + } + + const SourceSurfaceDual* ssDual = + static_cast<const SourceSurfaceDual*>(surfPat->mSurface.get()); + mA = new (mSurfPatA.addr()) + SurfacePattern(ssDual->mA, surfPat->mExtendMode, surfPat->mMatrix, + surfPat->mSamplingFilter); + mB = new (mSurfPatB.addr()) + SurfacePattern(ssDual->mB, surfPat->mExtendMode, surfPat->mMatrix, + surfPat->mSamplingFilter); + mPatternsInitialized = true; + } + + inline ~DualPattern() { + if (mPatternsInitialized) { + mA->~Pattern(); + mB->~Pattern(); + } + } + + ClassStorage<SurfacePattern> mSurfPatA; + ClassStorage<SurfacePattern> mSurfPatB; + + const Pattern* mA; + const Pattern* mB; + + bool mPatternsInitialized; +}; + +void DrawTargetDual::DetachAllSnapshots() { + mA->DetachAllSnapshots(); + mB->DetachAllSnapshots(); +} + +void DrawTargetDual::DrawSurface(SourceSurface* aSurface, const Rect& aDest, + const Rect& aSource, + const DrawSurfaceOptions& aSurfOptions, + const DrawOptions& aOptions) { + DualSurface surface(aSurface); + mA->DrawSurface(surface.mA, aDest, aSource, aSurfOptions, aOptions); + mB->DrawSurface(surface.mB, aDest, aSource, aSurfOptions, aOptions); +} + +void DrawTargetDual::DrawSurfaceWithShadow(SourceSurface* aSurface, + const Point& aDest, + const DeviceColor& aColor, + const Point& aOffset, Float aSigma, + CompositionOp aOp) { + DualSurface surface(aSurface); + mA->DrawSurfaceWithShadow(surface.mA, aDest, aColor, aOffset, aSigma, aOp); + mB->DrawSurfaceWithShadow(surface.mB, aDest, aColor, aOffset, aSigma, aOp); +} + +void DrawTargetDual::MaskSurface(const Pattern& aSource, SourceSurface* aMask, + Point aOffset, const DrawOptions& aOptions) { + DualPattern source(aSource); + DualSurface mask(aMask); + mA->MaskSurface(*source.mA, mask.mA, aOffset, aOptions); + mB->MaskSurface(*source.mB, mask.mB, aOffset, aOptions); +} + +void DrawTargetDual::ClearRect(const Rect& aRect) { + mA->FillRect(aRect, ColorPattern(DeviceColor::MaskOpaqueBlack())); + mB->FillRect(aRect, ColorPattern(DeviceColor::MaskOpaqueWhite())); +} + +void DrawTargetDual::CopySurface(SourceSurface* aSurface, + const IntRect& aSourceRect, + const IntPoint& aDestination) { + DualSurface surface(aSurface); + mA->CopySurface(surface.mA, aSourceRect, aDestination); + mB->CopySurface(surface.mB, aSourceRect, aDestination); +} + +void DrawTargetDual::FillRect(const Rect& aRect, const Pattern& aPattern, + const DrawOptions& aOptions) { + DualPattern pattern(aPattern); + mA->FillRect(aRect, *pattern.mA, aOptions); + mB->FillRect(aRect, *pattern.mB, aOptions); +} + +void DrawTargetDual::StrokeRect(const Rect& aRect, const Pattern& aPattern, + const StrokeOptions& aStrokeOptions, + const DrawOptions& aOptions) { + DualPattern pattern(aPattern); + mA->StrokeRect(aRect, *pattern.mA, aStrokeOptions, aOptions); + mB->StrokeRect(aRect, *pattern.mB, aStrokeOptions, aOptions); +} + +void DrawTargetDual::StrokeLine(const Point& aStart, const Point& aEnd, + const Pattern& aPattern, + const StrokeOptions& aStrokeOptions, + const DrawOptions& aOptions) { + DualPattern pattern(aPattern); + mA->StrokeLine(aStart, aEnd, *pattern.mA, aStrokeOptions, aOptions); + mB->StrokeLine(aStart, aEnd, *pattern.mB, aStrokeOptions, aOptions); +} + +void DrawTargetDual::Stroke(const Path* aPath, const Pattern& aPattern, + const StrokeOptions& aStrokeOptions, + const DrawOptions& aOptions) { + DualPattern pattern(aPattern); + mA->Stroke(aPath, *pattern.mA, aStrokeOptions, aOptions); + mB->Stroke(aPath, *pattern.mB, aStrokeOptions, aOptions); +} + +void DrawTargetDual::Fill(const Path* aPath, const Pattern& aPattern, + const DrawOptions& aOptions) { + DualPattern pattern(aPattern); + mA->Fill(aPath, *pattern.mA, aOptions); + mB->Fill(aPath, *pattern.mB, aOptions); +} + +void DrawTargetDual::FillGlyphs(ScaledFont* aScaledFont, + const GlyphBuffer& aBuffer, + const Pattern& aPattern, + const DrawOptions& aOptions) { + DualPattern pattern(aPattern); + mA->FillGlyphs(aScaledFont, aBuffer, *pattern.mA, aOptions); + mB->FillGlyphs(aScaledFont, aBuffer, *pattern.mB, aOptions); +} + +void DrawTargetDual::Mask(const Pattern& aSource, const Pattern& aMask, + const DrawOptions& aOptions) { + DualPattern source(aSource); + DualPattern mask(aMask); + mA->Mask(*source.mA, *mask.mA, aOptions); + mB->Mask(*source.mB, *mask.mB, aOptions); +} + +void DrawTargetDual::PushLayer(bool aOpaque, Float aOpacity, + SourceSurface* aMask, + const Matrix& aMaskTransform, + const IntRect& aBounds, bool aCopyBackground) { + DualSurface mask(aMask); + mA->PushLayer(aOpaque, aOpacity, mask.mA, aMaskTransform, aBounds, + aCopyBackground); + mB->PushLayer(aOpaque, aOpacity, mask.mB, aMaskTransform, aBounds, + aCopyBackground); +} + +already_AddRefed<DrawTarget> DrawTargetDual::CreateSimilarDrawTarget( + const IntSize& aSize, SurfaceFormat aFormat) const { + /* Now that we have PushLayer there a very few cases where a user of + * DrawTargetDual wants to have a DualTarget when creating a similar one. */ + return mA->CreateSimilarDrawTarget(aSize, aFormat); +} + +RefPtr<DrawTarget> DrawTargetDual::CreateClippedDrawTarget( + const Rect& aBounds, SurfaceFormat aFormat) { + /* The user probably doesn't want a DualDrawTarget here. */ + return mA->CreateClippedDrawTarget(aBounds, aFormat); +} + +bool DrawTargetDual::CanCreateSimilarDrawTarget(const IntSize& aSize, + SurfaceFormat aFormat) const { + return mA->CanCreateSimilarDrawTarget(aSize, aFormat); +} + +} // namespace gfx +} // namespace mozilla |