• 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 "SkFlattenableBuffers.h"
11 #include "SkLayerDrawLooper.h"
12 #include "SkString.h"
13 #include "SkStringUtils.h"
14 #include "SkUnPreMultiply.h"
15 
LayerInfo()16 SkLayerDrawLooper::LayerInfo::LayerInfo() {
17     fFlagsMask = 0;                     // ignore our paint flags
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           fCurrRec(NULL) {
29 }
30 
~SkLayerDrawLooper()31 SkLayerDrawLooper::~SkLayerDrawLooper() {
32     Rec* rec = fRecs;
33     while (rec) {
34         Rec* next = rec->fNext;
35         SkDELETE(rec);
36         rec = next;
37     }
38 }
39 
addLayer(const LayerInfo & info)40 SkPaint* SkLayerDrawLooper::addLayer(const LayerInfo& info) {
41     fCount += 1;
42 
43     Rec* rec = SkNEW(Rec);
44     rec->fNext = fRecs;
45     rec->fInfo = info;
46     fRecs = rec;
47     if (NULL == fTopRec) {
48         fTopRec = rec;
49     }
50 
51     return &rec->fPaint;
52 }
53 
addLayer(SkScalar dx,SkScalar dy)54 void SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) {
55     LayerInfo info;
56 
57     info.fOffset.set(dx, dy);
58     (void)this->addLayer(info);
59 }
60 
addLayerOnTop(const LayerInfo & info)61 SkPaint* SkLayerDrawLooper::addLayerOnTop(const LayerInfo& info) {
62     fCount += 1;
63 
64     Rec* rec = SkNEW(Rec);
65     rec->fNext = NULL;
66     rec->fInfo = info;
67     if (NULL == fRecs) {
68         fRecs = rec;
69     } else {
70         SkASSERT(NULL != fTopRec);
71         fTopRec->fNext = rec;
72     }
73     fTopRec = rec;
74 
75     return &rec->fPaint;
76 }
77 
init(SkCanvas * canvas)78 void SkLayerDrawLooper::init(SkCanvas* canvas) {
79     fCurrRec = fRecs;
80     canvas->save(SkCanvas::kMatrix_SaveFlag);
81 }
82 
xferColor(SkColor src,SkColor dst,SkXfermode::Mode mode)83 static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) {
84     switch (mode) {
85         case SkXfermode::kSrc_Mode:
86             return src;
87         case SkXfermode::kDst_Mode:
88             return dst;
89         default: {
90             SkPMColor pmS = SkPreMultiplyColor(src);
91             SkPMColor pmD = SkPreMultiplyColor(dst);
92             SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD);
93             return SkUnPreMultiply::PMColorToColor(result);
94         }
95     }
96 }
97 
98 // Even with kEntirePaint_Bits, we always ensure that the master paint's
99 // text-encoding is respected, since that controls how we interpret the
100 // text/length parameters of a draw[Pos]Text call.
ApplyInfo(SkPaint * dst,const SkPaint & src,const LayerInfo & info)101 void SkLayerDrawLooper::ApplyInfo(SkPaint* dst, const SkPaint& src,
102                                   const LayerInfo& info) {
103 
104     uint32_t mask = info.fFlagsMask;
105     dst->setFlags((dst->getFlags() & ~mask) | (src.getFlags() & mask));
106     dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode));
107 
108     BitFlags bits = info.fPaintBits;
109     SkPaint::TextEncoding encoding = dst->getTextEncoding();
110 
111     if (0 == bits) {
112         return;
113     }
114     if (kEntirePaint_Bits == bits) {
115         // we've already computed these, so save it from the assignment
116         uint32_t f = dst->getFlags();
117         SkColor c = dst->getColor();
118         *dst = src;
119         dst->setFlags(f);
120         dst->setColor(c);
121         dst->setTextEncoding(encoding);
122         return;
123     }
124 
125     if (bits & kStyle_Bit) {
126         dst->setStyle(src.getStyle());
127         dst->setStrokeWidth(src.getStrokeWidth());
128         dst->setStrokeMiter(src.getStrokeMiter());
129         dst->setStrokeCap(src.getStrokeCap());
130         dst->setStrokeJoin(src.getStrokeJoin());
131     }
132 
133     if (bits & kTextSkewX_Bit) {
134         dst->setTextSkewX(src.getTextSkewX());
135     }
136 
137     if (bits & kPathEffect_Bit) {
138         dst->setPathEffect(src.getPathEffect());
139     }
140     if (bits & kMaskFilter_Bit) {
141         dst->setMaskFilter(src.getMaskFilter());
142     }
143     if (bits & kShader_Bit) {
144         dst->setShader(src.getShader());
145     }
146     if (bits & kColorFilter_Bit) {
147         dst->setColorFilter(src.getColorFilter());
148     }
149     if (bits & kXfermode_Bit) {
150         dst->setXfermode(src.getXfermode());
151     }
152 
153     // we don't override these
154 #if 0
155     dst->setTypeface(src.getTypeface());
156     dst->setTextSize(src.getTextSize());
157     dst->setTextScaleX(src.getTextScaleX());
158     dst->setRasterizer(src.getRasterizer());
159     dst->setLooper(src.getLooper());
160     dst->setTextEncoding(src.getTextEncoding());
161     dst->setHinting(src.getHinting());
162 #endif
163 }
164 
165 // Should we add this to canvas?
postTranslate(SkCanvas * canvas,SkScalar dx,SkScalar dy)166 static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) {
167     SkMatrix m = canvas->getTotalMatrix();
168     m.postTranslate(dx, dy);
169     canvas->setMatrix(m);
170 }
171 
next(SkCanvas * canvas,SkPaint * paint)172 bool SkLayerDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
173     canvas->restore();
174     if (NULL == fCurrRec) {
175         return false;
176     }
177 
178     ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo);
179 
180     canvas->save(SkCanvas::kMatrix_SaveFlag);
181     if (fCurrRec->fInfo.fPostTranslate) {
182         postTranslate(canvas, fCurrRec->fInfo.fOffset.fX,
183                       fCurrRec->fInfo.fOffset.fY);
184     } else {
185         canvas->translate(fCurrRec->fInfo.fOffset.fX, fCurrRec->fInfo.fOffset.fY);
186     }
187     fCurrRec = fCurrRec->fNext;
188 
189     return true;
190 }
191 
192 ///////////////////////////////////////////////////////////////////////////////
193 
flatten(SkFlattenableWriteBuffer & buffer) const194 void SkLayerDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
195     this->INHERITED::flatten(buffer);
196 
197 #ifdef SK_DEBUG
198     {
199         Rec* rec = fRecs;
200         int count = 0;
201         while (rec) {
202             rec = rec->fNext;
203             count += 1;
204         }
205         SkASSERT(count == fCount);
206     }
207 #endif
208 
209     buffer.writeInt(fCount);
210 
211     Rec* rec = fRecs;
212     for (int i = 0; i < fCount; i++) {
213         buffer.writeInt(rec->fInfo.fFlagsMask);
214         buffer.writeInt(rec->fInfo.fPaintBits);
215         buffer.writeInt(rec->fInfo.fColorMode);
216         buffer.writePoint(rec->fInfo.fOffset);
217         buffer.writeBool(rec->fInfo.fPostTranslate);
218         buffer.writePaint(rec->fPaint);
219         rec = rec->fNext;
220     }
221 }
222 
SkLayerDrawLooper(SkFlattenableReadBuffer & buffer)223 SkLayerDrawLooper::SkLayerDrawLooper(SkFlattenableReadBuffer& buffer)
224         : INHERITED(buffer),
225           fRecs(NULL),
226           fTopRec(NULL),
227           fCount(0),
228           fCurrRec(NULL) {
229     int count = buffer.readInt();
230 
231     for (int i = 0; i < count; i++) {
232         LayerInfo info;
233         info.fFlagsMask = buffer.readInt();
234         info.fPaintBits = buffer.readInt();
235         info.fColorMode = (SkXfermode::Mode)buffer.readInt();
236         buffer.readPoint(&info.fOffset);
237         info.fPostTranslate = buffer.readBool();
238         buffer.readPaint(this->addLayerOnTop(info));
239     }
240     SkASSERT(count == fCount);
241 
242 #ifdef SK_DEBUG
243     {
244         Rec* rec = fRecs;
245         int n = 0;
246         while (rec) {
247             rec = rec->fNext;
248             n += 1;
249         }
250         SkASSERT(count == n);
251     }
252 #endif
253 }
254 
255 #ifdef SK_DEVELOPER
toString(SkString * str) const256 void SkLayerDrawLooper::toString(SkString* str) const {
257     str->appendf("SkLayerDrawLooper (%d): ", fCount);
258 
259     Rec* rec = fRecs;
260     for (int i = 0; i < fCount; i++) {
261         str->appendf("%d: ", i);
262 
263         str->append("flagsMask: (");
264         if (0 == rec->fInfo.fFlagsMask) {
265             str->append("None");
266         } else {
267             bool needSeparator = false;
268             SkAddFlagToString(str, SkToBool(SkPaint::kAntiAlias_Flag & rec->fInfo.fFlagsMask),
269                               "AntiAlias", &needSeparator);
270 //            SkAddFlagToString(str, SkToBool(SkPaint::kFilterBitmap_Flag & rec->fInfo.fFlagsMask), "FilterBitmap", &needSeparator);
271             SkAddFlagToString(str, SkToBool(SkPaint::kDither_Flag & rec->fInfo.fFlagsMask),
272                               "Dither", &needSeparator);
273             SkAddFlagToString(str, SkToBool(SkPaint::kUnderlineText_Flag & rec->fInfo.fFlagsMask),
274                               "UnderlineText", &needSeparator);
275             SkAddFlagToString(str, SkToBool(SkPaint::kStrikeThruText_Flag & rec->fInfo.fFlagsMask),
276                               "StrikeThruText", &needSeparator);
277             SkAddFlagToString(str, SkToBool(SkPaint::kFakeBoldText_Flag & rec->fInfo.fFlagsMask),
278                               "FakeBoldText", &needSeparator);
279             SkAddFlagToString(str, SkToBool(SkPaint::kLinearText_Flag & rec->fInfo.fFlagsMask),
280                               "LinearText", &needSeparator);
281             SkAddFlagToString(str, SkToBool(SkPaint::kSubpixelText_Flag & rec->fInfo.fFlagsMask),
282                               "SubpixelText", &needSeparator);
283             SkAddFlagToString(str, SkToBool(SkPaint::kDevKernText_Flag & rec->fInfo.fFlagsMask),
284                               "DevKernText", &needSeparator);
285             SkAddFlagToString(str, SkToBool(SkPaint::kLCDRenderText_Flag & rec->fInfo.fFlagsMask),
286                               "LCDRenderText", &needSeparator);
287             SkAddFlagToString(str, SkToBool(SkPaint::kEmbeddedBitmapText_Flag & rec->fInfo.fFlagsMask),
288                               "EmbeddedBitmapText", &needSeparator);
289             SkAddFlagToString(str, SkToBool(SkPaint::kAutoHinting_Flag & rec->fInfo.fFlagsMask),
290                               "Autohinted", &needSeparator);
291             SkAddFlagToString(str, SkToBool(SkPaint::kVerticalText_Flag & rec->fInfo.fFlagsMask),
292                               "VerticalText", &needSeparator);
293             SkAddFlagToString(str, SkToBool(SkPaint::kGenA8FromLCD_Flag & rec->fInfo.fFlagsMask),
294                               "GenA8FromLCD", &needSeparator);
295         }
296         str->append(") ");
297 
298         str->append("paintBits: (");
299         if (0 == rec->fInfo.fPaintBits) {
300             str->append("None");
301         } else if (kEntirePaint_Bits == rec->fInfo.fPaintBits) {
302             str->append("EntirePaint");
303         } else {
304             bool needSeparator = false;
305             SkAddFlagToString(str, SkToBool(kStyle_Bit & rec->fInfo.fPaintBits), "Style",
306                               &needSeparator);
307             SkAddFlagToString(str, SkToBool(kTextSkewX_Bit & rec->fInfo.fPaintBits), "TextSkewX",
308                               &needSeparator);
309             SkAddFlagToString(str, SkToBool(kPathEffect_Bit & rec->fInfo.fPaintBits), "PathEffect",
310                               &needSeparator);
311             SkAddFlagToString(str, SkToBool(kMaskFilter_Bit & rec->fInfo.fPaintBits), "MaskFilter",
312                               &needSeparator);
313             SkAddFlagToString(str, SkToBool(kShader_Bit & rec->fInfo.fPaintBits), "Shader",
314                               &needSeparator);
315             SkAddFlagToString(str, SkToBool(kColorFilter_Bit & rec->fInfo.fPaintBits), "ColorFilter",
316                               &needSeparator);
317             SkAddFlagToString(str, SkToBool(kXfermode_Bit & rec->fInfo.fPaintBits), "Xfermode",
318                               &needSeparator);
319         }
320         str->append(") ");
321 
322         static const char* gModeStrings[SkXfermode::kLastMode+1] = {
323             "kClear", "kSrc", "kDst", "kSrcOver", "kDstOver", "kSrcIn", "kDstIn",
324             "kSrcOut", "kDstOut", "kSrcATop", "kDstATop", "kXor", "kPlus",
325             "kMultiply", "kScreen", "kOverlay", "kDarken", "kLighten", "kColorDodge",
326             "kColorBurn", "kHardLight", "kSoftLight", "kDifference", "kExclusion"
327         };
328 
329         str->appendf("mode: %s ", gModeStrings[rec->fInfo.fColorMode]);
330 
331         str->append("offset: (");
332         str->appendScalar(rec->fInfo.fOffset.fX);
333         str->append(", ");
334         str->appendScalar(rec->fInfo.fOffset.fY);
335         str->append(") ");
336 
337         str->append("postTranslate: ");
338         if (rec->fInfo.fPostTranslate) {
339             str->append("true ");
340         } else {
341             str->append("false ");
342         }
343 
344         rec->fPaint.toString(str);
345         rec = rec->fNext;
346     }
347 }
348 #endif
349