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 "SkLayerDrawLooper.h"
11 #include "SkPaint.h"
12 #include "SkUnPreMultiply.h"
13
LayerInfo()14 SkLayerDrawLooper::LayerInfo::LayerInfo() {
15 fFlagsMask = 0; // ignore our paint flags
16 fPaintBits = 0; // ignore our paint fields
17 fColorMode = SkXfermode::kDst_Mode; // ignore our color
18 fOffset.set(0, 0);
19 fPostTranslate = false;
20 }
21
SkLayerDrawLooper()22 SkLayerDrawLooper::SkLayerDrawLooper()
23 : fRecs(NULL),
24 fCount(0),
25 fCurrRec(NULL) {
26 }
27
~SkLayerDrawLooper()28 SkLayerDrawLooper::~SkLayerDrawLooper() {
29 Rec* rec = fRecs;
30 while (rec) {
31 Rec* next = rec->fNext;
32 SkDELETE(rec);
33 rec = next;
34 }
35 }
36
addLayer(const LayerInfo & info)37 SkPaint* SkLayerDrawLooper::addLayer(const LayerInfo& info) {
38 fCount += 1;
39
40 Rec* rec = SkNEW(Rec);
41 rec->fNext = fRecs;
42 rec->fInfo = info;
43 fRecs = rec;
44
45 return &rec->fPaint;
46 }
47
addLayer(SkScalar dx,SkScalar dy)48 void SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) {
49 LayerInfo info;
50
51 info.fOffset.set(dx, dy);
52 (void)this->addLayer(info);
53 }
54
init(SkCanvas * canvas)55 void SkLayerDrawLooper::init(SkCanvas* canvas) {
56 fCurrRec = fRecs;
57 canvas->save(SkCanvas::kMatrix_SaveFlag);
58 }
59
xferColor(SkColor src,SkColor dst,SkXfermode::Mode mode)60 static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) {
61 switch (mode) {
62 case SkXfermode::kSrc_Mode:
63 return src;
64 case SkXfermode::kDst_Mode:
65 return dst;
66 default: {
67 SkPMColor pmS = SkPreMultiplyColor(src);
68 SkPMColor pmD = SkPreMultiplyColor(dst);
69 SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD);
70 return SkUnPreMultiply::PMColorToColor(result);
71 }
72 }
73 }
74
75 // Even with kEntirePaint_Bits, we always ensure that the master paint's
76 // text-encoding is respected, since that controls how we interpret the
77 // text/length parameters of a draw[Pos]Text call.
ApplyInfo(SkPaint * dst,const SkPaint & src,const LayerInfo & info)78 void SkLayerDrawLooper::ApplyInfo(SkPaint* dst, const SkPaint& src,
79 const LayerInfo& info) {
80
81 uint32_t mask = info.fFlagsMask;
82 dst->setFlags((dst->getFlags() & ~mask) | (src.getFlags() & mask));
83 dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode));
84
85 BitFlags bits = info.fPaintBits;
86 SkPaint::TextEncoding encoding = dst->getTextEncoding();
87
88 if (0 == bits) {
89 return;
90 }
91 if (kEntirePaint_Bits == bits) {
92 // we've already computed these, so save it from the assignment
93 uint32_t f = dst->getFlags();
94 SkColor c = dst->getColor();
95 *dst = src;
96 dst->setFlags(f);
97 dst->setColor(c);
98 dst->setTextEncoding(encoding);
99 return;
100 }
101
102 if (bits & kStyle_Bit) {
103 dst->setStyle(src.getStyle());
104 dst->setStrokeWidth(src.getStrokeWidth());
105 dst->setStrokeMiter(src.getStrokeMiter());
106 dst->setStrokeCap(src.getStrokeCap());
107 dst->setStrokeJoin(src.getStrokeJoin());
108 }
109
110 if (bits & kTextSkewX_Bit) {
111 dst->setTextSkewX(src.getTextSkewX());
112 }
113
114 if (bits & kPathEffect_Bit) {
115 dst->setPathEffect(src.getPathEffect());
116 }
117 if (bits & kMaskFilter_Bit) {
118 dst->setMaskFilter(src.getMaskFilter());
119 }
120 if (bits & kShader_Bit) {
121 dst->setShader(src.getShader());
122 }
123 if (bits & kColorFilter_Bit) {
124 dst->setColorFilter(src.getColorFilter());
125 }
126 if (bits & kXfermode_Bit) {
127 dst->setXfermode(src.getXfermode());
128 }
129
130 // we don't override these
131 #if 0
132 dst->setTypeface(src.getTypeface());
133 dst->setTextSize(src.getTextSize());
134 dst->setTextScaleX(src.getTextScaleX());
135 dst->setRasterizer(src.getRasterizer());
136 dst->setLooper(src.getLooper());
137 dst->setTextEncoding(src.getTextEncoding());
138 dst->setHinting(src.getHinting());
139 #endif
140 }
141
142 // Should we add this to canvas?
postTranslate(SkCanvas * canvas,SkScalar dx,SkScalar dy)143 static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) {
144 SkMatrix m = canvas->getTotalMatrix();
145 m.postTranslate(dx, dy);
146 canvas->setMatrix(m);
147 }
148
next(SkCanvas * canvas,SkPaint * paint)149 bool SkLayerDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
150 canvas->restore();
151 if (NULL == fCurrRec) {
152 return false;
153 }
154
155 ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo);
156
157 canvas->save(SkCanvas::kMatrix_SaveFlag);
158 if (fCurrRec->fInfo.fPostTranslate) {
159 postTranslate(canvas, fCurrRec->fInfo.fOffset.fX,
160 fCurrRec->fInfo.fOffset.fY);
161 } else {
162 canvas->translate(fCurrRec->fInfo.fOffset.fX, fCurrRec->fInfo.fOffset.fY);
163 }
164 fCurrRec = fCurrRec->fNext;
165
166 return true;
167 }
168
Reverse(Rec * head)169 SkLayerDrawLooper::Rec* SkLayerDrawLooper::Rec::Reverse(Rec* head) {
170 Rec* rec = head;
171 Rec* prev = NULL;
172 while (rec) {
173 Rec* next = rec->fNext;
174 rec->fNext = prev;
175 prev = rec;
176 rec = next;
177 }
178 return prev;
179 }
180
181 ///////////////////////////////////////////////////////////////////////////////
182
flatten(SkFlattenableWriteBuffer & buffer)183 void SkLayerDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) {
184 this->INHERITED::flatten(buffer);
185
186 #ifdef SK_DEBUG
187 {
188 Rec* rec = fRecs;
189 int count = 0;
190 while (rec) {
191 rec = rec->fNext;
192 count += 1;
193 }
194 SkASSERT(count == fCount);
195 }
196 #endif
197
198 buffer.writeInt(fCount);
199
200 Rec* rec = fRecs;
201 for (int i = 0; i < fCount; i++) {
202 buffer.writeInt(rec->fInfo.fPaintBits);
203 buffer.writeInt(rec->fInfo.fColorMode);
204 buffer.writeScalar(rec->fInfo.fOffset.fX);
205 buffer.writeScalar(rec->fInfo.fOffset.fY);
206 buffer.writeBool(rec->fInfo.fPostTranslate);
207 rec->fPaint.flatten(buffer);
208 rec = rec->fNext;
209 }
210 }
211
SkLayerDrawLooper(SkFlattenableReadBuffer & buffer)212 SkLayerDrawLooper::SkLayerDrawLooper(SkFlattenableReadBuffer& buffer)
213 : INHERITED(buffer),
214 fRecs(NULL),
215 fCount(0),
216 fCurrRec(NULL) {
217 int count = buffer.readInt();
218
219 for (int i = 0; i < count; i++) {
220 LayerInfo info;
221 if (buffer.getPictureVersion() == PICTURE_VERSION_ICS)
222 info.fFlagsMask = buffer.readInt();
223 info.fPaintBits = buffer.readInt();
224 info.fColorMode = (SkXfermode::Mode)buffer.readInt();
225 info.fOffset.fX = buffer.readScalar();
226 info.fOffset.fY = buffer.readScalar();
227 info.fPostTranslate = buffer.readBool();
228 this->addLayer(info)->unflatten(buffer);
229 }
230 SkASSERT(count == fCount);
231
232 // we're in reverse order, so fix it now
233 fRecs = Rec::Reverse(fRecs);
234
235 #ifdef SK_DEBUG
236 {
237 Rec* rec = fRecs;
238 int n = 0;
239 while (rec) {
240 rec = rec->fNext;
241 n += 1;
242 }
243 SkASSERT(count == n);
244 }
245 #endif
246 }
247
248 ///////////////////////////////////////////////////////////////////////////////
249
250 SK_DEFINE_FLATTENABLE_REGISTRAR(SkLayerDrawLooper)
251