1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/core/SkTypes.h"
9
10 #ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkColor.h"
13 #include "include/core/SkMaskFilter.h"
14 #include "include/core/SkString.h"
15 #include "include/core/SkUnPreMultiply.h"
16 #include "include/effects/SkBlurDrawLooper.h"
17 #include "include/effects/SkLayerDrawLooper.h"
18 #include "src/base/SkArenaAlloc.h"
19 #include "src/core/SkBlendModePriv.h"
20 #include "src/core/SkColorSpacePriv.h"
21 #include "src/core/SkMaskFilterBase.h"
22 #include "src/core/SkReadBuffer.h"
23 #include "src/core/SkStringUtils.h"
24 #include "src/core/SkWriteBuffer.h"
25 #include "src/core/SkXfermodePriv.h"
26
LayerInfo()27 SkLayerDrawLooper::LayerInfo::LayerInfo() {
28 fPaintBits = 0; // ignore our paint fields
29 fColorMode = SkBlendMode::kDst; // ignore our color
30 fOffset.set(0, 0);
31 fPostTranslate = false;
32 }
33
SkLayerDrawLooper()34 SkLayerDrawLooper::SkLayerDrawLooper()
35 : fRecs(nullptr),
36 fCount(0) {
37 }
38
~SkLayerDrawLooper()39 SkLayerDrawLooper::~SkLayerDrawLooper() {
40 Rec* rec = fRecs;
41 while (rec) {
42 Rec* next = rec->fNext;
43 delete rec;
44 rec = next;
45 }
46 }
47
48 SkLayerDrawLooper::Context*
makeContext(SkArenaAlloc * alloc) const49 SkLayerDrawLooper::makeContext(SkArenaAlloc* alloc) const {
50 return alloc->make<LayerDrawLooperContext>(this);
51 }
52
xferColor(const SkColor4f & src,const SkColor4f & dst,SkBlendMode mode)53 static SkColor4f xferColor(const SkColor4f& src, const SkColor4f& dst, SkBlendMode mode) {
54 switch (mode) {
55 case SkBlendMode::kSrc:
56 return src;
57 case SkBlendMode::kDst:
58 return dst;
59 default: {
60 SkPMColor4f pmS = src.premul();
61 SkPMColor4f pmD = dst.premul();
62 return SkBlendMode_Apply(mode, pmS, pmD).unpremul();
63 }
64 }
65 }
66
67 // Even with kEntirePaint_Bits, we always ensure that the base paint's
68 // text-encoding is respected, since that controls how we interpret the
69 // text/length parameters of a draw[Pos]Text call.
ApplyInfo(SkPaint * dst,const SkPaint & src,const LayerInfo & info)70 void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo(
71 SkPaint* dst, const SkPaint& src, const LayerInfo& info) {
72 SkColor4f srcColor = src.getColor4f();
73 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
74 // The framework may respect the alpha value on the original paint.
75 // Match this legacy behavior.
76 if (src.getAlpha() == 255) {
77 srcColor.fA = dst->getColor4f().fA;
78 }
79 #endif
80 dst->setColor4f(xferColor(srcColor, dst->getColor4f(), (SkBlendMode)info.fColorMode),
81 sk_srgb_singleton());
82
83 BitFlags bits = info.fPaintBits;
84
85 if (0 == bits) {
86 return;
87 }
88 if (kEntirePaint_Bits == bits) {
89 // we've already computed these, so save it from the assignment
90 bool aa = dst->isAntiAlias();
91 bool di = dst->isDither();
92 SkColor4f c = dst->getColor4f();
93 *dst = src;
94 dst->setAntiAlias(aa);
95 dst->setDither(di);
96 dst->setColor4f(c, sk_srgb_singleton());
97 return;
98 }
99
100 if (bits & kStyle_Bit) {
101 dst->setStyle(src.getStyle());
102 dst->setStrokeWidth(src.getStrokeWidth());
103 dst->setStrokeMiter(src.getStrokeMiter());
104 dst->setStrokeCap(src.getStrokeCap());
105 dst->setStrokeJoin(src.getStrokeJoin());
106 }
107
108 if (bits & kPathEffect_Bit) {
109 dst->setPathEffect(src.refPathEffect());
110 }
111 if (bits & kMaskFilter_Bit) {
112 dst->setMaskFilter(src.refMaskFilter());
113 }
114 if (bits & kShader_Bit) {
115 dst->setShader(src.refShader());
116 }
117 if (bits & kColorFilter_Bit) {
118 dst->setColorFilter(src.refColorFilter());
119 }
120 if (bits & kXfermode_Bit) {
121 dst->setBlender(src.refBlender());
122 }
123
124 // we don't override these
125 #if 0
126 dst->setTypeface(src.getTypeface());
127 dst->setTextSize(src.getTextSize());
128 dst->setTextScaleX(src.getTextScaleX());
129 dst->setRasterizer(src.getRasterizer());
130 dst->setLooper(src.getLooper());
131 dst->setTextEncoding(src.getTextEncoding());
132 dst->setHinting(src.getHinting());
133 #endif
134 }
135
LayerDrawLooperContext(const SkLayerDrawLooper * looper)136 SkLayerDrawLooper::LayerDrawLooperContext::LayerDrawLooperContext(
137 const SkLayerDrawLooper* looper) : fCurrRec(looper->fRecs) {}
138
next(Info * info,SkPaint * paint)139 bool SkLayerDrawLooper::LayerDrawLooperContext::next(Info* info, SkPaint* paint) {
140 if (nullptr == fCurrRec) {
141 return false;
142 }
143
144 ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo);
145
146 if (info) {
147 info->fTranslate = fCurrRec->fInfo.fOffset;
148 info->fApplyPostCTM = fCurrRec->fInfo.fPostTranslate;
149 }
150 fCurrRec = fCurrRec->fNext;
151 return true;
152 }
153
asABlurShadow(BlurShadowRec * bsRec) const154 bool SkLayerDrawLooper::asABlurShadow(BlurShadowRec* bsRec) const {
155 if (fCount != 2) {
156 return false;
157 }
158 const Rec* rec = fRecs;
159
160 // bottom layer needs to be just blur(maskfilter)
161 if ((rec->fInfo.fPaintBits & ~kMaskFilter_Bit)) {
162 return false;
163 }
164 if (SkBlendMode::kSrc != (SkBlendMode)rec->fInfo.fColorMode) {
165 return false;
166 }
167 const SkMaskFilter* mf = rec->fPaint.getMaskFilter();
168 if (nullptr == mf) {
169 return false;
170 }
171 SkMaskFilterBase::BlurRec maskBlur;
172 if (!as_MFB(mf)->asABlur(&maskBlur)) {
173 return false;
174 }
175
176 rec = rec->fNext;
177 // top layer needs to be "plain"
178 if (rec->fInfo.fPaintBits) {
179 return false;
180 }
181 if (SkBlendMode::kDst != (SkBlendMode)rec->fInfo.fColorMode) {
182 return false;
183 }
184 if (!rec->fInfo.fOffset.equals(0, 0)) {
185 return false;
186 }
187
188 if (bsRec) {
189 bsRec->fSigma = maskBlur.fSigma;
190 bsRec->fOffset = fRecs->fInfo.fOffset;
191 // TODO: Update BlurShadowRec to use SkColor4f?
192 bsRec->fColor = fRecs->fPaint.getColor();
193 bsRec->fStyle = maskBlur.fStyle;
194 }
195 return true;
196 }
197
198 ///////////////////////////////////////////////////////////////////////////////
199
flatten(SkWriteBuffer & buffer) const200 void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const {
201 buffer.writeInt(fCount);
202
203 Rec* rec = fRecs;
204 for (int i = 0; i < fCount; i++) {
205 // Legacy "flagsmask" field -- now ignored, remove when we bump version
206 buffer.writeInt(0);
207
208 buffer.writeInt(rec->fInfo.fPaintBits);
209 buffer.writeInt((int)rec->fInfo.fColorMode);
210 buffer.writePoint(rec->fInfo.fOffset);
211 buffer.writeBool(rec->fInfo.fPostTranslate);
212 buffer.writePaint(rec->fPaint);
213 rec = rec->fNext;
214 }
215 }
216
CreateProc(SkReadBuffer & buffer)217 sk_sp<SkFlattenable> SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) {
218 int count = buffer.readInt();
219
220 #if defined(SK_BUILD_FOR_FUZZER)
221 if (count > 100) {
222 count = 100;
223 }
224 #endif
225 Builder builder;
226 for (int i = 0; i < count; i++) {
227 LayerInfo info;
228 // Legacy "flagsmask" field -- now ignored, remove when we bump version
229 (void)buffer.readInt();
230
231 info.fPaintBits = buffer.readInt();
232 info.fColorMode = (SkBlendMode)buffer.readInt();
233 buffer.readPoint(&info.fOffset);
234 info.fPostTranslate = buffer.readBool();
235 *builder.addLayerOnTop(info) = buffer.readPaint();
236 if (!buffer.isValid()) {
237 return nullptr;
238 }
239 }
240 return builder.detach();
241 }
242
Builder()243 SkLayerDrawLooper::Builder::Builder()
244 : fRecs(nullptr),
245 fTopRec(nullptr),
246 fCount(0) {
247 }
248
~Builder()249 SkLayerDrawLooper::Builder::~Builder() {
250 Rec* rec = fRecs;
251 while (rec) {
252 Rec* next = rec->fNext;
253 delete rec;
254 rec = next;
255 }
256 }
257
addLayer(const LayerInfo & info)258 SkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) {
259 fCount += 1;
260
261 Rec* rec = new Rec;
262 rec->fNext = fRecs;
263 rec->fInfo = info;
264 fRecs = rec;
265 if (nullptr == fTopRec) {
266 fTopRec = rec;
267 }
268
269 return &rec->fPaint;
270 }
271
addLayer(SkScalar dx,SkScalar dy)272 void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) {
273 LayerInfo info;
274
275 info.fOffset.set(dx, dy);
276 (void)this->addLayer(info);
277 }
278
addLayerOnTop(const LayerInfo & info)279 SkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) {
280 fCount += 1;
281
282 Rec* rec = new Rec;
283 rec->fNext = nullptr;
284 rec->fInfo = info;
285 if (nullptr == fRecs) {
286 fRecs = rec;
287 } else {
288 SkASSERT(fTopRec);
289 fTopRec->fNext = rec;
290 }
291 fTopRec = rec;
292
293 return &rec->fPaint;
294 }
295
detach()296 sk_sp<SkDrawLooper> SkLayerDrawLooper::Builder::detach() {
297 SkLayerDrawLooper* looper = new SkLayerDrawLooper;
298 looper->fCount = fCount;
299 looper->fRecs = fRecs;
300
301 fCount = 0;
302 fRecs = nullptr;
303 fTopRec = nullptr;
304
305 return sk_sp<SkDrawLooper>(looper);
306 }
307
Make(SkColor color,SkScalar sigma,SkScalar dx,SkScalar dy)308 sk_sp<SkDrawLooper> SkBlurDrawLooper::Make(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy)
309 {
310 return Make(SkColor4f::FromColor(color), sk_srgb_singleton(), sigma, dx, dy);
311 }
312
Make(SkColor4f color,SkColorSpace * cs,SkScalar sigma,SkScalar dx,SkScalar dy)313 sk_sp<SkDrawLooper> SkBlurDrawLooper::Make(SkColor4f color, SkColorSpace* cs,
314 SkScalar sigma, SkScalar dx, SkScalar dy)
315 {
316 sk_sp<SkMaskFilter> blur = nullptr;
317 if (sigma > 0.0f) {
318 blur = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, sigma, true);
319 }
320
321 SkLayerDrawLooper::Builder builder;
322
323 // First layer
324 SkLayerDrawLooper::LayerInfo defaultLayer;
325 builder.addLayer(defaultLayer);
326
327 // Blur layer
328 SkLayerDrawLooper::LayerInfo blurInfo;
329 blurInfo.fColorMode = SkBlendMode::kSrc;
330 blurInfo.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit;
331 blurInfo.fOffset = SkVector::Make(dx, dy);
332 SkPaint* paint = builder.addLayer(blurInfo);
333 paint->setMaskFilter(std::move(blur));
334 paint->setColor4f(color, cs);
335
336 return builder.detach();
337 }
338
339 #endif
340