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