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