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