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