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