180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMaskFilter.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkBlitter.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkBounder.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkDraw.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRasterClip.h"
15910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#include "SkRRect.h"
1658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkTypes.h"
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#if SK_SUPPORT_GPU
1958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "GrTexture.h"
2058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkGr.h"
2158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkGrPixelRef.h"
2258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#endif
23363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMaskFilter::filterMask(SkMask*, const SkMask&, const SkMatrix&,
25363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                              SkIPoint*) const {
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void extractMaskSubset(const SkMask& src, SkMask* dst) {
30363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(src.fBounds.contains(dst->fBounds));
31363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
32363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const int dx = dst->fBounds.left() - src.fBounds.left();
33363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const int dy = dst->fBounds.top() - src.fBounds.top();
34363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    dst->fImage = src.fImage + dy * src.fRowBytes + dx;
35363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    dst->fRowBytes = src.fRowBytes;
36363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    dst->fFormat = src.fFormat;
37363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
38363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
39363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void blitClippedMask(SkBlitter* blitter, const SkMask& mask,
40363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            const SkIRect& bounds, const SkIRect& clipR) {
41363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkIRect r;
42363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (r.intersect(bounds, clipR)) {
43363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        blitter->blitMask(mask, r);
44363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
45363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
46363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
47363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void blitClippedRect(SkBlitter* blitter, const SkIRect& rect, const SkIRect& clipR) {
48363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkIRect r;
49363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (r.intersect(rect, clipR)) {
50363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        blitter->blitRect(r.left(), r.top(), r.width(), r.height());
51363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
52363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
53363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
54363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#if 0
55363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void dump(const SkMask& mask) {
56363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (int y = mask.fBounds.top(); y < mask.fBounds.bottom(); ++y) {
57363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (int x = mask.fBounds.left(); x < mask.fBounds.right(); ++x) {
58363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkDebugf("%02X", *mask.getAddr8(x, y));
59363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
60363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkDebugf("\n");
61363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
62363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkDebugf("\n");
63363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
64363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#endif
65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
66363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void draw_nine_clipped(const SkMask& mask, const SkIRect& outerR,
67363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                              const SkIPoint& center, bool fillCenter,
68363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                              const SkIRect& clipR, SkBlitter* blitter) {
69363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    int cx = center.x();
70363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    int cy = center.y();
71363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkMask m;
72363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
73363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // top-left
74363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds = mask.fBounds;
75363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds.fRight = cx;
76363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds.fBottom = cy;
777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        extractMaskSubset(mask, &m);
797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        m.fBounds.offsetTo(outerR.left(), outerR.top());
807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        blitClippedMask(blitter, m, m.fBounds, clipR);
817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
82363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
83363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // top-right
84363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds = mask.fBounds;
85363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds.fLeft = cx + 1;
86363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds.fBottom = cy;
877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        extractMaskSubset(mask, &m);
897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        m.fBounds.offsetTo(outerR.right() - m.fBounds.width(), outerR.top());
907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        blitClippedMask(blitter, m, m.fBounds, clipR);
917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
92363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
93363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // bottom-left
94363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds = mask.fBounds;
95363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds.fRight = cx;
96363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds.fTop = cy + 1;
977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        extractMaskSubset(mask, &m);
997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        m.fBounds.offsetTo(outerR.left(), outerR.bottom() - m.fBounds.height());
1007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        blitClippedMask(blitter, m, m.fBounds, clipR);
1017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
102363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
103363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // bottom-right
104363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds = mask.fBounds;
105363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds.fLeft = cx + 1;
106363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    m.fBounds.fTop = cy + 1;
1077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
1087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        extractMaskSubset(mask, &m);
1097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        m.fBounds.offsetTo(outerR.right() - m.fBounds.width(),
1107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                           outerR.bottom() - m.fBounds.height());
1117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        blitClippedMask(blitter, m, m.fBounds, clipR);
1127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
113363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkIRect innerR;
115363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    innerR.set(outerR.left() + cx - mask.fBounds.left(),
116363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger               outerR.top() + cy - mask.fBounds.top(),
117363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger               outerR.right() + (cx + 1 - mask.fBounds.right()),
118363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger               outerR.bottom() + (cy + 1 - mask.fBounds.bottom()));
119363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (fillCenter) {
120363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        blitClippedRect(blitter, innerR, clipR);
121363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
122363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
123363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const int innerW = innerR.width();
124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    size_t storageSize = (innerW + 1) * (sizeof(int16_t) + sizeof(uint8_t));
125363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkAutoSMalloc<4*1024> storage(storageSize);
126363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    int16_t* runs = (int16_t*)storage.get();
127363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    uint8_t* alpha = (uint8_t*)(runs + innerW + 1);
128363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkIRect r;
130363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // top
131363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    r.set(innerR.left(), outerR.top(), innerR.right(), innerR.top());
132363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (r.intersect(clipR)) {
133363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int startY = SkMax32(0, r.top() - outerR.top());
134363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int stopY = startY + r.height();
135363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int width = r.width();
136363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (int y = startY; y < stopY; ++y) {
137363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            runs[0] = width;
138363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            runs[width] = 0;
139363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            alpha[0] = *mask.getAddr8(cx, mask.fBounds.top() + y);
140363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            blitter->blitAntiH(r.left(), outerR.top() + y, alpha, runs);
141363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
142363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
143363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // bottom
144363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    r.set(innerR.left(), innerR.bottom(), innerR.right(), outerR.bottom());
145363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (r.intersect(clipR)) {
146363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int startY = outerR.bottom() - r.bottom();
147363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int stopY = startY + r.height();
148363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int width = r.width();
149363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (int y = startY; y < stopY; ++y) {
150363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            runs[0] = width;
151363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            runs[width] = 0;
152363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            alpha[0] = *mask.getAddr8(cx, mask.fBounds.bottom() - y - 1);
153363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            blitter->blitAntiH(r.left(), outerR.bottom() - y - 1, alpha, runs);
154363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
155363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
156363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // left
157363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    r.set(outerR.left(), innerR.top(), innerR.left(), innerR.bottom());
158363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (r.intersect(clipR)) {
159363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int startX = r.left() - outerR.left();
160363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int stopX = startX + r.width();
161363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int height = r.height();
162363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (int x = startX; x < stopX; ++x) {
163363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            blitter->blitV(outerR.left() + x, r.top(), height,
164363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                           *mask.getAddr8(mask.fBounds.left() + x, mask.fBounds.top() + cy));
165363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
166363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
167363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // right
168363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    r.set(innerR.right(), innerR.top(), outerR.right(), innerR.bottom());
169363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (r.intersect(clipR)) {
170363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int startX = outerR.right() - r.right();
171363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int stopX = startX + r.width();
172363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int height = r.height();
173363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (int x = startX; x < stopX; ++x) {
174363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            blitter->blitV(outerR.right() - x - 1, r.top(), height,
175363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                           *mask.getAddr8(mask.fBounds.right() - x - 1, mask.fBounds.top() + cy));
176363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
177363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
178363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
179363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
180363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic void draw_nine(const SkMask& mask, const SkIRect& outerR,
181363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                      const SkIPoint& center, bool fillCenter,
182363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                      const SkRasterClip& clip, SkBounder* bounder,
183363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                      SkBlitter* blitter) {
184363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // if we get here, we need to (possibly) resolve the clip and blitter
185363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkAAClipBlitterWrapper wrapper(clip, blitter);
186363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    blitter = wrapper.getBlitter();
187363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
188363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkRegion::Cliperator clipper(wrapper.getRgn(), outerR);
189363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
190363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!clipper.done() && (!bounder || bounder->doIRect(outerR))) {
191363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        const SkIRect& cr = clipper.rect();
192363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        do {
193363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            draw_nine_clipped(mask, outerR, center, fillCenter, cr, blitter);
194363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            clipper.next();
195363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        } while (!clipper.done());
196363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
197363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
198363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
199363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic int countNestedRects(const SkPath& path, SkRect rects[2]) {
200363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (path.isNestedRects(rects)) {
201363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return 2;
202363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
203363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return path.isRect(&rects[0]);
204363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
205363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
206910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerbool SkMaskFilter::filterRRect(const SkRRect& devRRect, const SkMatrix& matrix,
207910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                               const SkRasterClip& clip, SkBounder* bounder,
208910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                               SkBlitter* blitter, SkPaint::Style style) const {
209910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    // Attempt to speed up drawing by creating a nine patch. If a nine patch
210910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    // cannot be used, return false to allow our caller to recover and perform
211910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    // the drawing another way.
212910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    NinePatch patch;
213910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    patch.fMask.fImage = NULL;
214910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    if (kTrue_FilterReturn != this->filterRRectToNine(devRRect, matrix,
215910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                                      clip.getBounds(),
216910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                                      &patch)) {
217910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        SkASSERT(NULL == patch.fMask.fImage);
218910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        return false;
219910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    }
220910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, true, clip,
221910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger              bounder, blitter);
222910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    SkMask::FreeImage(patch.fMask.fImage);
223910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    return true;
224910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger}
225910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix,
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              const SkRasterClip& clip, SkBounder* bounder,
228363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                              SkBlitter* blitter, SkPaint::Style style) const {
229363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkRect rects[2];
230363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    int rectCount = 0;
231363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (SkPaint::kFill_Style == style) {
232363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        rectCount = countNestedRects(devPath, rects);
233363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
234363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (rectCount > 0) {
235363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        NinePatch patch;
236363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
237363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        patch.fMask.fImage = NULL;
238363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        switch (this->filterRectsToNine(rects, rectCount, matrix,
239363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                        clip.getBounds(), &patch)) {
240363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case kFalse_FilterReturn:
241363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                SkASSERT(NULL == patch.fMask.fImage);
242363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                return false;
243363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
244363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case kTrue_FilterReturn:
245363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter,
246363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                          1 == rectCount, clip, bounder, blitter);
247363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                SkMask::FreeImage(patch.fMask.fImage);
248363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                return true;
249363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
250363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case kUnimplemented_FilterReturn:
251363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                SkASSERT(NULL == patch.fMask.fImage);
252363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                // fall through
253363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                break;
254363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
255363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
256363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMask  srcM, dstM;
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!SkDraw::DrawToMask(devPath, &clip.getBounds(), this, &matrix, &srcM,
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkMask::kComputeBoundsAndRenderImage_CreateMode,
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            style)) {
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoMaskFreeImage autoSrc(srcM.fImage);
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!this->filterMask(&dstM, srcM, matrix, NULL)) {
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoMaskFreeImage autoDst(dstM.fImage);
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // if we get here, we need to (possibly) resolve the clip and blitter
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAAClipBlitterWrapper wrapper(clip, blitter);
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    blitter = wrapper.getBlitter();
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRegion::Cliperator clipper(wrapper.getRgn(), dstM.fBounds);
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!clipper.done() && (bounder == NULL || bounder->doIRect(dstM.fBounds))) {
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkIRect& cr = clipper.rect();
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            blitter->blitMask(dstM, cr);
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            clipper.next();
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (!clipper.done());
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
288363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerSkMaskFilter::FilterReturn
289910f694aefb0b671dd8522a9afe9b6be645701c1Derek SollenbergerSkMaskFilter::filterRRectToNine(const SkRRect&, const SkMatrix&,
290910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                const SkIRect& clipBounds, NinePatch*) const {
291910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    return kUnimplemented_FilterReturn;
292910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger}
293910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
294910f694aefb0b671dd8522a9afe9b6be645701c1Derek SollenbergerSkMaskFilter::FilterReturn
295363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerSkMaskFilter::filterRectsToNine(const SkRect[], int count, const SkMatrix&,
296363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                const SkIRect& clipBounds, NinePatch*) const {
297363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return kUnimplemented_FilterReturn;
298363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
299363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
30058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#if SK_SUPPORT_GPU
30158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerbool SkMaskFilter::asNewEffect(GrEffectRef** effect, GrTexture*) const {
30258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return false;
30358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
30458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
30558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerbool SkMaskFilter::canFilterMaskGPU(const SkRect& devBounds,
30658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                    const SkIRect& clipBounds,
30758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                    const SkMatrix& ctm,
30858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                    SkRect* maskRect) const {
30958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return false;
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerbool SkMaskFilter::filterMaskGPU(GrContext* context,
31358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                 const SkBitmap& srcBM,
31458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                 const SkRect& maskRect,
31558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                 SkBitmap* resultBM) const {
31658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkAutoTUnref<GrTexture> src;
31758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    bool canOverwriteSrc = false;
31858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (NULL == srcBM.getTexture()) {
31958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        GrTextureDesc desc;
32058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Needs to be a render target to be overwritten in filterMaskGPU
32158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        desc.fFlags     = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
32258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        desc.fConfig    = SkBitmapConfig2GrPixelConfig(srcBM.config());
32358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        desc.fWidth     = srcBM.width();
32458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        desc.fHeight    = srcBM.height();
32558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
32658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // TODO: right now this is exact to guard against out of bounds reads
32758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // by the filter code. More thought needs to be devoted to the
32858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // "filterMaskGPU" contract and then enforced (i.e., clamp the code
32958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // in "filterMaskGPU" so it never samples beyond maskRect)
33058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        GrAutoScratchTexture ast(context, desc, GrContext::kExact_ScratchTexMatch);
33158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (NULL == ast.texture()) {
33258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            return false;
33358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
33458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
33558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkAutoLockPixels alp(srcBM);
33658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        ast.texture()->writePixels(0, 0, srcBM.width(), srcBM.height(),
33758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                   desc.fConfig,
33858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                   srcBM.getPixels(), srcBM.rowBytes());
33958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
34058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        src.reset(ast.detach());
34158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        canOverwriteSrc = true;
34258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    } else {
34358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        src.reset((GrTexture*) srcBM.getTexture());
34458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        src.get()->ref();
34558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
34658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    GrTexture* dst;
34758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
34858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    bool result = this->filterMaskGPU(src, maskRect, &dst, canOverwriteSrc);
34958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (!result) {
35058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return false;
35158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
352910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    SkAutoUnref aur(dst);
35358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
354910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    SkImageInfo info;
35558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    resultBM->setConfig(srcBM.config(), dst->width(), dst->height());
356910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    if (!resultBM->asImageInfo(&info)) {
357910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        return false;
358910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    }
359910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    resultBM->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, dst)))->unref();
36058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return true;
36158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
36258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
36358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerbool SkMaskFilter::filterMaskGPU(GrTexture* src,
36458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                 const SkRect& maskRect,
36558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                 GrTexture** result,
36658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                 bool canOverwriteSrc) const {
36758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return false;
36858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
36958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#endif
37058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
371363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkMaskFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkMask  srcM, dstM;
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    srcM.fImage = NULL;
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    src.roundOut(&srcM.fBounds);
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    srcM.fRowBytes = 0;
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    srcM.fFormat = SkMask::kA8_Format;
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkIPoint margin;    // ignored
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->filterMask(&dstM, srcM, SkMatrix::I(), &margin)) {
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst->set(dstM.fBounds);
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst->set(srcM.fBounds);
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
386