|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "BasicLayersImpl.h" |
|
7 #include <new> // for operator new |
|
8 #include "Layers.h" // for Layer, etc |
|
9 #include "basic/BasicImplData.h" // for BasicImplData |
|
10 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc |
|
11 #include "mozilla/DebugOnly.h" // for DebugOnly |
|
12 #include "mozilla/layers/CompositorTypes.h" |
|
13 #include "mozilla/layers/ISurfaceAllocator.h" |
|
14 #include "AutoMaskData.h" |
|
15 |
|
16 using namespace mozilla::gfx; |
|
17 |
|
18 namespace mozilla { |
|
19 namespace layers { |
|
20 |
|
21 bool |
|
22 GetMaskData(Layer* aMaskLayer, |
|
23 const Point& aDeviceOffset, |
|
24 AutoMoz2DMaskData* aMaskData) |
|
25 { |
|
26 if (aMaskLayer) { |
|
27 RefPtr<SourceSurface> surface = |
|
28 static_cast<BasicImplData*>(aMaskLayer->ImplData())->GetAsSourceSurface(); |
|
29 if (surface) { |
|
30 Matrix transform; |
|
31 Matrix4x4 effectiveTransform = aMaskLayer->GetEffectiveTransform(); |
|
32 DebugOnly<bool> maskIs2D = effectiveTransform.CanDraw2D(&transform); |
|
33 NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!"); |
|
34 transform.Translate(-aDeviceOffset.x, -aDeviceOffset.y); |
|
35 aMaskData->Construct(transform, surface); |
|
36 return true; |
|
37 } |
|
38 } |
|
39 return false; |
|
40 } |
|
41 |
|
42 void |
|
43 PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer) |
|
44 { |
|
45 AutoMoz2DMaskData mask; |
|
46 if (GetMaskData(aMaskLayer, Point(), &mask)) { |
|
47 if (aOpacity < 1.0) { |
|
48 aContext->PushGroup(gfxContentType::COLOR_ALPHA); |
|
49 aContext->Paint(aOpacity); |
|
50 aContext->PopGroupToSource(); |
|
51 } |
|
52 aContext->SetMatrix(ThebesMatrix(mask.GetTransform())); |
|
53 aContext->Mask(mask.GetSurface()); |
|
54 return; |
|
55 } |
|
56 |
|
57 // if there is no mask, just paint normally |
|
58 aContext->Paint(aOpacity); |
|
59 } |
|
60 |
|
61 void |
|
62 FillRectWithMask(DrawTarget* aDT, |
|
63 const Rect& aRect, |
|
64 const Color& aColor, |
|
65 const DrawOptions& aOptions, |
|
66 SourceSurface* aMaskSource, |
|
67 const Matrix* aMaskTransform) |
|
68 { |
|
69 if (aMaskSource && aMaskTransform) { |
|
70 aDT->PushClipRect(aRect); |
|
71 Matrix oldTransform = aDT->GetTransform(); |
|
72 |
|
73 aDT->SetTransform(*aMaskTransform); |
|
74 aDT->MaskSurface(ColorPattern(aColor), aMaskSource, Point(), aOptions); |
|
75 aDT->SetTransform(oldTransform); |
|
76 aDT->PopClip(); |
|
77 return; |
|
78 } |
|
79 |
|
80 aDT->FillRect(aRect, ColorPattern(aColor), aOptions); |
|
81 } |
|
82 void |
|
83 FillRectWithMask(DrawTarget* aDT, |
|
84 const gfx::Point& aDeviceOffset, |
|
85 const Rect& aRect, |
|
86 const Color& aColor, |
|
87 const DrawOptions& aOptions, |
|
88 Layer* aMaskLayer) |
|
89 { |
|
90 AutoMoz2DMaskData mask; |
|
91 if (GetMaskData(aMaskLayer, aDeviceOffset, &mask)) { |
|
92 const Matrix& maskTransform = mask.GetTransform(); |
|
93 FillRectWithMask(aDT, aRect, aColor, aOptions, mask.GetSurface(), &maskTransform); |
|
94 return; |
|
95 } |
|
96 |
|
97 FillRectWithMask(aDT, aRect, aColor, aOptions); |
|
98 } |
|
99 |
|
100 void |
|
101 FillRectWithMask(DrawTarget* aDT, |
|
102 const Rect& aRect, |
|
103 SourceSurface* aSurface, |
|
104 Filter aFilter, |
|
105 const DrawOptions& aOptions, |
|
106 ExtendMode aExtendMode, |
|
107 SourceSurface* aMaskSource, |
|
108 const Matrix* aMaskTransform, |
|
109 const Matrix* aSurfaceTransform) |
|
110 { |
|
111 if (aMaskSource && aMaskTransform) { |
|
112 aDT->PushClipRect(aRect); |
|
113 Matrix oldTransform = aDT->GetTransform(); |
|
114 |
|
115 Matrix inverseMask = *aMaskTransform; |
|
116 inverseMask.Invert(); |
|
117 |
|
118 Matrix transform = oldTransform * inverseMask; |
|
119 if (aSurfaceTransform) { |
|
120 transform = (*aSurfaceTransform) * transform; |
|
121 } |
|
122 |
|
123 SurfacePattern source(aSurface, aExtendMode, transform, aFilter); |
|
124 |
|
125 aDT->SetTransform(*aMaskTransform); |
|
126 aDT->MaskSurface(source, aMaskSource, Point(0, 0), aOptions); |
|
127 aDT->SetTransform(oldTransform); |
|
128 aDT->PopClip(); |
|
129 return; |
|
130 } |
|
131 |
|
132 aDT->FillRect(aRect, |
|
133 SurfacePattern(aSurface, aExtendMode, |
|
134 aSurfaceTransform ? (*aSurfaceTransform) : Matrix(), |
|
135 aFilter), aOptions); |
|
136 } |
|
137 |
|
138 void |
|
139 FillRectWithMask(DrawTarget* aDT, |
|
140 const gfx::Point& aDeviceOffset, |
|
141 const Rect& aRect, |
|
142 SourceSurface* aSurface, |
|
143 Filter aFilter, |
|
144 const DrawOptions& aOptions, |
|
145 Layer* aMaskLayer) |
|
146 { |
|
147 AutoMoz2DMaskData mask; |
|
148 if (GetMaskData(aMaskLayer, aDeviceOffset, &mask)) { |
|
149 const Matrix& maskTransform = mask.GetTransform(); |
|
150 FillRectWithMask(aDT, aRect, aSurface, aFilter, aOptions, ExtendMode::CLAMP, |
|
151 mask.GetSurface(), &maskTransform); |
|
152 return; |
|
153 } |
|
154 |
|
155 FillRectWithMask(aDT, aRect, aSurface, aFilter, aOptions, ExtendMode::CLAMP); |
|
156 } |
|
157 |
|
158 BasicImplData* |
|
159 ToData(Layer* aLayer) |
|
160 { |
|
161 return static_cast<BasicImplData*>(aLayer->ImplData()); |
|
162 } |
|
163 |
|
164 gfx::CompositionOp |
|
165 GetEffectiveOperator(Layer* aLayer) |
|
166 { |
|
167 CompositionOp op = aLayer->GetEffectiveMixBlendMode(); |
|
168 |
|
169 if (op != CompositionOp::OP_OVER) { |
|
170 return op; |
|
171 } |
|
172 |
|
173 return ToData(aLayer)->GetOperator(); |
|
174 } |
|
175 |
|
176 ShadowableLayer* |
|
177 ToShadowable(Layer* aLayer) |
|
178 { |
|
179 return aLayer->AsShadowableLayer(); |
|
180 } |
|
181 |
|
182 bool |
|
183 ShouldShadow(Layer* aLayer) |
|
184 { |
|
185 if (!ToShadowable(aLayer)) { |
|
186 NS_ABORT_IF_FALSE(aLayer->GetType() == Layer::TYPE_READBACK, |
|
187 "Only expect not to shadow ReadbackLayers"); |
|
188 return false; |
|
189 } |
|
190 return true; |
|
191 } |
|
192 |
|
193 |
|
194 } |
|
195 } |