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