1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/* 3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project 4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */ 8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBlurMaskFilter.h" 10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBlurMask.h" 113ef45971cdc72a20db91e8bce37e16d669947e4arobertphillips@google.com#include "SkGpuBlurUtils.h" 129ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com#include "SkFlattenableBuffers.h" 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkMaskFilter.h" 14524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com#include "SkRRect.h" 158c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com#include "SkRTConf.h" 16494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com#include "SkStringUtils.h" 171c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#include "SkStrokeRec.h" 181c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 191c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#if SK_SUPPORT_GPU 201c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#include "GrContext.h" 211c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#include "GrTexture.h" 221c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#include "effects/GrSimpleTextureEffect.h" 231c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#include "SkGrPixelRef.h" 241c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#endif 25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass SkBlurMaskFilterImpl : public SkMaskFilter { 27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic: 289df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkBlurMaskFilterImpl(SkScalar sigma, SkBlurMaskFilter::BlurStyle, uint32_t flags); 29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // overrides from SkMaskFilter 319011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com virtual SkMask::Format getFormat() const SK_OVERRIDE; 32ff0114918f0420778dfac164d810af08eadbac26reed@google.com virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, 339011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com SkIPoint* margin) const SK_OVERRIDE; 34b75bc072b3a26cafed919573412f7ca2fd8d0953skia.committer@gmail.com 351c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#if SK_SUPPORT_GPU 3652373f2a535a319f6b6d4a144e57491c5e56e311skia.committer@gmail.com virtual bool canFilterMaskGPU(const SkRect& devBounds, 371c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com const SkIRect& clipBounds, 381c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com const SkMatrix& ctm, 391c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com SkRect* maskRect) const SK_OVERRIDE; 4052373f2a535a319f6b6d4a144e57491c5e56e311skia.committer@gmail.com virtual bool filterMaskGPU(GrTexture* src, 4152373f2a535a319f6b6d4a144e57491c5e56e311skia.committer@gmail.com const SkRect& maskRect, 421c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com GrTexture** result, 431c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com bool canOverwriteSrc) const; 441c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#endif 451c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 469011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; 47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 48494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;) 494d1d95c61576960796347e1dd5006d878e9d2dc0djsollen@google.com SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) 50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 511e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.comprotected: 52bb6529fbc4553260f434113a62a20af53c525649reed@google.com virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMatrix&, 53bb6529fbc4553260f434113a62a20af53c525649reed@google.com const SkIRect& clipBounds, 549011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com NinePatch*) const SK_OVERRIDE; 55b75bc072b3a26cafed919573412f7ca2fd8d0953skia.committer@gmail.com 56524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&, 57524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkIRect& clipBounds, 58524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com NinePatch*) const SK_OVERRIDE; 59524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 60b75bc072b3a26cafed919573412f7ca2fd8d0953skia.committer@gmail.com bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, 618c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com SkIPoint* margin, SkMask::CreateMode createMode) const; 62a29024e9f900c5565340a27e925bca7d0f6ea8e1skia.committer@gmail.com 63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate: 641c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // To avoid unseemly allocation requests (esp. for finite platforms like 651c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // handset) we limit the radius so something manageable. (as opposed to 661c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // a request like 10,000) 679df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com static const SkScalar kMAX_BLUR_SIGMA; 689df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com 699df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkScalar fSigma; 70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBlurMaskFilter::BlurStyle fBlurStyle; 71740de996d9e77a695864fdd8b89b4bd55f8d304asenorblanco@chromium.org uint32_t fBlurFlags; 72bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBlurMaskFilterImpl(SkFlattenableReadBuffer&); 74cd2e444e946f5cfec4723f5bc46e9487d82e8e54djsollen@google.com virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; 759df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com 769df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkScalar computeXformedSigma(const SkMatrix& ctm) const { 771c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com bool ignoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag); 781c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 799df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkScalar xformedSigma = ignoreTransform ? fSigma : ctm.mapRadius(fSigma); 809df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); 811c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com } 82935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com typedef SkMaskFilter INHERITED; 84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 869df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.comconst SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); 871c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 88ff0114918f0420778dfac164d810af08eadbac26reed@google.comSkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius, 89ff0114918f0420778dfac164d810af08eadbac26reed@google.com SkBlurMaskFilter::BlurStyle style, 90ff0114918f0420778dfac164d810af08eadbac26reed@google.com uint32_t flags) { 914c003748338174e594471cfe86ec1bcb53fda6fcreed@google.com // use !(radius > 0) instead of radius <= 0 to reject NaN values 92935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount 93ff0114918f0420778dfac164d810af08eadbac26reed@google.com || flags > SkBlurMaskFilter::kAll_BlurFlag) { 94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return NULL; 95ff0114918f0420778dfac164d810af08eadbac26reed@google.com } 96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 979df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius); 989df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com 999df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com return SkNEW_ARGS(SkBlurMaskFilterImpl, (sigma, style, flags)); 1009df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com} 1019df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com 1029df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.comSkMaskFilter* SkBlurMaskFilter::Create(SkBlurMaskFilter::BlurStyle style, 1039df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkScalar sigma, 1049df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com uint32_t flags) { 1059df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com // use !(sigma > 0) instead of sigma <= 0 to reject NaN values 1069df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com if (!(sigma > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount 1079df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com || flags > SkBlurMaskFilter::kAll_BlurFlag) { 1089df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com return NULL; 1099df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com } 1109df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com 1119df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com return SkNEW_ARGS(SkBlurMaskFilterImpl, (sigma, style, flags)); 112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 114ff0114918f0420778dfac164d810af08eadbac26reed@google.com/////////////////////////////////////////////////////////////////////////////// 115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1169df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.comSkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, 117ff0114918f0420778dfac164d810af08eadbac26reed@google.com SkBlurMaskFilter::BlurStyle style, 118740de996d9e77a695864fdd8b89b4bd55f8d304asenorblanco@chromium.org uint32_t flags) 1199df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com : fSigma(sigma), fBlurStyle(style), fBlurFlags(flags) { 120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if 0 121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fGamma = NULL; 122ff0114918f0420778dfac164d810af08eadbac26reed@google.com if (gammaScale) { 123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fGamma = new U8[256]; 124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (gammaScale > 0) 125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBlurMask::BuildSqrGamma(fGamma, gammaScale); 126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com else 127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale); 128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 1309df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkASSERT(fSigma >= 0); 131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount); 132740de996d9e77a695864fdd8b89b4bd55f8d304asenorblanco@chromium.org SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); 133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1359011c23655acf4186fca1789daee7e94fc0bbe61reed@google.comSkMask::Format SkBlurMaskFilterImpl::getFormat() const { 136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkMask::kA8_Format; 137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 139ff0114918f0420778dfac164d810af08eadbac26reed@google.combool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, 1409011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com const SkMatrix& matrix, 1419011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com SkIPoint* margin) const{ 1429df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkScalar sigma = this->computeXformedSigma(matrix); 143740de996d9e77a695864fdd8b89b4bd55f8d304asenorblanco@chromium.org 144ff0114918f0420778dfac164d810af08eadbac26reed@google.com SkBlurMask::Quality blurQuality = 145935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? 146ff0114918f0420778dfac164d810af08eadbac26reed@google.com SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality; 147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1489df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com return SkBlurMask::BoxBlur(dst, src, sigma, (SkBlurMask::Style)fBlurStyle, 1499df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com blurQuality, margin); 150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1528c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.combool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, 1538c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com const SkMatrix& matrix, 1548c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com SkIPoint* margin, SkMask::CreateMode createMode) const{ 1559df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkScalar sigma = computeXformedSigma(matrix); 1568c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com 1579df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com return SkBlurMask::BlurRect(sigma, dst, r, (SkBlurMask::Style)fBlurStyle, 1588c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com margin, createMode); 1598c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com} 1608c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com 1611e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com#include "SkCanvas.h" 1621e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com 163524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.comstatic bool prepare_to_draw_into_mask(const SkRect& bounds, SkMask* mask) { 164524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkASSERT(mask != NULL); 165524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 166524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com bounds.roundOut(&mask->fBounds); 1671e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com mask->fRowBytes = SkAlign4(mask->fBounds.width()); 1681e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com mask->fFormat = SkMask::kA8_Format; 169524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const size_t size = mask->computeImageSize(); 1701e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com mask->fImage = SkMask::AllocImage(size); 1711e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com if (NULL == mask->fImage) { 1721e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com return false; 1731e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com } 174524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 175524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // FIXME: use sk_calloc in AllocImage? 1761e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com sk_bzero(mask->fImage, size); 177524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return true; 178524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com} 179524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 180524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.comstatic bool draw_rrect_into_mask(const SkRRect rrect, SkMask* mask) { 181524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com if (!prepare_to_draw_into_mask(rrect.rect(), mask)) { 182524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return false; 183524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com } 184524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 185524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // FIXME: This code duplicates code in draw_rects_into_mask, below. Is there a 186524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // clean way to share more code? 187524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkBitmap bitmap; 188524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com bitmap.setConfig(SkBitmap::kA8_Config, 189524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com mask->fBounds.width(), mask->fBounds.height(), 190524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com mask->fRowBytes); 191524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com bitmap.setPixels(mask->fImage); 192524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 193524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkCanvas canvas(bitmap); 194524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com canvas.translate(-SkIntToScalar(mask->fBounds.left()), 195524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com -SkIntToScalar(mask->fBounds.top())); 196524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 197524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkPaint paint; 198524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com paint.setAntiAlias(true); 199524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com canvas.drawRRect(rrect, paint); 200524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return true; 201524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com} 202524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 203524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.comstatic bool draw_rects_into_mask(const SkRect rects[], int count, SkMask* mask) { 204524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com if (!prepare_to_draw_into_mask(rects[0], mask)) { 205524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return false; 206524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com } 2071e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com 2081e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com SkBitmap bitmap; 2091e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com bitmap.setConfig(SkBitmap::kA8_Config, 2101e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com mask->fBounds.width(), mask->fBounds.height(), 2111e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com mask->fRowBytes); 2121e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com bitmap.setPixels(mask->fImage); 2131e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com 2141e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com SkCanvas canvas(bitmap); 215bb6529fbc4553260f434113a62a20af53c525649reed@google.com canvas.translate(-SkIntToScalar(mask->fBounds.left()), 216bb6529fbc4553260f434113a62a20af53c525649reed@google.com -SkIntToScalar(mask->fBounds.top())); 2171e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com 2181e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com SkPaint paint; 2191e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com paint.setAntiAlias(true); 2201e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com 221bb6529fbc4553260f434113a62a20af53c525649reed@google.com if (1 == count) { 222bb6529fbc4553260f434113a62a20af53c525649reed@google.com canvas.drawRect(rects[0], paint); 223bb6529fbc4553260f434113a62a20af53c525649reed@google.com } else { 224bb6529fbc4553260f434113a62a20af53c525649reed@google.com // todo: do I need a fast way to do this? 225bb6529fbc4553260f434113a62a20af53c525649reed@google.com SkPath path; 226bb6529fbc4553260f434113a62a20af53c525649reed@google.com path.addRect(rects[0]); 227bb6529fbc4553260f434113a62a20af53c525649reed@google.com path.addRect(rects[1]); 228bb6529fbc4553260f434113a62a20af53c525649reed@google.com path.setFillType(SkPath::kEvenOdd_FillType); 229bb6529fbc4553260f434113a62a20af53c525649reed@google.com canvas.drawPath(path, paint); 230bb6529fbc4553260f434113a62a20af53c525649reed@google.com } 2311e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com return true; 2321e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com} 2331e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com 23436f4104a411facb6f8a7b4830e9235c2a1610265reed@google.comstatic bool rect_exceeds(const SkRect& r, SkScalar v) { 23536f4104a411facb6f8a7b4830e9235c2a1610265reed@google.com return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v || 23636f4104a411facb6f8a7b4830e9235c2a1610265reed@google.com r.width() > v || r.height() > v; 2370cd465fde832c0441cad1809ee7b18e50266e385reed@google.com} 2380cd465fde832c0441cad1809ee7b18e50266e385reed@google.com 239524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.comSkMaskFilter::FilterReturn 240524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.comSkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& matrix, 241524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkIRect& clipBounds, 242524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com NinePatch* patch) const { 243524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkASSERT(patch != NULL); 244524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com switch (rrect.getType()) { 245524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com case SkRRect::kUnknown_Type: 246524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // Unknown should never be returned. 247524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkASSERT(false); 248524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // Fall through. 249524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com case SkRRect::kEmpty_Type: 250524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // Nothing to draw. 251524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return kFalse_FilterReturn; 252524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 253524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com case SkRRect::kRect_Type: 254524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // We should have caught this earlier. 255524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkASSERT(false); 256524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // Fall through. 257524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com case SkRRect::kOval_Type: 258524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // The nine patch special case does not handle ovals, and we 259524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // already have code for rectangles. 260524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return kUnimplemented_FilterReturn; 261524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 262524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com case SkRRect::kSimple_Type: 263524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // Fall through. 264524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com case SkRRect::kComplex_Type: 265524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // These can take advantage of this fast path. 266524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com break; 267524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com } 268524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 269524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // TODO: report correct metrics for innerstyle, where we do not grow the 270524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // total bounds, but we do need an inset the size of our blur-radius 271524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com if (SkBlurMaskFilter::kInner_BlurStyle == fBlurStyle) { 272524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return kUnimplemented_FilterReturn; 273524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com } 274524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 275524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // TODO: take clipBounds into account to limit our coordinates up front 276524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // for now, just skip too-large src rects (to take the old code path). 277524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com if (rect_exceeds(rrect.rect(), SkIntToScalar(32767))) { 278524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return kUnimplemented_FilterReturn; 279524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com } 280524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 281524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkIPoint margin; 282524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkMask srcM, dstM; 283524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com rrect.rect().roundOut(&srcM.fBounds); 284524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com srcM.fImage = NULL; 285524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com srcM.fFormat = SkMask::kA8_Format; 286524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com srcM.fRowBytes = 0; 287524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 288524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com if (!this->filterMask(&dstM, srcM, matrix, &margin)) { 289524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return kFalse_FilterReturn; 290524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com } 291524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 292524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // Now figure out the appropriate width and height of the smaller round rectangle 293524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // to stretch. It will take into account the larger radius per side as well as double 294524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // the margin, to account for inner and outer blur. 295524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkVector& UL = rrect.radii(SkRRect::kUpperLeft_Corner); 296524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkVector& UR = rrect.radii(SkRRect::kUpperRight_Corner); 297524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkVector& LR = rrect.radii(SkRRect::kLowerRight_Corner); 298524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkVector& LL = rrect.radii(SkRRect::kLowerLeft_Corner); 299524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 300524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkScalar leftUnstretched = SkTMax(UL.fX, LL.fX) + SkIntToScalar(2 * margin.fX); 301524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkScalar rightUnstretched = SkTMax(UR.fX, LR.fX) + SkIntToScalar(2 * margin.fX); 302524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 303524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // Extra space in the middle to ensure an unchanging piece for stretching. Use 3 to cover 304524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // any fractional space on either side plus 1 for the part to stretch. 305524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkScalar stretchSize = SkIntToScalar(3); 306524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 307524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkScalar totalSmallWidth = leftUnstretched + rightUnstretched + stretchSize; 308524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com if (totalSmallWidth >= rrect.rect().width()) { 309524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // There is no valid piece to stretch. 310524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return kUnimplemented_FilterReturn; 311524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com } 312524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 313524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkScalar topUnstretched = SkTMax(UL.fY, UR.fY) + SkIntToScalar(2 * margin.fY); 314524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkScalar bottomUnstretched = SkTMax(LL.fY, LR.fY) + SkIntToScalar(2 * margin.fY); 315524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 316524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com const SkScalar totalSmallHeight = topUnstretched + bottomUnstretched + stretchSize; 317524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com if (totalSmallHeight >= rrect.rect().height()) { 318524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com // There is no valid piece to stretch. 319524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return kUnimplemented_FilterReturn; 320524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com } 321524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 322524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight); 323524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 324524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkRRect smallRR; 325524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com SkVector radii[4]; 326524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com radii[SkRRect::kUpperLeft_Corner] = UL; 327524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com radii[SkRRect::kUpperRight_Corner] = UR; 328524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com radii[SkRRect::kLowerRight_Corner] = LR; 329524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com radii[SkRRect::kLowerLeft_Corner] = LL; 330524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com smallRR.setRectRadii(smallR, radii); 331524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 332524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com if (!draw_rrect_into_mask(smallRR, &srcM)) { 333524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return kFalse_FilterReturn; 334524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com } 335524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 33610af2de2eb34c9a354c0d248fa7f66ddaacdcc4drobertphillips@google.com SkAutoMaskFreeImage amf(srcM.fImage); 33710af2de2eb34c9a354c0d248fa7f66ddaacdcc4drobertphillips@google.com 338524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { 339524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return kFalse_FilterReturn; 340524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com } 341524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 342524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com patch->fMask.fBounds.offsetTo(0, 0); 343524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com patch->fOuterRect = dstM.fBounds; 344524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; 345524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; 346524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com return kTrue_FilterReturn; 347524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com} 348524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com 3498c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com#ifdef SK_IGNORE_FAST_RECT_BLUR 3500cbcedc421fcbf653d1ceace58b14c07fed197a4humper@google.comSK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", false, "Use the faster analytic blur approach for ninepatch rects" ); 3518c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com#else 3520cbcedc421fcbf653d1ceace58b14c07fed197a4humper@google.comSK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects" ); 3538c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com#endif 3548c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com 3551e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.comSkMaskFilter::FilterReturn 356bb6529fbc4553260f434113a62a20af53c525649reed@google.comSkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, 357bb6529fbc4553260f434113a62a20af53c525649reed@google.com const SkMatrix& matrix, 358bb6529fbc4553260f434113a62a20af53c525649reed@google.com const SkIRect& clipBounds, 3599011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com NinePatch* patch) const { 360bb6529fbc4553260f434113a62a20af53c525649reed@google.com if (count < 1 || count > 2) { 361bb6529fbc4553260f434113a62a20af53c525649reed@google.com return kUnimplemented_FilterReturn; 362bb6529fbc4553260f434113a62a20af53c525649reed@google.com } 363108dd7dcdabcd42196cf0621789f02b6fb6c2c54skia.committer@gmail.com 3644356a168a36b9f85a84374e6798ab4bb5bb09c89reed@google.com // TODO: report correct metrics for innerstyle, where we do not grow the 3654356a168a36b9f85a84374e6798ab4bb5bb09c89reed@google.com // total bounds, but we do need an inset the size of our blur-radius 36661bc1f48551cec76674cf7a9524c1914dc862255robertphillips@google.com if (SkBlurMaskFilter::kInner_BlurStyle == fBlurStyle || 36761bc1f48551cec76674cf7a9524c1914dc862255robertphillips@google.com SkBlurMaskFilter::kOuter_BlurStyle == fBlurStyle) { 3684356a168a36b9f85a84374e6798ab4bb5bb09c89reed@google.com return kUnimplemented_FilterReturn; 3694356a168a36b9f85a84374e6798ab4bb5bb09c89reed@google.com } 3704356a168a36b9f85a84374e6798ab4bb5bb09c89reed@google.com 3710cd465fde832c0441cad1809ee7b18e50266e385reed@google.com // TODO: take clipBounds into account to limit our coordinates up front 3720cd465fde832c0441cad1809ee7b18e50266e385reed@google.com // for now, just skip too-large src rects (to take the old code path). 37336f4104a411facb6f8a7b4830e9235c2a1610265reed@google.com if (rect_exceeds(rects[0], SkIntToScalar(32767))) { 3740cd465fde832c0441cad1809ee7b18e50266e385reed@google.com return kUnimplemented_FilterReturn; 3750cd465fde832c0441cad1809ee7b18e50266e385reed@google.com } 376108dd7dcdabcd42196cf0621789f02b6fb6c2c54skia.committer@gmail.com 3771e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com SkIPoint margin; 3781e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com SkMask srcM, dstM; 379bb6529fbc4553260f434113a62a20af53c525649reed@google.com rects[0].roundOut(&srcM.fBounds); 3801e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com srcM.fImage = NULL; 3811e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com srcM.fFormat = SkMask::kA8_Format; 3821e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com srcM.fRowBytes = 0; 383b75bc072b3a26cafed919573412f7ca2fd8d0953skia.committer@gmail.com 3848c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com bool filterResult = false; 3858c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com if (count == 1 && c_analyticBlurNinepatch) { 3868c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com // special case for fast rect blur 3878c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com // don't actually do the blur the first time, just compute the correct size 388b75bc072b3a26cafed919573412f7ca2fd8d0953skia.committer@gmail.com filterResult = this->filterRectMask(&dstM, rects[0], matrix, &margin, 3898c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com SkMask::kJustComputeBounds_CreateMode); 3908c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com } else { 3918c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com filterResult = this->filterMask(&dstM, srcM, matrix, &margin); 3928c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com } 393b75bc072b3a26cafed919573412f7ca2fd8d0953skia.committer@gmail.com 3948c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com if (!filterResult) { 3951e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com return kFalse_FilterReturn; 3961e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com } 3971e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com 3981e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com /* 3991e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * smallR is the smallest version of 'rect' that will still guarantee that 4001e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * we get the same blur results on all edges, plus 1 center row/col that is 4011e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * representative of the extendible/stretchable edges of the ninepatch. 4021e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * Since our actual edge may be fractional we inset 1 more to be sure we 4031e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * don't miss any interior blur. 4041e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * x is an added pixel of blur, and { and } are the (fractional) edge 4051e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * pixels from the original rect. 4061e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * 4071e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * x x { x x .... x x } x x 4081e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * 4091e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * Thus, in this case, we inset by a total of 5 (on each side) beginning 4101e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com * with our outer-rect (dstM.fBounds) 4111e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com */ 412bb6529fbc4553260f434113a62a20af53c525649reed@google.com SkRect smallR[2]; 413bb6529fbc4553260f434113a62a20af53c525649reed@google.com SkIPoint center; 414bb6529fbc4553260f434113a62a20af53c525649reed@google.com 415bb6529fbc4553260f434113a62a20af53c525649reed@google.com // +2 is from +1 for each edge (to account for possible fractional edges 416bb6529fbc4553260f434113a62a20af53c525649reed@google.com int smallW = dstM.fBounds.width() - srcM.fBounds.width() + 2; 417bb6529fbc4553260f434113a62a20af53c525649reed@google.com int smallH = dstM.fBounds.height() - srcM.fBounds.height() + 2; 418bb6529fbc4553260f434113a62a20af53c525649reed@google.com SkIRect innerIR; 419bb6529fbc4553260f434113a62a20af53c525649reed@google.com 420bb6529fbc4553260f434113a62a20af53c525649reed@google.com if (1 == count) { 421bb6529fbc4553260f434113a62a20af53c525649reed@google.com innerIR = srcM.fBounds; 422bb6529fbc4553260f434113a62a20af53c525649reed@google.com center.set(smallW, smallH); 423bb6529fbc4553260f434113a62a20af53c525649reed@google.com } else { 424bb6529fbc4553260f434113a62a20af53c525649reed@google.com SkASSERT(2 == count); 425bb6529fbc4553260f434113a62a20af53c525649reed@google.com rects[1].roundIn(&innerIR); 426bb6529fbc4553260f434113a62a20af53c525649reed@google.com center.set(smallW + (innerIR.left() - srcM.fBounds.left()), 427bb6529fbc4553260f434113a62a20af53c525649reed@google.com smallH + (innerIR.top() - srcM.fBounds.top())); 428bb6529fbc4553260f434113a62a20af53c525649reed@google.com } 429bb6529fbc4553260f434113a62a20af53c525649reed@google.com 430bb6529fbc4553260f434113a62a20af53c525649reed@google.com // +1 so we get a clean, stretchable, center row/col 431bb6529fbc4553260f434113a62a20af53c525649reed@google.com smallW += 1; 432bb6529fbc4553260f434113a62a20af53c525649reed@google.com smallH += 1; 433bb6529fbc4553260f434113a62a20af53c525649reed@google.com 434bb6529fbc4553260f434113a62a20af53c525649reed@google.com // we want the inset amounts to be integral, so we don't change any 435bb6529fbc4553260f434113a62a20af53c525649reed@google.com // fractional phase on the fRight or fBottom of our smallR. 436bb6529fbc4553260f434113a62a20af53c525649reed@google.com const SkScalar dx = SkIntToScalar(innerIR.width() - smallW); 437bb6529fbc4553260f434113a62a20af53c525649reed@google.com const SkScalar dy = SkIntToScalar(innerIR.height() - smallH); 438bb6529fbc4553260f434113a62a20af53c525649reed@google.com if (dx < 0 || dy < 0) { 439bb6529fbc4553260f434113a62a20af53c525649reed@google.com // we're too small, relative to our blur, to break into nine-patch, 440bb6529fbc4553260f434113a62a20af53c525649reed@google.com // so we ask to have our normal filterMask() be called. 441bb6529fbc4553260f434113a62a20af53c525649reed@google.com return kUnimplemented_FilterReturn; 442bb6529fbc4553260f434113a62a20af53c525649reed@google.com } 443bb6529fbc4553260f434113a62a20af53c525649reed@google.com 444bb6529fbc4553260f434113a62a20af53c525649reed@google.com smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[0].bottom() - dy); 445ff56c4016ed5da2fced0edc846da54650d42aa87robertphillips@google.com if (smallR[0].width() < 2 || smallR[0].height() < 2) { 446ff56c4016ed5da2fced0edc846da54650d42aa87robertphillips@google.com return kUnimplemented_FilterReturn; 447ff56c4016ed5da2fced0edc846da54650d42aa87robertphillips@google.com } 448bb6529fbc4553260f434113a62a20af53c525649reed@google.com if (2 == count) { 449bb6529fbc4553260f434113a62a20af53c525649reed@google.com smallR[1].set(rects[1].left(), rects[1].top(), 450bb6529fbc4553260f434113a62a20af53c525649reed@google.com rects[1].right() - dx, rects[1].bottom() - dy); 451bb6529fbc4553260f434113a62a20af53c525649reed@google.com SkASSERT(!smallR[1].isEmpty()); 4521e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com } 4531e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com 4548c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com if (count > 1 || !c_analyticBlurNinepatch) { 455524d5209f4a557c8984ee7ef88774df12656727cscroggo@google.com if (!draw_rects_into_mask(smallR, count, &srcM)) { 4568c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com return kFalse_FilterReturn; 4578c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com } 4581e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com 4598c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com SkAutoMaskFreeImage amf(srcM.fImage); 460794353e38a07c796fb2b65745655d0c64d278d93reed@google.com 4618c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { 4628c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com return kFalse_FilterReturn; 4638c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com } 4648c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com } else { 465b75bc072b3a26cafed919573412f7ca2fd8d0953skia.committer@gmail.com if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, 4668c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com SkMask::kComputeBoundsAndRenderImage_CreateMode)) { 4678c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com return kFalse_FilterReturn; 4688c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com } 4691e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com } 470bb6529fbc4553260f434113a62a20af53c525649reed@google.com patch->fMask.fBounds.offsetTo(0, 0); 471bb6529fbc4553260f434113a62a20af53c525649reed@google.com patch->fOuterRect = dstM.fBounds; 472bb6529fbc4553260f434113a62a20af53c525649reed@google.com patch->fCenter = center; 4731e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com return kTrue_FilterReturn; 4741e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com} 4751e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com 4769011c23655acf4186fca1789daee7e94fc0bbe61reed@google.comvoid SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, 4779011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com SkRect* dst) const { 4789df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkScalar pad = 3.0f * fSigma; 4792b8064fbf34570dbc8e70186b0bf6d886acdc2d0robertphillips@google.com 4802b8064fbf34570dbc8e70186b0bf6d886acdc2d0robertphillips@google.com dst->set(src.fLeft - pad, src.fTop - pad, 4812b8064fbf34570dbc8e70186b0bf6d886acdc2d0robertphillips@google.com src.fRight + pad, src.fBottom + pad); 482d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com} 483d9f04f47c2d6f1c3c341d14eae875933fe4242acreed@google.com 484ff0114918f0420778dfac164d810af08eadbac26reed@google.comSkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer) 485ff0114918f0420778dfac164d810af08eadbac26reed@google.com : SkMaskFilter(buffer) { 486264d90fca00ebdb782a0c131d8185480e5d8fde6robertphillips@google.com#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO 487264d90fca00ebdb782a0c131d8185480e5d8fde6robertphillips@google.com // TODO: when the skps are recaptured at > v15 the SkScalarAbs can be removed 4889df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com#endif 489264d90fca00ebdb782a0c131d8185480e5d8fde6robertphillips@google.com fSigma = SkScalarAbs(buffer.readScalar()); 4909ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt(); 4919ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag; 4929df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkASSERT(fSigma >= 0); 493bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount); 494bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 495bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 496cd2e444e946f5cfec4723f5bc46e9487d82e8e54djsollen@google.comvoid SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const { 497bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->INHERITED::flatten(buffer); 498264d90fca00ebdb782a0c131d8185480e5d8fde6robertphillips@google.com buffer.writeScalar(fSigma); 4999ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com buffer.writeInt(fBlurStyle); 5009ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com buffer.writeUInt(fBlurFlags); 501bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 502bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5031c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#if SK_SUPPORT_GPU 5048a5829bbe742bc830803989e5c91c272a1f252d4reed@google.com 5051c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.combool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds, 5061c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com const SkIRect& clipBounds, 5071c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com const SkMatrix& ctm, 5081c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com SkRect* maskRect) const { 5099df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkScalar xformedSigma = this->computeXformedSigma(ctm); 5109df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com if (xformedSigma <= 0) { 5111c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com return false; 5128a5829bbe742bc830803989e5c91c272a1f252d4reed@google.com } 5131c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5149df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); 5159df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32); 5161c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5171c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com if (srcBounds.width() <= kMIN_GPU_BLUR_SIZE && 5181c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com srcBounds.height() <= kMIN_GPU_BLUR_SIZE && 5199df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com xformedSigma <= kMIN_GPU_BLUR_SIGMA) { 5201c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // We prefer to blur small rect with small radius via CPU. 5211c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com return false; 5221c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com } 5231c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5241c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com if (NULL == maskRect) { 5251c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // don't need to compute maskRect 5261c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com return true; 5271c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com } 5281c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5299df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com float sigma3 = 3 * SkScalarToFloat(xformedSigma); 5301c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 531bb6a0d330cd7dae11f94aff99c001d4d1eca0716reed@google.com SkRect clipRect = SkRect::Make(clipBounds); 5321c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com SkRect srcRect(srcBounds); 5331c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5341c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // Outset srcRect and clipRect by 3 * sigma, to compute affected blur area. 535dfc928cc9afc242d1125e8d5ae48e8bca66c4834commit-bot@chromium.org srcRect.outset(sigma3, sigma3); 536dfc928cc9afc242d1125e8d5ae48e8bca66c4834commit-bot@chromium.org clipRect.outset(sigma3, sigma3); 5371c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com srcRect.intersect(clipRect); 5381c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com *maskRect = srcRect; 53952373f2a535a319f6b6d4a144e57491c5e56e311skia.committer@gmail.com return true; 5401c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com} 5411c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 54252373f2a535a319f6b6d4a144e57491c5e56e311skia.committer@gmail.combool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src, 54352373f2a535a319f6b6d4a144e57491c5e56e311skia.committer@gmail.com const SkRect& maskRect, 5441c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com GrTexture** result, 5451c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com bool canOverwriteSrc) const { 5461c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height()); 5471c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5481c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com GrContext* context = src->getContext(); 5491c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5501c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com GrContext::AutoWideOpenIdentityDraw awo(context, NULL); 5511c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5529df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkScalar xformedSigma = this->computeXformedSigma(context->getMatrix()); 5539df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com SkASSERT(xformedSigma > 0); 5541c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5551c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // If we're doing a normal blur, we can clobber the pathTexture in the 5561c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // gaussianBlur. Otherwise, we need to save it for later compositing. 5571c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com bool isNormalBlur = (SkBlurMaskFilter::kNormal_BlurStyle == fBlurStyle); 5583ef45971cdc72a20db91e8bce37e16d669947e4arobertphillips@google.com *result = SkGpuBlurUtils::GaussianBlur(context, src, isNormalBlur && canOverwriteSrc, 5599df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com clipRect, false, xformedSigma, xformedSigma); 5601fc0d09711aac2f523c6dfc9b40f0af2ea5842a4robertphillips@google.com if (NULL == *result) { 5611c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com return false; 5621c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com } 5631c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5641c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com if (!isNormalBlur) { 5651c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com context->setIdentityMatrix(); 5661c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com GrPaint paint; 5671c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com SkMatrix matrix; 5681c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com matrix.setIDiv(src->width(), src->height()); 5691c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // Blend pathTexture over blurTexture. 5701c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com GrContext::AutoRenderTarget art(context, (*result)->asRenderTarget()); 5714de2cfb9a63682aa6624f781a7454956ef6619a7commit-bot@chromium.org paint.addColorEffect(GrSimpleTextureEffect::Create(src, matrix))->unref(); 5721c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com if (SkBlurMaskFilter::kInner_BlurStyle == fBlurStyle) { 5731c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // inner: dst = dst * src 5741c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com paint.setBlendFunc(kDC_GrBlendCoeff, kZero_GrBlendCoeff); 5751c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com } else if (SkBlurMaskFilter::kSolid_BlurStyle == fBlurStyle) { 5761c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // solid: dst = src + dst - src * dst 5771c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // = (1 - dst) * src + 1 * dst 5781c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com paint.setBlendFunc(kIDC_GrBlendCoeff, kOne_GrBlendCoeff); 5791c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com } else if (SkBlurMaskFilter::kOuter_BlurStyle == fBlurStyle) { 5801c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // outer: dst = dst * (1 - src) 5811c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com // = 0 * src + (1 - src) * dst 5821c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com paint.setBlendFunc(kZero_GrBlendCoeff, kISC_GrBlendCoeff); 5831c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com } 5841c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com context->drawRect(paint, clipRect); 5851c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com } 5861c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5871c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com return true; 5888a5829bbe742bc830803989e5c91c272a1f252d4reed@google.com} 5898a5829bbe742bc830803989e5c91c272a1f252d4reed@google.com 5901c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#endif // SK_SUPPORT_GPU 5911c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 5921c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com 593494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com#ifdef SK_DEVELOPER 594494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.comvoid SkBlurMaskFilterImpl::toString(SkString* str) const { 595494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com str->append("SkBlurMaskFilterImpl: ("); 596494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com 5979df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com str->append("sigma: "); 5989df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com str->appendScalar(fSigma); 599494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com str->append(" "); 600494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com 601494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com static const char* gStyleName[SkBlurMaskFilter::kBlurStyleCount] = { 602494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com "normal", "solid", "outer", "inner" 603494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com }; 604494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com 605494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com str->appendf("style: %s ", gStyleName[fBlurStyle]); 606494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com str->append("flags: ("); 607494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com if (fBlurFlags) { 608494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com bool needSeparator = false; 60937dcc776768d5988f52f883978ecf82e36d2e17eskia.committer@gmail.com SkAddFlagToString(str, 61037dcc776768d5988f52f883978ecf82e36d2e17eskia.committer@gmail.com SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag), 611494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com "IgnoreXform", &needSeparator); 61237dcc776768d5988f52f883978ecf82e36d2e17eskia.committer@gmail.com SkAddFlagToString(str, 61337dcc776768d5988f52f883978ecf82e36d2e17eskia.committer@gmail.com SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag), 614494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com "HighQuality", &needSeparator); 615494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com } else { 616494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com str->append("None"); 617494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com } 618494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com str->append("))"); 619494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com} 620494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com#endif 621494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com 622d4a9619748aea7758b82a24e882955233cae899ccaryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) 623d4a9619748aea7758b82a24e882955233cae899ccaryclark@google.com SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) 624d4a9619748aea7758b82a24e882955233cae899ccaryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 625