blob: c8da568a411a295d01eeee1c581cfaa66838324d [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkCanvas.h"
reed@google.com0716c632011-04-12 18:32:06 +00009#include "SkColor.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#include "SkLayerDrawLooper.h"
11#include "SkPaint.h"
reed@google.com0716c632011-04-12 18:32:06 +000012#include "SkUnPreMultiply.h"
13
robertphillips@google.com0456e0b2012-06-27 14:03:26 +000014SK_DEFINE_INST_COUNT(SkLayerDrawLooper)
15
reed@google.com0716c632011-04-12 18:32:06 +000016SkLayerDrawLooper::LayerInfo::LayerInfo() {
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000017 fFlagsMask = 0; // ignore our paint flags
18 fPaintBits = 0; // ignore our paint fields
reed@google.com0716c632011-04-12 18:32:06 +000019 fColorMode = SkXfermode::kDst_Mode; // ignore our color
20 fOffset.set(0, 0);
21 fPostTranslate = false;
22}
reed@android.com8a1c16f2008-12-17 15:59:43 +000023
vandebo@chromium.org3c898182011-06-22 05:01:28 +000024SkLayerDrawLooper::SkLayerDrawLooper()
25 : fRecs(NULL),
26 fCount(0),
27 fCurrRec(NULL) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000028}
29
30SkLayerDrawLooper::~SkLayerDrawLooper() {
31 Rec* rec = fRecs;
32 while (rec) {
33 Rec* next = rec->fNext;
34 SkDELETE(rec);
35 rec = next;
36 }
37}
reed@google.com0716c632011-04-12 18:32:06 +000038
39SkPaint* SkLayerDrawLooper::addLayer(const LayerInfo& info) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000040 fCount += 1;
41
42 Rec* rec = SkNEW(Rec);
43 rec->fNext = fRecs;
reed@google.com0716c632011-04-12 18:32:06 +000044 rec->fInfo = info;
reed@android.com8a1c16f2008-12-17 15:59:43 +000045 fRecs = rec;
46
47 return &rec->fPaint;
48}
49
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000050void SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) {
reed@google.com0716c632011-04-12 18:32:06 +000051 LayerInfo info;
52
53 info.fOffset.set(dx, dy);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000054 (void)this->addLayer(info);
reed@google.com0716c632011-04-12 18:32:06 +000055}
56
reed@google.com4e2b3d32011-04-07 14:18:59 +000057void SkLayerDrawLooper::init(SkCanvas* canvas) {
58 fCurrRec = fRecs;
reed@android.com8a1c16f2008-12-17 15:59:43 +000059 canvas->save(SkCanvas::kMatrix_SaveFlag);
60}
61
reed@google.com0716c632011-04-12 18:32:06 +000062static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) {
63 switch (mode) {
64 case SkXfermode::kSrc_Mode:
65 return src;
66 case SkXfermode::kDst_Mode:
67 return dst;
68 default: {
69 SkPMColor pmS = SkPreMultiplyColor(src);
70 SkPMColor pmD = SkPreMultiplyColor(dst);
71 SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD);
72 return SkUnPreMultiply::PMColorToColor(result);
73 }
74 }
75}
76
reed@google.com84260582011-11-21 16:42:10 +000077// Even with kEntirePaint_Bits, we always ensure that the master paint's
78// text-encoding is respected, since that controls how we interpret the
79// text/length parameters of a draw[Pos]Text call.
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000080void SkLayerDrawLooper::ApplyInfo(SkPaint* dst, const SkPaint& src,
81 const LayerInfo& info) {
82
83 uint32_t mask = info.fFlagsMask;
84 dst->setFlags((dst->getFlags() & ~mask) | (src.getFlags() & mask));
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000085 dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode));
86
87 BitFlags bits = info.fPaintBits;
reed@google.com84260582011-11-21 16:42:10 +000088 SkPaint::TextEncoding encoding = dst->getTextEncoding();
reed@google.com0716c632011-04-12 18:32:06 +000089
mike@reedtribe.org3c1225b2011-04-09 18:54:08 +000090 if (0 == bits) {
91 return;
92 }
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +000093 if (kEntirePaint_Bits == bits) {
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000094 // we've already computed these, so save it from the assignment
95 uint32_t f = dst->getFlags();
reed@google.com0716c632011-04-12 18:32:06 +000096 SkColor c = dst->getColor();
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +000097 *dst = src;
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000098 dst->setFlags(f);
reed@google.com0716c632011-04-12 18:32:06 +000099 dst->setColor(c);
reed@google.com84260582011-11-21 16:42:10 +0000100 dst->setTextEncoding(encoding);
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +0000101 return;
102 }
103
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +0000104 if (bits & kStyle_Bit) {
105 dst->setStyle(src.getStyle());
106 dst->setStrokeWidth(src.getStrokeWidth());
107 dst->setStrokeMiter(src.getStrokeMiter());
108 dst->setStrokeCap(src.getStrokeCap());
109 dst->setStrokeJoin(src.getStrokeJoin());
110 }
111
112 if (bits & kTextSkewX_Bit) {
113 dst->setTextSkewX(src.getTextSkewX());
114 }
115
116 if (bits & kPathEffect_Bit) {
117 dst->setPathEffect(src.getPathEffect());
118 }
119 if (bits & kMaskFilter_Bit) {
120 dst->setMaskFilter(src.getMaskFilter());
121 }
122 if (bits & kShader_Bit) {
123 dst->setShader(src.getShader());
124 }
125 if (bits & kColorFilter_Bit) {
126 dst->setColorFilter(src.getColorFilter());
127 }
128 if (bits & kXfermode_Bit) {
129 dst->setXfermode(src.getXfermode());
130 }
131
reed@google.com84260582011-11-21 16:42:10 +0000132 // we don't override these
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +0000133#if 0
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +0000134 dst->setTypeface(src.getTypeface());
135 dst->setTextSize(src.getTextSize());
136 dst->setTextScaleX(src.getTextScaleX());
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +0000137 dst->setRasterizer(src.getRasterizer());
138 dst->setLooper(src.getLooper());
139 dst->setTextEncoding(src.getTextEncoding());
140 dst->setHinting(src.getHinting());
141#endif
142}
143
reed@google.com0716c632011-04-12 18:32:06 +0000144// Should we add this to canvas?
145static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) {
146 SkMatrix m = canvas->getTotalMatrix();
147 m.postTranslate(dx, dy);
148 canvas->setMatrix(m);
149}
150
reed@google.com4e2b3d32011-04-07 14:18:59 +0000151bool SkLayerDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
152 canvas->restore();
153 if (NULL == fCurrRec) {
154 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000155 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000156
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000157 ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo);
reed@google.com0716c632011-04-12 18:32:06 +0000158
reed@google.com4e2b3d32011-04-07 14:18:59 +0000159 canvas->save(SkCanvas::kMatrix_SaveFlag);
reed@google.com0716c632011-04-12 18:32:06 +0000160 if (fCurrRec->fInfo.fPostTranslate) {
161 postTranslate(canvas, fCurrRec->fInfo.fOffset.fX,
162 fCurrRec->fInfo.fOffset.fY);
163 } else {
164 canvas->translate(fCurrRec->fInfo.fOffset.fX, fCurrRec->fInfo.fOffset.fY);
165 }
mike@reedtribe.orge5d0def2011-04-08 00:53:48 +0000166 fCurrRec = fCurrRec->fNext;
167
reed@google.com4e2b3d32011-04-07 14:18:59 +0000168 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000169}
170
171SkLayerDrawLooper::Rec* SkLayerDrawLooper::Rec::Reverse(Rec* head) {
172 Rec* rec = head;
173 Rec* prev = NULL;
174 while (rec) {
175 Rec* next = rec->fNext;
176 rec->fNext = prev;
177 prev = rec;
178 rec = next;
179 }
180 return prev;
181}
182
183///////////////////////////////////////////////////////////////////////////////
184
djsollen@google.com54924242012-03-29 15:18:04 +0000185void SkLayerDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186 this->INHERITED::flatten(buffer);
187
188#ifdef SK_DEBUG
189 {
190 Rec* rec = fRecs;
191 int count = 0;
192 while (rec) {
193 rec = rec->fNext;
194 count += 1;
195 }
196 SkASSERT(count == fCount);
197 }
198#endif
199
200 buffer.writeInt(fCount);
201
202 Rec* rec = fRecs;
203 for (int i = 0; i < fCount; i++) {
reed@google.com076f4c92012-07-31 14:32:38 +0000204 buffer.writeInt(rec->fInfo.fFlagsMask);
reed@google.com0716c632011-04-12 18:32:06 +0000205 buffer.writeInt(rec->fInfo.fPaintBits);
206 buffer.writeInt(rec->fInfo.fColorMode);
207 buffer.writeScalar(rec->fInfo.fOffset.fX);
208 buffer.writeScalar(rec->fInfo.fOffset.fY);
209 buffer.writeBool(rec->fInfo.fPostTranslate);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210 rec->fPaint.flatten(buffer);
211 rec = rec->fNext;
212 }
213}
214
215SkLayerDrawLooper::SkLayerDrawLooper(SkFlattenableReadBuffer& buffer)
vandebo@chromium.org3c898182011-06-22 05:01:28 +0000216 : INHERITED(buffer),
217 fRecs(NULL),
218 fCount(0),
219 fCurrRec(NULL) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000220 int count = buffer.readInt();
221
222 for (int i = 0; i < count; i++) {
reed@google.com0716c632011-04-12 18:32:06 +0000223 LayerInfo info;
reed@google.com076f4c92012-07-31 14:32:38 +0000224 info.fFlagsMask = buffer.readInt();
reed@google.com0716c632011-04-12 18:32:06 +0000225 info.fPaintBits = buffer.readInt();
226 info.fColorMode = (SkXfermode::Mode)buffer.readInt();
227 info.fOffset.fX = buffer.readScalar();
228 info.fOffset.fY = buffer.readScalar();
229 info.fPostTranslate = buffer.readBool();
230 this->addLayer(info)->unflatten(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000231 }
232 SkASSERT(count == fCount);
233
234 // we're in reverse order, so fix it now
235 fRecs = Rec::Reverse(fRecs);
236
237#ifdef SK_DEBUG
238 {
239 Rec* rec = fRecs;
240 int n = 0;
241 while (rec) {
242 rec = rec->fNext;
243 n += 1;
244 }
245 SkASSERT(count == n);
246 }
247#endif
248}
249
250///////////////////////////////////////////////////////////////////////////////
251
caryclark@google.comd26147a2011-12-15 14:16:43 +0000252SK_DEFINE_FLATTENABLE_REGISTRAR(SkLayerDrawLooper)