SkLayerDrawLooper.cpp revision ab1c13864df34aecfd4840ea7d1e4f8730b44f4e
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
16SkLayerDrawLooper::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
24SkLayerDrawLooper::SkLayerDrawLooper()
25        : fRecs(NULL),
26          fTopRec(NULL),
27          fCount(0),
28          fCurrRec(NULL) {
29}
30
31SkLayerDrawLooper::~SkLayerDrawLooper() {
32    Rec* rec = fRecs;
33    while (rec) {
34        Rec* next = rec->fNext;
35        SkDELETE(rec);
36        rec = next;
37    }
38}
39
40SkPaint* 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
54void SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) {
55    LayerInfo info;
56
57    info.fOffset.set(dx, dy);
58    (void)this->addLayer(info);
59}
60
61SkPaint* 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
78void SkLayerDrawLooper::init(SkCanvas* canvas) {
79    fCurrRec = fRecs;
80    canvas->save(SkCanvas::kMatrix_SaveFlag);
81}
82
83static 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.
101void 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?
166static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) {
167    SkMatrix m = canvas->getTotalMatrix();
168    m.postTranslate(dx, dy);
169    canvas->setMatrix(m);
170}
171
172bool 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
194void 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
223SkLayerDrawLooper::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
256void 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