1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurMaskFilter.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurMask.h" 10736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#include "SkGpuBlurUtils.h" 1180747ef591ff3c09c2b610eb21258132d1ff4ef5Mike Reed#include "SkMaskFilterBase.h" 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 13242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed#include "SkRRectPriv.h" 148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h" 16a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com#include "SkRRect.h" 170bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com#include "SkStringUtils.h" 18491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "SkStrokeRec.h" 19e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman#include "SkVertices.h" 20491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 21491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#if SK_SUPPORT_GPU 2230c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips#include "GrCircleBlurFragmentProcessor.h" 23c65aec97619682b2c0191554f44ddf35f618a94dBrian Salomon#include "GrClip.h" 24491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "GrContext.h" 25c65aec97619682b2c0191554f44ddf35f618a94dBrian Salomon#include "GrFragmentProcessor.h" 261105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman#include "GrRenderTargetContext.h" 2732342f032e1dfd133040324f851f0365f9d4cb51Brian Osman#include "GrResourceProvider.h" 2894efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon#include "GrShaderCaps.h" 29f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips#include "GrStyle.h" 304a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips#include "GrTextureProxy.h" 31823994624aa5e805e16833ecd3d748fc769a164dEthan Nicholas#include "effects/GrRectBlurEffect.h" 32297d6efe852ebb98a324a71c79df8f7bbdcc3b94Ethan Nicholas#include "effects/GrRRectBlurEffect.h" 33eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "effects/GrSimpleTextureEffect.h" 34039a7c70cea29aa40c4fb880b0d6bb523d449568wutao#include "effects/GrTextureDomain.h" 3564c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLFragmentProcessor.h" 362d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h" 37018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h" 387ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h" 39491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#endif 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 41508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.orgSkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) { 42508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.org return SkBlurMask::ConvertRadiusToSigma(radius); 43508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.org} 44508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.org 4580747ef591ff3c09c2b610eb21258132d1ff4ef5Mike Reedclass SkBlurMaskFilterImpl : public SkMaskFilterBase { 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 4727cdd947903a4262bb483e7d35153358f4541bf8robertphillips SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, const SkRect& occluder, uint32_t flags); 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // overrides from SkMaskFilter 5036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkMask::Format getFormat() const override; 51ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, 52ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkIPoint* margin) const override; 532e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 54491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#if SK_SUPPORT_GPU 5530c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips bool canFilterMaskGPU(const SkRRect& devRRect, 56ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkIRect& clipBounds, 57ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkMatrix& ctm, 58ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkRect* maskRect) const override; 59d3749485db2de966a80e39669a49192fc7c0bd9dRobert Phillips bool directFilterMaskGPU(GrContext*, 601105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman GrRenderTargetContext* renderTargetContext, 6182f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon GrPaint&&, 62ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const GrClip&, 63ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkMatrix& viewMatrix, 64ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkStrokeRec& strokeRec, 65ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkPath& path) const override; 66f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips bool directFilterRRectMaskGPU(GrContext*, 671105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman GrRenderTargetContext* renderTargetContext, 6882f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon GrPaint&&, 69ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const GrClip&, 70ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkMatrix& viewMatrix, 71ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkStrokeRec& strokeRec, 7227cdd947903a4262bb483e7d35153358f4541bf8robertphillips const SkRRect& rrect, 7327cdd947903a4262bb483e7d35153358f4541bf8robertphillips const SkRRect& devRRect) const override; 744a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips sk_sp<GrTextureProxy> filterMaskGPU(GrContext*, 754a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips sk_sp<GrTextureProxy> srcProxy, 764a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips const SkMatrix& ctm, 774a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips const SkIRect& maskRect) const override; 78491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#endif 79491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 8036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void computeFastBounds(const SkRect&, SkRect*) const override; 8136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool asABlur(BlurRec*) const override; 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 830f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org SK_TO_STRING_OVERRIDE() 84ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 86d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comprotected: 87ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips FilterReturn filterRectsToNine(const SkRect[], int count, const SkMatrix&, 88ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkIRect& clipBounds, 89ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips NinePatch*) const override; 902e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 91ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&, 92ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips const SkIRect& clipBounds, 93ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips NinePatch*) const override; 94a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 952e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, 967c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com SkIPoint* margin, SkMask::CreateMode createMode) const; 97a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org bool filterRRectMask(SkMask* dstM, const SkRRect& r, const SkMatrix& matrix, 98a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org SkIPoint* margin, SkMask::CreateMode createMode) const; 99453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com 1009aff85a545703af5880e10726dfb40005ea9934erobertphillips bool ignoreXform() const { 1019aff85a545703af5880e10726dfb40005ea9934erobertphillips return SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag); 1029aff85a545703af5880e10726dfb40005ea9934erobertphillips } 1039aff85a545703af5880e10726dfb40005ea9934erobertphillips 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 105491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // To avoid unseemly allocation requests (esp. for finite platforms like 106491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // handset) we limit the radius so something manageable. (as opposed to 107491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // a request like 10,000) 1087ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com static const SkScalar kMAX_BLUR_SIGMA; 1097ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com 110e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkScalar fSigma; 111e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkBlurStyle fBlurStyle; 11227cdd947903a4262bb483e7d35153358f4541bf8robertphillips SkRect fOccluder; 113e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org uint32_t fBlurFlags; 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 115daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkBlurQuality getQuality() const { 116daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com return (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? 117daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com kHigh_SkBlurQuality : kLow_SkBlurQuality; 118daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 119daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 1208b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org SkBlurMaskFilterImpl(SkReadBuffer&); 12136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void flatten(SkWriteBuffer&) const override; 1227ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com 1237ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar computeXformedSigma(const SkMatrix& ctm) const { 1249aff85a545703af5880e10726dfb40005ea9934erobertphillips SkScalar xformedSigma = this->ignoreXform() ? fSigma : ctm.mapRadius(fSigma); 1257ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); 126491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 127fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed friend class SkBlurMaskFilter; 1299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkMaskFilter INHERITED; 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1337ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.comconst SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); 134491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 135fc6c37b981daeece7474ce61070c707c37eefa62Mike Kleinsk_sp<SkMaskFilter> SkBlurMaskFilter::Make(SkBlurStyle style, SkScalar sigma, 13627cdd947903a4262bb483e7d35153358f4541bf8robertphillips const SkRect& occluder, uint32_t flags) { 13798624d249d279f68127c76754d542ab5cd0f8eabRobert Phillips SkASSERT(!(flags & ~SkBlurMaskFilter::kAll_BlurFlag)); 13898624d249d279f68127c76754d542ab5cd0f8eabRobert Phillips SkASSERT(style <= kLastEnum_SkBlurStyle); 13998624d249d279f68127c76754d542ab5cd0f8eabRobert Phillips 140e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if (!SkScalarIsFinite(sigma) || sigma <= 0) { 14196fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 14203016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com } 1439aff85a545703af5880e10726dfb40005ea9934erobertphillips 14427cdd947903a4262bb483e7d35153358f4541bf8robertphillips return sk_sp<SkMaskFilter>(new SkBlurMaskFilterImpl(sigma, style, occluder, flags)); 145e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org} 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 147c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips// linearly interpolate between y1 & y3 to match x2's position between x1 & x3 148c4d2f907311fca08303c254b2488bd7990fa2f32robertphillipsstatic SkScalar interp(SkScalar x1, SkScalar x2, SkScalar x3, SkScalar y1, SkScalar y3) { 149c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkASSERT(x1 <= x2 && x2 <= x3); 150c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkASSERT(y1 <= y3); 151c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 152c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkScalar t = (x2 - x1) / (x3 - x1); 153c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips return y1 + t * (y3 - y1); 154c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips} 155c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 156c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips// Insert 'lower' and 'higher' into 'array1' and insert a new value at each matching insertion 157c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips// point in 'array2' that linearly interpolates between the existing values. 158c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips// Return a bit mask which contains a copy of 'inputMask' for all the cells between the two 159c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips// insertion points. 160c4d2f907311fca08303c254b2488bd7990fa2f32robertphillipsstatic uint32_t insert_into_arrays(SkScalar* array1, SkScalar* array2, 161c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkScalar lower, SkScalar higher, 162c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips int* num, uint32_t inputMask, int maskSize) { 163c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkASSERT(lower < higher); 164c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkASSERT(lower >= array1[0] && higher <= array1[*num-1]); 165c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 166c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips int32_t skipMask = 0x0; 167c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips int i; 168c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips for (i = 0; i < *num; ++i) { 169c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips if (lower >= array1[i] && lower < array1[i+1]) { 170c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips if (!SkScalarNearlyEqual(lower, array1[i])) { 171c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips memmove(&array1[i+2], &array1[i+1], (*num-i-1)*sizeof(SkScalar)); 172c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips array1[i+1] = lower; 173c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips memmove(&array2[i+2], &array2[i+1], (*num-i-1)*sizeof(SkScalar)); 174c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips array2[i+1] = interp(array1[i], lower, array1[i+2], array2[i], array2[i+2]); 175c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips i++; 176c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips (*num)++; 177c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips } 178c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips break; 179c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips } 180c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips } 181c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips for ( ; i < *num; ++i) { 182c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips skipMask |= inputMask << (i*maskSize); 183c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips if (higher > array1[i] && higher <= array1[i+1]) { 184c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips if (!SkScalarNearlyEqual(higher, array1[i+1])) { 185c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips memmove(&array1[i+2], &array1[i+1], (*num-i-1)*sizeof(SkScalar)); 186c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips array1[i+1] = higher; 187c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips memmove(&array2[i+2], &array2[i+1], (*num-i-1)*sizeof(SkScalar)); 188c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips array2[i+1] = interp(array1[i], higher, array1[i+2], array2[i], array2[i+2]); 189c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips (*num)++; 190c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips } 191c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips break; 192fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein } 193c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips } 194c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 195c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips return skipMask; 196c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips} 197c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 198c4d2f907311fca08303c254b2488bd7990fa2f32robertphillipsbool SkBlurMaskFilter::ComputeBlurredRRectParams(const SkRRect& srcRRect, const SkRRect& devRRect, 199c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkRect& occluder, 200c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkScalar sigma, SkScalar xformedSigma, 201f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips SkRRect* rrectToDraw, 202f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips SkISize* widthHeight, 203c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkScalar rectXs[kMaxDivisions], 204c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkScalar rectYs[kMaxDivisions], 205c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkScalar texXs[kMaxDivisions], 206c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkScalar texYs[kMaxDivisions], 207c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips int* numXs, int* numYs, uint32_t* skipMask) { 208c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips unsigned int devBlurRadius = 3*SkScalarCeilToInt(xformedSigma-1/6.0f); 209c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkScalar srcBlurRadius = 3.0f * sigma; 210c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 211c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkRect& devOrig = devRRect.getBounds(); 212c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkVector& devRadiiUL = devRRect.radii(SkRRect::kUpperLeft_Corner); 213c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkVector& devRadiiUR = devRRect.radii(SkRRect::kUpperRight_Corner); 214c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkVector& devRadiiLR = devRRect.radii(SkRRect::kLowerRight_Corner); 215c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkVector& devRadiiLL = devRRect.radii(SkRRect::kLowerLeft_Corner); 216c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 217c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const int devLeft = SkScalarCeilToInt(SkTMax<SkScalar>(devRadiiUL.fX, devRadiiLL.fX)); 218c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const int devTop = SkScalarCeilToInt(SkTMax<SkScalar>(devRadiiUL.fY, devRadiiUR.fY)); 219c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const int devRight = SkScalarCeilToInt(SkTMax<SkScalar>(devRadiiUR.fX, devRadiiLR.fX)); 220c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const int devBot = SkScalarCeilToInt(SkTMax<SkScalar>(devRadiiLL.fY, devRadiiLR.fY)); 221f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips 222f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips // This is a conservative check for nine-patchability 223c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips if (devOrig.fLeft + devLeft + devBlurRadius >= devOrig.fRight - devRight - devBlurRadius || 224c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips devOrig.fTop + devTop + devBlurRadius >= devOrig.fBottom - devBot - devBlurRadius) { 225f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips return false; 226f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips } 227f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips 228c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkVector& srcRadiiUL = srcRRect.radii(SkRRect::kUpperLeft_Corner); 229c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkVector& srcRadiiUR = srcRRect.radii(SkRRect::kUpperRight_Corner); 230c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkVector& srcRadiiLR = srcRRect.radii(SkRRect::kLowerRight_Corner); 231c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkVector& srcRadiiLL = srcRRect.radii(SkRRect::kLowerLeft_Corner); 232c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 233c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkScalar srcLeft = SkTMax<SkScalar>(srcRadiiUL.fX, srcRadiiLL.fX); 234c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkScalar srcTop = SkTMax<SkScalar>(srcRadiiUL.fY, srcRadiiUR.fY); 235c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkScalar srcRight = SkTMax<SkScalar>(srcRadiiUR.fX, srcRadiiLR.fX); 236c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkScalar srcBot = SkTMax<SkScalar>(srcRadiiLL.fY, srcRadiiLR.fY); 237c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 238c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips int newRRWidth = 2*devBlurRadius + devLeft + devRight + 1; 239c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips int newRRHeight = 2*devBlurRadius + devTop + devBot + 1; 240c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips widthHeight->fWidth = newRRWidth + 2 * devBlurRadius; 241c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips widthHeight->fHeight = newRRHeight + 2 * devBlurRadius; 242c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 243c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkRect srcProxyRect = srcRRect.getBounds().makeOutset(srcBlurRadius, srcBlurRadius); 244c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 245c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips rectXs[0] = srcProxyRect.fLeft; 246c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips rectXs[1] = srcProxyRect.fLeft + 2*srcBlurRadius + srcLeft; 247c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips rectXs[2] = srcProxyRect.fRight - 2*srcBlurRadius - srcRight; 248c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips rectXs[3] = srcProxyRect.fRight; 249c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 250c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips rectYs[0] = srcProxyRect.fTop; 251c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips rectYs[1] = srcProxyRect.fTop + 2*srcBlurRadius + srcTop; 252c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips rectYs[2] = srcProxyRect.fBottom - 2*srcBlurRadius - srcBot; 253c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips rectYs[3] = srcProxyRect.fBottom; 254c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 255c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips texXs[0] = 0.0f; 256c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips texXs[1] = 2.0f*devBlurRadius + devLeft; 257c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips texXs[2] = 2.0f*devBlurRadius + devLeft + 1; 258c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips texXs[3] = SkIntToScalar(widthHeight->fWidth); 259c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 260c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips texYs[0] = 0.0f; 261c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips texYs[1] = 2.0f*devBlurRadius + devTop; 262c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips texYs[2] = 2.0f*devBlurRadius + devTop + 1; 263c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips texYs[3] = SkIntToScalar(widthHeight->fHeight); 264c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 265c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkRect temp = occluder; 266c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips 267f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips *numXs = 4; 268f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips *numYs = 4; 269c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips *skipMask = 0; 270c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips if (!temp.isEmpty() && (srcProxyRect.contains(temp) || temp.intersect(srcProxyRect))) { 271c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips *skipMask = insert_into_arrays(rectXs, texXs, temp.fLeft, temp.fRight, numXs, 0x1, 1); 272c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips *skipMask = insert_into_arrays(rectYs, texYs, temp.fTop, temp.fBottom, 273c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips numYs, *skipMask, *numXs-1); 274c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips } 275f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips 276c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips const SkRect newRect = SkRect::MakeXYWH(SkIntToScalar(devBlurRadius), 277c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkIntToScalar(devBlurRadius), 278c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkIntToScalar(newRRWidth), 279c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips SkIntToScalar(newRRHeight)); 280f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips SkVector newRadii[4]; 281c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips newRadii[0] = { SkScalarCeilToScalar(devRadiiUL.fX), SkScalarCeilToScalar(devRadiiUL.fY) }; 282c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips newRadii[1] = { SkScalarCeilToScalar(devRadiiUR.fX), SkScalarCeilToScalar(devRadiiUR.fY) }; 283c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips newRadii[2] = { SkScalarCeilToScalar(devRadiiLR.fX), SkScalarCeilToScalar(devRadiiLR.fY) }; 284c4d2f907311fca08303c254b2488bd7990fa2f32robertphillips newRadii[3] = { SkScalarCeilToScalar(devRadiiLL.fX), SkScalarCeilToScalar(devRadiiLL.fY) }; 285f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips 286f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips rrectToDraw->setRectRadii(newRect, newRadii); 287f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips return true; 288f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips} 289f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips 29003016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com/////////////////////////////////////////////////////////////////////////////// 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 29227cdd947903a4262bb483e7d35153358f4541bf8robertphillipsSkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle style, 29327cdd947903a4262bb483e7d35153358f4541bf8robertphillips const SkRect& occluder, uint32_t flags) 294e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org : fSigma(sigma) 295e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org , fBlurStyle(style) 29627cdd947903a4262bb483e7d35153358f4541bf8robertphillips , fOccluder(occluder) 297e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org , fBlurFlags(flags) { 298e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkASSERT(fSigma > 0); 299e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkASSERT((unsigned)style <= kLastEnum_SkBlurStyle); 300038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 30330711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.comSkMask::Format SkBlurMaskFilterImpl::getFormat() const { 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkMask::kA8_Format; 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 307daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.combool SkBlurMaskFilterImpl::asABlur(BlurRec* rec) const { 3089aff85a545703af5880e10726dfb40005ea9934erobertphillips if (this->ignoreXform()) { 309daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com return false; 310daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 311daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 312daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (rec) { 313daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com rec->fSigma = fSigma; 314daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com rec->fStyle = fBlurStyle; 315daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com rec->fQuality = this->getQuality(); 316daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 317daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com return true; 318daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com} 319daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 32003016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.combool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, 32130711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com const SkMatrix& matrix, 32230c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkIPoint* margin) const { 3237ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar sigma = this->computeXformedSigma(matrix); 324daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com return SkBlurMask::BoxBlur(dst, src, sigma, fBlurStyle, this->getQuality(), margin); 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3277c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.combool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, 3287c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com const SkMatrix& matrix, 32930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkIPoint* margin, SkMask::CreateMode createMode) const { 3307ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar sigma = computeXformedSigma(matrix); 3317c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com 33230c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips return SkBlurMask::BlurRect(sigma, dst, r, fBlurStyle, margin, createMode); 3337c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com} 3347c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com 335a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.orgbool SkBlurMaskFilterImpl::filterRRectMask(SkMask* dst, const SkRRect& r, 336a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org const SkMatrix& matrix, 33730c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkIPoint* margin, SkMask::CreateMode createMode) const { 338a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org SkScalar sigma = computeXformedSigma(matrix); 339a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 34030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips return SkBlurMask::BlurRRect(sigma, dst, r, fBlurStyle, margin, createMode); 341a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org} 342a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 343d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com#include "SkCanvas.h" 344d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 345a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comstatic bool prepare_to_draw_into_mask(const SkRect& bounds, SkMask* mask) { 34696fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(mask != nullptr); 347a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 348b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed mask->fBounds = bounds.roundOut(); 349d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com mask->fRowBytes = SkAlign4(mask->fBounds.width()); 350d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com mask->fFormat = SkMask::kA8_Format; 351a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const size_t size = mask->computeImageSize(); 352baafcdcd543571238654df87f060a9f5be0eb570Mike Reed mask->fImage = SkMask::AllocImage(size, SkMask::kZeroInit_Alloc); 35396fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == mask->fImage) { 354d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com return false; 355d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com } 356a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return true; 357a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com} 358a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 359a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comstatic bool draw_rrect_into_mask(const SkRRect rrect, SkMask* mask) { 360a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (!prepare_to_draw_into_mask(rrect.rect(), mask)) { 361a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return false; 362a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 363a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 364a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // FIXME: This code duplicates code in draw_rects_into_mask, below. Is there a 365a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // clean way to share more code? 366a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkBitmap bitmap; 367dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org bitmap.installMaskPixels(*mask); 368a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 369a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkCanvas canvas(bitmap); 370a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com canvas.translate(-SkIntToScalar(mask->fBounds.left()), 371a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com -SkIntToScalar(mask->fBounds.top())); 372a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 373a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkPaint paint; 374a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com paint.setAntiAlias(true); 375a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com canvas.drawRRect(rrect, paint); 376a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return true; 377a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com} 378a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 379a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comstatic bool draw_rects_into_mask(const SkRect rects[], int count, SkMask* mask) { 380a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (!prepare_to_draw_into_mask(rects[0], mask)) { 381a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return false; 382a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 383d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 384d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com SkBitmap bitmap; 385e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org bitmap.installPixels(SkImageInfo::Make(mask->fBounds.width(), 386e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org mask->fBounds.height(), 387e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org kAlpha_8_SkColorType, 388e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org kPremul_SkAlphaType), 38900f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org mask->fImage, mask->fRowBytes); 390d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 391d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com SkCanvas canvas(bitmap); 392dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com canvas.translate(-SkIntToScalar(mask->fBounds.left()), 393dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com -SkIntToScalar(mask->fBounds.top())); 394d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 395d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com SkPaint paint; 396d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com paint.setAntiAlias(true); 397d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 398dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com if (1 == count) { 399dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com canvas.drawRect(rects[0], paint); 400dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } else { 401dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // todo: do I need a fast way to do this? 402dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkPath path; 403dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com path.addRect(rects[0]); 404dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com path.addRect(rects[1]); 405dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com path.setFillType(SkPath::kEvenOdd_FillType); 406dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com canvas.drawPath(path, paint); 407dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } 408d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com return true; 409d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com} 410d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 411f276fa74f56d0c691716163d3149fce5de97c9eareed@google.comstatic bool rect_exceeds(const SkRect& r, SkScalar v) { 412f276fa74f56d0c691716163d3149fce5de97c9eareed@google.com return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v || 413f276fa74f56d0c691716163d3149fce5de97c9eareed@google.com r.width() > v || r.height() > v; 41407784a041925f9a921e390e782195a622c76fbfareed@google.com} 41507784a041925f9a921e390e782195a622c76fbfareed@google.com 416eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao#include "SkMaskCache.h" 417eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 418b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reedstatic SkCachedData* copy_mask_to_cacheddata(SkMask* mask) { 419b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed const size_t size = mask->computeTotalImageSize(); 420eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao SkCachedData* data = SkResourceCache::NewCachedData(size); 421eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao if (data) { 422b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed memcpy(data->writable_data(), mask->fImage, size); 423b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkMask::FreeImage(mask->fImage); 424b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed mask->fImage = (uint8_t*)data->data(); 425eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao } 426b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed return data; 427eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao} 428eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 429b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reedstatic SkCachedData* find_cached_rrect(SkMask* mask, SkScalar sigma, SkBlurStyle style, 430b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkBlurQuality quality, const SkRRect& rrect) { 431b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed return SkMaskCache::FindAndRef(sigma, style, quality, rrect, mask); 432eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao} 433eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 434b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reedstatic SkCachedData* add_cached_rrect(SkMask* mask, SkScalar sigma, SkBlurStyle style, 435b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkBlurQuality quality, const SkRRect& rrect) { 436b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkCachedData* cache = copy_mask_to_cacheddata(mask); 437b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed if (cache) { 438b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkMaskCache::Add(sigma, style, quality, rrect, *mask, cache); 439eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao } 440b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed return cache; 441eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao} 442eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 443b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reedstatic SkCachedData* find_cached_rects(SkMask* mask, SkScalar sigma, SkBlurStyle style, 444b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkBlurQuality quality, const SkRect rects[], int count) { 445b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed return SkMaskCache::FindAndRef(sigma, style, quality, rects, count, mask); 446eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao} 447eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 448b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reedstatic SkCachedData* add_cached_rects(SkMask* mask, SkScalar sigma, SkBlurStyle style, 449b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkBlurQuality quality, const SkRect rects[], int count) { 450b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkCachedData* cache = copy_mask_to_cacheddata(mask); 451b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed if (cache) { 452b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkMaskCache::Add(sigma, style, quality, rects, count, *mask, cache); 453eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao } 454b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed return cache; 455eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao} 456eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao 457a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org#ifdef SK_IGNORE_FAST_RRECT_BLUR 4584e44efe50474d4eebcb30b762e784b3ef2126750halcanary // Use the faster analytic blur approach for ninepatch round rects 4594e44efe50474d4eebcb30b762e784b3ef2126750halcanary static const bool c_analyticBlurRRect{false}; 460a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org#else 4614e44efe50474d4eebcb30b762e784b3ef2126750halcanary static const bool c_analyticBlurRRect{true}; 462a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org#endif 463a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 46480747ef591ff3c09c2b610eb21258132d1ff4ef5Mike ReedSkMaskFilterBase::FilterReturn 465a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comSkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& matrix, 466a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkIRect& clipBounds, 467a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com NinePatch* patch) const { 46896fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(patch != nullptr); 469a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com switch (rrect.getType()) { 470a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com case SkRRect::kEmpty_Type: 471a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Nothing to draw. 472a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kFalse_FilterReturn; 473a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 474a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com case SkRRect::kRect_Type: 475a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // We should have caught this earlier. 476a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkASSERT(false); 477a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Fall through. 478a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com case SkRRect::kOval_Type: 479a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // The nine patch special case does not handle ovals, and we 480a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // already have code for rectangles. 481a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kUnimplemented_FilterReturn; 482a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 483f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org // These three can take advantage of this fast path. 484a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com case SkRRect::kSimple_Type: 485f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org case SkRRect::kNinePatch_Type: 486a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com case SkRRect::kComplex_Type: 487a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com break; 488a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 489a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 490a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // TODO: report correct metrics for innerstyle, where we do not grow the 491a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // total bounds, but we do need an inset the size of our blur-radius 492e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if (kInner_SkBlurStyle == fBlurStyle) { 493a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kUnimplemented_FilterReturn; 494a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 495a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 496a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // TODO: take clipBounds into account to limit our coordinates up front 497a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // for now, just skip too-large src rects (to take the old code path). 498a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (rect_exceeds(rrect.rect(), SkIntToScalar(32767))) { 499a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kUnimplemented_FilterReturn; 500a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 501a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 502a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkIPoint margin; 503a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkMask srcM, dstM; 504b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed srcM.fBounds = rrect.rect().roundOut(); 505a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com srcM.fFormat = SkMask::kA8_Format; 506a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com srcM.fRowBytes = 0; 507a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 508a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org bool filterResult = false; 509a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org if (c_analyticBlurRRect) { 510a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org // special case for fast round rect blur 511a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org // don't actually do the blur the first time, just compute the correct size 512a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org filterResult = this->filterRRectMask(&dstM, rrect, matrix, &margin, 513a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org SkMask::kJustComputeBounds_CreateMode); 514a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org } 515a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 516a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org if (!filterResult) { 517a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org filterResult = this->filterMask(&dstM, srcM, matrix, &margin); 518a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org } 519a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 520a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org if (!filterResult) { 521a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kFalse_FilterReturn; 522a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 523a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 524a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Now figure out the appropriate width and height of the smaller round rectangle 525a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // to stretch. It will take into account the larger radius per side as well as double 526a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // the margin, to account for inner and outer blur. 527a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkVector& UL = rrect.radii(SkRRect::kUpperLeft_Corner); 528a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkVector& UR = rrect.radii(SkRRect::kUpperRight_Corner); 529a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkVector& LR = rrect.radii(SkRRect::kLowerRight_Corner); 530a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkVector& LL = rrect.radii(SkRRect::kLowerLeft_Corner); 531a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 532a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar leftUnstretched = SkTMax(UL.fX, LL.fX) + SkIntToScalar(2 * margin.fX); 533a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar rightUnstretched = SkTMax(UR.fX, LR.fX) + SkIntToScalar(2 * margin.fX); 534a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 535a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Extra space in the middle to ensure an unchanging piece for stretching. Use 3 to cover 536a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // any fractional space on either side plus 1 for the part to stretch. 537a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar stretchSize = SkIntToScalar(3); 538a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 539a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar totalSmallWidth = leftUnstretched + rightUnstretched + stretchSize; 540a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (totalSmallWidth >= rrect.rect().width()) { 541a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // There is no valid piece to stretch. 542a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kUnimplemented_FilterReturn; 543a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 544a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 545a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar topUnstretched = SkTMax(UL.fY, UR.fY) + SkIntToScalar(2 * margin.fY); 546a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar bottomUnstretched = SkTMax(LL.fY, LR.fY) + SkIntToScalar(2 * margin.fY); 547a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 548a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com const SkScalar totalSmallHeight = topUnstretched + bottomUnstretched + stretchSize; 549a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (totalSmallHeight >= rrect.rect().height()) { 550a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // There is no valid piece to stretch. 551a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kUnimplemented_FilterReturn; 552a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 553a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 554a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight); 555a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 556a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkRRect smallRR; 557a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkVector radii[4]; 558a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com radii[SkRRect::kUpperLeft_Corner] = UL; 559a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com radii[SkRRect::kUpperRight_Corner] = UR; 560a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com radii[SkRRect::kLowerRight_Corner] = LR; 561a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com radii[SkRRect::kLowerLeft_Corner] = LL; 562a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com smallRR.setRectRadii(smallR, radii); 563a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 5644dca7a829635b552be369186ff508a94aba6a903reed const SkScalar sigma = this->computeXformedSigma(matrix); 565b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkCachedData* cache = find_cached_rrect(&patch->fMask, sigma, fBlurStyle, 566b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed this->getQuality(), smallRR); 567b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed if (!cache) { 5684dca7a829635b552be369186ff508a94aba6a903reed bool analyticBlurWorked = false; 5694dca7a829635b552be369186ff508a94aba6a903reed if (c_analyticBlurRRect) { 5704dca7a829635b552be369186ff508a94aba6a903reed analyticBlurWorked = 5714dca7a829635b552be369186ff508a94aba6a903reed this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin, 5724dca7a829635b552be369186ff508a94aba6a903reed SkMask::kComputeBoundsAndRenderImage_CreateMode); 573a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org } 574ad99358bdd7ca4ffb047121946abf0d5fdbde1e8robertphillips@google.com 5754dca7a829635b552be369186ff508a94aba6a903reed if (!analyticBlurWorked) { 5764dca7a829635b552be369186ff508a94aba6a903reed if (!draw_rrect_into_mask(smallRR, &srcM)) { 5774dca7a829635b552be369186ff508a94aba6a903reed return kFalse_FilterReturn; 5784dca7a829635b552be369186ff508a94aba6a903reed } 579a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org 5804dca7a829635b552be369186ff508a94aba6a903reed SkAutoMaskFreeImage amf(srcM.fImage); 5814dca7a829635b552be369186ff508a94aba6a903reed 5824dca7a829635b552be369186ff508a94aba6a903reed if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { 5834dca7a829635b552be369186ff508a94aba6a903reed return kFalse_FilterReturn; 5844dca7a829635b552be369186ff508a94aba6a903reed } 585a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org } 586b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed cache = add_cached_rrect(&patch->fMask, sigma, fBlurStyle, this->getQuality(), smallRR); 587a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 588a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 589a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com patch->fMask.fBounds.offsetTo(0, 0); 590a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com patch->fOuterRect = dstM.fBounds; 591a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; 592a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; 59396fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(nullptr == patch->fCache); 594b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed patch->fCache = cache; // transfer ownership to patch 595a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return kTrue_FilterReturn; 596a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com} 597a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 5984e44efe50474d4eebcb30b762e784b3ef2126750halcanary// Use the faster analytic blur approach for ninepatch rects 5994e44efe50474d4eebcb30b762e784b3ef2126750halcanarystatic const bool c_analyticBlurNinepatch{true}; 6007c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com 60180747ef591ff3c09c2b610eb21258132d1ff4ef5Mike ReedSkMaskFilterBase::FilterReturn 602dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.comSkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, 603dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com const SkMatrix& matrix, 604dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com const SkIRect& clipBounds, 60530711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com NinePatch* patch) const { 606dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com if (count < 1 || count > 2) { 607dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com return kUnimplemented_FilterReturn; 608dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } 6093458716b52aa25dcd1b270141c7628c380696e35skia.committer@gmail.com 61057850b9daddd941f880d94faaf83f2169355a0c8reed@google.com // TODO: report correct metrics for innerstyle, where we do not grow the 61157850b9daddd941f880d94faaf83f2169355a0c8reed@google.com // total bounds, but we do need an inset the size of our blur-radius 612e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if (kInner_SkBlurStyle == fBlurStyle || kOuter_SkBlurStyle == fBlurStyle) { 61357850b9daddd941f880d94faaf83f2169355a0c8reed@google.com return kUnimplemented_FilterReturn; 61457850b9daddd941f880d94faaf83f2169355a0c8reed@google.com } 61557850b9daddd941f880d94faaf83f2169355a0c8reed@google.com 61607784a041925f9a921e390e782195a622c76fbfareed@google.com // TODO: take clipBounds into account to limit our coordinates up front 61707784a041925f9a921e390e782195a622c76fbfareed@google.com // for now, just skip too-large src rects (to take the old code path). 618f276fa74f56d0c691716163d3149fce5de97c9eareed@google.com if (rect_exceeds(rects[0], SkIntToScalar(32767))) { 61907784a041925f9a921e390e782195a622c76fbfareed@google.com return kUnimplemented_FilterReturn; 62007784a041925f9a921e390e782195a622c76fbfareed@google.com } 6213458716b52aa25dcd1b270141c7628c380696e35skia.committer@gmail.com 622d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com SkIPoint margin; 623d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com SkMask srcM, dstM; 624b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed srcM.fBounds = rects[0].roundOut(); 625d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com srcM.fFormat = SkMask::kA8_Format; 626d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com srcM.fRowBytes = 0; 6272e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 6287c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com bool filterResult = false; 6297c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com if (count == 1 && c_analyticBlurNinepatch) { 6307c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com // special case for fast rect blur 6317c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com // don't actually do the blur the first time, just compute the correct size 6322e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com filterResult = this->filterRectMask(&dstM, rects[0], matrix, &margin, 6337c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com SkMask::kJustComputeBounds_CreateMode); 6347c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com } else { 6357c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com filterResult = this->filterMask(&dstM, srcM, matrix, &margin); 6367c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com } 6372e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com 6387c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com if (!filterResult) { 639d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com return kFalse_FilterReturn; 640d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com } 641d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 642d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com /* 643d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * smallR is the smallest version of 'rect' that will still guarantee that 644d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * we get the same blur results on all edges, plus 1 center row/col that is 645d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * representative of the extendible/stretchable edges of the ninepatch. 646d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * Since our actual edge may be fractional we inset 1 more to be sure we 647d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * don't miss any interior blur. 648d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * x is an added pixel of blur, and { and } are the (fractional) edge 649d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * pixels from the original rect. 650d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * 651d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * x x { x x .... x x } x x 652d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * 653d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * Thus, in this case, we inset by a total of 5 (on each side) beginning 654d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com * with our outer-rect (dstM.fBounds) 655d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com */ 656dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkRect smallR[2]; 657dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkIPoint center; 658dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com 659dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // +2 is from +1 for each edge (to account for possible fractional edges 660dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com int smallW = dstM.fBounds.width() - srcM.fBounds.width() + 2; 661dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com int smallH = dstM.fBounds.height() - srcM.fBounds.height() + 2; 662dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkIRect innerIR; 663dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com 664dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com if (1 == count) { 665dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com innerIR = srcM.fBounds; 666dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com center.set(smallW, smallH); 667dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } else { 668dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkASSERT(2 == count); 669dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com rects[1].roundIn(&innerIR); 670dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com center.set(smallW + (innerIR.left() - srcM.fBounds.left()), 671dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com smallH + (innerIR.top() - srcM.fBounds.top())); 672dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } 673dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com 674dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // +1 so we get a clean, stretchable, center row/col 675dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com smallW += 1; 676dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com smallH += 1; 677dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com 678dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // we want the inset amounts to be integral, so we don't change any 679dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // fractional phase on the fRight or fBottom of our smallR. 680dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com const SkScalar dx = SkIntToScalar(innerIR.width() - smallW); 681dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com const SkScalar dy = SkIntToScalar(innerIR.height() - smallH); 682dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com if (dx < 0 || dy < 0) { 683dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // we're too small, relative to our blur, to break into nine-patch, 684dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com // so we ask to have our normal filterMask() be called. 685dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com return kUnimplemented_FilterReturn; 686dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com } 687dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com 688dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[0].bottom() - dy); 689112a23e0fa027b423a656f0a1aa06868617e982arobertphillips@google.com if (smallR[0].width() < 2 || smallR[0].height() < 2) { 690112a23e0fa027b423a656f0a1aa06868617e982arobertphillips@google.com return kUnimplemented_FilterReturn; 691112a23e0fa027b423a656f0a1aa06868617e982arobertphillips@google.com } 692dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com if (2 == count) { 693dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com smallR[1].set(rects[1].left(), rects[1].top(), 694dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com rects[1].right() - dx, rects[1].bottom() - dy); 695dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com SkASSERT(!smallR[1].isEmpty()); 696d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com } 697d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 6984dca7a829635b552be369186ff508a94aba6a903reed const SkScalar sigma = this->computeXformedSigma(matrix); 699b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed SkCachedData* cache = find_cached_rects(&patch->fMask, sigma, fBlurStyle, 700b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed this->getQuality(), smallR, count); 701b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed if (!cache) { 7024dca7a829635b552be369186ff508a94aba6a903reed if (count > 1 || !c_analyticBlurNinepatch) { 7034dca7a829635b552be369186ff508a94aba6a903reed if (!draw_rects_into_mask(smallR, count, &srcM)) { 7044dca7a829635b552be369186ff508a94aba6a903reed return kFalse_FilterReturn; 7054dca7a829635b552be369186ff508a94aba6a903reed } 7064dca7a829635b552be369186ff508a94aba6a903reed 7074dca7a829635b552be369186ff508a94aba6a903reed SkAutoMaskFreeImage amf(srcM.fImage); 7084dca7a829635b552be369186ff508a94aba6a903reed 7094dca7a829635b552be369186ff508a94aba6a903reed if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { 7104dca7a829635b552be369186ff508a94aba6a903reed return kFalse_FilterReturn; 7114dca7a829635b552be369186ff508a94aba6a903reed } 7124dca7a829635b552be369186ff508a94aba6a903reed } else { 7134dca7a829635b552be369186ff508a94aba6a903reed if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, 7144dca7a829635b552be369186ff508a94aba6a903reed SkMask::kComputeBoundsAndRenderImage_CreateMode)) { 7154dca7a829635b552be369186ff508a94aba6a903reed return kFalse_FilterReturn; 7164dca7a829635b552be369186ff508a94aba6a903reed } 7177c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com } 718b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed cache = add_cached_rects(&patch->fMask, sigma, fBlurStyle, this->getQuality(), smallR, count); 719d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com } 720dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com patch->fMask.fBounds.offsetTo(0, 0); 721dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com patch->fOuterRect = dstM.fBounds; 722dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com patch->fCenter = center; 72396fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(nullptr == patch->fCache); 724b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed patch->fCache = cache; // transfer ownership to patch 725d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com return kTrue_FilterReturn; 726d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com} 727d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com 72830711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.comvoid SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, 72930711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com SkRect* dst) const { 7307ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar pad = 3.0f * fSigma; 73117ad2bd077af50dcaca18cf00607b194a1491a44robertphillips@google.com 73217ad2bd077af50dcaca18cf00607b194a1491a44robertphillips@google.com dst->set(src.fLeft - pad, src.fTop - pad, 73317ad2bd077af50dcaca18cf00607b194a1491a44robertphillips@google.com src.fRight + pad, src.fBottom + pad); 7349efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com} 7359efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com 73660c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkBlurMaskFilterImpl::CreateProc(SkReadBuffer& buffer) { 737a83d0132baa681339e7e7f018dbdcc4051caae3dRobert Phillips const SkScalar sigma = buffer.readScalar(); 738de5c50268c3ff0af507c0a9b47ab58809b89867cMike Reed SkBlurStyle style = buffer.read32LE(kLastEnum_SkBlurStyle); 739de5c50268c3ff0af507c0a9b47ab58809b89867cMike Reed unsigned flags = buffer.read32LE(SkBlurMaskFilter::kAll_BlurFlag); 74027cdd947903a4262bb483e7d35153358f4541bf8robertphillips 74127cdd947903a4262bb483e7d35153358f4541bf8robertphillips SkRect occluder; 74270bc94f273224ed0755ae11dc479c57ff37e0436Mike Reed buffer.readRect(&occluder); 74327cdd947903a4262bb483e7d35153358f4541bf8robertphillips 744a83d0132baa681339e7e7f018dbdcc4051caae3dRobert Phillips return SkBlurMaskFilter::Make((SkBlurStyle)style, sigma, occluder, flags); 7459fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7478b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkBlurMaskFilterImpl::flatten(SkWriteBuffer& buffer) const { 74811e055518a0cbe5329232a55fe2cd177e83836d8robertphillips@google.com buffer.writeScalar(fSigma); 7499fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.writeUInt(fBlurStyle); 750c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com buffer.writeUInt(fBlurFlags); 75127cdd947903a4262bb483e7d35153358f4541bf8robertphillips buffer.writeRect(fOccluder); 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 754f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillips 755491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#if SK_SUPPORT_GPU 7562b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 757d3749485db2de966a80e39669a49192fc7c0bd9dRobert Phillipsbool SkBlurMaskFilterImpl::directFilterMaskGPU(GrContext* context, 7581105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman GrRenderTargetContext* renderTargetContext, 75982f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon GrPaint&& paint, 760570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt const GrClip& clip, 7615531d51ce7426bdae7563547326fcf0bf926a083joshualitt const SkMatrix& viewMatrix, 762cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org const SkStrokeRec& strokeRec, 763cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org const SkPath& path) const { 7641105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman SkASSERT(renderTargetContext); 765ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips 766e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if (fBlurStyle != kNormal_SkBlurStyle) { 767cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org return false; 768cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } 7694c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 77030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips // TODO: we could handle blurred stroked circles 771cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org if (!strokeRec.isFillStyle()) { 772cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org return false; 773cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } 7744c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 775ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); 7764a24cd8ff41a8b3d292d60e4351a631240a7ed75humper 7771afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider(); 778aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon std::unique_ptr<GrFragmentProcessor> fp; 77930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips 78030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkRect rect; 78130c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips if (path.isRect(&rect)) { 7823a0c3696f0ece5e408baf9d1ed14251ba7a223e3robertphillips SkScalar pad = 3.0f * xformedSigma; 7833a0c3696f0ece5e408baf9d1ed14251ba7a223e3robertphillips rect.outset(pad, pad); 78430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips 7851afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips fp = GrRectBlurEffect::Make(proxyProvider, rect, xformedSigma); 78630c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips } else if (path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height())) { 7871afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips fp = GrCircleBlurFragmentProcessor::Make(proxyProvider, rect, xformedSigma); 78830c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips 78930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips // expand the rect for the coverage geometry 79030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips int pad = SkScalarCeilToInt(6*xformedSigma)/2; 79130c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips rect.outset(SkIntToScalar(pad), SkIntToScalar(pad)); 79230c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips } else { 79330c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips return false; 79430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips } 7954c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com 796b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (!fp) { 797cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org return false; 798cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org } 799cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 800c2625821b34d89e8df2ba89cc84db6957189f250joshualitt SkMatrix inverse; 801c2625821b34d89e8df2ba89cc84db6957189f250joshualitt if (!viewMatrix.invert(&inverse)) { 802c2625821b34d89e8df2ba89cc84db6957189f250joshualitt return false; 803c2625821b34d89e8df2ba89cc84db6957189f250joshualitt } 804ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips 80582f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon paint.addCoverageFragmentProcessor(std::move(fp)); 80682f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon renderTargetContext->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), 80782f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon rect, inverse); 808ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips return true; 809cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org} 810cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org 811f5a83e818483ef910ffd107df8f98b5ee24671f5robertphillipsbool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context, 8121105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman GrRenderTargetContext* renderTargetContext, 81382f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon GrPaint&& paint, 814570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt const GrClip& clip, 8155531d51ce7426bdae7563547326fcf0bf926a083joshualitt const SkMatrix& viewMatrix, 816821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org const SkStrokeRec& strokeRec, 81727cdd947903a4262bb483e7d35153358f4541bf8robertphillips const SkRRect& srcRRect, 81827cdd947903a4262bb483e7d35153358f4541bf8robertphillips const SkRRect& devRRect) const { 8191105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman SkASSERT(renderTargetContext); 820ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips 8213d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org if (fBlurStyle != kNormal_SkBlurStyle) { 8223d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org return false; 8233d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org } 8243d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 8253d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org if (!strokeRec.isFillStyle()) { 8263d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org return false; 8273d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org } 8283d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 8291afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider(); 830ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips SkScalar xformedSigma = this->computeXformedSigma(viewMatrix); 831ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips 832242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed if (devRRect.isRect() || SkRRectPriv::IsCircle(devRRect)) { 833aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon std::unique_ptr<GrFragmentProcessor> fp; 8346cfb10600250c5a67f0912694fd16719cf41ed51robertphillips if (devRRect.isRect()) { 8356cfb10600250c5a67f0912694fd16719cf41ed51robertphillips SkScalar pad = 3.0f * xformedSigma; 8366cfb10600250c5a67f0912694fd16719cf41ed51robertphillips const SkRect dstCoverageRect = devRRect.rect().makeOutset(pad, pad); 8376cfb10600250c5a67f0912694fd16719cf41ed51robertphillips 8381afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips fp = GrRectBlurEffect::Make(proxyProvider, dstCoverageRect, xformedSigma); 8396cfb10600250c5a67f0912694fd16719cf41ed51robertphillips } else { 8401afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips fp = GrCircleBlurFragmentProcessor::Make(proxyProvider, 84126c90e04797e15c37ec00e0f836292b8a207d294Robert Phillips devRRect.rect(), xformedSigma); 8426cfb10600250c5a67f0912694fd16719cf41ed51robertphillips } 8436cfb10600250c5a67f0912694fd16719cf41ed51robertphillips 8440dafbde31f4485470471dc9885785e2b9ac4b4carobertphillips if (!fp) { 8450dafbde31f4485470471dc9885785e2b9ac4b4carobertphillips return false; 8460dafbde31f4485470471dc9885785e2b9ac4b4carobertphillips } 84782f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon paint.addCoverageFragmentProcessor(std::move(fp)); 8480dafbde31f4485470471dc9885785e2b9ac4b4carobertphillips 8490dafbde31f4485470471dc9885785e2b9ac4b4carobertphillips SkRect srcProxyRect = srcRRect.rect(); 85059a8b9c12e4b6152f9a5807bd3fd45664de35048Greg Daniel SkScalar outsetX = 3.0f*fSigma; 85159a8b9c12e4b6152f9a5807bd3fd45664de35048Greg Daniel SkScalar outsetY = 3.0f*fSigma; 85259a8b9c12e4b6152f9a5807bd3fd45664de35048Greg Daniel if (this->ignoreXform()) { 85359a8b9c12e4b6152f9a5807bd3fd45664de35048Greg Daniel // When we're ignoring the CTM the padding added to the source rect also needs to ignore 85459a8b9c12e4b6152f9a5807bd3fd45664de35048Greg Daniel // the CTM. The matrix passed in here is guaranteed to be just scale and translate so we 85559a8b9c12e4b6152f9a5807bd3fd45664de35048Greg Daniel // can just grab the X and Y scales off the matrix and pre-undo the scale. 85659a8b9c12e4b6152f9a5807bd3fd45664de35048Greg Daniel outsetX /= viewMatrix.getScaleX(); 85759a8b9c12e4b6152f9a5807bd3fd45664de35048Greg Daniel outsetY /= viewMatrix.getScaleY(); 85859a8b9c12e4b6152f9a5807bd3fd45664de35048Greg Daniel } 85959a8b9c12e4b6152f9a5807bd3fd45664de35048Greg Daniel srcProxyRect.outset(outsetX, outsetY); 8600dafbde31f4485470471dc9885785e2b9ac4b4carobertphillips 86182f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon renderTargetContext->drawRect(clip, std::move(paint), GrAA::kNo, viewMatrix, srcProxyRect); 8620dafbde31f4485470471dc9885785e2b9ac4b4carobertphillips return true; 8630dafbde31f4485470471dc9885785e2b9ac4b4carobertphillips } 8640dafbde31f4485470471dc9885785e2b9ac4b4carobertphillips 865aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon auto fp = GrRRectBlurEffect::Make(context, fSigma, xformedSigma, srcRRect, devRRect); 866287e7cb936f06634cadf1c6d908dc677012c996brobertphillips if (!fp) { 8673d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org return false; 8683d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org } 8693d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org 870287e7cb936f06634cadf1c6d908dc677012c996brobertphillips if (!this->ignoreXform()) { 871287e7cb936f06634cadf1c6d908dc677012c996brobertphillips SkRect srcProxyRect = srcRRect.rect(); 872287e7cb936f06634cadf1c6d908dc677012c996brobertphillips srcProxyRect.outset(3.0f*fSigma, 3.0f*fSigma); 87327cdd947903a4262bb483e7d35153358f4541bf8robertphillips 874e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman sk_sp<SkVertices> vertices = nullptr; 875287e7cb936f06634cadf1c6d908dc677012c996brobertphillips SkRect temp = fOccluder; 87627cdd947903a4262bb483e7d35153358f4541bf8robertphillips 877287e7cb936f06634cadf1c6d908dc677012c996brobertphillips if (!temp.isEmpty() && (srcProxyRect.contains(temp) || temp.intersect(srcProxyRect))) { 878e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman SkVertices::Builder builder(SkVertices::kTriangles_VertexMode, 8, 24, 0); 879e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman srcProxyRect.toQuad(builder.positions()); 880e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman temp.toQuad(builder.positions() + 4); 88127cdd947903a4262bb483e7d35153358f4541bf8robertphillips 882287e7cb936f06634cadf1c6d908dc677012c996brobertphillips static const uint16_t ringI[24] = { 0, 1, 5, 5, 4, 0, 883287e7cb936f06634cadf1c6d908dc677012c996brobertphillips 1, 2, 6, 6, 5, 1, 884287e7cb936f06634cadf1c6d908dc677012c996brobertphillips 2, 3, 7, 7, 6, 2, 885287e7cb936f06634cadf1c6d908dc677012c996brobertphillips 3, 0, 4, 4, 7, 3 }; 886e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman memcpy(builder.indices(), ringI, sizeof(ringI)); 887e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman vertices = builder.detach(); 888287e7cb936f06634cadf1c6d908dc677012c996brobertphillips } else { 889287e7cb936f06634cadf1c6d908dc677012c996brobertphillips // full rect case 890e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman SkVertices::Builder builder(SkVertices::kTriangles_VertexMode, 4, 6, 0); 891e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman srcProxyRect.toQuad(builder.positions()); 892287e7cb936f06634cadf1c6d908dc677012c996brobertphillips 893287e7cb936f06634cadf1c6d908dc677012c996brobertphillips static const uint16_t fullI[6] = { 0, 1, 2, 0, 2, 3 }; 894e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman memcpy(builder.indices(), fullI, sizeof(fullI)); 895e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman vertices = builder.detach(); 896fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein } 897287e7cb936f06634cadf1c6d908dc677012c996brobertphillips 89882f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon paint.addCoverageFragmentProcessor(std::move(fp)); 899e2fc5632346a4544d86814bbab1dfb1d58d93a5eBrian Osman renderTargetContext->drawVertices(clip, std::move(paint), viewMatrix, std::move(vertices)); 900287e7cb936f06634cadf1c6d908dc677012c996brobertphillips } else { 90127cdd947903a4262bb483e7d35153358f4541bf8robertphillips SkMatrix inverse; 90227cdd947903a4262bb483e7d35153358f4541bf8robertphillips if (!viewMatrix.invert(&inverse)) { 90327cdd947903a4262bb483e7d35153358f4541bf8robertphillips return false; 90427cdd947903a4262bb483e7d35153358f4541bf8robertphillips } 90527cdd947903a4262bb483e7d35153358f4541bf8robertphillips 90627cdd947903a4262bb483e7d35153358f4541bf8robertphillips float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f); 90727cdd947903a4262bb483e7d35153358f4541bf8robertphillips SkRect proxyRect = devRRect.rect(); 90827cdd947903a4262bb483e7d35153358f4541bf8robertphillips proxyRect.outset(extra, extra); 90927cdd947903a4262bb483e7d35153358f4541bf8robertphillips 91082f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon paint.addCoverageFragmentProcessor(std::move(fp)); 91182f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon renderTargetContext->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, 91282f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon SkMatrix::I(), proxyRect, inverse); 91327cdd947903a4262bb483e7d35153358f4541bf8robertphillips } 9149aff85a545703af5880e10726dfb40005ea9934erobertphillips 915ff0ca5ed825d9106edc2df6ab3865e1c17c326bfrobertphillips return true; 916821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org} 917821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org 91830c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillipsbool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect, 919491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com const SkIRect& clipBounds, 920491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com const SkMatrix& ctm, 921491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com SkRect* maskRect) const { 9227ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkScalar xformedSigma = this->computeXformedSigma(ctm); 9237ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com if (xformedSigma <= 0) { 924491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com return false; 9252b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com } 926491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 927865606df97b7a52baefd75de624aaa7f912721b6robertphillips // We always do circles and simple circular rrects on the GPU 928242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed if (!SkRRectPriv::IsCircle(devRRect) && !SkRRectPriv::IsSimpleCircular(devRRect)) { 92930c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64); 93030c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32); 931491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 93230c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips if (devRRect.width() <= kMIN_GPU_BLUR_SIZE && 93330c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips devRRect.height() <= kMIN_GPU_BLUR_SIZE && 93430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips xformedSigma <= kMIN_GPU_BLUR_SIGMA) { 93530c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips // We prefer to blur small rects with small radii on the CPU. 93630c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips return false; 93730c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips } 938491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 939491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 94096fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == maskRect) { 941491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // don't need to compute maskRect 942491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com return true; 943491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 944491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 9457ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com float sigma3 = 3 * SkScalarToFloat(xformedSigma); 946491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 9474469938e92d779dff05e745559e67907bbf21e78reed@google.com SkRect clipRect = SkRect::Make(clipBounds); 94830c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkRect srcRect(devRRect.rect()); 949491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 950491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // Outset srcRect and clipRect by 3 * sigma, to compute affected blur area. 9514b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org srcRect.outset(sigma3, sigma3); 9524b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org clipRect.outset(sigma3, sigma3); 953f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips if (!srcRect.intersect(clipRect)) { 954f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips srcRect.setEmpty(); 955f4e5995ac70d4614e0a05b92a8a03e2b7d76bd9crobertphillips } 956491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com *maskRect = srcRect; 9571842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.com return true; 958491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com} 959491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 9604a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillipssk_sp<GrTextureProxy> SkBlurMaskFilterImpl::filterMaskGPU(GrContext* context, 9614a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips sk_sp<GrTextureProxy> srcProxy, 9624a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips const SkMatrix& ctm, 9634a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips const SkIRect& maskRect) const { 964f054b1766b96d270b98efd9afc87835d299d4a4erobertphillips // 'maskRect' isn't snapped to the UL corner but the mask in 'src' is. 965f054b1766b96d270b98efd9afc87835d299d4a4erobertphillips const SkIRect clipRect = SkIRect::MakeWH(maskRect.width(), maskRect.height()); 966491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 967439ff1b9ca2b74a9dc3b04346aa1032c11b142e9commit-bot@chromium.org SkScalar xformedSigma = this->computeXformedSigma(ctm); 9687ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com SkASSERT(xformedSigma > 0); 969491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 970491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // If we're doing a normal blur, we can clobber the pathTexture in the 971491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // gaussianBlur. Otherwise, we need to save it for later compositing. 972e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org bool isNormalBlur = (kNormal_SkBlurStyle == fBlurStyle); 973039a7c70cea29aa40c4fb880b0d6bb523d449568wutao sk_sp<GrRenderTargetContext> renderTargetContext( 974039a7c70cea29aa40c4fb880b0d6bb523d449568wutao SkGpuBlurUtils::GaussianBlur(context, 975039a7c70cea29aa40c4fb880b0d6bb523d449568wutao srcProxy, 976039a7c70cea29aa40c4fb880b0d6bb523d449568wutao nullptr, 977039a7c70cea29aa40c4fb880b0d6bb523d449568wutao clipRect, 978039a7c70cea29aa40c4fb880b0d6bb523d449568wutao SkIRect::EmptyIRect(), 979039a7c70cea29aa40c4fb880b0d6bb523d449568wutao xformedSigma, 980039a7c70cea29aa40c4fb880b0d6bb523d449568wutao xformedSigma, 981039a7c70cea29aa40c4fb880b0d6bb523d449568wutao GrTextureDomain::kIgnore_Mode)); 9821105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman if (!renderTargetContext) { 9834a24da5ceccbbd5eb91c75ce680c42191a5342d0Robert Phillips return nullptr; 984491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 985491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 986491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com if (!isNormalBlur) { 987491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com GrPaint paint; 988491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // Blend pathTexture over blurTexture. 989fbcef6eb8abad142daf45418516550f7635b4a52Robert Phillips paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(std::move(srcProxy), 9902240be96d97b5ac0886381d74a21f1e2a0928f55Brian Osman SkMatrix::I())); 991e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org if (kInner_SkBlurStyle == fBlurStyle) { 992491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // inner: dst = dst * src 993b197b8ff31b73ccb20423023e03592df8ae78ea6egdaniel paint.setCoverageSetOpXPFactory(SkRegion::kIntersect_Op); 994e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org } else if (kSolid_SkBlurStyle == fBlurStyle) { 995491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // solid: dst = src + dst - src * dst 996b197b8ff31b73ccb20423023e03592df8ae78ea6egdaniel // = src + (1 - src) * dst 997b197b8ff31b73ccb20423023e03592df8ae78ea6egdaniel paint.setCoverageSetOpXPFactory(SkRegion::kUnion_Op); 998e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org } else if (kOuter_SkBlurStyle == fBlurStyle) { 999491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // outer: dst = dst * (1 - src) 1000491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com // = 0 * src + (1 - src) * dst 1001b197b8ff31b73ccb20423023e03592df8ae78ea6egdaniel paint.setCoverageSetOpXPFactory(SkRegion::kDifference_Op); 1002c4b72720e75313079212e69e46a5ef7c474b2305egdaniel } else { 1003c4b72720e75313079212e69e46a5ef7c474b2305egdaniel paint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op); 1004491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 1005ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips 100682f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), 10070e8fc8b9e6a138cf4a66b421fb824679df717329Brian Salomon SkRect::Make(clipRect)); 1008491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com } 1009491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 1010f200a90f3e58ce20753420cadced850d7d00dca1Robert Phillips return renderTargetContext->asTextureProxyRef(); 10112b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com} 10122b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 1013491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#endif // SK_SUPPORT_GPU 1014491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 1015491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com 10160f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 10170bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.comvoid SkBlurMaskFilterImpl::toString(SkString* str) const { 10180bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->append("SkBlurMaskFilterImpl: ("); 10190bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com 10207ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com str->append("sigma: "); 10217ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com str->appendScalar(fSigma); 10220bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->append(" "); 10230bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com 1024e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org static const char* gStyleName[kLastEnum_SkBlurStyle + 1] = { 10250bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com "normal", "solid", "outer", "inner" 10260bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com }; 10270bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com 10280bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->appendf("style: %s ", gStyleName[fBlurStyle]); 10290bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->append("flags: ("); 10300bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com if (fBlurFlags) { 10310bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com bool needSeparator = false; 103227cdd947903a4262bb483e7d35153358f4541bf8robertphillips SkAddFlagToString(str, this->ignoreXform(), "IgnoreXform", &needSeparator); 10338eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com SkAddFlagToString(str, 10348eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag), 10350bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com "HighQuality", &needSeparator); 10360bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com } else { 10370bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->append("None"); 10380bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com } 10390bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com str->append("))"); 10400bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com} 10410bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com#endif 10420bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com 1043d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) 1044d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) 1045d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1046