• 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 "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