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
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
13045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "SkRasterClip.h"
14a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com#include "SkRRect.h"
15491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "SkTypes.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
170b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#if SK_SUPPORT_GPU
180b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#include "GrTexture.h"
190b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#include "SkGr.h"
200b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#include "SkGrPixelRef.h"
210b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#endif
22d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
23feb8cc870df055099c6fcdfebdd6c1486bd91b27reed@google.combool SkMaskFilter::filterMask(SkMask*, const SkMask&, const SkMatrix&,
2430711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com                              SkIPoint*) const {
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.combool SkMaskFilter::asABlur(BlurRec*) const {
29daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    return false;
30daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com}
31daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com
32d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comstatic void extractMaskSubset(const SkMask& src, SkMask* dst) {
33d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkASSERT(src.fBounds.contains(dst->fBounds));
34d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
35d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    const int dx = dst->fBounds.left() - src.fBounds.left();
36d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    const int dy = dst->fBounds.top() - src.fBounds.top();
37d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    dst->fImage = src.fImage + dy * src.fRowBytes + dx;
38d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    dst->fRowBytes = src.fRowBytes;
39d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    dst->fFormat = src.fFormat;
40d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
41d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
42d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comstatic void blitClippedMask(SkBlitter* blitter, const SkMask& mask,
43d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                            const SkIRect& bounds, const SkIRect& clipR) {
44d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkIRect r;
45d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(bounds, clipR)) {
46d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        blitter->blitMask(mask, r);
47d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
48d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
49d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
50d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comstatic void blitClippedRect(SkBlitter* blitter, const SkIRect& rect, const SkIRect& clipR) {
51d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkIRect r;
52d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(rect, clipR)) {
53d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        blitter->blitRect(r.left(), r.top(), r.width(), r.height());
54d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
55d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
56d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
57d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com#if 0
58d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comstatic void dump(const SkMask& mask) {
59d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    for (int y = mask.fBounds.top(); y < mask.fBounds.bottom(); ++y) {
60d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        for (int x = mask.fBounds.left(); x < mask.fBounds.right(); ++x) {
61d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            SkDebugf("%02X", *mask.getAddr8(x, y));
62d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
63d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        SkDebugf("\n");
64d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
65d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkDebugf("\n");
66d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
67d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com#endif
68d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
69d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comstatic void draw_nine_clipped(const SkMask& mask, const SkIRect& outerR,
70dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                              const SkIPoint& center, bool fillCenter,
71d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                              const SkIRect& clipR, SkBlitter* blitter) {
72dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    int cx = center.x();
73dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    int cy = center.y();
74d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkMask m;
75453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
76d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // top-left
77d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds = mask.fBounds;
78d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fRight = cx;
79d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fBottom = cy;
803c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
813c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        extractMaskSubset(mask, &m);
823c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        m.fBounds.offsetTo(outerR.left(), outerR.top());
833c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        blitClippedMask(blitter, m, m.fBounds, clipR);
843c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    }
85453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
86d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // top-right
87d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds = mask.fBounds;
88d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fLeft = cx + 1;
89d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fBottom = cy;
903c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
913c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        extractMaskSubset(mask, &m);
923c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        m.fBounds.offsetTo(outerR.right() - m.fBounds.width(), outerR.top());
933c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        blitClippedMask(blitter, m, m.fBounds, clipR);
943c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    }
95453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
96d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // bottom-left
97d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds = mask.fBounds;
98d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fRight = cx;
99d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fTop = cy + 1;
1003c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
1013c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        extractMaskSubset(mask, &m);
1023c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        m.fBounds.offsetTo(outerR.left(), outerR.bottom() - m.fBounds.height());
1033c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        blitClippedMask(blitter, m, m.fBounds, clipR);
1043c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    }
105453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
106d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // bottom-right
107d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds = mask.fBounds;
108d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fLeft = cx + 1;
109d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fTop = cy + 1;
1103c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
1113c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        extractMaskSubset(mask, &m);
1123c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        m.fBounds.offsetTo(outerR.right() - m.fBounds.width(),
1133c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com                           outerR.bottom() - m.fBounds.height());
1143c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        blitClippedMask(blitter, m, m.fBounds, clipR);
1153c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    }
116d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
117d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkIRect innerR;
118d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    innerR.set(outerR.left() + cx - mask.fBounds.left(),
119d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com               outerR.top() + cy - mask.fBounds.top(),
120d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com               outerR.right() + (cx + 1 - mask.fBounds.right()),
121d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com               outerR.bottom() + (cy + 1 - mask.fBounds.bottom()));
122dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    if (fillCenter) {
123dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        blitClippedRect(blitter, innerR, clipR);
124dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    }
125d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
126d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    const int innerW = innerR.width();
127d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    size_t storageSize = (innerW + 1) * (sizeof(int16_t) + sizeof(uint8_t));
128d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkAutoSMalloc<4*1024> storage(storageSize);
129d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    int16_t* runs = (int16_t*)storage.get();
130d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    uint8_t* alpha = (uint8_t*)(runs + innerW + 1);
131d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
132d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkIRect r;
133d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // top
134d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    r.set(innerR.left(), outerR.top(), innerR.right(), innerR.top());
135d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(clipR)) {
136d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int startY = SkMax32(0, r.top() - outerR.top());
137d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int stopY = startY + r.height();
138d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int width = r.width();
139d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        for (int y = startY; y < stopY; ++y) {
140d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            runs[0] = width;
141d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            runs[width] = 0;
142d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            alpha[0] = *mask.getAddr8(cx, mask.fBounds.top() + y);
143d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            blitter->blitAntiH(r.left(), outerR.top() + y, alpha, runs);
144d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
145d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
146d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // bottom
147d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    r.set(innerR.left(), innerR.bottom(), innerR.right(), outerR.bottom());
148d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(clipR)) {
149d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int startY = outerR.bottom() - r.bottom();
150d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int stopY = startY + r.height();
151d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int width = r.width();
152d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        for (int y = startY; y < stopY; ++y) {
153d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            runs[0] = width;
154d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            runs[width] = 0;
155d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            alpha[0] = *mask.getAddr8(cx, mask.fBounds.bottom() - y - 1);
156d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            blitter->blitAntiH(r.left(), outerR.bottom() - y - 1, alpha, runs);
157d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
158d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
159d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // left
160d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    r.set(outerR.left(), innerR.top(), innerR.left(), innerR.bottom());
161d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(clipR)) {
162d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int startX = r.left() - outerR.left();
163d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int stopX = startX + r.width();
164d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int height = r.height();
165d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        for (int x = startX; x < stopX; ++x) {
166d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            blitter->blitV(outerR.left() + x, r.top(), height,
167d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                           *mask.getAddr8(mask.fBounds.left() + x, mask.fBounds.top() + cy));
168d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
169d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
170d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // right
171d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    r.set(innerR.right(), innerR.top(), outerR.right(), innerR.bottom());
172d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(clipR)) {
173d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int startX = outerR.right() - r.right();
174d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int stopX = startX + r.width();
175d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int height = r.height();
176d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        for (int x = startX; x < stopX; ++x) {
177d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            blitter->blitV(outerR.right() - x - 1, r.top(), height,
178d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                           *mask.getAddr8(mask.fBounds.right() - x - 1, mask.fBounds.top() + cy));
179d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
180d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
181d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
182d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
183868074b50b0fc3e460d2aa97c1096827fe0a1935reedstatic void draw_nine(const SkMask& mask, const SkIRect& outerR, const SkIPoint& center,
184868074b50b0fc3e460d2aa97c1096827fe0a1935reed                      bool fillCenter, const SkRasterClip& clip, SkBlitter* blitter) {
185d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // if we get here, we need to (possibly) resolve the clip and blitter
186d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkAAClipBlitterWrapper wrapper(clip, blitter);
187d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    blitter = wrapper.getBlitter();
188453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
189d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkRegion::Cliperator clipper(wrapper.getRgn(), outerR);
190453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
191868074b50b0fc3e460d2aa97c1096827fe0a1935reed    if (!clipper.done()) {
192d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        const SkIRect& cr = clipper.rect();
193d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        do {
194dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com            draw_nine_clipped(mask, outerR, center, fillCenter, cr, blitter);
195d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            clipper.next();
196d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        } while (!clipper.done());
197d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
198d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
199d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
200dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.comstatic int countNestedRects(const SkPath& path, SkRect rects[2]) {
201dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    if (path.isNestedRects(rects)) {
202dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        return 2;
203dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    }
204dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    return path.isRect(&rects[0]);
205dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com}
206dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
207a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.combool SkMaskFilter::filterRRect(const SkRRect& devRRect, const SkMatrix& matrix,
208868074b50b0fc3e460d2aa97c1096827fe0a1935reed                               const SkRasterClip& clip, SkBlitter* blitter,
209868074b50b0fc3e460d2aa97c1096827fe0a1935reed                               SkPaint::Style style) const {
210a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // Attempt to speed up drawing by creating a nine patch. If a nine patch
211a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // cannot be used, return false to allow our caller to recover and perform
212a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // the drawing another way.
213a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    NinePatch patch;
214a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    patch.fMask.fImage = NULL;
215a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    if (kTrue_FilterReturn != this->filterRRectToNine(devRRect, matrix,
216a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com                                                      clip.getBounds(),
217a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com                                                      &patch)) {
218a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        SkASSERT(NULL == patch.fMask.fImage);
219a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        return false;
220a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
221868074b50b0fc3e460d2aa97c1096827fe0a1935reed    draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, true, clip, blitter);
222a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    SkMask::FreeImage(patch.fMask.fImage);
223a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    return true;
224a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com}
225a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix,
227868074b50b0fc3e460d2aa97c1096827fe0a1935reed                              const SkRasterClip& clip, SkBlitter* blitter,
228868074b50b0fc3e460d2aa97c1096827fe0a1935reed                              SkPaint::Style style) const {
229dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    SkRect rects[2];
230dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    int rectCount = 0;
2315f0add3ad6e1d6129307276c81ba6624f92ca112reed@google.com    if (SkPaint::kFill_Style == style) {
232dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        rectCount = countNestedRects(devPath, rects);
233dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    }
234dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    if (rectCount > 0) {
235dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        NinePatch patch;
236dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
237dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        patch.fMask.fImage = NULL;
238dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        switch (this->filterRectsToNine(rects, rectCount, matrix,
239dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                                        clip.getBounds(), &patch)) {
240d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            case kFalse_FilterReturn:
241dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                SkASSERT(NULL == patch.fMask.fImage);
242d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                return false;
243dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
244d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            case kTrue_FilterReturn:
245868074b50b0fc3e460d2aa97c1096827fe0a1935reed                draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, 1 == rectCount, clip,
246868074b50b0fc3e460d2aa97c1096827fe0a1935reed                          blitter);
247dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                SkMask::FreeImage(patch.fMask.fImage);
248d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                return true;
249dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
250d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            case kUnimplemented_FilterReturn:
251dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                SkASSERT(NULL == patch.fMask.fImage);
252d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                // fall through
253d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                break;
254d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
255d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
256d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMask  srcM, dstM;
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!SkDraw::DrawToMask(devPath, &clip.getBounds(), this, &matrix, &srcM,
2602ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org                            SkMask::kComputeBoundsAndRenderImage_CreateMode,
2612ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org                            style)) {
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26402f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com    SkAutoMaskFreeImage autoSrc(srcM.fImage);
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
266feb8cc870df055099c6fcdfebdd6c1486bd91b27reed@google.com    if (!this->filterMask(&dstM, srcM, matrix, NULL)) {
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
268feb8cc870df055099c6fcdfebdd6c1486bd91b27reed@google.com    }
26902f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com    SkAutoMaskFreeImage autoDst(dstM.fImage);
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
271045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // if we get here, we need to (possibly) resolve the clip and blitter
272045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkAAClipBlitterWrapper wrapper(clip, blitter);
273045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    blitter = wrapper.getBlitter();
274045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
275045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRegion::Cliperator clipper(wrapper.getRgn(), dstM.fBounds);
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
277868074b50b0fc3e460d2aa97c1096827fe0a1935reed    if (!clipper.done()) {
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& cr = clipper.rect();
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            blitter->blitMask(dstM, cr);
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            clipper.next();
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (!clipper.done());
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
288d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comSkMaskFilter::FilterReturn
289a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comSkMaskFilter::filterRRectToNine(const SkRRect&, const SkMatrix&,
290a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com                                const SkIRect& clipBounds, NinePatch*) const {
291a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    return kUnimplemented_FilterReturn;
292a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com}
293a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
294a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comSkMaskFilter::FilterReturn
295dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.comSkMaskFilter::filterRectsToNine(const SkRect[], int count, const SkMatrix&,
29630711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com                                const SkIRect& clipBounds, NinePatch*) const {
297d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    return kUnimplemented_FilterReturn;
298d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
299d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
3000b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#if SK_SUPPORT_GPU
30141bf930039314cc71039b12957195f1c65c30ce1commit-bot@chromium.orgbool SkMaskFilter::asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix&) const {
302491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    return false;
303491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com}
304491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
3051842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.combool SkMaskFilter::canFilterMaskGPU(const SkRect& devBounds,
306491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                    const SkIRect& clipBounds,
307491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                    const SkMatrix& ctm,
308491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                    SkRect* maskRect) const {
309491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    return false;
310491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com}
311491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
312cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org bool SkMaskFilter::directFilterMaskGPU(GrContext* context,
313cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                        GrPaint* grp,
314cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                        const SkStrokeRec& strokeRec,
315cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                        const SkPath& path) const {
316cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    return false;
317cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
318cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
319491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
320821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.orgbool SkMaskFilter::directFilterRRectMaskGPU(GrContext* context,
321821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                            GrPaint* grp,
322821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                            const SkStrokeRec& strokeRec,
323821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                            const SkRRect& rrect) const {
324821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org    return false;
325821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org}
326821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org
3271842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.combool SkMaskFilter::filterMaskGPU(GrTexture* src,
32841bf930039314cc71039b12957195f1c65c30ce1commit-bot@chromium.org                                 const SkMatrix& ctm,
3291842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.com                                 const SkRect& maskRect,
330491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                 GrTexture** result,
331491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                 bool canOverwriteSrc) const {
332491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    return false;
3332b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com}
3340b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#endif
3352b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com
33630711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.comvoid SkMaskFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
3379efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    SkMask  srcM, dstM;
3389efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
3399efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    srcM.fImage = NULL;
3409efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    src.roundOut(&srcM.fBounds);
3419efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    srcM.fRowBytes = 0;
3429efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    srcM.fFormat = SkMask::kA8_Format;
3439efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
3449efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    SkIPoint margin;    // ignored
3459efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    if (this->filterMask(&dstM, srcM, SkMatrix::I(), &margin)) {
3469efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        dst->set(dstM.fBounds);
3479efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    } else {
3489efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        dst->set(srcM.fBounds);
3499efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    }
3509efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com}
351