aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/SkMaskFilter.cpp56
-rw-r--r--src/effects/SkBlurMaskFilter.cpp105
2 files changed, 104 insertions, 57 deletions
diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp
index 90925f1ff0..e02717824e 100644
--- a/src/core/SkMaskFilter.cpp
+++ b/src/core/SkMaskFilter.cpp
@@ -66,9 +66,10 @@ static void dump(const SkMask& mask) {
#endif
static void draw_nine_clipped(const SkMask& mask, const SkIRect& outerR,
+ const SkIPoint& center, bool fillCenter,
const SkIRect& clipR, SkBlitter* blitter) {
- int cx = mask.fBounds.centerX();
- int cy = mask.fBounds.centerY();
+ int cx = center.x();
+ int cy = center.y();
SkMask m;
// top-left
@@ -109,7 +110,9 @@ static void draw_nine_clipped(const SkMask& mask, const SkIRect& outerR,
outerR.top() + cy - mask.fBounds.top(),
outerR.right() + (cx + 1 - mask.fBounds.right()),
outerR.bottom() + (cy + 1 - mask.fBounds.bottom()));
- blitClippedRect(blitter, innerR, clipR);
+ if (fillCenter) {
+ blitClippedRect(blitter, innerR, clipR);
+ }
const int innerW = innerR.width();
size_t storageSize = (innerW + 1) * (sizeof(int16_t) + sizeof(uint8_t));
@@ -169,6 +172,7 @@ static void draw_nine_clipped(const SkMask& mask, const SkIRect& outerR,
}
static void draw_nine(const SkMask& mask, const SkIRect& outerR,
+ const SkIPoint& center, bool fillCenter,
const SkRasterClip& clip, SkBounder* bounder,
SkBlitter* blitter) {
// if we get here, we need to (possibly) resolve the clip and blitter
@@ -180,33 +184,45 @@ static void draw_nine(const SkMask& mask, const SkIRect& outerR,
if (!clipper.done() && (!bounder || bounder->doIRect(outerR))) {
const SkIRect& cr = clipper.rect();
do {
- draw_nine_clipped(mask, outerR, cr, blitter);
+ draw_nine_clipped(mask, outerR, center, fillCenter, cr, blitter);
clipper.next();
} while (!clipper.done());
}
}
+static int countNestedRects(const SkPath& path, SkRect rects[2]) {
+ if (path.isNestedRects(rects)) {
+ return 2;
+ }
+ return path.isRect(&rects[0]);
+}
+
bool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix,
const SkRasterClip& clip, SkBounder* bounder,
SkBlitter* blitter, SkPaint::Style style) {
- SkRect rect;
- if (!SK_IGNORE_FAST_BLURRECT &&
- devPath.isRect(&rect) && SkPaint::kFill_Style == style) {
- SkMask mask;
- SkIRect outerBounds;
-
- mask.fImage = NULL;
- switch (this->filterRectToNine(rect, matrix, clip.getBounds(), &mask,
- &outerBounds)) {
+ SkRect rects[2];
+ int rectCount = 0;
+ if (!SK_IGNORE_FAST_BLURRECT && SkPaint::kFill_Style == style) {
+ rectCount = countNestedRects(devPath, rects);
+ }
+ if (rectCount > 0) {
+ NinePatch patch;
+
+ patch.fMask.fImage = NULL;
+ switch (this->filterRectsToNine(rects, rectCount, matrix,
+ clip.getBounds(), &patch)) {
case kFalse_FilterReturn:
- SkASSERT(!mask.fImage);
+ SkASSERT(NULL == patch.fMask.fImage);
return false;
+
case kTrue_FilterReturn:
- draw_nine(mask, outerBounds, clip, bounder, blitter);
- SkMask::FreeImage(mask.fImage);
+ draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter,
+ 1 == rectCount, clip, bounder, blitter);
+ SkMask::FreeImage(patch.fMask.fImage);
return true;
+
case kUnimplemented_FilterReturn:
- SkASSERT(!mask.fImage);
+ SkASSERT(NULL == patch.fMask.fImage);
// fall through
break;
}
@@ -244,10 +260,8 @@ bool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix,
}
SkMaskFilter::FilterReturn
-SkMaskFilter::filterRectToNine(const SkRect&, const SkMatrix&,
- const SkIRect& clipBounds,
- SkMask* ninePatchMask,
- SkIRect* outerRect) {
+SkMaskFilter::filterRectsToNine(const SkRect[], int count, const SkMatrix&,
+ const SkIRect& clipBounds, NinePatch*) {
return kUnimplemented_FilterReturn;
}
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index c42bd8c9ed..467af23204 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -27,10 +27,9 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl)
protected:
- virtual FilterReturn filterRectToNine(const SkRect&, const SkMatrix&,
- const SkIRect& clipBounds,
- SkMask* ninePatchMask,
- SkIRect* outerRect) SK_OVERRIDE;
+ virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMatrix&,
+ const SkIRect& clipBounds,
+ NinePatch*) SK_OVERRIDE;
private:
SkScalar fRadius;
@@ -104,8 +103,8 @@ bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
#include "SkCanvas.h"
-static bool drawRectIntoMask(const SkRect& r, SkMask* mask) {
- r.roundOut(&mask->fBounds);
+static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) {
+ rects[0].roundOut(&mask->fBounds);
mask->fRowBytes = SkAlign4(mask->fBounds.width());
mask->fFormat = SkMask::kA8_Format;
size_t size = mask->computeImageSize();
@@ -122,24 +121,37 @@ static bool drawRectIntoMask(const SkRect& r, SkMask* mask) {
bitmap.setPixels(mask->fImage);
SkCanvas canvas(bitmap);
- canvas.translate(-SkScalarFloorToScalar(r.left()),
- -SkScalarFloorToScalar(r.top()));
+ canvas.translate(-SkIntToScalar(mask->fBounds.left()),
+ -SkIntToScalar(mask->fBounds.top()));
SkPaint paint;
paint.setAntiAlias(true);
- canvas.drawRect(r, paint);
+ if (1 == count) {
+ canvas.drawRect(rects[0], paint);
+ } else {
+ // todo: do I need a fast way to do this?
+ SkPath path;
+ path.addRect(rects[0]);
+ path.addRect(rects[1]);
+ path.setFillType(SkPath::kEvenOdd_FillType);
+ canvas.drawPath(path, paint);
+ }
return true;
}
SkMaskFilter::FilterReturn
-SkBlurMaskFilterImpl::filterRectToNine(const SkRect& rect, const SkMatrix& matrix,
- const SkIRect& clipBounds,
- SkMask* ninePatchMask,
- SkIRect* outerRect) {
+SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
+ const SkMatrix& matrix,
+ const SkIRect& clipBounds,
+ NinePatch* patch) {
+ if (count < 1 || count > 2) {
+ return kUnimplemented_FilterReturn;
+ }
+
SkIPoint margin;
SkMask srcM, dstM;
- rect.roundOut(&srcM.fBounds);
+ rects[0].roundOut(&srcM.fBounds);
srcM.fImage = NULL;
srcM.fFormat = SkMask::kA8_Format;
srcM.fRowBytes = 0;
@@ -161,35 +173,56 @@ SkBlurMaskFilterImpl::filterRectToNine(const SkRect& rect, const SkMatrix& matri
* Thus, in this case, we inset by a total of 5 (on each side) beginning
* with our outer-rect (dstM.fBounds)
*/
- SkRect smallR = rect;
- {
- // +3 is from +1 for each edge (to account for possible fractional pixel
- // edges, and +1 to make room for a center rol/col.
- int smallW = dstM.fBounds.width() - srcM.fBounds.width() + 3;
- int smallH = dstM.fBounds.height() - srcM.fBounds.height() + 3;
- // we want the inset amounts to be integral, so we don't change any
- // fractional phase on the fRight or fBottom of our smallR.
- SkScalar dx = SkIntToScalar(srcM.fBounds.width() - smallW);
- SkScalar dy = SkIntToScalar(srcM.fBounds.height() - smallH);
- if (dx < 0 || dy < 0) {
- // we're too small, relative to our blur, to break into nine-patch,
- // so we ask to have our normal filterMask() be called.
- return kUnimplemented_FilterReturn;
- }
- SkASSERT(dx >= 0 && dy >= 0);
- smallR.set(rect.left(), rect.top(), rect.right() - dx, rect.bottom() - dy);
- SkASSERT(!smallR.isEmpty());
+ SkRect smallR[2];
+ SkIPoint center;
+
+ // +2 is from +1 for each edge (to account for possible fractional edges
+ int smallW = dstM.fBounds.width() - srcM.fBounds.width() + 2;
+ int smallH = dstM.fBounds.height() - srcM.fBounds.height() + 2;
+ SkIRect innerIR;
+
+ if (1 == count) {
+ innerIR = srcM.fBounds;
+ center.set(smallW, smallH);
+ } else {
+ SkASSERT(2 == count);
+ rects[1].roundIn(&innerIR);
+ center.set(smallW + (innerIR.left() - srcM.fBounds.left()),
+ smallH + (innerIR.top() - srcM.fBounds.top()));
+ }
+
+ // +1 so we get a clean, stretchable, center row/col
+ smallW += 1;
+ smallH += 1;
+
+ // we want the inset amounts to be integral, so we don't change any
+ // fractional phase on the fRight or fBottom of our smallR.
+ const SkScalar dx = SkIntToScalar(innerIR.width() - smallW);
+ const SkScalar dy = SkIntToScalar(innerIR.height() - smallH);
+ if (dx < 0 || dy < 0) {
+ // we're too small, relative to our blur, to break into nine-patch,
+ // so we ask to have our normal filterMask() be called.
+ return kUnimplemented_FilterReturn;
+ }
+
+ smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[0].bottom() - dy);
+ SkASSERT(!smallR[0].isEmpty());
+ if (2 == count) {
+ smallR[1].set(rects[1].left(), rects[1].top(),
+ rects[1].right() - dx, rects[1].bottom() - dy);
+ SkASSERT(!smallR[1].isEmpty());
}
- if (!drawRectIntoMask(smallR, &srcM)) {
+ if (!drawRectsIntoMask(smallR, count, &srcM)) {
return kFalse_FilterReturn;
}
- if (!this->filterMask(ninePatchMask, srcM, matrix, &margin)) {
+ if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) {
return kFalse_FilterReturn;
}
- ninePatchMask->fBounds.offsetTo(0, 0);
- *outerRect = dstM.fBounds;
+ patch->fMask.fBounds.offsetTo(0, 0);
+ patch->fOuterRect = dstM.fBounds;
+ patch->fCenter = center;
return kTrue_FilterReturn;
}