• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkBlurDrawLooper.h"
9 #include "SkBlurMaskFilter.h"
10 #include "SkCanvas.h"
11 #include "SkColorSpaceXformer.h"
12 #include "SkColor.h"
13 #include "SkReadBuffer.h"
14 #include "SkWriteBuffer.h"
15 #include "SkLayerDrawLooper.h"
16 #include "SkString.h"
17 #include "SkStringUtils.h"
18 #include "SkUnPreMultiply.h"
19 
LayerInfo()20 SkLayerDrawLooper::LayerInfo::LayerInfo() {
21     fPaintBits = 0;                     // ignore our paint fields
22     fColorMode = SkBlendMode::kDst;     // ignore our color
23     fOffset.set(0, 0);
24     fPostTranslate = false;
25 }
26 
SkLayerDrawLooper()27 SkLayerDrawLooper::SkLayerDrawLooper()
28         : fRecs(nullptr),
29           fCount(0) {
30 }
31 
~SkLayerDrawLooper()32 SkLayerDrawLooper::~SkLayerDrawLooper() {
33     Rec* rec = fRecs;
34     while (rec) {
35         Rec* next = rec->fNext;
36         delete rec;
37         rec = next;
38     }
39 }
40 
41 SkLayerDrawLooper::Context*
makeContext(SkCanvas * canvas,SkArenaAlloc * alloc) const42 SkLayerDrawLooper::makeContext(SkCanvas* canvas, SkArenaAlloc* alloc) const {
43     canvas->save();
44     return alloc->make<LayerDrawLooperContext>(this);
45 }
46 
xferColor(SkColor src,SkColor dst,SkBlendMode mode)47 static SkColor xferColor(SkColor src, SkColor dst, SkBlendMode mode) {
48     switch (mode) {
49         case SkBlendMode::kSrc:
50             return src;
51         case SkBlendMode::kDst:
52             return dst;
53         default: {
54             SkPMColor pmS = SkPreMultiplyColor(src);
55             SkPMColor pmD = SkPreMultiplyColor(dst);
56             SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD);
57             return SkUnPreMultiply::PMColorToColor(result);
58         }
59     }
60 }
61 
62 // Even with kEntirePaint_Bits, we always ensure that the master paint's
63 // text-encoding is respected, since that controls how we interpret the
64 // text/length parameters of a draw[Pos]Text call.
ApplyInfo(SkPaint * dst,const SkPaint & src,const LayerInfo & info)65 void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo(
66         SkPaint* dst, const SkPaint& src, const LayerInfo& info) {
67     SkColor srcColor = src.getColor();
68 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
69     // The framework may respect the alpha value on the original paint.
70     // Match this legacy behavior.
71     if (SkColorGetA(srcColor) == 255) {
72         srcColor = SkColorSetA(srcColor, dst->getAlpha());
73     }
74 #endif
75     dst->setColor(xferColor(srcColor, dst->getColor(), (SkBlendMode)info.fColorMode));
76 
77     BitFlags bits = info.fPaintBits;
78     SkPaint::TextEncoding encoding = dst->getTextEncoding();
79 
80     if (0 == bits) {
81         return;
82     }
83     if (kEntirePaint_Bits == bits) {
84         // we've already computed these, so save it from the assignment
85         uint32_t f = dst->getFlags();
86         SkColor c = dst->getColor();
87         *dst = src;
88         dst->setFlags(f);
89         dst->setColor(c);
90         dst->setTextEncoding(encoding);
91         return;
92     }
93 
94     if (bits & kStyle_Bit) {
95         dst->setStyle(src.getStyle());
96         dst->setStrokeWidth(src.getStrokeWidth());
97         dst->setStrokeMiter(src.getStrokeMiter());
98         dst->setStrokeCap(src.getStrokeCap());
99         dst->setStrokeJoin(src.getStrokeJoin());
100     }
101 
102     if (bits & kTextSkewX_Bit) {
103         dst->setTextSkewX(src.getTextSkewX());
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     SkMaskFilter::BlurRec maskBlur;
184     if (!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         bsRec->fColor = fRecs->fPaint.getColor();
204         bsRec->fStyle = maskBlur.fStyle;
205         bsRec->fQuality = maskBlur.fQuality;
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));
274     }
275     return builder.detach();
276 }
277 
278 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const279 void SkLayerDrawLooper::toString(SkString* str) const {
280     str->appendf("SkLayerDrawLooper (%d): ", fCount);
281 
282     Rec* rec = fRecs;
283     for (int i = 0; i < fCount; i++) {
284         str->appendf("%d: paintBits: (", i);
285         if (0 == rec->fInfo.fPaintBits) {
286             str->append("None");
287         } else if (kEntirePaint_Bits == rec->fInfo.fPaintBits) {
288             str->append("EntirePaint");
289         } else {
290             bool needSeparator = false;
291             SkAddFlagToString(str, SkToBool(kStyle_Bit & rec->fInfo.fPaintBits), "Style",
292                               &needSeparator);
293             SkAddFlagToString(str, SkToBool(kTextSkewX_Bit & rec->fInfo.fPaintBits), "TextSkewX",
294                               &needSeparator);
295             SkAddFlagToString(str, SkToBool(kPathEffect_Bit & rec->fInfo.fPaintBits), "PathEffect",
296                               &needSeparator);
297             SkAddFlagToString(str, SkToBool(kMaskFilter_Bit & rec->fInfo.fPaintBits), "MaskFilter",
298                               &needSeparator);
299             SkAddFlagToString(str, SkToBool(kShader_Bit & rec->fInfo.fPaintBits), "Shader",
300                               &needSeparator);
301             SkAddFlagToString(str, SkToBool(kColorFilter_Bit & rec->fInfo.fPaintBits), "ColorFilter",
302                               &needSeparator);
303             SkAddFlagToString(str, SkToBool(kXfermode_Bit & rec->fInfo.fPaintBits), "Xfermode",
304                               &needSeparator);
305         }
306         str->append(") ");
307 
308         static const char* gModeStrings[(int)SkBlendMode::kLastMode+1] = {
309             "kClear", "kSrc", "kDst", "kSrcOver", "kDstOver", "kSrcIn", "kDstIn",
310             "kSrcOut", "kDstOut", "kSrcATop", "kDstATop", "kXor", "kPlus",
311             "kMultiply", "kScreen", "kOverlay", "kDarken", "kLighten", "kColorDodge",
312             "kColorBurn", "kHardLight", "kSoftLight", "kDifference", "kExclusion"
313         };
314 
315         str->appendf("mode: %s ", gModeStrings[(int)rec->fInfo.fColorMode]);
316 
317         str->append("offset: (");
318         str->appendScalar(rec->fInfo.fOffset.fX);
319         str->append(", ");
320         str->appendScalar(rec->fInfo.fOffset.fY);
321         str->append(") ");
322 
323         str->append("postTranslate: ");
324         if (rec->fInfo.fPostTranslate) {
325             str->append("true ");
326         } else {
327             str->append("false ");
328         }
329 
330         rec->fPaint.toString(str);
331         rec = rec->fNext;
332     }
333 }
334 #endif
335 
Builder()336 SkLayerDrawLooper::Builder::Builder()
337         : fRecs(nullptr),
338           fTopRec(nullptr),
339           fCount(0) {
340 }
341 
~Builder()342 SkLayerDrawLooper::Builder::~Builder() {
343     Rec* rec = fRecs;
344     while (rec) {
345         Rec* next = rec->fNext;
346         delete rec;
347         rec = next;
348     }
349 }
350 
addLayer(const LayerInfo & info)351 SkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) {
352     fCount += 1;
353 
354     Rec* rec = new Rec;
355     rec->fNext = fRecs;
356     rec->fInfo = info;
357     fRecs = rec;
358     if (nullptr == fTopRec) {
359         fTopRec = rec;
360     }
361 
362     return &rec->fPaint;
363 }
364 
addLayer(SkScalar dx,SkScalar dy)365 void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) {
366     LayerInfo info;
367 
368     info.fOffset.set(dx, dy);
369     (void)this->addLayer(info);
370 }
371 
addLayerOnTop(const LayerInfo & info)372 SkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) {
373     fCount += 1;
374 
375     Rec* rec = new Rec;
376     rec->fNext = nullptr;
377     rec->fInfo = info;
378     if (nullptr == fRecs) {
379         fRecs = rec;
380     } else {
381         SkASSERT(fTopRec);
382         fTopRec->fNext = rec;
383     }
384     fTopRec = rec;
385 
386     return &rec->fPaint;
387 }
388 
detach()389 sk_sp<SkDrawLooper> SkLayerDrawLooper::Builder::detach() {
390     SkLayerDrawLooper* looper = new SkLayerDrawLooper;
391     looper->fCount = fCount;
392     looper->fRecs = fRecs;
393 
394     fCount = 0;
395     fRecs = nullptr;
396     fTopRec = nullptr;
397 
398     return sk_sp<SkDrawLooper>(looper);
399 }
400 
Make(SkColor color,SkScalar sigma,SkScalar dx,SkScalar dy)401 sk_sp<SkDrawLooper> SkBlurDrawLooper::Make(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy)
402 {
403     sk_sp<SkMaskFilter> blur = nullptr;
404     if (sigma > 0.0f) {
405         blur = SkBlurMaskFilter::Make(kNormal_SkBlurStyle, sigma, SkBlurMaskFilter::kNone_BlurFlag);
406     }
407 
408     SkLayerDrawLooper::Builder builder;
409 
410     // First layer
411     SkLayerDrawLooper::LayerInfo defaultLayer;
412     builder.addLayer(defaultLayer);
413 
414     // Blur layer
415     SkLayerDrawLooper::LayerInfo blurInfo;
416     blurInfo.fColorMode = SkBlendMode::kSrc;
417     blurInfo.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit;
418     blurInfo.fOffset = SkVector::Make(dx, dy);
419     SkPaint* paint = builder.addLayer(blurInfo);
420     paint->setMaskFilter(std::move(blur));
421     paint->setColor(color);
422 
423     return builder.detach();
424 }
425