summaryrefslogtreecommitdiffstats
path: root/gfx/2d/DrawTargetDual.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/2d/DrawTargetDual.cpp215
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