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