1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/effects/SkBlurDrawLooper.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,171 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 +#include "SkBlurDrawLooper.h" 1.12 +#include "SkBlurMask.h" // just for SkBlurMask::ConvertRadiusToSigma 1.13 +#include "SkBlurMaskFilter.h" 1.14 +#include "SkCanvas.h" 1.15 +#include "SkColorFilter.h" 1.16 +#include "SkReadBuffer.h" 1.17 +#include "SkWriteBuffer.h" 1.18 +#include "SkMaskFilter.h" 1.19 +#include "SkPaint.h" 1.20 +#include "SkString.h" 1.21 +#include "SkStringUtils.h" 1.22 + 1.23 +SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy, 1.24 + SkColor color, uint32_t flags) { 1.25 + this->init(SkBlurMask::ConvertRadiusToSigma(radius), dx, dy, color, flags); 1.26 +} 1.27 + 1.28 +SkBlurDrawLooper::SkBlurDrawLooper(SkColor color, SkScalar sigma, 1.29 + SkScalar dx, SkScalar dy, uint32_t flags) { 1.30 + this->init(sigma, dx, dy, color, flags); 1.31 +} 1.32 + 1.33 +void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy, 1.34 + SkColor color, uint32_t flags) { 1.35 + fDx = dx; 1.36 + fDy = dy; 1.37 + fBlurColor = color; 1.38 + fBlurFlags = flags; 1.39 + 1.40 + SkASSERT(flags <= kAll_BlurFlag); 1.41 + if (sigma > 0) { 1.42 + uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ? 1.43 + SkBlurMaskFilter::kIgnoreTransform_BlurFlag : 1.44 + SkBlurMaskFilter::kNone_BlurFlag; 1.45 + 1.46 + blurFlags |= flags & kHighQuality_BlurFlag ? 1.47 + SkBlurMaskFilter::kHighQuality_BlurFlag : 1.48 + SkBlurMaskFilter::kNone_BlurFlag; 1.49 + 1.50 + fBlur = SkBlurMaskFilter::Create(SkBlurMaskFilter::kNormal_BlurStyle, 1.51 + sigma, 1.52 + blurFlags); 1.53 + } else { 1.54 + fBlur = NULL; 1.55 + } 1.56 + 1.57 + if (flags & kOverrideColor_BlurFlag) { 1.58 + // Set alpha to 1 for the override since transparency will already 1.59 + // be baked into the blurred mask. 1.60 + SkColor opaqueColor = SkColorSetA(color, 255); 1.61 + //The SrcIn xfer mode will multiply 'color' by the incoming alpha 1.62 + fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor, 1.63 + SkXfermode::kSrcIn_Mode); 1.64 + } else { 1.65 + fColorFilter = NULL; 1.66 + } 1.67 +} 1.68 + 1.69 +SkBlurDrawLooper::SkBlurDrawLooper(SkReadBuffer& buffer) 1.70 +: INHERITED(buffer) { 1.71 + 1.72 + fDx = buffer.readScalar(); 1.73 + fDy = buffer.readScalar(); 1.74 + fBlurColor = buffer.readColor(); 1.75 + fBlur = buffer.readMaskFilter(); 1.76 + fColorFilter = buffer.readColorFilter(); 1.77 + fBlurFlags = buffer.readUInt() & kAll_BlurFlag; 1.78 +} 1.79 + 1.80 +SkBlurDrawLooper::~SkBlurDrawLooper() { 1.81 + SkSafeUnref(fBlur); 1.82 + SkSafeUnref(fColorFilter); 1.83 +} 1.84 + 1.85 +void SkBlurDrawLooper::flatten(SkWriteBuffer& buffer) const { 1.86 + this->INHERITED::flatten(buffer); 1.87 + buffer.writeScalar(fDx); 1.88 + buffer.writeScalar(fDy); 1.89 + buffer.writeColor(fBlurColor); 1.90 + buffer.writeFlattenable(fBlur); 1.91 + buffer.writeFlattenable(fColorFilter); 1.92 + buffer.writeUInt(fBlurFlags); 1.93 +} 1.94 + 1.95 +SkDrawLooper::Context* SkBlurDrawLooper::createContext(SkCanvas*, void* storage) const { 1.96 + return SkNEW_PLACEMENT_ARGS(storage, BlurDrawLooperContext, (this)); 1.97 +} 1.98 + 1.99 +SkBlurDrawLooper::BlurDrawLooperContext::BlurDrawLooperContext( 1.100 + const SkBlurDrawLooper* looper) 1.101 + : fLooper(looper), fState(SkBlurDrawLooper::kBeforeEdge) {} 1.102 + 1.103 +bool SkBlurDrawLooper::BlurDrawLooperContext::next(SkCanvas* canvas, 1.104 + SkPaint* paint) { 1.105 + switch (fState) { 1.106 + case kBeforeEdge: 1.107 + // we do nothing if a maskfilter is already installed 1.108 + if (paint->getMaskFilter()) { 1.109 + fState = kDone; 1.110 + return false; 1.111 + } 1.112 +#ifdef SK_BUILD_FOR_ANDROID 1.113 + SkColor blurColor; 1.114 + blurColor = fLooper->fBlurColor; 1.115 + if (SkColorGetA(blurColor) == 255) { 1.116 + blurColor = SkColorSetA(blurColor, paint->getAlpha()); 1.117 + } 1.118 + paint->setColor(blurColor); 1.119 +#else 1.120 + paint->setColor(fLooper->fBlurColor); 1.121 +#endif 1.122 + paint->setMaskFilter(fLooper->fBlur); 1.123 + paint->setColorFilter(fLooper->fColorFilter); 1.124 + canvas->save(SkCanvas::kMatrix_SaveFlag); 1.125 + if (fLooper->fBlurFlags & kIgnoreTransform_BlurFlag) { 1.126 + SkMatrix transform(canvas->getTotalMatrix()); 1.127 + transform.postTranslate(fLooper->fDx, fLooper->fDy); 1.128 + canvas->setMatrix(transform); 1.129 + } else { 1.130 + canvas->translate(fLooper->fDx, fLooper->fDy); 1.131 + } 1.132 + fState = kAfterEdge; 1.133 + return true; 1.134 + case kAfterEdge: 1.135 + canvas->restore(); 1.136 + fState = kDone; 1.137 + return true; 1.138 + default: 1.139 + SkASSERT(kDone == fState); 1.140 + return false; 1.141 + } 1.142 +} 1.143 + 1.144 +#ifndef SK_IGNORE_TO_STRING 1.145 +void SkBlurDrawLooper::toString(SkString* str) const { 1.146 + str->append("SkBlurDrawLooper: "); 1.147 + 1.148 + str->append("dx: "); 1.149 + str->appendScalar(fDx); 1.150 + 1.151 + str->append(" dy: "); 1.152 + str->appendScalar(fDy); 1.153 + 1.154 + str->append(" color: "); 1.155 + str->appendHex(fBlurColor); 1.156 + 1.157 + str->append(" flags: ("); 1.158 + if (kNone_BlurFlag == fBlurFlags) { 1.159 + str->append("None"); 1.160 + } else { 1.161 + bool needsSeparator = false; 1.162 + SkAddFlagToString(str, SkToBool(kIgnoreTransform_BlurFlag & fBlurFlags), "IgnoreTransform", 1.163 + &needsSeparator); 1.164 + SkAddFlagToString(str, SkToBool(kOverrideColor_BlurFlag & fBlurFlags), "OverrideColor", 1.165 + &needsSeparator); 1.166 + SkAddFlagToString(str, SkToBool(kHighQuality_BlurFlag & fBlurFlags), "HighQuality", 1.167 + &needsSeparator); 1.168 + } 1.169 + str->append(")"); 1.170 + 1.171 + // TODO: add optional "fBlurFilter->toString(str);" when SkMaskFilter::toString is added 1.172 + // alternatively we could cache the radius in SkBlurDrawLooper and just add it here 1.173 +} 1.174 +#endif