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