Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / effects / SkBlurDrawLooper.cpp
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 "SkBlurDrawLooper.h"
9 #include "SkBlurMask.h"     // just for SkBlurMask::ConvertRadiusToSigma
10 #include "SkBlurMaskFilter.h"
11 #include "SkCanvas.h"
12 #include "SkColorFilter.h"
13 #include "SkReadBuffer.h"
14 #include "SkWriteBuffer.h"
15 #include "SkMaskFilter.h"
16 #include "SkPaint.h"
17 #include "SkString.h"
18 #include "SkStringUtils.h"
19
20 SkBlurDrawLooper::SkBlurDrawLooper(SkColor color, SkScalar sigma,
21                                    SkScalar dx, SkScalar dy, uint32_t flags) {
22     this->init(sigma, dx, dy, color, flags);
23 }
24
25 // only call from constructor
26 void SkBlurDrawLooper::initEffects() {
27     SkASSERT(fBlurFlags <= kAll_BlurFlag);
28     if (fSigma > 0) {
29         uint32_t flags = fBlurFlags & kIgnoreTransform_BlurFlag ?
30                             SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
31                             SkBlurMaskFilter::kNone_BlurFlag;
32
33         flags |= fBlurFlags & kHighQuality_BlurFlag ?
34                     SkBlurMaskFilter::kHighQuality_BlurFlag :
35                     SkBlurMaskFilter::kNone_BlurFlag;
36
37         fBlur = SkBlurMaskFilter::Create(kNormal_SkBlurStyle, fSigma, flags);
38     } else {
39         fBlur = NULL;
40     }
41
42     if (fBlurFlags & kOverrideColor_BlurFlag) {
43         // Set alpha to 1 for the override since transparency will already
44         // be baked into the blurred mask.
45         SkColor opaqueColor = SkColorSetA(fBlurColor, 255);
46         //The SrcIn xfer mode will multiply 'color' by the incoming alpha
47         fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
48                                                        SkXfermode::kSrcIn_Mode);
49     } else {
50         fColorFilter = NULL;
51     }
52 }
53
54 void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy,
55                             SkColor color, uint32_t flags) {
56     fSigma = sigma;
57     fDx = dx;
58     fDy = dy;
59     fBlurColor = color;
60     fBlurFlags = flags;
61
62     this->initEffects();
63 }
64
65 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
66 SkBlurDrawLooper::SkBlurDrawLooper(SkReadBuffer& buffer) : INHERITED(buffer) {
67
68     fSigma = buffer.readScalar();
69     fDx = buffer.readScalar();
70     fDy = buffer.readScalar();
71     fBlurColor = buffer.readColor();
72     fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
73
74     this->initEffects();
75 }
76 #endif
77
78 SkFlattenable* SkBlurDrawLooper::CreateProc(SkReadBuffer& buffer) {
79     const SkColor color = buffer.readColor();
80     const SkScalar sigma = buffer.readScalar();
81     const SkScalar dx = buffer.readScalar();
82     const SkScalar dy = buffer.readScalar();
83     const uint32_t flags = buffer.read32();
84     return Create(color, sigma, dx, dy, flags);
85 }
86
87 void SkBlurDrawLooper::flatten(SkWriteBuffer& buffer) const {
88     buffer.writeColor(fBlurColor);
89     buffer.writeScalar(fSigma);
90     buffer.writeScalar(fDx);
91     buffer.writeScalar(fDy);
92     buffer.write32(fBlurFlags);
93 }
94
95 SkBlurDrawLooper::~SkBlurDrawLooper() {
96     SkSafeUnref(fBlur);
97     SkSafeUnref(fColorFilter);
98 }
99
100 bool SkBlurDrawLooper::asABlurShadow(BlurShadowRec* rec) const {
101     if (fSigma <= 0 || (fBlurFlags & fBlurFlags & kIgnoreTransform_BlurFlag)) {
102         return false;
103     }
104
105     if (rec) {
106         rec->fSigma = fSigma;
107         rec->fColor = fBlurColor;
108         rec->fOffset.set(fDx, fDy);
109         rec->fStyle = kNormal_SkBlurStyle;
110         rec->fQuality = (fBlurFlags & kHighQuality_BlurFlag) ?
111                         kHigh_SkBlurQuality : kLow_SkBlurQuality;
112     }
113     return true;
114 }
115
116 ////////////////////////////////////////////////////////////////////////////////////////
117
118 SkDrawLooper::Context* SkBlurDrawLooper::createContext(SkCanvas*, void* storage) const {
119     return SkNEW_PLACEMENT_ARGS(storage, BlurDrawLooperContext, (this));
120 }
121
122 SkBlurDrawLooper::BlurDrawLooperContext::BlurDrawLooperContext(
123         const SkBlurDrawLooper* looper)
124     : fLooper(looper), fState(SkBlurDrawLooper::kBeforeEdge) {}
125
126 bool SkBlurDrawLooper::BlurDrawLooperContext::next(SkCanvas* canvas,
127                                                    SkPaint* paint) {
128     switch (fState) {
129         case kBeforeEdge:
130             // we do nothing if a maskfilter is already installed
131             if (paint->getMaskFilter()) {
132                 fState = kDone;
133                 return false;
134             }
135 #ifdef SK_BUILD_FOR_ANDROID
136             SkColor blurColor;
137             blurColor = fLooper->fBlurColor;
138             if (SkColorGetA(blurColor) == 255) {
139                 blurColor = SkColorSetA(blurColor, paint->getAlpha());
140             }
141             paint->setColor(blurColor);
142 #else
143             paint->setColor(fLooper->fBlurColor);
144 #endif
145             paint->setMaskFilter(fLooper->fBlur);
146             paint->setColorFilter(fLooper->fColorFilter);
147             canvas->save();
148             if (fLooper->fBlurFlags & kIgnoreTransform_BlurFlag) {
149                 SkMatrix transform(canvas->getTotalMatrix());
150                 transform.postTranslate(fLooper->fDx, fLooper->fDy);
151                 canvas->setMatrix(transform);
152             } else {
153                 canvas->translate(fLooper->fDx, fLooper->fDy);
154             }
155             fState = kAfterEdge;
156             return true;
157         case kAfterEdge:
158             canvas->restore();
159             fState = kDone;
160             return true;
161         default:
162             SkASSERT(kDone == fState);
163             return false;
164     }
165 }
166
167 #ifndef SK_IGNORE_TO_STRING
168 void SkBlurDrawLooper::toString(SkString* str) const {
169     str->append("SkBlurDrawLooper: ");
170
171     str->append("dx: ");
172     str->appendScalar(fDx);
173
174     str->append(" dy: ");
175     str->appendScalar(fDy);
176
177     str->append(" color: ");
178     str->appendHex(fBlurColor);
179
180     str->append(" flags: (");
181     if (kNone_BlurFlag == fBlurFlags) {
182         str->append("None");
183     } else {
184         bool needsSeparator = false;
185         SkAddFlagToString(str, SkToBool(kIgnoreTransform_BlurFlag & fBlurFlags), "IgnoreTransform",
186                           &needsSeparator);
187         SkAddFlagToString(str, SkToBool(kOverrideColor_BlurFlag & fBlurFlags), "OverrideColor",
188                           &needsSeparator);
189         SkAddFlagToString(str, SkToBool(kHighQuality_BlurFlag & fBlurFlags), "HighQuality",
190                           &needsSeparator);
191     }
192     str->append(")");
193
194     // TODO: add optional "fBlurFilter->toString(str);" when SkMaskFilter::toString is added
195     // alternatively we could cache the radius in SkBlurDrawLooper and just add it here
196 }
197 #endif