1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 #include "include/core/SkCanvas.h"
8 #include "include/core/SkColor.h"
9 #include "include/core/SkMaskFilter.h"
10 #include "include/core/SkString.h"
11 #include "include/core/SkUnPreMultiply.h"
12 #include "src/core/SkArenaAlloc.h"
13 #include "src/core/SkBlendModePriv.h"
14 #include "src/core/SkColorSpacePriv.h"
15 #include "src/core/SkMaskFilterBase.h"
16 #include "src/core/SkReadBuffer.h"
17 #include "src/core/SkStringUtils.h"
18 #include "src/core/SkWriteBuffer.h"
19 #include "src/core/SkXfermodePriv.h"
20
21 #ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
22
23 #include "include/effects/SkBlurDrawLooper.h"
24 #include "include/effects/SkLayerDrawLooper.h"
25
LayerInfo()26 SkLayerDrawLooper::LayerInfo::LayerInfo() {
27 fPaintBits = 0; // ignore our paint fields
28 fColorMode = SkBlendMode::kDst; // ignore our color
29 fOffset.set(0, 0);
30 fPostTranslate = false;
31 }
32
SkLayerDrawLooper()33 SkLayerDrawLooper::SkLayerDrawLooper()
34 : fRecs(nullptr),
35 fCount(0) {
36 }
37
~SkLayerDrawLooper()38 SkLayerDrawLooper::~SkLayerDrawLooper() {
39 Rec* rec = fRecs;
40 while (rec) {
41 Rec* next = rec->fNext;
42 delete rec;
43 rec = next;
44 }
45 }
46
47 SkLayerDrawLooper::Context*
makeContext(SkArenaAlloc * alloc) const48 SkLayerDrawLooper::makeContext(SkArenaAlloc* alloc) const {
49 return alloc->make<LayerDrawLooperContext>(this);
50 }
51
xferColor(const SkColor4f & src,const SkColor4f & dst,SkBlendMode mode)52 static SkColor4f xferColor(const SkColor4f& src, const SkColor4f& dst, SkBlendMode mode) {
53 switch (mode) {
54 case SkBlendMode::kSrc:
55 return src;
56 case SkBlendMode::kDst:
57 return dst;
58 default: {
59 SkPMColor4f pmS = src.premul();
60 SkPMColor4f pmD = dst.premul();
61 return SkBlendMode_Apply(mode, pmS, pmD).unpremul();
62 }
63 }
64 }
65
66 // Even with kEntirePaint_Bits, we always ensure that the base paint's
67 // text-encoding is respected, since that controls how we interpret the
68 // text/length parameters of a draw[Pos]Text call.
ApplyInfo(SkPaint * dst,const SkPaint & src,const LayerInfo & info)69 void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo(
70 SkPaint* dst, const SkPaint& src, const LayerInfo& info) {
71 SkColor4f srcColor = src.getColor4f();
72 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
73 // The framework may respect the alpha value on the original paint.
74 // Match this legacy behavior.
75 if (src.getAlpha() == 255) {
76 srcColor.fA = dst->getColor4f().fA;
77 }
78 #endif
79 dst->setColor4f(xferColor(srcColor, dst->getColor4f(), (SkBlendMode)info.fColorMode),
80 sk_srgb_singleton());
81
82 BitFlags bits = info.fPaintBits;
83
84 if (0 == bits) {
85 return;
86 }
87 if (kEntirePaint_Bits == bits) {
88 // we've already computed these, so save it from the assignment
89 bool aa = dst->isAntiAlias();
90 bool di = dst->isDither();
91 SkColor4f c = dst->getColor4f();
92 *dst = src;
93 dst->setAntiAlias(aa);
94 dst->setDither(di);
95 dst->setColor4f(c, sk_srgb_singleton());
96 return;
97 }
98
99 if (bits & kStyle_Bit) {
100 dst->setStyle(src.getStyle());
101 dst->setStrokeWidth(src.getStrokeWidth());
102 dst->setStrokeMiter(src.getStrokeMiter());
103 dst->setStrokeCap(src.getStrokeCap());
104 dst->setStrokeJoin(src.getStrokeJoin());
105 }
106
107 if (bits & kPathEffect_Bit) {
108 dst->setPathEffect(src.refPathEffect());
109 }
110 if (bits & kMaskFilter_Bit) {
111 dst->setMaskFilter(src.refMaskFilter());
112 }
113 if (bits & kShader_Bit) {
114 dst->setShader(src.refShader());
115 }
116 if (bits & kColorFilter_Bit) {
117 dst->setColorFilter(src.refColorFilter());
118 }
119 if (bits & kXfermode_Bit) {
120 dst->setBlender(src.refBlender());
121 }
122
123 // we don't override these
124 #if 0
125 dst->setTypeface(src.getTypeface());
126 dst->setTextSize(src.getTextSize());
127 dst->setTextScaleX(src.getTextScaleX());
128 dst->setRasterizer(src.getRasterizer());
129 dst->setLooper(src.getLooper());
130 dst->setTextEncoding(src.getTextEncoding());
131 dst->setHinting(src.getHinting());
132 #endif
133 }
134
LayerDrawLooperContext(const SkLayerDrawLooper * looper)135 SkLayerDrawLooper::LayerDrawLooperContext::LayerDrawLooperContext(
136 const SkLayerDrawLooper* looper) : fCurrRec(looper->fRecs) {}
137
next(Info * info,SkPaint * paint)138 bool SkLayerDrawLooper::LayerDrawLooperContext::next(Info* info, SkPaint* paint) {
139 if (nullptr == fCurrRec) {
140 return false;
141 }
142
143 ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo);
144
145 if (info) {
146 info->fTranslate = fCurrRec->fInfo.fOffset;
147 info->fApplyPostCTM = fCurrRec->fInfo.fPostTranslate;
148 }
149 fCurrRec = fCurrRec->fNext;
150 return true;
151 }
152
asABlurShadow(BlurShadowRec * bsRec) const153 bool SkLayerDrawLooper::asABlurShadow(BlurShadowRec* bsRec) const {
154 if (fCount != 2) {
155 return false;
156 }
157 const Rec* rec = fRecs;
158
159 // bottom layer needs to be just blur(maskfilter)
160 if ((rec->fInfo.fPaintBits & ~kMaskFilter_Bit)) {
161 return false;
162 }
163 if (SkBlendMode::kSrc != (SkBlendMode)rec->fInfo.fColorMode) {
164 return false;
165 }
166 const SkMaskFilter* mf = rec->fPaint.getMaskFilter();
167 if (nullptr == mf) {
168 return false;
169 }
170 SkMaskFilterBase::BlurRec maskBlur;
171 if (!as_MFB(mf)->asABlur(&maskBlur)) {
172 return false;
173 }
174
175 rec = rec->fNext;
176 // top layer needs to be "plain"
177 if (rec->fInfo.fPaintBits) {
178 return false;
179 }
180 if (SkBlendMode::kDst != (SkBlendMode)rec->fInfo.fColorMode) {
181 return false;
182 }
183 if (!rec->fInfo.fOffset.equals(0, 0)) {
184 return false;
185 }
186
187 if (bsRec) {
188 bsRec->fSigma = maskBlur.fSigma;
189 bsRec->fOffset = fRecs->fInfo.fOffset;
190 // TODO: Update BlurShadowRec to use SkColor4f?
191 bsRec->fColor = fRecs->fPaint.getColor();
192 bsRec->fStyle = maskBlur.fStyle;
193 }
194 return true;
195 }
196
197 ///////////////////////////////////////////////////////////////////////////////
198
flatten(SkWriteBuffer & buffer) const199 void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const {
200 buffer.writeInt(fCount);
201
202 Rec* rec = fRecs;
203 for (int i = 0; i < fCount; i++) {
204 // Legacy "flagsmask" field -- now ignored, remove when we bump version
205 buffer.writeInt(0);
206
207 buffer.writeInt(rec->fInfo.fPaintBits);
208 buffer.writeInt((int)rec->fInfo.fColorMode);
209 buffer.writePoint(rec->fInfo.fOffset);
210 buffer.writeBool(rec->fInfo.fPostTranslate);
211 buffer.writePaint(rec->fPaint);
212 rec = rec->fNext;
213 }
214 }
215
CreateProc(SkReadBuffer & buffer)216 sk_sp<SkFlattenable> SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) {
217 int count = buffer.readInt();
218
219 #if defined(SK_BUILD_FOR_FUZZER)
220 if (count > 100) {
221 count = 100;
222 }
223 #endif
224 Builder builder;
225 for (int i = 0; i < count; i++) {
226 LayerInfo info;
227 // Legacy "flagsmask" field -- now ignored, remove when we bump version
228 (void)buffer.readInt();
229
230 info.fPaintBits = buffer.readInt();
231 info.fColorMode = (SkBlendMode)buffer.readInt();
232 buffer.readPoint(&info.fOffset);
233 info.fPostTranslate = buffer.readBool();
234 *builder.addLayerOnTop(info) = buffer.readPaint();
235 if (!buffer.isValid()) {
236 return nullptr;
237 }
238 }
239 return builder.detach();
240 }
241
Builder()242 SkLayerDrawLooper::Builder::Builder()
243 : fRecs(nullptr),
244 fTopRec(nullptr),
245 fCount(0) {
246 }
247
~Builder()248 SkLayerDrawLooper::Builder::~Builder() {
249 Rec* rec = fRecs;
250 while (rec) {
251 Rec* next = rec->fNext;
252 delete rec;
253 rec = next;
254 }
255 }
256
addLayer(const LayerInfo & info)257 SkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) {
258 fCount += 1;
259
260 Rec* rec = new Rec;
261 rec->fNext = fRecs;
262 rec->fInfo = info;
263 fRecs = rec;
264 if (nullptr == fTopRec) {
265 fTopRec = rec;
266 }
267
268 return &rec->fPaint;
269 }
270
addLayer(SkScalar dx,SkScalar dy)271 void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) {
272 LayerInfo info;
273
274 info.fOffset.set(dx, dy);
275 (void)this->addLayer(info);
276 }
277
addLayerOnTop(const LayerInfo & info)278 SkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) {
279 fCount += 1;
280
281 Rec* rec = new Rec;
282 rec->fNext = nullptr;
283 rec->fInfo = info;
284 if (nullptr == fRecs) {
285 fRecs = rec;
286 } else {
287 SkASSERT(fTopRec);
288 fTopRec->fNext = rec;
289 }
290 fTopRec = rec;
291
292 return &rec->fPaint;
293 }
294
detach()295 sk_sp<SkDrawLooper> SkLayerDrawLooper::Builder::detach() {
296 SkLayerDrawLooper* looper = new SkLayerDrawLooper;
297 looper->fCount = fCount;
298 looper->fRecs = fRecs;
299
300 fCount = 0;
301 fRecs = nullptr;
302 fTopRec = nullptr;
303
304 return sk_sp<SkDrawLooper>(looper);
305 }
306
Make(SkColor color,SkScalar sigma,SkScalar dx,SkScalar dy)307 sk_sp<SkDrawLooper> SkBlurDrawLooper::Make(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy)
308 {
309 return Make(SkColor4f::FromColor(color), sk_srgb_singleton(), sigma, dx, dy);
310 }
311
Make(SkColor4f color,SkColorSpace * cs,SkScalar sigma,SkScalar dx,SkScalar dy)312 sk_sp<SkDrawLooper> SkBlurDrawLooper::Make(SkColor4f color, SkColorSpace* cs,
313 SkScalar sigma, SkScalar dx, SkScalar dy)
314 {
315 sk_sp<SkMaskFilter> blur = nullptr;
316 if (sigma > 0.0f) {
317 blur = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, sigma, true);
318 }
319
320 SkLayerDrawLooper::Builder builder;
321
322 // First layer
323 SkLayerDrawLooper::LayerInfo defaultLayer;
324 builder.addLayer(defaultLayer);
325
326 // Blur layer
327 SkLayerDrawLooper::LayerInfo blurInfo;
328 blurInfo.fColorMode = SkBlendMode::kSrc;
329 blurInfo.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit;
330 blurInfo.fOffset = SkVector::Make(dx, dy);
331 SkPaint* paint = builder.addLayer(blurInfo);
332 paint->setMaskFilter(std::move(blur));
333 paint->setColor4f(color, cs);
334
335 return builder.detach();
336 }
337
338 #endif
339