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