diff options
Diffstat (limited to 'src/effects')
-rw-r--r-- | src/effects/SkBlurDrawLooper.cpp | 89 | ||||
-rw-r--r-- | src/effects/SkBlurMask.cpp | 24 | ||||
-rw-r--r-- | src/effects/SkBlurMask.h | 3 | ||||
-rw-r--r-- | src/effects/SkBlurMaskFilter.cpp | 26 | ||||
-rw-r--r-- | src/effects/SkEmbossMaskFilter.cpp | 6 | ||||
-rw-r--r-- | src/effects/SkLayerDrawLooper.cpp | 44 |
6 files changed, 141 insertions, 51 deletions
diff --git a/src/effects/SkBlurDrawLooper.cpp b/src/effects/SkBlurDrawLooper.cpp index 03e635be12..5af02db8ee 100644 --- a/src/effects/SkBlurDrawLooper.cpp +++ b/src/effects/SkBlurDrawLooper.cpp @@ -1,10 +1,10 @@ - /* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ + #include "SkBlurDrawLooper.h" #include "SkBlurMask.h" // just for SkBlurMask::ConvertRadiusToSigma #include "SkBlurMaskFilter.h" @@ -29,32 +29,27 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkColor color, SkScalar sigma, this->init(sigma, dx, dy, color, flags); } -void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy, - SkColor color, uint32_t flags) { - fDx = dx; - fDy = dy; - fBlurColor = color; - fBlurFlags = flags; - - SkASSERT(flags <= kAll_BlurFlag); - if (sigma > 0) { - uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ? - SkBlurMaskFilter::kIgnoreTransform_BlurFlag : - SkBlurMaskFilter::kNone_BlurFlag; - - blurFlags |= flags & kHighQuality_BlurFlag ? - SkBlurMaskFilter::kHighQuality_BlurFlag : - SkBlurMaskFilter::kNone_BlurFlag; - - fBlur = SkBlurMaskFilter::Create(kNormal_SkBlurStyle, sigma, blurFlags); +// only call from constructor +void SkBlurDrawLooper::initEffects() { + SkASSERT(fBlurFlags <= kAll_BlurFlag); + if (fSigma > 0) { + uint32_t flags = fBlurFlags & kIgnoreTransform_BlurFlag ? + SkBlurMaskFilter::kIgnoreTransform_BlurFlag : + SkBlurMaskFilter::kNone_BlurFlag; + + flags |= fBlurFlags & kHighQuality_BlurFlag ? + SkBlurMaskFilter::kHighQuality_BlurFlag : + SkBlurMaskFilter::kNone_BlurFlag; + + fBlur = SkBlurMaskFilter::Create(kNormal_SkBlurStyle, fSigma, flags); } else { fBlur = NULL; } - - if (flags & kOverrideColor_BlurFlag) { + + if (fBlurFlags & kOverrideColor_BlurFlag) { // Set alpha to 1 for the override since transparency will already // be baked into the blurred mask. - SkColor opaqueColor = SkColorSetA(color, 255); + SkColor opaqueColor = SkColorSetA(fBlurColor, 255); //The SrcIn xfer mode will multiply 'color' by the incoming alpha fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor, SkXfermode::kSrcIn_Mode); @@ -63,32 +58,60 @@ void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy, } } -SkBlurDrawLooper::SkBlurDrawLooper(SkReadBuffer& buffer) -: INHERITED(buffer) { +void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy, + SkColor color, uint32_t flags) { + fSigma = sigma; + fDx = dx; + fDy = dy; + fBlurColor = color; + fBlurFlags = flags; + + this->initEffects(); +} + +SkBlurDrawLooper::SkBlurDrawLooper(SkReadBuffer& buffer) : INHERITED(buffer) { + fSigma = buffer.readScalar(); fDx = buffer.readScalar(); fDy = buffer.readScalar(); fBlurColor = buffer.readColor(); - fBlur = buffer.readMaskFilter(); - fColorFilter = buffer.readColorFilter(); fBlurFlags = buffer.readUInt() & kAll_BlurFlag; -} -SkBlurDrawLooper::~SkBlurDrawLooper() { - SkSafeUnref(fBlur); - SkSafeUnref(fColorFilter); + this->initEffects(); } void SkBlurDrawLooper::flatten(SkWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); + buffer.writeScalar(fSigma); buffer.writeScalar(fDx); buffer.writeScalar(fDy); buffer.writeColor(fBlurColor); - buffer.writeFlattenable(fBlur); - buffer.writeFlattenable(fColorFilter); - buffer.writeUInt(fBlurFlags); + buffer.write32(fBlurFlags); +} + +SkBlurDrawLooper::~SkBlurDrawLooper() { + SkSafeUnref(fBlur); + SkSafeUnref(fColorFilter); } +bool SkBlurDrawLooper::asABlurShadow(BlurShadowRec* rec) const { + if (fSigma <= 0 || (fBlurFlags & fBlurFlags & kIgnoreTransform_BlurFlag)) { + return false; + } + + if (rec) { + rec->fSigma = fSigma; + rec->fColor = fBlurColor; + rec->fOffset.set(fDx, fDy); + rec->fStyle = kNormal_SkBlurStyle; + rec->fQuality = (fBlurFlags & kHighQuality_BlurFlag) ? + kHigh_SkBlurQuality : kLow_SkBlurQuality; + } + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////// + SkDrawLooper::Context* SkBlurDrawLooper::createContext(SkCanvas*, void* storage) const { return SkNEW_PLACEMENT_ARGS(storage, BlurDrawLooperContext, (this)); } diff --git a/src/effects/SkBlurMask.cpp b/src/effects/SkBlurMask.cpp index c04a6f89f8..bf50845ab6 100644 --- a/src/effects/SkBlurMask.cpp +++ b/src/effects/SkBlurMask.cpp @@ -13,17 +13,21 @@ #include "SkEndian.h" +// This constant approximates the scaling done in the software path's +// "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)). +// IMHO, it actually should be 1: we blur "less" than we should do +// according to the CSS and canvas specs, simply because Safari does the same. +// Firefox used to do the same too, until 4.0 where they fixed it. So at some +// point we should probably get rid of these scaling constants and rebaseline +// all the blur tests. +static const SkScalar kBLUR_SIGMA_SCALE = 0.57735f; + SkScalar SkBlurMask::ConvertRadiusToSigma(SkScalar radius) { - // This constant approximates the scaling done in the software path's - // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)). - // IMHO, it actually should be 1: we blur "less" than we should do - // according to the CSS and canvas specs, simply because Safari does the same. - // Firefox used to do the same too, until 4.0 where they fixed it. So at some - // point we should probably get rid of these scaling constants and rebaseline - // all the blur tests. - static const SkScalar kBLUR_SIGMA_SCALE = 0.57735f; - - return radius ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f; + return radius > 0 ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f; +} + +SkScalar SkBlurMask::ConvertSigmaToRadius(SkScalar sigma) { + return sigma > 0.5f ? (sigma - 0.5f) / kBLUR_SIGMA_SCALE : 0.0f; } #define UNROLL_SEPARABLE_LOOPS diff --git a/src/effects/SkBlurMask.h b/src/effects/SkBlurMask.h index 39adb96f9a..71f60d91fa 100644 --- a/src/effects/SkBlurMask.h +++ b/src/effects/SkBlurMask.h @@ -39,7 +39,10 @@ public: static bool BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src, SkBlurStyle, SkIPoint* margin = NULL); + // If radius > 0, return the corresponding sigma, else return 0 static SkScalar ConvertRadiusToSigma(SkScalar radius); + // If sigma > 0.5, return the corresponding radius, else return 0 + static SkScalar ConvertSigmaToRadius(SkScalar sigma); /* Helper functions for analytic rectangle blurs */ diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index 2bed2fe8d6..5dffd6fd1f 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -59,6 +59,7 @@ public: #endif virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; + virtual bool asABlur(BlurRec*) const SK_OVERRIDE; SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) @@ -87,6 +88,11 @@ private: SkBlurStyle fBlurStyle; uint32_t fBlurFlags; + SkBlurQuality getQuality() const { + return (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? + kHigh_SkBlurQuality : kLow_SkBlurQuality; + } + SkBlurMaskFilterImpl(SkReadBuffer&); virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; @@ -145,16 +151,24 @@ SkMask::Format SkBlurMaskFilterImpl::getFormat() const { return SkMask::kA8_Format; } +bool SkBlurMaskFilterImpl::asABlur(BlurRec* rec) const { + if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { + return false; + } + + if (rec) { + rec->fSigma = fSigma; + rec->fStyle = fBlurStyle; + rec->fQuality = this->getQuality(); + } + return true; +} + bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, const SkMatrix& matrix, SkIPoint* margin) const{ SkScalar sigma = this->computeXformedSigma(matrix); - - SkBlurQuality blurQuality = - (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? - kHigh_SkBlurQuality : kLow_SkBlurQuality; - - return SkBlurMask::BoxBlur(dst, src, sigma, fBlurStyle, blurQuality, margin); + return SkBlurMask::BoxBlur(dst, src, sigma, fBlurStyle, this->getQuality(), margin); } bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, diff --git a/src/effects/SkEmbossMaskFilter.cpp b/src/effects/SkEmbossMaskFilter.cpp index 9bf5025e70..cdd55fcc5b 100644 --- a/src/effects/SkEmbossMaskFilter.cpp +++ b/src/effects/SkEmbossMaskFilter.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #include "SkEmbossMaskFilter.h" #include "SkBlurMaskFilter.h" #include "SkBlurMask.h" @@ -15,6 +13,10 @@ #include "SkWriteBuffer.h" #include "SkString.h" +SkEmbossMaskFilter* SkEmbossMaskFilter::Create(SkScalar blurSigma, const Light& light) { + return SkNEW_ARGS(SkEmbossMaskFilter, (blurSigma, light)); +} + static inline int pin2byte(int n) { if (n < 0) { n = 0; diff --git a/src/effects/SkLayerDrawLooper.cpp b/src/effects/SkLayerDrawLooper.cpp index fa590d2d3f..aed2c9bbd4 100644 --- a/src/effects/SkLayerDrawLooper.cpp +++ b/src/effects/SkLayerDrawLooper.cpp @@ -153,6 +153,50 @@ bool SkLayerDrawLooper::LayerDrawLooperContext::next(SkCanvas* canvas, return true; } +bool SkLayerDrawLooper::asABlurShadow(BlurShadowRec* bsRec) const { + if (fCount != 2) { + return false; + } + const Rec* rec = fRecs; + + // bottom layer needs to be just blur(maskfilter) + if ((rec->fInfo.fPaintBits & ~kMaskFilter_Bit)) { + return false; + } + if (SkXfermode::kSrc_Mode != rec->fInfo.fColorMode) { + return false; + } + const SkMaskFilter* mf = rec->fPaint.getMaskFilter(); + if (NULL == mf) { + return false; + } + SkMaskFilter::BlurRec maskBlur; + if (!mf->asABlur(&maskBlur)) { + return false; + } + + rec = rec->fNext; + // top layer needs to be "plain" + if (rec->fInfo.fPaintBits) { + return false; + } + if (SkXfermode::kDst_Mode != rec->fInfo.fColorMode) { + return false; + } + if (!rec->fInfo.fOffset.equals(0, 0)) { + return false; + } + + if (bsRec) { + bsRec->fSigma = maskBlur.fSigma; + bsRec->fOffset = fRecs->fInfo.fOffset; + bsRec->fColor = fRecs->fPaint.getColor(); + bsRec->fStyle = maskBlur.fStyle; + bsRec->fQuality = maskBlur.fQuality; + } + return true; +} + /////////////////////////////////////////////////////////////////////////////// void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const { |