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