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