• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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