1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurMaskFilter.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlurMask.h"
11736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com#include "SkGpuBlurUtils.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
15a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com#include "SkRRect.h"
167c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com#include "SkRTConf.h"
170bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com#include "SkStringUtils.h"
18491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "SkStrokeRec.h"
19491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
20491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#if SK_SUPPORT_GPU
21491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "GrContext.h"
22491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "GrTexture.h"
23b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrProcessor.h"
24b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h"
2530ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h"
26491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "effects/GrSimpleTextureEffect.h"
27b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h"
28491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "SkGrPixelRef.h"
293d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org#include "SkDraw.h"
30491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#endif
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
32508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.orgSkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) {
33508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.org    return SkBlurMask::ConvertRadiusToSigma(radius);
34508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.org}
35508022cff04c5226cfd1714ba049528f57f9f25ecommit-bot@chromium.org
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkBlurMaskFilterImpl : public SkMaskFilter {
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
38e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, uint32_t flags);
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // overrides from SkMaskFilter
4130711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com    virtual SkMask::Format getFormat() const SK_OVERRIDE;
4203016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
4330711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com                            SkIPoint* margin) const SK_OVERRIDE;
442e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com
45491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#if SK_SUPPORT_GPU
461842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.com    virtual bool canFilterMaskGPU(const SkRect& devBounds,
47491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                  const SkIRect& clipBounds,
48491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                  const SkMatrix& ctm,
49491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                  SkRect* maskRect) const SK_OVERRIDE;
50cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    virtual bool directFilterMaskGPU(GrContext* context,
51cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                     GrPaint* grp,
52cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                     const SkStrokeRec& strokeRec,
53cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                     const SkPath& path) const SK_OVERRIDE;
54821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org    virtual bool directFilterRRectMaskGPU(GrContext* context,
55821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                          GrPaint* grp,
56821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                          const SkStrokeRec& strokeRec,
57821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                          const SkRRect& rrect) const SK_OVERRIDE;
58cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
591842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.com    virtual bool filterMaskGPU(GrTexture* src,
6041bf930039314cc71039b12957195f1c65c30ce1commit-bot@chromium.org                               const SkMatrix& ctm,
611842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.com                               const SkRect& maskRect,
62491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                               GrTexture** result,
6341bf930039314cc71039b12957195f1c65c30ce1commit-bot@chromium.org                               bool canOverwriteSrc) const SK_OVERRIDE;
64491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#endif
65491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
6630711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com    virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE;
67daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    virtual bool asABlur(BlurRec*) const SK_OVERRIDE;
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
690f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org    SK_TO_STRING_OVERRIDE()
70ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl)
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
72d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comprotected:
73dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMatrix&,
74dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                                           const SkIRect& clipBounds,
7530711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com                                           NinePatch*) const SK_OVERRIDE;
762e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com
77a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&,
78a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com                                           const SkIRect& clipBounds,
79a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com                                           NinePatch*) const SK_OVERRIDE;
80a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
812e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com    bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix,
827c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com                        SkIPoint* margin, SkMask::CreateMode createMode) const;
83a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org    bool filterRRectMask(SkMask* dstM, const SkRRect& r, const SkMatrix& matrix,
84a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org                        SkIPoint* margin, SkMask::CreateMode createMode) const;
85453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
87491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    // To avoid unseemly allocation requests (esp. for finite platforms like
88491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    // handset) we limit the radius so something manageable. (as opposed to
89491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    // a request like 10,000)
907ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    static const SkScalar kMAX_BLUR_SIGMA;
917ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com
92e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    SkScalar    fSigma;
93e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    SkBlurStyle fBlurStyle;
94e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    uint32_t    fBlurFlags;
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
96daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    SkBlurQuality getQuality() const {
97daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        return (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
98daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com                kHigh_SkBlurQuality : kLow_SkBlurQuality;
99daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
100daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com
1018b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkBlurMaskFilterImpl(SkReadBuffer&);
1028b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
1037ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com
1047ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    SkScalar computeXformedSigma(const SkMatrix& ctm) const {
105491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        bool ignoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
106491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
1077ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com        SkScalar xformedSigma = ignoreTransform ? fSigma : ctm.mapRadius(fSigma);
1087ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com        return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA);
109491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    }
110fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1119fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    friend class SkBlurMaskFilter;
1129fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkMaskFilter INHERITED;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1167ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.comconst SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128);
117491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
118e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.orgSkMaskFilter* SkBlurMaskFilter::Create(SkBlurStyle style, SkScalar sigma, uint32_t flags) {
119e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    if (!SkScalarIsFinite(sigma) || sigma <= 0) {
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
12103016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com    }
122e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    if ((unsigned)style > (unsigned)kLastEnum_SkBlurStyle) {
123e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org        return NULL;
124e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    }
125e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    if (flags > SkBlurMaskFilter::kAll_BlurFlag) {
126e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org        return NULL;
127e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    }
128e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    return SkNEW_ARGS(SkBlurMaskFilterImpl, (sigma, style, flags));
129e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org}
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13103016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.com///////////////////////////////////////////////////////////////////////////////
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
133e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.orgSkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle style, uint32_t flags)
134e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    : fSigma(sigma)
135e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    , fBlurStyle(style)
136e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    , fBlurFlags(flags) {
137e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    SkASSERT(fSigma > 0);
138e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    SkASSERT((unsigned)style <= kLastEnum_SkBlurStyle);
139038aff623d9fd47946cd31685f74cf473f7c84f0senorblanco@chromium.org    SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14230711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.comSkMask::Format SkBlurMaskFilterImpl::getFormat() const {
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkMask::kA8_Format;
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
146daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.combool SkBlurMaskFilterImpl::asABlur(BlurRec* rec) const {
147daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
148daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        return false;
149daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
150daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com
151daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    if (rec) {
152daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        rec->fSigma = fSigma;
153daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        rec->fStyle = fBlurStyle;
154daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com        rec->fQuality = this->getQuality();
155daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    }
156daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    return true;
157daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com}
158daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com
15903016a36206be42e91e8e0eb62fe8fb95da97b38reed@google.combool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
16030711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com                                      const SkMatrix& matrix,
16130711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com                                      SkIPoint* margin) const{
1627ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    SkScalar sigma = this->computeXformedSigma(matrix);
163daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    return SkBlurMask::BoxBlur(dst, src, sigma, fBlurStyle, this->getQuality(), margin);
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1667c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.combool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r,
1677c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com                                          const SkMatrix& matrix,
1687c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com                                          SkIPoint* margin, SkMask::CreateMode createMode) const{
1697ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    SkScalar sigma = computeXformedSigma(matrix);
1707c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com
171e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    return SkBlurMask::BlurRect(sigma, dst, r, fBlurStyle,
1727c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com                                margin, createMode);
1737c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com}
1747c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com
175a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.orgbool SkBlurMaskFilterImpl::filterRRectMask(SkMask* dst, const SkRRect& r,
176a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org                                          const SkMatrix& matrix,
177a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org                                          SkIPoint* margin, SkMask::CreateMode createMode) const{
178a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org    SkScalar sigma = computeXformedSigma(matrix);
179a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org
180e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    return SkBlurMask::BlurRRect(sigma, dst, r, fBlurStyle,
181a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org                                margin, createMode);
182a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org}
183a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org
184d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com#include "SkCanvas.h"
185d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
186a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comstatic bool prepare_to_draw_into_mask(const SkRect& bounds, SkMask* mask) {
187a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkASSERT(mask != NULL);
188a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
189a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    bounds.roundOut(&mask->fBounds);
190d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    mask->fRowBytes = SkAlign4(mask->fBounds.width());
191d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    mask->fFormat = SkMask::kA8_Format;
192a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const size_t size = mask->computeImageSize();
193d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    mask->fImage = SkMask::AllocImage(size);
194d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (NULL == mask->fImage) {
195d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        return false;
196d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
197a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
198a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // FIXME: use sk_calloc in AllocImage?
199d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    sk_bzero(mask->fImage, size);
200a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    return true;
201a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com}
202a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
203a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comstatic bool draw_rrect_into_mask(const SkRRect rrect, SkMask* mask) {
204a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    if (!prepare_to_draw_into_mask(rrect.rect(), mask)) {
205a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        return false;
206a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
207a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
208a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // FIXME: This code duplicates code in draw_rects_into_mask, below. Is there a
209a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // clean way to share more code?
210a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkBitmap bitmap;
211dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org    bitmap.installMaskPixels(*mask);
212a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
213a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkCanvas canvas(bitmap);
214a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    canvas.translate(-SkIntToScalar(mask->fBounds.left()),
215a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com                     -SkIntToScalar(mask->fBounds.top()));
216a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
217a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkPaint paint;
218a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    paint.setAntiAlias(true);
219a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    canvas.drawRRect(rrect, paint);
220a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    return true;
221a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com}
222a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
223a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comstatic bool draw_rects_into_mask(const SkRect rects[], int count, SkMask* mask) {
224a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    if (!prepare_to_draw_into_mask(rects[0], mask)) {
225a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        return false;
226a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
227d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
228d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkBitmap bitmap;
229e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org    bitmap.installPixels(SkImageInfo::Make(mask->fBounds.width(),
230e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org                                           mask->fBounds.height(),
231e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org                                           kAlpha_8_SkColorType,
232e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org                                           kPremul_SkAlphaType),
23300f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org                         mask->fImage, mask->fRowBytes);
234d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
235d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkCanvas canvas(bitmap);
236dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    canvas.translate(-SkIntToScalar(mask->fBounds.left()),
237dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                     -SkIntToScalar(mask->fBounds.top()));
238d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
239d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkPaint paint;
240d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    paint.setAntiAlias(true);
241d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
242dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    if (1 == count) {
243dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        canvas.drawRect(rects[0], paint);
244dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    } else {
245dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        // todo: do I need a fast way to do this?
246dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        SkPath path;
247dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        path.addRect(rects[0]);
248dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        path.addRect(rects[1]);
249dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        path.setFillType(SkPath::kEvenOdd_FillType);
250dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        canvas.drawPath(path, paint);
251dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    }
252d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    return true;
253d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
254d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
255f276fa74f56d0c691716163d3149fce5de97c9eareed@google.comstatic bool rect_exceeds(const SkRect& r, SkScalar v) {
256f276fa74f56d0c691716163d3149fce5de97c9eareed@google.com    return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v ||
257f276fa74f56d0c691716163d3149fce5de97c9eareed@google.com           r.width() > v || r.height() > v;
25807784a041925f9a921e390e782195a622c76fbfareed@google.com}
25907784a041925f9a921e390e782195a622c76fbfareed@google.com
260a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org#ifdef SK_IGNORE_FAST_RRECT_BLUR
2613d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgSK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", false, "Use the faster analytic blur approach for ninepatch rects" );
262a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org#else
2633d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgSK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", true, "Use the faster analytic blur approach for ninepatch round rects" );
264a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org#endif
265a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org
266a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comSkMaskFilter::FilterReturn
267a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comSkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& matrix,
268a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com                                        const SkIRect& clipBounds,
269a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com                                        NinePatch* patch) const {
270a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkASSERT(patch != NULL);
271a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    switch (rrect.getType()) {
272a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        case SkRRect::kUnknown_Type:
273a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            // Unknown should never be returned.
274a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            SkASSERT(false);
275a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            // Fall through.
276a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        case SkRRect::kEmpty_Type:
277a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            // Nothing to draw.
278a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            return kFalse_FilterReturn;
279a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
280a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        case SkRRect::kRect_Type:
281a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            // We should have caught this earlier.
282a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            SkASSERT(false);
283a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            // Fall through.
284a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        case SkRRect::kOval_Type:
285a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            // The nine patch special case does not handle ovals, and we
286a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            // already have code for rectangles.
287a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            return kUnimplemented_FilterReturn;
288a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
289f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org        // These three can take advantage of this fast path.
290a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        case SkRRect::kSimple_Type:
291f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org        case SkRRect::kNinePatch_Type:
292a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        case SkRRect::kComplex_Type:
293a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com            break;
294a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
295a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
296a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // TODO: report correct metrics for innerstyle, where we do not grow the
297a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // total bounds, but we do need an inset the size of our blur-radius
298e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    if (kInner_SkBlurStyle == fBlurStyle) {
299a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        return kUnimplemented_FilterReturn;
300a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
301a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
302a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // TODO: take clipBounds into account to limit our coordinates up front
303a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // for now, just skip too-large src rects (to take the old code path).
304a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    if (rect_exceeds(rrect.rect(), SkIntToScalar(32767))) {
305a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        return kUnimplemented_FilterReturn;
306a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
307a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
308a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkIPoint margin;
309a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkMask  srcM, dstM;
310a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    rrect.rect().roundOut(&srcM.fBounds);
311a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    srcM.fImage = NULL;
312a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    srcM.fFormat = SkMask::kA8_Format;
313a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    srcM.fRowBytes = 0;
314a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
315a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org    bool filterResult = false;
316a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org    if (c_analyticBlurRRect) {
317a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org        // special case for fast round rect blur
318a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org        // don't actually do the blur the first time, just compute the correct size
319a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org        filterResult = this->filterRRectMask(&dstM, rrect, matrix, &margin,
320a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org                                            SkMask::kJustComputeBounds_CreateMode);
321a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org    }
322a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org
323a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org    if (!filterResult) {
324a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org        filterResult = this->filterMask(&dstM, srcM, matrix, &margin);
325a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org    }
326a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org
327a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org    if (!filterResult) {
328a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        return kFalse_FilterReturn;
329a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
330a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
331a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // Now figure out the appropriate width and height of the smaller round rectangle
332a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // to stretch. It will take into account the larger radius per side as well as double
333a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // the margin, to account for inner and outer blur.
334a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const SkVector& UL = rrect.radii(SkRRect::kUpperLeft_Corner);
335a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const SkVector& UR = rrect.radii(SkRRect::kUpperRight_Corner);
336a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const SkVector& LR = rrect.radii(SkRRect::kLowerRight_Corner);
337a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const SkVector& LL = rrect.radii(SkRRect::kLowerLeft_Corner);
338a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
339a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const SkScalar leftUnstretched = SkTMax(UL.fX, LL.fX) + SkIntToScalar(2 * margin.fX);
340a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const SkScalar rightUnstretched = SkTMax(UR.fX, LR.fX) + SkIntToScalar(2 * margin.fX);
341a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
342a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // Extra space in the middle to ensure an unchanging piece for stretching. Use 3 to cover
343a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // any fractional space on either side plus 1 for the part to stretch.
344a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const SkScalar stretchSize = SkIntToScalar(3);
345a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
346a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const SkScalar totalSmallWidth = leftUnstretched + rightUnstretched + stretchSize;
347a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    if (totalSmallWidth >= rrect.rect().width()) {
348a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        // There is no valid piece to stretch.
349a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        return kUnimplemented_FilterReturn;
350a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
351a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
352a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const SkScalar topUnstretched = SkTMax(UL.fY, UR.fY) + SkIntToScalar(2 * margin.fY);
353a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const SkScalar bottomUnstretched = SkTMax(LL.fY, LR.fY) + SkIntToScalar(2 * margin.fY);
354a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
355a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    const SkScalar totalSmallHeight = topUnstretched + bottomUnstretched + stretchSize;
356a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    if (totalSmallHeight >= rrect.rect().height()) {
357a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        // There is no valid piece to stretch.
358a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        return kUnimplemented_FilterReturn;
359a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
360a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
361a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight);
362a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
363a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkRRect smallRR;
364a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkVector radii[4];
365a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    radii[SkRRect::kUpperLeft_Corner] = UL;
366a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    radii[SkRRect::kUpperRight_Corner] = UR;
367a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    radii[SkRRect::kLowerRight_Corner] = LR;
368a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    radii[SkRRect::kLowerLeft_Corner] = LL;
369a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    smallRR.setRectRadii(smallR, radii);
370a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
371a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org    bool analyticBlurWorked = false;
372a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org    if (c_analyticBlurRRect) {
373a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org        analyticBlurWorked =
374a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org            this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin,
375a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org                                  SkMask::kComputeBoundsAndRenderImage_CreateMode);
376a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
377a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
378a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org    if (!analyticBlurWorked) {
379a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org        if (!draw_rrect_into_mask(smallRR, &srcM)) {
380a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org            return kFalse_FilterReturn;
381a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org        }
382ad99358bdd7ca4ffb047121946abf0d5fdbde1e8robertphillips@google.com
383a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org        SkAutoMaskFreeImage amf(srcM.fImage);
384a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org
385a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org        if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) {
386a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org            return kFalse_FilterReturn;
387a477154cfce6276277f4eacc20908a6c986c112ccommit-bot@chromium.org        }
388a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
389a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
390a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    patch->fMask.fBounds.offsetTo(0, 0);
391a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    patch->fOuterRect = dstM.fBounds;
392a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1;
393a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1;
394a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    return kTrue_FilterReturn;
395a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com}
396a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
397e86af1f4bacd4a9aa99a09905e29b3cf4cea9322humper@google.comSK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects" );
3987c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com
399d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comSkMaskFilter::FilterReturn
400dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.comSkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
401dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                                        const SkMatrix& matrix,
402dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                                        const SkIRect& clipBounds,
40330711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com                                        NinePatch* patch) const {
404dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    if (count < 1 || count > 2) {
405dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        return kUnimplemented_FilterReturn;
406dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    }
4073458716b52aa25dcd1b270141c7628c380696e35skia.committer@gmail.com
40857850b9daddd941f880d94faaf83f2169355a0c8reed@google.com    // TODO: report correct metrics for innerstyle, where we do not grow the
40957850b9daddd941f880d94faaf83f2169355a0c8reed@google.com    // total bounds, but we do need an inset the size of our blur-radius
410e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    if (kInner_SkBlurStyle == fBlurStyle || kOuter_SkBlurStyle == fBlurStyle) {
41157850b9daddd941f880d94faaf83f2169355a0c8reed@google.com        return kUnimplemented_FilterReturn;
41257850b9daddd941f880d94faaf83f2169355a0c8reed@google.com    }
41357850b9daddd941f880d94faaf83f2169355a0c8reed@google.com
41407784a041925f9a921e390e782195a622c76fbfareed@google.com    // TODO: take clipBounds into account to limit our coordinates up front
41507784a041925f9a921e390e782195a622c76fbfareed@google.com    // for now, just skip too-large src rects (to take the old code path).
416f276fa74f56d0c691716163d3149fce5de97c9eareed@google.com    if (rect_exceeds(rects[0], SkIntToScalar(32767))) {
41707784a041925f9a921e390e782195a622c76fbfareed@google.com        return kUnimplemented_FilterReturn;
41807784a041925f9a921e390e782195a622c76fbfareed@google.com    }
4193458716b52aa25dcd1b270141c7628c380696e35skia.committer@gmail.com
420d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkIPoint margin;
421d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkMask  srcM, dstM;
422dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    rects[0].roundOut(&srcM.fBounds);
423d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    srcM.fImage = NULL;
424d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    srcM.fFormat = SkMask::kA8_Format;
425d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    srcM.fRowBytes = 0;
4262e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com
4277c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com    bool filterResult = false;
4287c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com    if (count == 1 && c_analyticBlurNinepatch) {
4297c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com        // special case for fast rect blur
4307c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com        // don't actually do the blur the first time, just compute the correct size
4312e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com        filterResult = this->filterRectMask(&dstM, rects[0], matrix, &margin,
4327c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com                                            SkMask::kJustComputeBounds_CreateMode);
4337c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com    } else {
4347c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com        filterResult = this->filterMask(&dstM, srcM, matrix, &margin);
4357c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com    }
4362e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com
4377c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com    if (!filterResult) {
438d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        return kFalse_FilterReturn;
439d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
440d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
441d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    /*
442d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *  smallR is the smallest version of 'rect' that will still guarantee that
443d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *  we get the same blur results on all edges, plus 1 center row/col that is
444d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *  representative of the extendible/stretchable edges of the ninepatch.
445d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *  Since our actual edge may be fractional we inset 1 more to be sure we
446d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *  don't miss any interior blur.
447d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *  x is an added pixel of blur, and { and } are the (fractional) edge
448d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *  pixels from the original rect.
449d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *
450d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *   x x { x x .... x x } x x
451d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *
452d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *  Thus, in this case, we inset by a total of 5 (on each side) beginning
453d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     *  with our outer-rect (dstM.fBounds)
454d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com     */
455dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    SkRect smallR[2];
456dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    SkIPoint center;
457dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
458dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    // +2 is from +1 for each edge (to account for possible fractional edges
459dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    int smallW = dstM.fBounds.width() - srcM.fBounds.width() + 2;
460dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    int smallH = dstM.fBounds.height() - srcM.fBounds.height() + 2;
461dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    SkIRect innerIR;
462dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
463dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    if (1 == count) {
464dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        innerIR = srcM.fBounds;
465dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        center.set(smallW, smallH);
466dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    } else {
467dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        SkASSERT(2 == count);
468dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        rects[1].roundIn(&innerIR);
469dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        center.set(smallW + (innerIR.left() - srcM.fBounds.left()),
470dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                   smallH + (innerIR.top() - srcM.fBounds.top()));
471dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    }
472dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
473dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    // +1 so we get a clean, stretchable, center row/col
474dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    smallW += 1;
475dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    smallH += 1;
476dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
477dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    // we want the inset amounts to be integral, so we don't change any
478dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    // fractional phase on the fRight or fBottom of our smallR.
479dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    const SkScalar dx = SkIntToScalar(innerIR.width() - smallW);
480dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    const SkScalar dy = SkIntToScalar(innerIR.height() - smallH);
481dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    if (dx < 0 || dy < 0) {
482dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        // we're too small, relative to our blur, to break into nine-patch,
483dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        // so we ask to have our normal filterMask() be called.
484dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        return kUnimplemented_FilterReturn;
485dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    }
486dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
487dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[0].bottom() - dy);
488112a23e0fa027b423a656f0a1aa06868617e982arobertphillips@google.com    if (smallR[0].width() < 2 || smallR[0].height() < 2) {
489112a23e0fa027b423a656f0a1aa06868617e982arobertphillips@google.com        return kUnimplemented_FilterReturn;
490112a23e0fa027b423a656f0a1aa06868617e982arobertphillips@google.com    }
491dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    if (2 == count) {
492dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        smallR[1].set(rects[1].left(), rects[1].top(),
493dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                      rects[1].right() - dx, rects[1].bottom() - dy);
494dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        SkASSERT(!smallR[1].isEmpty());
495d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
496d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
4977c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com    if (count > 1 || !c_analyticBlurNinepatch) {
498a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        if (!draw_rects_into_mask(smallR, count, &srcM)) {
4997c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com            return kFalse_FilterReturn;
5007c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com        }
501d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
5027c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com        SkAutoMaskFreeImage amf(srcM.fImage);
503d198a5b8a706d2bcfa94e351d3a41f5379777e4areed@google.com
5047c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com        if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) {
5057c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com            return kFalse_FilterReturn;
5067c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com        }
5077c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com    } else {
5082e71f1619d9a2c51c1292e618f42a56ad2da1de8skia.committer@gmail.com        if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin,
5097c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com                                  SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
5107c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com            return kFalse_FilterReturn;
5117c5d7b781385c47e5be9a343d60c5b7d33b5b8cdhumper@google.com        }
512d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
513dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    patch->fMask.fBounds.offsetTo(0, 0);
514dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    patch->fOuterRect = dstM.fBounds;
515dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    patch->fCenter = center;
516d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    return kTrue_FilterReturn;
517d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
518d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
51930711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.comvoid SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src,
52030711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com                                             SkRect* dst) const {
5217ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    SkScalar pad = 3.0f * fSigma;
52217ad2bd077af50dcaca18cf00607b194a1491a44robertphillips@google.com
52317ad2bd077af50dcaca18cf00607b194a1491a44robertphillips@google.com    dst->set(src.fLeft  - pad, src.fTop    - pad,
52417ad2bd077af50dcaca18cf00607b194a1491a44robertphillips@google.com             src.fRight + pad, src.fBottom + pad);
5259efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com}
5269efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
5279fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
5289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkReadBuffer& buffer) : SkMaskFilter(buffer) {
529fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    fSigma = buffer.readScalar();
530e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    fBlurStyle = (SkBlurStyle)buffer.readInt();
531c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag;
532e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    SkASSERT(fSigma > 0);
533e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    SkASSERT((unsigned)fBlurStyle <= kLastEnum_SkBlurStyle);
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5359fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
5369fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
5379fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkBlurMaskFilterImpl::CreateProc(SkReadBuffer& buffer) {
5389fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const SkScalar sigma = buffer.readScalar();
5399fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const unsigned style = buffer.readUInt();
5409fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const unsigned flags = buffer.readUInt();
5419fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (style <= kLastEnum_SkBlurStyle) {
5429fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return SkBlurMaskFilter::Create((SkBlurStyle)style, sigma, flags);
5439fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
5449fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return NULL;
5459fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5478b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkBlurMaskFilterImpl::flatten(SkWriteBuffer& buffer) const {
54811e055518a0cbe5329232a55fe2cd177e83836d8robertphillips@google.com    buffer.writeScalar(fSigma);
5499fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.writeUInt(fBlurStyle);
550c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    buffer.writeUInt(fBlurFlags);
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
553491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#if SK_SUPPORT_GPU
5542b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com
555cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgclass GrGLRectBlurEffect;
556cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
557b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrRectBlurEffect : public GrFragmentProcessor {
558cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgpublic:
559cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    virtual ~GrRectBlurEffect();
560cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
561cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    static const char* Name() { return "RectBlur"; }
562cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
563b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLRectBlurEffect GLProcessor;
564cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
565b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
566cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
567cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
568cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    /**
569cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org     * Create a simple filter effect with custom bicubic coefficients.
570cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org     */
571b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static GrFragmentProcessor* Create(GrContext *context, const SkRect& rect, float sigma) {
5724a24cd8ff41a8b3d292d60e4351a631240a7ed75humper        GrTexture *blurProfileTexture = NULL;
5734a24cd8ff41a8b3d292d60e4351a631240a7ed75humper        int doubleProfileSize = SkScalarCeilToInt(12*sigma);
5744a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
5754a24cd8ff41a8b3d292d60e4351a631240a7ed75humper        if (doubleProfileSize >= rect.width() || doubleProfileSize >= rect.height()) {
5764a24cd8ff41a8b3d292d60e4351a631240a7ed75humper            // if the blur sigma is too large so the gaussian overlaps the whole
5774a24cd8ff41a8b3d292d60e4351a631240a7ed75humper            // rect in either direction, fall back to CPU path for now.
5784a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
579cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org            return NULL;
580cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org        }
5814a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
5824a24cd8ff41a8b3d292d60e4351a631240a7ed75humper        bool createdBlurProfileTexture = CreateBlurProfileTexture(context, sigma, &blurProfileTexture);
5834a24cd8ff41a8b3d292d60e4351a631240a7ed75humper        SkAutoTUnref<GrTexture> hunref(blurProfileTexture);
5844a24cd8ff41a8b3d292d60e4351a631240a7ed75humper        if (!createdBlurProfileTexture) {
5854a24cd8ff41a8b3d292d60e4351a631240a7ed75humper           return NULL;
5864a24cd8ff41a8b3d292d60e4351a631240a7ed75humper        }
58755fad7af61c21d502acb9891d631e8aa29e3628cbsalomon        return SkNEW_ARGS(GrRectBlurEffect, (rect, sigma, blurProfileTexture));
588cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    }
5894c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
5904a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    const SkRect& getRect() const { return fRect; }
591cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    float getSigma() const { return fSigma; }
592cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
593cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgprivate:
5944a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blur_profile);
595b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
5964c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
5974a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    static bool CreateBlurProfileTexture(GrContext *context, float sigma,
5984a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                       GrTexture **blurProfileTexture);
5994c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
6004a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    SkRect          fRect;
6014a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    float           fSigma;
6024a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    GrTextureAccess fBlurProfileAccess;
603cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
604b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
605cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
606b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrFragmentProcessor INHERITED;
607cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org};
608cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
609b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrGLRectBlurEffect : public GrGLFragmentProcessor {
610cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgpublic:
611b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrGLRectBlurEffect(const GrBackendProcessorFactory& factory,
612b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                       const GrProcessor&);
61330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitCode(GrGLProgramBuilder*,
614b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                          const GrFragmentProcessor&,
615b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                          const GrProcessorKey&,
616cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                          const char* outputColor,
617cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                          const char* inputColor,
618cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                          const TransformedCoordsArray&,
619cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                          const TextureSamplerArray&) SK_OVERRIDE;
620cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
621b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
622cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
623cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgprivate:
6247510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    typedef GrGLProgramDataManager::UniformHandle UniformHandle;
625cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
6264a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    UniformHandle       fProxyRectUniform;
6274a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    UniformHandle       fProfileSizeUniform;
628cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
629b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLFragmentProcessor INHERITED;
630cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org};
631cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
6324a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
6334a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
634b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGLRectBlurEffect::GrGLRectBlurEffect(const GrBackendProcessorFactory& factory, const GrProcessor&)
635cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    : INHERITED(factory) {
636cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
637cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
63830ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid OutputRectBlurProfileLookup(GrGLFragmentShaderBuilder* fsBuilder,
6394a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                 const GrGLShaderBuilder::TextureSampler& sampler,
6404a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                 const char *output,
6414a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                 const char *profileSize, const char *loc,
6424a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                 const char *blurred_width,
6434a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                 const char *sharp_width) {
64430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\tfloat %s;\n", output);
64530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t{\n");
64630ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t\tfloat coord = (0.5 * (abs(2.0*%s - %s) - %s))/%s;\n",
6474a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                           loc, blurred_width, sharp_width, profileSize);
64830ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t\t%s = ", output);
64930ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->appendTextureLookup(sampler, "vec2(coord,0.5)");
65030ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppend(".a;\n");
65130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t}\n");
6524a24cd8ff41a8b3d292d60e4351a631240a7ed75humper}
6534a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
65430ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLRectBlurEffect::emitCode(GrGLProgramBuilder* builder,
655b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                 const GrFragmentProcessor&,
656b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                 const GrProcessorKey& key,
657cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                 const char* outputColor,
658cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                 const char* inputColor,
659cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                 const TransformedCoordsArray& coords,
660cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                 const TextureSamplerArray& samplers) {
6614c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
6624a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    const char *rectName;
6634a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    const char *profileSizeName;
6644a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
66530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fProxyRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
6664a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                            kVec4f_GrSLType,
6674a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                            "proxyRect",
6684a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                            &rectName);
66930ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fProfileSizeUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
6704a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                            kFloat_GrSLType,
6714a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                            "profileSize",
6724a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                            &profileSizeName);
6734a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
67430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
67530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    const char *fragmentPos = fsBuilder->fragmentPosition();
6764c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
677cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    if (inputColor) {
67830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tvec4 src=%s;\n", inputColor);
679cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    } else {
68030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\tvec4 src=vec4(1)\n;");
681cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    }
6824c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
68330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\tvec2 translatedPos = %s.xy - %s.xy;\n", fragmentPos, rectName );
68430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\tfloat width = %s.z - %s.x;\n", rectName, rectName);
68530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\tfloat height = %s.w - %s.y;\n", rectName, rectName);
6864c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
68730ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\tvec2 smallDims = vec2(width - %s, height-%s);\n", profileSizeName, profileSizeName);
68830ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\tfloat center = 2.0 * floor(%s/2.0 + .25) - 1.0;\n", profileSizeName);
68930ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\tvec2 wh = smallDims - vec2(center,center);\n");
6904a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
69130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    OutputRectBlurProfileLookup(fsBuilder, samplers[0], "horiz_lookup", profileSizeName, "translatedPos.x", "width", "wh.x");
69230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    OutputRectBlurProfileLookup(fsBuilder, samplers[0], "vert_lookup", profileSizeName, "translatedPos.y", "height", "wh.y");
6934a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
69430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\tfloat final = horiz_lookup * vert_lookup;\n");
69530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t%s = src * vec4(final);\n", outputColor );
696cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
697cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
6987510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLRectBlurEffect::setData(const GrGLProgramDataManager& pdman,
699b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                 const GrProcessor& proc) {
700b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrRectBlurEffect& rbe = proc.cast<GrRectBlurEffect>();
7014a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    SkRect rect = rbe.getRect();
7024a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
7037510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
7047510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fProfileSizeUniform, SkScalarCeilToScalar(6*rbe.getSigma()));
705cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
706cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
7074a24cd8ff41a8b3d292d60e4351a631240a7ed75humperbool GrRectBlurEffect::CreateBlurProfileTexture(GrContext *context, float sigma,
7084a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                              GrTexture **blurProfileTexture) {
709cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    GrTextureParams params;
710cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    GrTextureDesc texDesc;
7114c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
7124a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    unsigned int profile_size = SkScalarCeilToInt(6*sigma);
7134c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
7144a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    texDesc.fWidth = profile_size;
715cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    texDesc.fHeight = 1;
716cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    texDesc.fConfig = kAlpha_8_GrPixelConfig;
7174c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
718cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomain();
719cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    GrCacheID::Key key;
720cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    memset(&key, 0, sizeof(key));
721cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    key.fData32[0] = profile_size;
7224a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    key.fData32[1] = 1;
7234a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    GrCacheID blurProfileKey(gBlurProfileDomain, key);
7244c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
725cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    uint8_t *profile = NULL;
726cc787fa8029889877da8edbb70a284cb0e19de33commit-bot@chromium.org    SkAutoTDeleteArray<uint8_t> ada(NULL);
7274c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
7284a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    *blurProfileTexture = context->findAndRefTexture(texDesc, blurProfileKey, &params);
7294c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
7304a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    if (NULL == *blurProfileTexture) {
7314c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
732cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org        SkBlurMask::ComputeBlurProfile(sigma, &profile);
733cc787fa8029889877da8edbb70a284cb0e19de33commit-bot@chromium.org        ada.reset(profile);
7344c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
7354a24cd8ff41a8b3d292d60e4351a631240a7ed75humper        *blurProfileTexture = context->createTexture(&params, texDesc, blurProfileKey,
7364a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                                     profile, 0);
737e07c1ab40882078b505f2b0ceb7413c44af569e8scroggo
7384a24cd8ff41a8b3d292d60e4351a631240a7ed75humper        if (NULL == *blurProfileTexture) {
739cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org            return false;
740cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org        }
741cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    }
7424c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
743cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    return true;
744cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
745cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
746cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgGrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma,
7474a24cd8ff41a8b3d292d60e4351a631240a7ed75humper                                   GrTexture *blur_profile)
7484c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com  : INHERITED(),
7494a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    fRect(rect),
750cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    fSigma(sigma),
7514a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    fBlurProfileAccess(blur_profile) {
7524a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    this->addTextureAccess(&fBlurProfileAccess);
7534a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    this->setWillReadFragmentPosition();
754cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
755cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
756cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgGrRectBlurEffect::~GrRectBlurEffect() {
757cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
758cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
759b0a8a377f832c59cee939ad721e1f87d378b7142joshualittconst GrBackendFragmentProcessorFactory& GrRectBlurEffect::getFactory() const {
760b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    return GrTBackendFragmentProcessorFactory<GrRectBlurEffect>::getInstance();
761cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
762cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
763b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool GrRectBlurEffect::onIsEqual(const GrProcessor& sBase) const {
76449586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrRectBlurEffect& s = sBase.cast<GrRectBlurEffect>();
7654a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    return this->getSigma() == s.getSigma() && this->getRect() == s.getRect();
766cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
767cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
768cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgvoid GrRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
769cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    *validFlags = 0;
770cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    return;
771cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
772cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
773b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRectBlurEffect);
774cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
775b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrRectBlurEffect::TestCreate(SkRandom* random,
776b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                  GrContext* context,
777b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                  const GrDrawTargetCaps&,
778b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                  GrTexture**) {
779cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    float sigma = random->nextRangeF(3,8);
780cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    float width = random->nextRangeF(200,300);
781cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    float height = random->nextRangeF(200,300);
782cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    return GrRectBlurEffect::Create(context, SkRect::MakeWH(width, height), sigma);
783cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
784cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
785cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
786cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.orgbool SkBlurMaskFilterImpl::directFilterMaskGPU(GrContext* context,
787cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                               GrPaint* grp,
788cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                               const SkStrokeRec& strokeRec,
789cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                               const SkPath& path) const {
790e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    if (fBlurStyle != kNormal_SkBlurStyle) {
791cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org        return false;
792cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    }
7934c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
794cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    SkRect rect;
795cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    if (!path.isRect(&rect)) {
796cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org        return false;
797cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    }
7984c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
799cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    if (!strokeRec.isFillStyle()) {
800cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org        return false;
801cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    }
8024c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
803cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    SkMatrix ctm = context->getMatrix();
804cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    SkScalar xformedSigma = this->computeXformedSigma(ctm);
8054a24cd8ff41a8b3d292d60e4351a631240a7ed75humper
8064a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    int pad=SkScalarCeilToInt(6*xformedSigma)/2;
8074a24cd8ff41a8b3d292d60e4351a631240a7ed75humper    rect.outset(SkIntToScalar(pad), SkIntToScalar(pad));
8084c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
809b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    SkAutoTUnref<GrFragmentProcessor> fp(GrRectBlurEffect::Create(context, rect, xformedSigma));
810b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    if (!fp) {
811cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org        return false;
812cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    }
813cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
814cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    GrContext::AutoMatrix am;
815cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    if (!am.setIdentity(context, grp)) {
816cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org       return false;
817cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    }
818cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
819b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    grp->addCoverageProcessor(fp);
8204c18e9fbb685cccf23342757e786027a032197daskia.committer@gmail.com
821cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    context->drawRect(*grp, rect);
822cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    return true;
823cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
824cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
8253d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgclass GrGLRRectBlurEffect;
8263d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
827b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrRRectBlurEffect : public GrFragmentProcessor {
8283d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgpublic:
8293d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
830b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static GrFragmentProcessor* Create(GrContext* context, float sigma, const SkRRect&);
8313d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8323d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    virtual ~GrRRectBlurEffect() {};
8333d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    static const char* Name() { return "GrRRectBlur"; }
8343d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8353d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    const SkRRect& getRRect() const { return fRRect; }
8363d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    float getSigma() const { return fSigma; }
8373d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
838b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLRRectBlurEffect GLProcessor;
8393d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8403d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
8413d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
842b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
8433d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8443d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgprivate:
8453d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    GrRRectBlurEffect(float sigma, const SkRRect&, GrTexture* profileTexture);
8463d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
847b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool onIsEqual(const GrProcessor& other) const SK_OVERRIDE;
8483d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8493d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkRRect             fRRect;
8503d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    float               fSigma;
8513d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    GrTextureAccess     fNinePatchAccess;
8523d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
853b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
8543d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
855b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrFragmentProcessor INHERITED;
8563d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org};
8573d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8583d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
859b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrRRectBlurEffect::Create(GrContext* context, float sigma,
860b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                               const SkRRect& rrect) {
8613d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    if (!rrect.isSimpleCircular()) {
8623d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        return NULL;
8633d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    }
8643d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8653d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    // Make sure we can successfully ninepatch this rrect -- the blur sigma has to be
8663d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    // sufficiently small relative to both the size of the corner radius and the
8673d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    // width (and height) of the rrect.
8683d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8693d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    unsigned int blurRadius = 3*SkScalarCeilToInt(sigma-1/6.0f);
8703d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    unsigned int cornerRadius = SkScalarCeilToInt(rrect.getSimpleRadii().x());
8713d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    if (cornerRadius + blurRadius > rrect.width()/2 ||
8723d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        cornerRadius + blurRadius > rrect.height()/2) {
8733d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        return NULL;
8743d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    }
8753d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8763d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    static const GrCacheID::Domain gRRectBlurDomain = GrCacheID::GenerateDomain();
8773d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    GrCacheID::Key key;
8783d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    memset(&key, 0, sizeof(key));
8793d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    key.fData32[0] = blurRadius;
8803d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    key.fData32[1] = cornerRadius;
8813d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    GrCacheID blurRRectNinePatchID(gRRectBlurDomain, key);
8823d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8833d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    GrTextureParams params;
8843d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    params.setFilterMode(GrTextureParams::kBilerp_FilterMode);
8853d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8863d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    unsigned int smallRectSide = 2*(blurRadius + cornerRadius) + 1;
8873d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    unsigned int texSide = smallRectSide + 2*blurRadius;
8883d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    GrTextureDesc texDesc;
8893d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    texDesc.fWidth = texSide;
8903d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    texDesc.fHeight = texSide;
8913d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    texDesc.fConfig = kAlpha_8_GrPixelConfig;
8923d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8933d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    GrTexture *blurNinePatchTexture = context->findAndRefTexture(texDesc, blurRRectNinePatchID, &params);
8943d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8953d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    if (NULL == blurNinePatchTexture) {
8963d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        SkMask mask;
8973d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
8983d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        mask.fBounds = SkIRect::MakeWH(smallRectSide, smallRectSide);
8993d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        mask.fFormat = SkMask::kA8_Format;
9003d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        mask.fRowBytes = mask.fBounds.width();
9013d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        mask.fImage = SkMask::AllocImage(mask.computeTotalImageSize());
9023d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        SkAutoMaskFreeImage amfi(mask.fImage);
9033d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9043d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        memset(mask.fImage, 0, mask.computeTotalImageSize());
9053d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9063d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        SkRect smallRect;
9073d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        smallRect.setWH(SkIntToScalar(smallRectSide), SkIntToScalar(smallRectSide));
9083d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9093d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        SkRRect smallRRect;
9103d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        smallRRect.setRectXY(smallRect, SkIntToScalar(cornerRadius), SkIntToScalar(cornerRadius));
9113d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9123d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        SkPath path;
9133d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        path.addRRect( smallRRect );
9143d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9153d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        SkDraw::DrawToMask(path, &mask.fBounds, NULL, NULL, &mask, SkMask::kJustRenderImage_CreateMode, SkPaint::kFill_Style);
9163d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9173d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        SkMask blurred_mask;
9183d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        SkBlurMask::BoxBlur(&blurred_mask, mask, sigma, kNormal_SkBlurStyle, kHigh_SkBlurQuality, NULL, true );
9193d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9203d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        blurNinePatchTexture = context->createTexture(&params, texDesc, blurRRectNinePatchID, blurred_mask.fImage, 0);
9216b127cd2b1b2cb4ab5ef995f2f8f937b24f6d682commit-bot@chromium.org        SkMask::FreeImage(blurred_mask.fImage);
9223d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    }
9233d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9246b127cd2b1b2cb4ab5ef995f2f8f937b24f6d682commit-bot@chromium.org    SkAutoTUnref<GrTexture> blurunref(blurNinePatchTexture);
9253d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    if (NULL == blurNinePatchTexture) {
9263d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        return NULL;
9273d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    }
9283d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
92955fad7af61c21d502acb9891d631e8aa29e3628cbsalomon    return SkNEW_ARGS(GrRRectBlurEffect, (sigma, rrect, blurNinePatchTexture));
9303d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org}
9313d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9323d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgvoid GrRRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
9333d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    *validFlags = 0;
9343d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org}
9353d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
936b0a8a377f832c59cee939ad721e1f87d378b7142joshualittconst GrBackendFragmentProcessorFactory& GrRRectBlurEffect::getFactory() const {
937b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    return GrTBackendFragmentProcessorFactory<GrRRectBlurEffect>::getInstance();
9383d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org}
9393d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9403d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgGrRRectBlurEffect::GrRRectBlurEffect(float sigma, const SkRRect& rrect, GrTexture *ninePatchTexture)
9413d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    : fRRect(rrect),
9423d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org      fSigma(sigma),
9433d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org      fNinePatchAccess(ninePatchTexture) {
9443d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    this->addTextureAccess(&fNinePatchAccess);
9453d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    this->setWillReadFragmentPosition();
9463d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org}
9473d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
948b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool GrRRectBlurEffect::onIsEqual(const GrProcessor& other) const {
94949586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrRRectBlurEffect& rrbe = other.cast<GrRRectBlurEffect>();
9503d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    return fRRect.getSimpleRadii().fX == rrbe.fRRect.getSimpleRadii().fX && fSigma == rrbe.fSigma;
9513d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org}
9523d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9533d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////
9543d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
955b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRRectBlurEffect);
9563d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
957b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrRRectBlurEffect::TestCreate(SkRandom* random,
95883d081ae1d731b5039e99823620f5e287542ee39bsalomon                                        GrContext* context,
95983d081ae1d731b5039e99823620f5e287542ee39bsalomon                                        const GrDrawTargetCaps& caps,
96083d081ae1d731b5039e99823620f5e287542ee39bsalomon                                        GrTexture*[]) {
9613d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkScalar w = random->nextRangeScalar(100.f, 1000.f);
9623d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkScalar h = random->nextRangeScalar(100.f, 1000.f);
9633d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkScalar r = random->nextRangeF(1.f, 9.f);
9643d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkScalar sigma = random->nextRangeF(1.f,10.f);
9653d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkRRect rrect;
9663d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    rrect.setRectXY(SkRect::MakeWH(w, h), r, r);
9673d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    return GrRRectBlurEffect::Create(context, sigma, rrect);
9683d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org}
9693d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9703d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////
9713d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
972b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrGLRRectBlurEffect : public GrGLFragmentProcessor {
9733d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgpublic:
974b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrGLRRectBlurEffect(const GrBackendProcessorFactory&, const GrProcessor&);
9753d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
976b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual void emitCode(GrGLProgramBuilder*,
977b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                          const GrFragmentProcessor&,
978b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                          const GrProcessorKey&,
9793d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                          const char* outputColor,
9803d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                          const char* inputColor,
9813d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                          const TransformedCoordsArray&,
9823d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                          const TextureSamplerArray&) SK_OVERRIDE;
9833d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
984b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
9853d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
9863d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.orgprivate:
9877510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fProxyRectUniform;
9887510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fCornerRadiusUniform;
9897510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fBlurRadiusUniform;
990b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLFragmentProcessor INHERITED;
9913d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org};
9923d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
993b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGLRRectBlurEffect::GrGLRRectBlurEffect(const GrBackendProcessorFactory& factory,
994b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         const GrProcessor&)
9953d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    : INHERITED (factory) {
9963d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org}
9973d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
99830ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLRRectBlurEffect::emitCode(GrGLProgramBuilder* builder,
999b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                   const GrFragmentProcessor&,
1000b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                   const GrProcessorKey&,
1001b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                   const char* outputColor,
1002b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                   const char* inputColor,
1003b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                   const TransformedCoordsArray&,
1004b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                   const TextureSamplerArray& samplers) {
10053d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    const char *rectName;
10063d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    const char *cornerRadiusName;
10073d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    const char *blurRadiusName;
10083d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
10093d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    // The proxy rect has left, top, right, and bottom edges correspond to
10103d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    // components x, y, z, and w, respectively.
10113d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
101230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fProxyRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
10133d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                                            kVec4f_GrSLType,
10143d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                                            "proxyRect",
10153d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                                            &rectName);
101630ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fCornerRadiusUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
10173d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                                                 kFloat_GrSLType,
10183d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                                                 "cornerRadius",
10193d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                                                 &cornerRadiusName);
102030ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fBlurRadiusUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
10213d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                                                 kFloat_GrSLType,
10223d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                                                 "blurRadius",
10233d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org                                                 &blurRadiusName);
102430ba436f04e61d4505fb854d5fc56079636e0788joshualitt
102530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
102630ba436f04e61d4505fb854d5fc56079636e0788joshualitt    const char* fragmentPos = fsBuilder->fragmentPosition();
10273d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
10283d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    // warp the fragment position to the appropriate part of the 9patch blur texture
10293d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
103030ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tvec2 rectCenter = (%s.xy + %s.zw)/2.0;\n", rectName, rectName);
103130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tvec2 translatedFragPos = %s.xy - %s.xy;\n", fragmentPos, rectName);
103230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tfloat threshold = %s + 2.0*%s;\n", cornerRadiusName, blurRadiusName );
103330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tvec2 middle = %s.zw - %s.xy - 2.0*threshold;\n", rectName, rectName );
103430ba436f04e61d4505fb854d5fc56079636e0788joshualitt
103530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tif (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {\n" );
103630ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.x = threshold;\n");
103730ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t} else if (translatedFragPos.x >= (middle.x + threshold)) {\n");
103830ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.x -= middle.x - 1.0;\n");
103930ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t}\n");
104030ba436f04e61d4505fb854d5fc56079636e0788joshualitt
104130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tif (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y+threshold)) {\n" );
104230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.y = threshold;\n");
104330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t} else if (translatedFragPos.y >= (middle.y + threshold)) {\n");
104430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t\ttranslatedFragPos.y -= middle.y - 1.0;\n");
104530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t}\n");
104630ba436f04e61d4505fb854d5fc56079636e0788joshualitt
104730ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tvec2 proxyDims = vec2(2.0*threshold+1.0);\n");
104830ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tvec2 texCoord = translatedFragPos / proxyDims;\n");
104930ba436f04e61d4505fb854d5fc56079636e0788joshualitt
105030ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t%s = ", outputColor);
105130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->appendTextureLookupAndModulate(inputColor, samplers[0], "texCoord");
105230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppend(";\n");
10533d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org}
10543d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
10557510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLRRectBlurEffect::setData(const GrGLProgramDataManager& pdman,
1056b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                  const GrProcessor& proc) {
1057b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrRRectBlurEffect& brre = proc.cast<GrRRectBlurEffect>();
10583d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkRRect rrect = brre.getRRect();
10593d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
10603d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    float blurRadius = 3.f*SkScalarCeilToScalar(brre.getSigma()-1/6.0f);
10617510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fBlurRadiusUniform, blurRadius);
10623d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
10633d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkRect rect = rrect.getBounds();
10643d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    rect.outset(blurRadius, blurRadius);
10657510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
10663d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
10673d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkScalar radius = 0;
10683d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkASSERT(rrect.isSimpleCircular() || rrect.isRect());
10693d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    radius = rrect.getSimpleRadii().fX;
10707510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fCornerRadiusUniform, radius);
10713d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org}
10723d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
10733d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
1074821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.orgbool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context,
1075821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                                    GrPaint* grp,
1076821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                                    const SkStrokeRec& strokeRec,
1077821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                                    const SkRRect& rrect) const {
10783d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    if (fBlurStyle != kNormal_SkBlurStyle) {
10793d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        return false;
10803d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    }
10813d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
10823d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    if (!strokeRec.isFillStyle()) {
10833d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        return false;
10843d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    }
10853d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
10863d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkRect proxy_rect = rrect.rect();
10873d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkMatrix ctm = context->getMatrix();
10883d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    SkScalar xformedSigma = this->computeXformedSigma(ctm);
10893d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f);
10903d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    proxy_rect.outset(extra, extra);
10913d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
1092b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    SkAutoTUnref<GrFragmentProcessor> fp(GrRRectBlurEffect::Create(context, xformedSigma, rrect));
1093b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    if (!fp) {
10943d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org        return false;
10953d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    }
10963d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
10973d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    GrContext::AutoMatrix am;
10983d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    if (!am.setIdentity(context, grp)) {
10993d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org       return false;
11003d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    }
11013d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
1102b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    grp->addCoverageProcessor(fp);
11033d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org
11043d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    context->drawRect(*grp, proxy_rect);
11053d8bf232bd2e4903d2ee2bb575637e7555361604commit-bot@chromium.org    return true;
1106821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org}
1107821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org
1108491493119c11206c5823b76eb6420a705be243a1robertphillips@google.combool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
1109491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                            const SkIRect& clipBounds,
1110491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                            const SkMatrix& ctm,
1111491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                            SkRect* maskRect) const {
11127ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    SkScalar xformedSigma = this->computeXformedSigma(ctm);
11137ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    if (xformedSigma <= 0) {
1114491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        return false;
11152b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com    }
1116491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
11177ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    static const SkScalar kMIN_GPU_BLUR_SIZE  = SkIntToScalar(64);
11187ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32);
1119491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
1120491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    if (srcBounds.width() <= kMIN_GPU_BLUR_SIZE &&
1121491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        srcBounds.height() <= kMIN_GPU_BLUR_SIZE &&
11227ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com        xformedSigma <= kMIN_GPU_BLUR_SIGMA) {
1123491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        // We prefer to blur small rect with small radius via CPU.
1124491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        return false;
1125491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    }
1126491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
1127491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    if (NULL == maskRect) {
1128491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        // don't need to compute maskRect
1129491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        return true;
1130491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    }
1131491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
11327ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    float sigma3 = 3 * SkScalarToFloat(xformedSigma);
1133491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
11344469938e92d779dff05e745559e67907bbf21e78reed@google.com    SkRect clipRect = SkRect::Make(clipBounds);
1135491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    SkRect srcRect(srcBounds);
1136491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
1137491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    // Outset srcRect and clipRect by 3 * sigma, to compute affected blur area.
11384b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    srcRect.outset(sigma3, sigma3);
11394b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    clipRect.outset(sigma3, sigma3);
1140491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    srcRect.intersect(clipRect);
1141491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    *maskRect = srcRect;
11421842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.com    return true;
1143491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com}
1144491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
11451842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.combool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
1146439ff1b9ca2b74a9dc3b04346aa1032c11b142e9commit-bot@chromium.org                                         const SkMatrix& ctm,
11471842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.com                                         const SkRect& maskRect,
1148491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                         GrTexture** result,
1149491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                         bool canOverwriteSrc) const {
1150491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height());
1151491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
1152491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    GrContext* context = src->getContext();
1153491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
1154491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    GrContext::AutoWideOpenIdentityDraw awo(context, NULL);
1155491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
1156439ff1b9ca2b74a9dc3b04346aa1032c11b142e9commit-bot@chromium.org    SkScalar xformedSigma = this->computeXformedSigma(ctm);
11577ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    SkASSERT(xformedSigma > 0);
1158491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
1159491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    // If we're doing a normal blur, we can clobber the pathTexture in the
1160491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    // gaussianBlur.  Otherwise, we need to save it for later compositing.
1161e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    bool isNormalBlur = (kNormal_SkBlurStyle == fBlurStyle);
1162736dd031f177681bfa284e19291ef031ad0822d5robertphillips@google.com    *result = SkGpuBlurUtils::GaussianBlur(context, src, isNormalBlur && canOverwriteSrc,
11637ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com                                           clipRect, false, xformedSigma, xformedSigma);
11643cc820c0504dc6de081d08391affe68b69031c63robertphillips@google.com    if (NULL == *result) {
1165491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        return false;
1166491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    }
1167491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
1168491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    if (!isNormalBlur) {
1169491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        context->setIdentityMatrix();
1170491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        GrPaint paint;
1171491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        SkMatrix matrix;
1172491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        matrix.setIDiv(src->width(), src->height());
1173491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        // Blend pathTexture over blurTexture.
1174491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        GrContext::AutoRenderTarget art(context, (*result)->asRenderTarget());
1175b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        paint.addColorProcessor(GrSimpleTextureEffect::Create(src, matrix))->unref();
1176e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org        if (kInner_SkBlurStyle == fBlurStyle) {
1177491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com            // inner:  dst = dst * src
1178491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com            paint.setBlendFunc(kDC_GrBlendCoeff, kZero_GrBlendCoeff);
1179e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org        } else if (kSolid_SkBlurStyle == fBlurStyle) {
1180491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com            // solid:  dst = src + dst - src * dst
1181491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com            //             = (1 - dst) * src + 1 * dst
1182491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com            paint.setBlendFunc(kIDC_GrBlendCoeff, kOne_GrBlendCoeff);
1183e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org        } else if (kOuter_SkBlurStyle == fBlurStyle) {
1184491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com            // outer:  dst = dst * (1 - src)
1185491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com            //             = 0 * src + (1 - src) * dst
1186491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com            paint.setBlendFunc(kZero_GrBlendCoeff, kISC_GrBlendCoeff);
1187491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        }
1188491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        context->drawRect(paint, clipRect);
1189491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    }
1190491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
1191491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    return true;
11922b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com}
11932b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com
1194491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#endif // SK_SUPPORT_GPU
1195491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
1196491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
11970f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
11980bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.comvoid SkBlurMaskFilterImpl::toString(SkString* str) const {
11990bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com    str->append("SkBlurMaskFilterImpl: (");
12000bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com
12017ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    str->append("sigma: ");
12027ce661d19c5cf4484305a1b20c44bd111f129847robertphillips@google.com    str->appendScalar(fSigma);
12030bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com    str->append(" ");
12040bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com
1205e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org    static const char* gStyleName[kLastEnum_SkBlurStyle + 1] = {
12060bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com        "normal", "solid", "outer", "inner"
12070bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com    };
12080bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com
12090bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com    str->appendf("style: %s ", gStyleName[fBlurStyle]);
12100bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com    str->append("flags: (");
12110bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com    if (fBlurFlags) {
12120bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com        bool needSeparator = false;
12138eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com        SkAddFlagToString(str,
12148eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com                          SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag),
12150bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com                          "IgnoreXform", &needSeparator);
12168eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com        SkAddFlagToString(str,
12178eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com                          SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag),
12180bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com                          "HighQuality", &needSeparator);
12190bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com    } else {
12200bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com        str->append("None");
12210bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com    }
12220bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com    str->append("))");
12230bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com}
12240bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com#endif
12250bd80fa01bba2b3f0f49937fcb17928c74bde5a6robertphillips@google.com
1226d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
1227d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
1228d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1229