• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
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  */
8 #include "SkBlurDrawLooper.h"
9 #include "SkBlurMaskFilter.h"
10 #include "SkCanvas.h"
11 #include "SkColorFilter.h"
12 #include "SkFlattenableBuffers.h"
13 #include "SkMaskFilter.h"
14 #include "SkPaint.h"
15 #include "SkString.h"
16 #include "SkStringUtils.h"
17 
SkBlurDrawLooper(SkScalar radius,SkScalar dx,SkScalar dy,SkColor color,uint32_t flags)18 SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
19                                    SkColor color, uint32_t flags)
20     : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags), fState(kDone) {
21 
22     SkASSERT(flags <= kAll_BlurFlag);
23     if (radius > 0) {
24         uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
25             SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
26             SkBlurMaskFilter::kNone_BlurFlag;
27 
28         blurFlags |= flags & kHighQuality_BlurFlag ?
29             SkBlurMaskFilter::kHighQuality_BlurFlag :
30             SkBlurMaskFilter::kNone_BlurFlag;
31 
32         fBlur = SkBlurMaskFilter::Create(radius,
33                                          SkBlurMaskFilter::kNormal_BlurStyle,
34                                          blurFlags);
35     } else {
36         fBlur = NULL;
37     }
38 
39     if (flags & kOverrideColor_BlurFlag) {
40         // Set alpha to 1 for the override since transparency will already
41         // be baked into the blurred mask.
42         SkColor opaqueColor = SkColorSetA(color, 255);
43         //The SrcIn xfer mode will multiply 'color' by the incoming alpha
44         fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
45                                                        SkXfermode::kSrcIn_Mode);
46     } else {
47         fColorFilter = NULL;
48     }
49 }
50 
SkBlurDrawLooper(SkFlattenableReadBuffer & buffer)51 SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
52 : INHERITED(buffer) {
53 
54     fDx = buffer.readScalar();
55     fDy = buffer.readScalar();
56     fBlurColor = buffer.readColor();
57     fBlur = buffer.readFlattenableT<SkMaskFilter>();
58     fColorFilter = buffer.readFlattenableT<SkColorFilter>();
59     fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
60 }
61 
~SkBlurDrawLooper()62 SkBlurDrawLooper::~SkBlurDrawLooper() {
63     SkSafeUnref(fBlur);
64     SkSafeUnref(fColorFilter);
65 }
66 
flatten(SkFlattenableWriteBuffer & buffer) const67 void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
68     this->INHERITED::flatten(buffer);
69     buffer.writeScalar(fDx);
70     buffer.writeScalar(fDy);
71     buffer.writeColor(fBlurColor);
72     buffer.writeFlattenable(fBlur);
73     buffer.writeFlattenable(fColorFilter);
74     buffer.writeUInt(fBlurFlags);
75 }
76 
init(SkCanvas * canvas)77 void SkBlurDrawLooper::init(SkCanvas* canvas) {
78     fState = kBeforeEdge;
79 }
80 
next(SkCanvas * canvas,SkPaint * paint)81 bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
82     switch (fState) {
83         case kBeforeEdge:
84             // we do nothing if a maskfilter is already installed
85             if (paint->getMaskFilter()) {
86                 fState = kDone;
87                 return false;
88             }
89 #ifdef SK_BUILD_FOR_ANDROID
90             SkColor blurColor;
91             blurColor = fBlurColor;
92             if (SkColorGetA(blurColor) == 255) {
93                 blurColor = SkColorSetA(blurColor, paint->getAlpha());
94             }
95             paint->setColor(blurColor);
96 #else
97             paint->setColor(fBlurColor);
98 #endif
99             paint->setMaskFilter(fBlur);
100             paint->setColorFilter(fColorFilter);
101             canvas->save(SkCanvas::kMatrix_SaveFlag);
102             if (fBlurFlags & kIgnoreTransform_BlurFlag) {
103                 SkMatrix transform(canvas->getTotalMatrix());
104                 transform.postTranslate(fDx, fDy);
105                 canvas->setMatrix(transform);
106             } else {
107                 canvas->translate(fDx, fDy);
108             }
109             fState = kAfterEdge;
110             return true;
111         case kAfterEdge:
112             canvas->restore();
113             fState = kDone;
114             return true;
115         default:
116             SkASSERT(kDone == fState);
117             return false;
118     }
119 }
120 
121 #ifdef SK_DEVELOPER
toString(SkString * str) const122 void SkBlurDrawLooper::toString(SkString* str) const {
123     str->append("SkBlurDrawLooper: ");
124 
125     str->append("dx: ");
126     str->appendScalar(fDx);
127 
128     str->append(" dy: ");
129     str->appendScalar(fDy);
130 
131     str->append(" color: ");
132     str->appendHex(fBlurColor);
133 
134     str->append(" flags: (");
135     if (kNone_BlurFlag == fBlurFlags) {
136         str->append("None");
137     } else {
138         bool needsSeparator = false;
139         SkAddFlagToString(str, SkToBool(kIgnoreTransform_BlurFlag & fBlurFlags), "IgnoreTransform",
140                           &needsSeparator);
141         SkAddFlagToString(str, SkToBool(kOverrideColor_BlurFlag & fBlurFlags), "OverrideColor",
142                           &needsSeparator);
143         SkAddFlagToString(str, SkToBool(kHighQuality_BlurFlag & fBlurFlags), "HighQuality",
144                           &needsSeparator);
145     }
146     str->append(")");
147 
148     // TODO: add optional "fBlurFilter->toString(str);" when SkMaskFilter::toString is added
149     // alternatively we could cache the radius in SkBlurDrawLooper and just add it here
150 }
151 #endif
152