1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "SkCanvas.h"
9 #include "SkColor.h"
10 #include "SkReadBuffer.h"
11 #include "SkWriteBuffer.h"
12 #include "SkLayerDrawLooper.h"
13 #include "SkString.h"
14 #include "SkStringUtils.h"
15 #include "SkUnPreMultiply.h"
16 
LayerInfo()17 SkLayerDrawLooper::LayerInfo::LayerInfo() {
18     fPaintBits = 0;                     // ignore our paint fields
19     fColorMode = SkXfermode::kDst_Mode; // ignore our color
20     fOffset.set(0, 0);
21     fPostTranslate = false;
22 }
23 
SkLayerDrawLooper()24 SkLayerDrawLooper::SkLayerDrawLooper()
25         : fRecs(nullptr),
26           fCount(0) {
27 }
28 
~SkLayerDrawLooper()29 SkLayerDrawLooper::~SkLayerDrawLooper() {
30     Rec* rec = fRecs;
31     while (rec) {
32         Rec* next = rec->fNext;
33         delete rec;
34         rec = next;
35     }
36 }
37 
createContext(SkCanvas * canvas,void * storage) const38 SkLayerDrawLooper::Context* SkLayerDrawLooper::createContext(SkCanvas* canvas, void* storage) const {
39     canvas->save();
40     return new (storage) LayerDrawLooperContext(this);
41 }
42 
xferColor(SkColor src,SkColor dst,SkXfermode::Mode mode)43 static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) {
44     switch (mode) {
45         case SkXfermode::kSrc_Mode:
46             return src;
47         case SkXfermode::kDst_Mode:
48             return dst;
49         default: {
50             SkPMColor pmS = SkPreMultiplyColor(src);
51             SkPMColor pmD = SkPreMultiplyColor(dst);
52             SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD);
53             return SkUnPreMultiply::PMColorToColor(result);
54         }
55     }
56 }
57 
58 // Even with kEntirePaint_Bits, we always ensure that the master paint's
59 // text-encoding is respected, since that controls how we interpret the
60 // text/length parameters of a draw[Pos]Text call.
ApplyInfo(SkPaint * dst,const SkPaint & src,const LayerInfo & info)61 void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo(
62         SkPaint* dst, const SkPaint& src, const LayerInfo& info) {
63 
64     dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode));
65 
66     BitFlags bits = info.fPaintBits;
67     SkPaint::TextEncoding encoding = dst->getTextEncoding();
68 
69     if (0 == bits) {
70         return;
71     }
72     if (kEntirePaint_Bits == bits) {
73         // we've already computed these, so save it from the assignment
74         uint32_t f = dst->getFlags();
75         SkColor c = dst->getColor();
76         *dst = src;
77         dst->setFlags(f);
78         dst->setColor(c);
79         dst->setTextEncoding(encoding);
80         return;
81     }
82 
83     if (bits & kStyle_Bit) {
84         dst->setStyle(src.getStyle());
85         dst->setStrokeWidth(src.getStrokeWidth());
86         dst->setStrokeMiter(src.getStrokeMiter());
87         dst->setStrokeCap(src.getStrokeCap());
88         dst->setStrokeJoin(src.getStrokeJoin());
89     }
90 
91     if (bits & kTextSkewX_Bit) {
92         dst->setTextSkewX(src.getTextSkewX());
93     }
94 
95     if (bits & kPathEffect_Bit) {
96         dst->setPathEffect(src.getPathEffect());
97     }
98     if (bits & kMaskFilter_Bit) {
99         dst->setMaskFilter(src.getMaskFilter());
100     }
101     if (bits & kShader_Bit) {
102         dst->setShader(src.getShader());
103     }
104     if (bits & kColorFilter_Bit) {
105         dst->setColorFilter(src.getColorFilter());
106     }
107     if (bits & kXfermode_Bit) {
108         dst->setXfermode(src.getXfermode());
109     }
110 
111     // we don't override these
112 #if 0
113     dst->setTypeface(src.getTypeface());
114     dst->setTextSize(src.getTextSize());
115     dst->setTextScaleX(src.getTextScaleX());
116     dst->setRasterizer(src.getRasterizer());
117     dst->setLooper(src.getLooper());
118     dst->setTextEncoding(src.getTextEncoding());
119     dst->setHinting(src.getHinting());
120 #endif
121 }
122 
123 // Should we add this to canvas?
postTranslate(SkCanvas * canvas,SkScalar dx,SkScalar dy)124 static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) {
125     SkMatrix m = canvas->getTotalMatrix();
126     m.postTranslate(dx, dy);
127     canvas->setMatrix(m);
128 }
129 
LayerDrawLooperContext(const SkLayerDrawLooper * looper)130 SkLayerDrawLooper::LayerDrawLooperContext::LayerDrawLooperContext(
131         const SkLayerDrawLooper* looper) : fCurrRec(looper->fRecs) {}
132 
next(SkCanvas * canvas,SkPaint * paint)133 bool SkLayerDrawLooper::LayerDrawLooperContext::next(SkCanvas* canvas,
134                                                      SkPaint* paint) {
135     canvas->restore();
136     if (nullptr == fCurrRec) {
137         return false;
138     }
139 
140     ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo);
141 
142     canvas->save();
143     if (fCurrRec->fInfo.fPostTranslate) {
144         postTranslate(canvas, fCurrRec->fInfo.fOffset.fX,
145                       fCurrRec->fInfo.fOffset.fY);
146     } else {
147         canvas->translate(fCurrRec->fInfo.fOffset.fX,
148                           fCurrRec->fInfo.fOffset.fY);
149     }
150     fCurrRec = fCurrRec->fNext;
151 
152     return true;
153 }
154 
asABlurShadow(BlurShadowRec * bsRec) const155 bool SkLayerDrawLooper::asABlurShadow(BlurShadowRec* bsRec) const {
156     if (fCount != 2) {
157         return false;
158     }
159     const Rec* rec = fRecs;
160 
161     // bottom layer needs to be just blur(maskfilter)
162     if ((rec->fInfo.fPaintBits & ~kMaskFilter_Bit)) {
163         return false;
164     }
165     if (SkXfermode::kSrc_Mode != rec->fInfo.fColorMode) {
166         return false;
167     }
168     const SkMaskFilter* mf = rec->fPaint.getMaskFilter();
169     if (nullptr == mf) {
170         return false;
171     }
172     SkMaskFilter::BlurRec maskBlur;
173     if (!mf->asABlur(&maskBlur)) {
174         return false;
175     }
176 
177     rec = rec->fNext;
178     // top layer needs to be "plain"
179     if (rec->fInfo.fPaintBits) {
180         return false;
181     }
182     if (SkXfermode::kDst_Mode != rec->fInfo.fColorMode) {
183         return false;
184     }
185     if (!rec->fInfo.fOffset.equals(0, 0)) {
186         return false;
187     }
188 
189     if (bsRec) {
190         bsRec->fSigma = maskBlur.fSigma;
191         bsRec->fOffset = fRecs->fInfo.fOffset;
192         bsRec->fColor = fRecs->fPaint.getColor();
193         bsRec->fStyle = maskBlur.fStyle;
194         bsRec->fQuality = maskBlur.fQuality;
195     }
196     return true;
197 }
198 
199 ///////////////////////////////////////////////////////////////////////////////
200 
flatten(SkWriteBuffer & buffer) const201 void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const {
202     buffer.writeInt(fCount);
203 
204     Rec* rec = fRecs;
205     for (int i = 0; i < fCount; i++) {
206         // Legacy "flagsmask" field -- now ignored, remove when we bump version
207         buffer.writeInt(0);
208 
209         buffer.writeInt(rec->fInfo.fPaintBits);
210         buffer.writeInt(rec->fInfo.fColorMode);
211         buffer.writePoint(rec->fInfo.fOffset);
212         buffer.writeBool(rec->fInfo.fPostTranslate);
213         buffer.writePaint(rec->fPaint);
214         rec = rec->fNext;
215     }
216 }
217 
CreateProc(SkReadBuffer & buffer)218 SkFlattenable* SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) {
219     int count = buffer.readInt();
220 
221     Builder builder;
222     for (int i = 0; i < count; i++) {
223         LayerInfo info;
224         // Legacy "flagsmask" field -- now ignored, remove when we bump version
225         (void)buffer.readInt();
226 
227         info.fPaintBits = buffer.readInt();
228         info.fColorMode = (SkXfermode::Mode)buffer.readInt();
229         buffer.readPoint(&info.fOffset);
230         info.fPostTranslate = buffer.readBool();
231         buffer.readPaint(builder.addLayerOnTop(info));
232     }
233     return builder.detachLooper();
234 }
235 
236 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const237 void SkLayerDrawLooper::toString(SkString* str) const {
238     str->appendf("SkLayerDrawLooper (%d): ", fCount);
239 
240     Rec* rec = fRecs;
241     for (int i = 0; i < fCount; i++) {
242         str->appendf("%d: paintBits: (", i);
243         if (0 == rec->fInfo.fPaintBits) {
244             str->append("None");
245         } else if (kEntirePaint_Bits == rec->fInfo.fPaintBits) {
246             str->append("EntirePaint");
247         } else {
248             bool needSeparator = false;
249             SkAddFlagToString(str, SkToBool(kStyle_Bit & rec->fInfo.fPaintBits), "Style",
250                               &needSeparator);
251             SkAddFlagToString(str, SkToBool(kTextSkewX_Bit & rec->fInfo.fPaintBits), "TextSkewX",
252                               &needSeparator);
253             SkAddFlagToString(str, SkToBool(kPathEffect_Bit & rec->fInfo.fPaintBits), "PathEffect",
254                               &needSeparator);
255             SkAddFlagToString(str, SkToBool(kMaskFilter_Bit & rec->fInfo.fPaintBits), "MaskFilter",
256                               &needSeparator);
257             SkAddFlagToString(str, SkToBool(kShader_Bit & rec->fInfo.fPaintBits), "Shader",
258                               &needSeparator);
259             SkAddFlagToString(str, SkToBool(kColorFilter_Bit & rec->fInfo.fPaintBits), "ColorFilter",
260                               &needSeparator);
261             SkAddFlagToString(str, SkToBool(kXfermode_Bit & rec->fInfo.fPaintBits), "Xfermode",
262                               &needSeparator);
263         }
264         str->append(") ");
265 
266         static const char* gModeStrings[SkXfermode::kLastMode+1] = {
267             "kClear", "kSrc", "kDst", "kSrcOver", "kDstOver", "kSrcIn", "kDstIn",
268             "kSrcOut", "kDstOut", "kSrcATop", "kDstATop", "kXor", "kPlus",
269             "kMultiply", "kScreen", "kOverlay", "kDarken", "kLighten", "kColorDodge",
270             "kColorBurn", "kHardLight", "kSoftLight", "kDifference", "kExclusion"
271         };
272 
273         str->appendf("mode: %s ", gModeStrings[rec->fInfo.fColorMode]);
274 
275         str->append("offset: (");
276         str->appendScalar(rec->fInfo.fOffset.fX);
277         str->append(", ");
278         str->appendScalar(rec->fInfo.fOffset.fY);
279         str->append(") ");
280 
281         str->append("postTranslate: ");
282         if (rec->fInfo.fPostTranslate) {
283             str->append("true ");
284         } else {
285             str->append("false ");
286         }
287 
288         rec->fPaint.toString(str);
289         rec = rec->fNext;
290     }
291 }
292 #endif
293 
Builder()294 SkLayerDrawLooper::Builder::Builder()
295         : fRecs(nullptr),
296           fTopRec(nullptr),
297           fCount(0) {
298 }
299 
~Builder()300 SkLayerDrawLooper::Builder::~Builder() {
301     Rec* rec = fRecs;
302     while (rec) {
303         Rec* next = rec->fNext;
304         delete rec;
305         rec = next;
306     }
307 }
308 
addLayer(const LayerInfo & info)309 SkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) {
310     fCount += 1;
311 
312     Rec* rec = new Rec;
313     rec->fNext = fRecs;
314     rec->fInfo = info;
315     fRecs = rec;
316     if (nullptr == fTopRec) {
317         fTopRec = rec;
318     }
319 
320     return &rec->fPaint;
321 }
322 
addLayer(SkScalar dx,SkScalar dy)323 void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) {
324     LayerInfo info;
325 
326     info.fOffset.set(dx, dy);
327     (void)this->addLayer(info);
328 }
329 
addLayerOnTop(const LayerInfo & info)330 SkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) {
331     fCount += 1;
332 
333     Rec* rec = new Rec;
334     rec->fNext = nullptr;
335     rec->fInfo = info;
336     if (nullptr == fRecs) {
337         fRecs = rec;
338     } else {
339         SkASSERT(fTopRec);
340         fTopRec->fNext = rec;
341     }
342     fTopRec = rec;
343 
344     return &rec->fPaint;
345 }
346 
detachLooper()347 SkLayerDrawLooper* SkLayerDrawLooper::Builder::detachLooper() {
348     SkLayerDrawLooper* looper = new SkLayerDrawLooper;
349     looper->fCount = fCount;
350     looper->fRecs = fRecs;
351 
352     fCount = 0;
353     fRecs = nullptr;
354     fTopRec = nullptr;
355 
356     return looper;
357 }
358