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