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"
13b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed#include "SkCachedData.h"
14045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "SkRasterClip.h"
15a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com#include "SkRRect.h"
16491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com#include "SkTypes.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
180b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#if SK_SUPPORT_GPU
190b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#include "GrTexture.h"
200b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#include "SkGr.h"
210b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#include "SkGrPixelRef.h"
220b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#endif
23d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
24b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reedSkMaskFilter::NinePatch::~NinePatch() {
25b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed    if (fCache) {
26b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed        SkASSERT((const void*)fMask.fImage == fCache->data());
27b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed        fCache->unref();
28b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed    } else {
29b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed        SkMask::FreeImage(fMask.fImage);
30b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed    }
31b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed}
32b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed
33feb8cc870df055099c6fcdfebdd6c1486bd91b27reed@google.combool SkMaskFilter::filterMask(SkMask*, const SkMask&, const SkMatrix&,
3430711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com                              SkIPoint*) const {
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
38daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.combool SkMaskFilter::asABlur(BlurRec*) const {
39daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com    return false;
40daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com}
41daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com
42d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comstatic void extractMaskSubset(const SkMask& src, SkMask* dst) {
43d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkASSERT(src.fBounds.contains(dst->fBounds));
44d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
45d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    const int dx = dst->fBounds.left() - src.fBounds.left();
46d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    const int dy = dst->fBounds.top() - src.fBounds.top();
47d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    dst->fImage = src.fImage + dy * src.fRowBytes + dx;
48d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    dst->fRowBytes = src.fRowBytes;
49d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    dst->fFormat = src.fFormat;
50d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
51d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
52d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comstatic void blitClippedMask(SkBlitter* blitter, const SkMask& mask,
53d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                            const SkIRect& bounds, const SkIRect& clipR) {
54d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkIRect r;
55d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(bounds, clipR)) {
56d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        blitter->blitMask(mask, r);
57d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
58d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
59d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
60d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comstatic void blitClippedRect(SkBlitter* blitter, const SkIRect& rect, const SkIRect& clipR) {
61d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkIRect r;
62d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(rect, clipR)) {
63d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        blitter->blitRect(r.left(), r.top(), r.width(), r.height());
64d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
65d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
66d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
67d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com#if 0
68d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comstatic void dump(const SkMask& mask) {
69d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    for (int y = mask.fBounds.top(); y < mask.fBounds.bottom(); ++y) {
70d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        for (int x = mask.fBounds.left(); x < mask.fBounds.right(); ++x) {
71d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            SkDebugf("%02X", *mask.getAddr8(x, y));
72d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
73d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        SkDebugf("\n");
74d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
75d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkDebugf("\n");
76d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
77d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com#endif
78d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
79d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comstatic void draw_nine_clipped(const SkMask& mask, const SkIRect& outerR,
80dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                              const SkIPoint& center, bool fillCenter,
81d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                              const SkIRect& clipR, SkBlitter* blitter) {
82dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    int cx = center.x();
83dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    int cy = center.y();
84d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkMask m;
85453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
86d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // top-left
87d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds = mask.fBounds;
88d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fRight = cx;
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.left(), outerR.top());
933c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        blitClippedMask(blitter, m, m.fBounds, clipR);
943c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    }
95453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
96d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // top-right
97d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds = mask.fBounds;
98d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fLeft = cx + 1;
99d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fBottom = cy;
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.right() - m.fBounds.width(), outerR.top());
1033c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        blitClippedMask(blitter, m, m.fBounds, clipR);
1043c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    }
105453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
106d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // bottom-left
107d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds = mask.fBounds;
108d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fRight = cx;
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.left(), outerR.bottom() - m.fBounds.height());
1133c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        blitClippedMask(blitter, m, m.fBounds, clipR);
1143c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    }
115453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
116d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // bottom-right
117d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds = mask.fBounds;
118d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fLeft = cx + 1;
119d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    m.fBounds.fTop = cy + 1;
1203c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
1213c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        extractMaskSubset(mask, &m);
1223c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        m.fBounds.offsetTo(outerR.right() - m.fBounds.width(),
1233c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com                           outerR.bottom() - m.fBounds.height());
1243c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com        blitClippedMask(blitter, m, m.fBounds, clipR);
1253c0ecc588b145497232b24eeaee409d7878ad4f2tomhudson@google.com    }
126d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
127d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkIRect innerR;
128d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    innerR.set(outerR.left() + cx - mask.fBounds.left(),
129d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com               outerR.top() + cy - mask.fBounds.top(),
130d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com               outerR.right() + (cx + 1 - mask.fBounds.right()),
131d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com               outerR.bottom() + (cy + 1 - mask.fBounds.bottom()));
132dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    if (fillCenter) {
133dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        blitClippedRect(blitter, innerR, clipR);
134dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    }
135d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
136d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    const int innerW = innerR.width();
137d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    size_t storageSize = (innerW + 1) * (sizeof(int16_t) + sizeof(uint8_t));
138d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkAutoSMalloc<4*1024> storage(storageSize);
139d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    int16_t* runs = (int16_t*)storage.get();
140d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    uint8_t* alpha = (uint8_t*)(runs + innerW + 1);
141d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
142d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkIRect r;
143d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // top
144d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    r.set(innerR.left(), outerR.top(), innerR.right(), innerR.top());
145d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(clipR)) {
146d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int startY = SkMax32(0, r.top() - outerR.top());
147d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int stopY = startY + r.height();
148d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int width = r.width();
149d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        for (int y = startY; y < stopY; ++y) {
150d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            runs[0] = width;
151d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            runs[width] = 0;
152d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            alpha[0] = *mask.getAddr8(cx, mask.fBounds.top() + y);
153d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            blitter->blitAntiH(r.left(), outerR.top() + y, alpha, runs);
154d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
155d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
156d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // bottom
157d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    r.set(innerR.left(), innerR.bottom(), innerR.right(), outerR.bottom());
158d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(clipR)) {
159d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int startY = outerR.bottom() - r.bottom();
160d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int stopY = startY + r.height();
161d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int width = r.width();
162d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        for (int y = startY; y < stopY; ++y) {
163d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            runs[0] = width;
164d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            runs[width] = 0;
165d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            alpha[0] = *mask.getAddr8(cx, mask.fBounds.bottom() - y - 1);
166d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            blitter->blitAntiH(r.left(), outerR.bottom() - y - 1, alpha, runs);
167d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
168d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
169d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // left
170d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    r.set(outerR.left(), innerR.top(), innerR.left(), innerR.bottom());
171d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(clipR)) {
172d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int startX = r.left() - outerR.left();
173d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int stopX = startX + r.width();
174d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int height = r.height();
175d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        for (int x = startX; x < stopX; ++x) {
176d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            blitter->blitV(outerR.left() + x, r.top(), height,
177d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                           *mask.getAddr8(mask.fBounds.left() + x, mask.fBounds.top() + cy));
178d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
179d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
180d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // right
181d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    r.set(innerR.right(), innerR.top(), outerR.right(), innerR.bottom());
182d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    if (r.intersect(clipR)) {
183d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int startX = outerR.right() - r.right();
184d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int stopX = startX + r.width();
185d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        int height = r.height();
186d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        for (int x = startX; x < stopX; ++x) {
187d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            blitter->blitV(outerR.right() - x - 1, r.top(), height,
188d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                           *mask.getAddr8(mask.fBounds.right() - x - 1, mask.fBounds.top() + cy));
189d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
190d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
191d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
192d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
193868074b50b0fc3e460d2aa97c1096827fe0a1935reedstatic void draw_nine(const SkMask& mask, const SkIRect& outerR, const SkIPoint& center,
194868074b50b0fc3e460d2aa97c1096827fe0a1935reed                      bool fillCenter, const SkRasterClip& clip, SkBlitter* blitter) {
195d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    // if we get here, we need to (possibly) resolve the clip and blitter
196d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkAAClipBlitterWrapper wrapper(clip, blitter);
197d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    blitter = wrapper.getBlitter();
198453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
199d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    SkRegion::Cliperator clipper(wrapper.getRgn(), outerR);
200453995e01d884d62ce2e808e0067e494c0c9c7faskia.committer@gmail.com
201868074b50b0fc3e460d2aa97c1096827fe0a1935reed    if (!clipper.done()) {
202d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        const SkIRect& cr = clipper.rect();
203d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        do {
204dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com            draw_nine_clipped(mask, outerR, center, fillCenter, cr, blitter);
205d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            clipper.next();
206d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        } while (!clipper.done());
207d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
208d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
209d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
210dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.comstatic int countNestedRects(const SkPath& path, SkRect rects[2]) {
21195bc5f349561fef2d6fbae71adb08cf5c2eec0c9caryclark    if (path.isNestedFillRects(rects)) {
212dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        return 2;
213dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    }
214dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    return path.isRect(&rects[0]);
215dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com}
216dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
217a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.combool SkMaskFilter::filterRRect(const SkRRect& devRRect, const SkMatrix& matrix,
218868074b50b0fc3e460d2aa97c1096827fe0a1935reed                               const SkRasterClip& clip, SkBlitter* blitter,
219868074b50b0fc3e460d2aa97c1096827fe0a1935reed                               SkPaint::Style style) const {
220a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // Attempt to speed up drawing by creating a nine patch. If a nine patch
221a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // cannot be used, return false to allow our caller to recover and perform
222a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    // the drawing another way.
223a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    NinePatch patch;
224a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    patch.fMask.fImage = NULL;
225a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    if (kTrue_FilterReturn != this->filterRRectToNine(devRRect, matrix,
226a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com                                                      clip.getBounds(),
227a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com                                                      &patch)) {
228a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        SkASSERT(NULL == patch.fMask.fImage);
229a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com        return false;
230a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    }
231868074b50b0fc3e460d2aa97c1096827fe0a1935reed    draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, true, clip, blitter);
232a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    return true;
233a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com}
234a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix,
236868074b50b0fc3e460d2aa97c1096827fe0a1935reed                              const SkRasterClip& clip, SkBlitter* blitter,
237868074b50b0fc3e460d2aa97c1096827fe0a1935reed                              SkPaint::Style style) const {
238dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    SkRect rects[2];
239dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    int rectCount = 0;
2405f0add3ad6e1d6129307276c81ba6624f92ca112reed@google.com    if (SkPaint::kFill_Style == style) {
241dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        rectCount = countNestedRects(devPath, rects);
242dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    }
243dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com    if (rectCount > 0) {
244dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com        NinePatch patch;
245dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
246b0df8be137d8fb49436e46d1fd1a5aec8b7ab562reed        switch (this->filterRectsToNine(rects, rectCount, matrix, clip.getBounds(), &patch)) {
247d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            case kFalse_FilterReturn:
248dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                SkASSERT(NULL == patch.fMask.fImage);
249d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                return false;
250dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
251d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            case kTrue_FilterReturn:
252868074b50b0fc3e460d2aa97c1096827fe0a1935reed                draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, 1 == rectCount, clip,
253868074b50b0fc3e460d2aa97c1096827fe0a1935reed                          blitter);
254d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                return true;
255dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com
256d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com            case kUnimplemented_FilterReturn:
257dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.com                SkASSERT(NULL == patch.fMask.fImage);
258d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                // fall through
259d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com                break;
260d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com        }
261d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    }
262d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMask  srcM, dstM;
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!SkDraw::DrawToMask(devPath, &clip.getBounds(), this, &matrix, &srcM,
2662ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org                            SkMask::kComputeBoundsAndRenderImage_CreateMode,
2672ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org                            style)) {
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27002f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com    SkAutoMaskFreeImage autoSrc(srcM.fImage);
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
272eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao    if (!this->filterMask(&dstM, srcM, matrix, NULL)) {
273eabd0d73eebb940ec5ea06625f612a80156b61dbqiankun.miao        return false;
274feb8cc870df055099c6fcdfebdd6c1486bd91b27reed@google.com    }
27502f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com    SkAutoMaskFreeImage autoDst(dstM.fImage);
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
277045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // if we get here, we need to (possibly) resolve the clip and blitter
278045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkAAClipBlitterWrapper wrapper(clip, blitter);
279045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    blitter = wrapper.getBlitter();
280045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
281045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRegion::Cliperator clipper(wrapper.getRgn(), dstM.fBounds);
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
283868074b50b0fc3e460d2aa97c1096827fe0a1935reed    if (!clipper.done()) {
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& cr = clipper.rect();
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            blitter->blitMask(dstM, cr);
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            clipper.next();
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (!clipper.done());
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
294d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.comSkMaskFilter::FilterReturn
295a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comSkMaskFilter::filterRRectToNine(const SkRRect&, const SkMatrix&,
296a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com                                const SkIRect& clipBounds, NinePatch*) const {
297a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com    return kUnimplemented_FilterReturn;
298a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com}
299a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com
300a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comSkMaskFilter::FilterReturn
301dab9b4fe035c1e8a79e110139953c19bd48d66f9reed@google.comSkMaskFilter::filterRectsToNine(const SkRect[], int count, const SkMatrix&,
30230711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com                                const SkIRect& clipBounds, NinePatch*) const {
303d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com    return kUnimplemented_FilterReturn;
304d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com}
305d729b3e504ae547ee0978e8f7156bd8dd8124172reed@google.com
3060b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#if SK_SUPPORT_GPU
307b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkMaskFilter::asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&) const {
308491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    return false;
309491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com}
310491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
3111842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.combool SkMaskFilter::canFilterMaskGPU(const SkRect& devBounds,
312491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                    const SkIRect& clipBounds,
313491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                    const SkMatrix& ctm,
314491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                    SkRect* maskRect) const {
315491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    return false;
316491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com}
317491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
318cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org bool SkMaskFilter::directFilterMaskGPU(GrContext* context,
31925d9c154087d2132a51d1ca74a104726f60ef380joshualitt                                        GrRenderTarget* rt,
320cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                        GrPaint* grp,
321570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt                                        const GrClip&,
3225531d51ce7426bdae7563547326fcf0bf926a083joshualitt                                        const SkMatrix& viewMatrix,
323cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                        const SkStrokeRec& strokeRec,
324cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org                                        const SkPath& path) const {
325cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org    return false;
326cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org}
327cf34bc06347dd2734a7fdaef5cf8853e92979d5ecommit-bot@chromium.org
328491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com
329821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.orgbool SkMaskFilter::directFilterRRectMaskGPU(GrContext* context,
33025d9c154087d2132a51d1ca74a104726f60ef380joshualitt                                            GrRenderTarget* rt,
331821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                            GrPaint* grp,
332570d2f81a65fc868d6300a7edf34c0d5d048c5d6joshualitt                                            const GrClip&,
3335531d51ce7426bdae7563547326fcf0bf926a083joshualitt                                            const SkMatrix& viewMatrix,
334821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                            const SkStrokeRec& strokeRec,
335821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org                                            const SkRRect& rrect) const {
336821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org    return false;
337821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org}
338821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org
3391842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.combool SkMaskFilter::filterMaskGPU(GrTexture* src,
34041bf930039314cc71039b12957195f1c65c30ce1commit-bot@chromium.org                                 const SkMatrix& ctm,
3411842adf01320f9197b449de7375d08ccac43f389skia.committer@gmail.com                                 const SkRect& maskRect,
342491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                 GrTexture** result,
343491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com                                 bool canOverwriteSrc) const {
344491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com    return false;
3452b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com}
3460b82852b234753257835bf1f9ac0046848a283ecrobertphillips@google.com#endif
3472b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com
34830711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.comvoid SkMaskFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
3499efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    SkMask  srcM, dstM;
3509efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
3519efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    srcM.fImage = NULL;
352b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed    srcM.fBounds = src.roundOut();
3539efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    srcM.fRowBytes = 0;
3549efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    srcM.fFormat = SkMask::kA8_Format;
3559efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
3569efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    SkIPoint margin;    // ignored
3579efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    if (this->filterMask(&dstM, srcM, SkMatrix::I(), &margin)) {
3589efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        dst->set(dstM.fBounds);
3599efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    } else {
3609efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        dst->set(srcM.fBounds);
3619efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    }
3629efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com}
363