1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "DrawTargetDual.h"
8 #include "Tools.h"
9 #include "Logging.h"
10
11 namespace mozilla {
12 namespace gfx {
13
14 class DualSurface {
15 public:
DualSurface(SourceSurface * aSurface)16 inline explicit DualSurface(SourceSurface* aSurface) {
17 if (!aSurface) {
18 mA = mB = nullptr;
19 return;
20 }
21
22 if (aSurface->GetType() != SurfaceType::DUAL_DT) {
23 mA = mB = aSurface;
24 return;
25 }
26
27 SourceSurfaceDual* ssDual = static_cast<SourceSurfaceDual*>(aSurface);
28 mA = ssDual->mA;
29 mB = ssDual->mB;
30 }
31
32 SourceSurface* mA;
33 SourceSurface* mB;
34 };
35
36 /* This only needs to split patterns up for SurfacePatterns. Only in that
37 * case can we be dealing with a 'dual' source (SourceSurfaceDual) and do
38 * we need to pass separate patterns into our destination DrawTargets.
39 */
40 class DualPattern final {
41 public:
DualPattern(const Pattern & aPattern)42 inline explicit DualPattern(const Pattern& aPattern)
43 : mPatternsInitialized(false) {
44 if (aPattern.GetType() != PatternType::SURFACE) {
45 mA = mB = &aPattern;
46 return;
47 }
48
49 const SurfacePattern* surfPat =
50 static_cast<const SurfacePattern*>(&aPattern);
51
52 if (surfPat->mSurface->GetType() != SurfaceType::DUAL_DT) {
53 mA = mB = &aPattern;
54 return;
55 }
56
57 const SourceSurfaceDual* ssDual =
58 static_cast<const SourceSurfaceDual*>(surfPat->mSurface.get());
59 mA = new (mSurfPatA.addr())
60 SurfacePattern(ssDual->mA, surfPat->mExtendMode, surfPat->mMatrix,
61 surfPat->mSamplingFilter);
62 mB = new (mSurfPatB.addr())
63 SurfacePattern(ssDual->mB, surfPat->mExtendMode, surfPat->mMatrix,
64 surfPat->mSamplingFilter);
65 mPatternsInitialized = true;
66 }
67
~DualPattern()68 inline ~DualPattern() {
69 if (mPatternsInitialized) {
70 mA->~Pattern();
71 mB->~Pattern();
72 }
73 }
74
75 ClassStorage<SurfacePattern> mSurfPatA;
76 ClassStorage<SurfacePattern> mSurfPatB;
77
78 const Pattern* mA;
79 const Pattern* mB;
80
81 bool mPatternsInitialized;
82 };
83
DetachAllSnapshots()84 void DrawTargetDual::DetachAllSnapshots() {
85 mA->DetachAllSnapshots();
86 mB->DetachAllSnapshots();
87 }
88
DrawSurface(SourceSurface * aSurface,const Rect & aDest,const Rect & aSource,const DrawSurfaceOptions & aSurfOptions,const DrawOptions & aOptions)89 void DrawTargetDual::DrawSurface(SourceSurface* aSurface, const Rect& aDest,
90 const Rect& aSource,
91 const DrawSurfaceOptions& aSurfOptions,
92 const DrawOptions& aOptions) {
93 DualSurface surface(aSurface);
94 mA->DrawSurface(surface.mA, aDest, aSource, aSurfOptions, aOptions);
95 mB->DrawSurface(surface.mB, aDest, aSource, aSurfOptions, aOptions);
96 }
97
DrawSurfaceWithShadow(SourceSurface * aSurface,const Point & aDest,const DeviceColor & aColor,const Point & aOffset,Float aSigma,CompositionOp aOp)98 void DrawTargetDual::DrawSurfaceWithShadow(SourceSurface* aSurface,
99 const Point& aDest,
100 const DeviceColor& aColor,
101 const Point& aOffset, Float aSigma,
102 CompositionOp aOp) {
103 DualSurface surface(aSurface);
104 mA->DrawSurfaceWithShadow(surface.mA, aDest, aColor, aOffset, aSigma, aOp);
105 mB->DrawSurfaceWithShadow(surface.mB, aDest, aColor, aOffset, aSigma, aOp);
106 }
107
MaskSurface(const Pattern & aSource,SourceSurface * aMask,Point aOffset,const DrawOptions & aOptions)108 void DrawTargetDual::MaskSurface(const Pattern& aSource, SourceSurface* aMask,
109 Point aOffset, const DrawOptions& aOptions) {
110 DualPattern source(aSource);
111 DualSurface mask(aMask);
112 mA->MaskSurface(*source.mA, mask.mA, aOffset, aOptions);
113 mB->MaskSurface(*source.mB, mask.mB, aOffset, aOptions);
114 }
115
ClearRect(const Rect & aRect)116 void DrawTargetDual::ClearRect(const Rect& aRect) {
117 mA->FillRect(aRect, ColorPattern(DeviceColor::MaskOpaqueBlack()));
118 mB->FillRect(aRect, ColorPattern(DeviceColor::MaskOpaqueWhite()));
119 }
120
CopySurface(SourceSurface * aSurface,const IntRect & aSourceRect,const IntPoint & aDestination)121 void DrawTargetDual::CopySurface(SourceSurface* aSurface,
122 const IntRect& aSourceRect,
123 const IntPoint& aDestination) {
124 DualSurface surface(aSurface);
125 mA->CopySurface(surface.mA, aSourceRect, aDestination);
126 mB->CopySurface(surface.mB, aSourceRect, aDestination);
127 }
128
FillRect(const Rect & aRect,const Pattern & aPattern,const DrawOptions & aOptions)129 void DrawTargetDual::FillRect(const Rect& aRect, const Pattern& aPattern,
130 const DrawOptions& aOptions) {
131 DualPattern pattern(aPattern);
132 mA->FillRect(aRect, *pattern.mA, aOptions);
133 mB->FillRect(aRect, *pattern.mB, aOptions);
134 }
135
StrokeRect(const Rect & aRect,const Pattern & aPattern,const StrokeOptions & aStrokeOptions,const DrawOptions & aOptions)136 void DrawTargetDual::StrokeRect(const Rect& aRect, const Pattern& aPattern,
137 const StrokeOptions& aStrokeOptions,
138 const DrawOptions& aOptions) {
139 DualPattern pattern(aPattern);
140 mA->StrokeRect(aRect, *pattern.mA, aStrokeOptions, aOptions);
141 mB->StrokeRect(aRect, *pattern.mB, aStrokeOptions, aOptions);
142 }
143
StrokeLine(const Point & aStart,const Point & aEnd,const Pattern & aPattern,const StrokeOptions & aStrokeOptions,const DrawOptions & aOptions)144 void DrawTargetDual::StrokeLine(const Point& aStart, const Point& aEnd,
145 const Pattern& aPattern,
146 const StrokeOptions& aStrokeOptions,
147 const DrawOptions& aOptions) {
148 DualPattern pattern(aPattern);
149 mA->StrokeLine(aStart, aEnd, *pattern.mA, aStrokeOptions, aOptions);
150 mB->StrokeLine(aStart, aEnd, *pattern.mB, aStrokeOptions, aOptions);
151 }
152
Stroke(const Path * aPath,const Pattern & aPattern,const StrokeOptions & aStrokeOptions,const DrawOptions & aOptions)153 void DrawTargetDual::Stroke(const Path* aPath, const Pattern& aPattern,
154 const StrokeOptions& aStrokeOptions,
155 const DrawOptions& aOptions) {
156 DualPattern pattern(aPattern);
157 mA->Stroke(aPath, *pattern.mA, aStrokeOptions, aOptions);
158 mB->Stroke(aPath, *pattern.mB, aStrokeOptions, aOptions);
159 }
160
Fill(const Path * aPath,const Pattern & aPattern,const DrawOptions & aOptions)161 void DrawTargetDual::Fill(const Path* aPath, const Pattern& aPattern,
162 const DrawOptions& aOptions) {
163 DualPattern pattern(aPattern);
164 mA->Fill(aPath, *pattern.mA, aOptions);
165 mB->Fill(aPath, *pattern.mB, aOptions);
166 }
167
FillGlyphs(ScaledFont * aScaledFont,const GlyphBuffer & aBuffer,const Pattern & aPattern,const DrawOptions & aOptions)168 void DrawTargetDual::FillGlyphs(ScaledFont* aScaledFont,
169 const GlyphBuffer& aBuffer,
170 const Pattern& aPattern,
171 const DrawOptions& aOptions) {
172 DualPattern pattern(aPattern);
173 mA->FillGlyphs(aScaledFont, aBuffer, *pattern.mA, aOptions);
174 mB->FillGlyphs(aScaledFont, aBuffer, *pattern.mB, aOptions);
175 }
176
Mask(const Pattern & aSource,const Pattern & aMask,const DrawOptions & aOptions)177 void DrawTargetDual::Mask(const Pattern& aSource, const Pattern& aMask,
178 const DrawOptions& aOptions) {
179 DualPattern source(aSource);
180 DualPattern mask(aMask);
181 mA->Mask(*source.mA, *mask.mA, aOptions);
182 mB->Mask(*source.mB, *mask.mB, aOptions);
183 }
184
PushLayer(bool aOpaque,Float aOpacity,SourceSurface * aMask,const Matrix & aMaskTransform,const IntRect & aBounds,bool aCopyBackground)185 void DrawTargetDual::PushLayer(bool aOpaque, Float aOpacity,
186 SourceSurface* aMask,
187 const Matrix& aMaskTransform,
188 const IntRect& aBounds, bool aCopyBackground) {
189 DualSurface mask(aMask);
190 mA->PushLayer(aOpaque, aOpacity, mask.mA, aMaskTransform, aBounds,
191 aCopyBackground);
192 mB->PushLayer(aOpaque, aOpacity, mask.mB, aMaskTransform, aBounds,
193 aCopyBackground);
194 }
195
CreateSimilarDrawTarget(const IntSize & aSize,SurfaceFormat aFormat) const196 already_AddRefed<DrawTarget> DrawTargetDual::CreateSimilarDrawTarget(
197 const IntSize& aSize, SurfaceFormat aFormat) const {
198 /* Now that we have PushLayer there a very few cases where a user of
199 * DrawTargetDual wants to have a DualTarget when creating a similar one. */
200 return mA->CreateSimilarDrawTarget(aSize, aFormat);
201 }
202
CreateClippedDrawTarget(const Rect & aBounds,SurfaceFormat aFormat)203 RefPtr<DrawTarget> DrawTargetDual::CreateClippedDrawTarget(
204 const Rect& aBounds, SurfaceFormat aFormat) {
205 /* The user probably doesn't want a DualDrawTarget here. */
206 return mA->CreateClippedDrawTarget(aBounds, aFormat);
207 }
208
CanCreateSimilarDrawTarget(const IntSize & aSize,SurfaceFormat aFormat) const209 bool DrawTargetDual::CanCreateSimilarDrawTarget(const IntSize& aSize,
210 SurfaceFormat aFormat) const {
211 return mA->CanCreateSimilarDrawTarget(aSize, aFormat);
212 }
213
214 } // namespace gfx
215 } // namespace mozilla
216