2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkBlurDrawLooper.h"
9 #include "SkBlurMask.h" // just for SkBlurMask::ConvertRadiusToSigma
10 #include "SkBlurMaskFilter.h"
12 #include "SkColorFilter.h"
13 #include "SkReadBuffer.h"
14 #include "SkWriteBuffer.h"
15 #include "SkMaskFilter.h"
18 #include "SkStringUtils.h"
20 SkBlurDrawLooper::SkBlurDrawLooper(SkColor color, SkScalar sigma,
21 SkScalar dx, SkScalar dy, uint32_t flags) {
22 this->init(sigma, dx, dy, color, flags);
25 // only call from constructor
26 void SkBlurDrawLooper::initEffects() {
27 SkASSERT(fBlurFlags <= kAll_BlurFlag);
29 uint32_t flags = fBlurFlags & kIgnoreTransform_BlurFlag ?
30 SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
31 SkBlurMaskFilter::kNone_BlurFlag;
33 flags |= fBlurFlags & kHighQuality_BlurFlag ?
34 SkBlurMaskFilter::kHighQuality_BlurFlag :
35 SkBlurMaskFilter::kNone_BlurFlag;
37 fBlur = SkBlurMaskFilter::Create(kNormal_SkBlurStyle, fSigma, flags);
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);
54 void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy,
55 SkColor color, uint32_t flags) {
65 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
66 SkBlurDrawLooper::SkBlurDrawLooper(SkReadBuffer& buffer) : INHERITED(buffer) {
68 fSigma = buffer.readScalar();
69 fDx = buffer.readScalar();
70 fDy = buffer.readScalar();
71 fBlurColor = buffer.readColor();
72 fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
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);
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);
95 SkBlurDrawLooper::~SkBlurDrawLooper() {
97 SkSafeUnref(fColorFilter);
100 bool SkBlurDrawLooper::asABlurShadow(BlurShadowRec* rec) const {
101 if (fSigma <= 0 || (fBlurFlags & fBlurFlags & kIgnoreTransform_BlurFlag)) {
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;
116 ////////////////////////////////////////////////////////////////////////////////////////
118 SkDrawLooper::Context* SkBlurDrawLooper::createContext(SkCanvas*, void* storage) const {
119 return SkNEW_PLACEMENT_ARGS(storage, BlurDrawLooperContext, (this));
122 SkBlurDrawLooper::BlurDrawLooperContext::BlurDrawLooperContext(
123 const SkBlurDrawLooper* looper)
124 : fLooper(looper), fState(SkBlurDrawLooper::kBeforeEdge) {}
126 bool SkBlurDrawLooper::BlurDrawLooperContext::next(SkCanvas* canvas,
130 // we do nothing if a maskfilter is already installed
131 if (paint->getMaskFilter()) {
135 #ifdef SK_BUILD_FOR_ANDROID
137 blurColor = fLooper->fBlurColor;
138 if (SkColorGetA(blurColor) == 255) {
139 blurColor = SkColorSetA(blurColor, paint->getAlpha());
141 paint->setColor(blurColor);
143 paint->setColor(fLooper->fBlurColor);
145 paint->setMaskFilter(fLooper->fBlur);
146 paint->setColorFilter(fLooper->fColorFilter);
148 if (fLooper->fBlurFlags & kIgnoreTransform_BlurFlag) {
149 SkMatrix transform(canvas->getTotalMatrix());
150 transform.postTranslate(fLooper->fDx, fLooper->fDy);
151 canvas->setMatrix(transform);
153 canvas->translate(fLooper->fDx, fLooper->fDy);
162 SkASSERT(kDone == fState);
167 #ifndef SK_IGNORE_TO_STRING
168 void SkBlurDrawLooper::toString(SkString* str) const {
169 str->append("SkBlurDrawLooper: ");
172 str->appendScalar(fDx);
174 str->append(" dy: ");
175 str->appendScalar(fDy);
177 str->append(" color: ");
178 str->appendHex(fBlurColor);
180 str->append(" flags: (");
181 if (kNone_BlurFlag == fBlurFlags) {
184 bool needsSeparator = false;
185 SkAddFlagToString(str, SkToBool(kIgnoreTransform_BlurFlag & fBlurFlags), "IgnoreTransform",
187 SkAddFlagToString(str, SkToBool(kOverrideColor_BlurFlag & fBlurFlags), "OverrideColor",
189 SkAddFlagToString(str, SkToBool(kHighQuality_BlurFlag & fBlurFlags), "HighQuality",
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