diff options
author | senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-03-14 17:44:41 +0000 |
---|---|---|
committer | senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-03-14 17:44:41 +0000 |
commit | 118252962f89a80db661a0544f1bd61cbaab6321 (patch) | |
tree | 0bf0a87ec36544ba76ca5099f07f078085dab2f2 /src/effects | |
parent | 18d6753bd0c1a2fea8fb51a33e9331be34d40061 (diff) |
Implement support for expanding crop rects in image filters
NOTE: this patch set is based on https://codereview.chromium.org/189913021/,
and needs that patch to land first.
Until now, crop rects in Skia have only been able to reduce
the size of the destination bounds, but not expand them.
SVG semantics require the latter as well. The heart of
the change is in applyCropRect(), which now assigns each
edge, instead of doing an intersection with the crop rect.
In order to support this (and still work well with tiled
drawing) we need to clip the resulting crop rect to the
clipping region of the filters. This uses the Context struct
previously landed from https://codereview.chromium.org/189913021/.
Many of the pixel loops are not yet ready to handle a
destination rect larger than the source rect. So we provide
a convenience version of applyCropRect() which creates an
offscreen and pads it out with transparent black. Once the
pixel loops and shaders have been fixed to support larger
destination bounds, they should be switched back to the
non-drawing version of applyCropRect().
BUG=skia:
R=bsalomon@google.com, reed@google.com
Committed: https://code.google.com/p/skia/source/detail?r=13805
Review URL: https://codereview.chromium.org/198003008
git-svn-id: http://skia.googlecode.com/svn/trunk@13809 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/effects')
-rw-r--r-- | src/effects/SkBlurImageFilter.cpp | 16 | ||||
-rwxr-xr-x | src/effects/SkColorFilterImageFilter.cpp | 4 | ||||
-rw-r--r-- | src/effects/SkDisplacementMapEffect.cpp | 60 | ||||
-rw-r--r-- | src/effects/SkDropShadowImageFilter.cpp | 7 | ||||
-rw-r--r-- | src/effects/SkLightingImageFilter.cpp | 25 | ||||
-rw-r--r-- | src/effects/SkMatrixConvolutionImageFilter.cpp | 4 | ||||
-rwxr-xr-x | src/effects/SkMergeImageFilter.cpp | 3 | ||||
-rw-r--r-- | src/effects/SkMorphologyImageFilter.cpp | 8 | ||||
-rw-r--r-- | src/effects/SkOffsetImageFilter.cpp | 5 | ||||
-rw-r--r-- | src/effects/SkRectShaderImageFilter.cpp | 3 | ||||
-rw-r--r-- | src/effects/SkXfermodeImageFilter.cpp | 11 |
11 files changed, 62 insertions, 84 deletions
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp index adcb28f90d..ffebe54225 100644 --- a/src/effects/SkBlurImageFilter.cpp +++ b/src/effects/SkBlurImageFilter.cpp @@ -146,15 +146,13 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy, return false; } - SkAutoLockPixels alp(src); - if (!src.getPixels()) { + SkIRect srcBounds, dstBounds; + if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &srcBounds, &src)) { return false; } - SkIRect srcBounds, dstBounds; - src.getBounds(&srcBounds); - srcBounds.offset(srcOffset); - if (!this->applyCropRect(&srcBounds, ctx.ctm())) { + SkAutoLockPixels alp(src); + if (!src.getPixels()) { return false; } @@ -258,13 +256,11 @@ bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) { return false; } - GrTexture* source = input.getTexture(); SkIRect rect; - src.getBounds(&rect); - rect.offset(srcOffset); - if (!this->applyCropRect(&rect, ctx.ctm())) { + if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &rect, &input)) { return false; } + GrTexture* source = input.getTexture(); SkVector sigma, localSigma = SkVector::Make(fSigma.width(), fSigma.height()); ctx.ctm().mapVectors(&sigma, &localSigma, 1); offset->fX = rect.fLeft; diff --git a/src/effects/SkColorFilterImageFilter.cpp b/src/effects/SkColorFilterImageFilter.cpp index 0de73301b1..8cdd546b99 100755 --- a/src/effects/SkColorFilterImageFilter.cpp +++ b/src/effects/SkColorFilterImageFilter.cpp @@ -109,9 +109,7 @@ bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& sourc } SkIRect bounds; - src.getBounds(&bounds); - bounds.offset(srcOffset); - if (!this->applyCropRect(&bounds, ctx.ctm())) { + if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) { return false; } diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp index a1c18c647e..4b26a5f846 100644 --- a/src/effects/SkDisplacementMapEffect.cpp +++ b/src/effects/SkDisplacementMapEffect.cpp @@ -209,26 +209,23 @@ bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy, (color.colorType() != kPMColor_SkColorType)) { return false; } - - SkAutoLockPixels alp_displacement(displ), alp_color(color); - if (!displ.getPixels() || !color.getPixels()) { - return false; - } SkIRect bounds; - color.getBounds(&bounds); - bounds.offset(colorOffset); - if (!this->applyCropRect(&bounds, ctx.ctm())) { + // Since computeDisplacement does bounds checking on color pixel access, we don't need to pad + // the color bitmap to bounds here. + if (!this->applyCropRect(ctx, color, colorOffset, &bounds)) { return false; } SkIRect displBounds; - displ.getBounds(&displBounds); - displBounds.offset(displOffset); - if (!this->applyCropRect(&displBounds, ctx.ctm())) { + if (!this->applyCropRect(ctx, proxy, displ, &displOffset, &displBounds, &displ)) { return false; } if (!bounds.intersect(displBounds)) { return false; } + SkAutoLockPixels alp_displacement(displ), alp_color(color); + if (!displ.getPixels() || !color.getPixels()) { + return false; + } dst->setConfig(color.config(), bounds.width(), bounds.height()); if (!dst->allocPixels()) { @@ -254,14 +251,18 @@ void SkDisplacementMapEffect::computeFastBounds(const SkRect& src, SkRect* dst) } else { *dst = src; } + dst->outset(fScale * SK_ScalarHalf, fScale * SK_ScalarHalf); } bool SkDisplacementMapEffect::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const { - if (getColorInput()) { - return getColorInput()->filterBounds(src, ctm, dst); + SkIRect bounds = src; + if (getColorInput() && !getColorInput()->filterBounds(src, ctm, &bounds)) { + return false; } - *dst = src; + bounds.outset(SkScalarCeilToInt(fScale * SK_ScalarHalf), + SkScalarCeilToInt(fScale * SK_ScalarHalf)); + *dst = bounds; return true; } @@ -356,7 +357,6 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, &colorOffset)) { return false; } - GrTexture* color = colorBM.getTexture(); SkBitmap displacementBM = src; SkIPoint displacementOffset = SkIPoint::Make(0, 0); if (getDisplacementInput() && @@ -364,6 +364,21 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, &displacementOffset)) { return false; } + SkIRect bounds; + // Since GrDisplacementMapEffect does bounds checking on color pixel access, we don't need to + // pad the color bitmap to bounds here. + if (!this->applyCropRect(ctx, colorBM, colorOffset, &bounds)) { + return false; + } + SkIRect displBounds; + if (!this->applyCropRect(ctx, proxy, displacementBM, + &displacementOffset, &displBounds, &displacementBM)) { + return false; + } + if (!bounds.intersect(displBounds)) { + return false; + } + GrTexture* color = colorBM.getTexture(); GrTexture* displacement = displacementBM.getTexture(); GrContext* context = color->getContext(); @@ -380,21 +395,6 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkVector scale = SkVector::Make(fScale, fScale); ctx.ctm().mapVectors(&scale, 1); - SkIRect bounds; - colorBM.getBounds(&bounds); - bounds.offset(colorOffset); - if (!this->applyCropRect(&bounds, ctx.ctm())) { - return false; - } - SkIRect displBounds; - displacementBM.getBounds(&displBounds); - displBounds.offset(displacementOffset); - if (!this->applyCropRect(&displBounds, ctx.ctm())) { - return false; - } - if (!bounds.intersect(displBounds)) { - return false; - } GrPaint paint; SkMatrix offsetMatrix = GrEffect::MakeDivByTextureWHMatrix(displacement); diff --git a/src/effects/SkDropShadowImageFilter.cpp b/src/effects/SkDropShadowImageFilter.cpp index 94055ce8ae..40ab8cf641 100644 --- a/src/effects/SkDropShadowImageFilter.cpp +++ b/src/effects/SkDropShadowImageFilter.cpp @@ -66,9 +66,7 @@ bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source return false; SkIRect bounds; - src.getBounds(&bounds); - bounds.offset(srcOffset); - if (!this->applyCropRect(&bounds, ctx.ctm())) { + if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) { return false; } @@ -90,7 +88,8 @@ bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); SkVector offsetVec, localOffsetVec = SkVector::Make(fDx, fDy); ctx.ctm().mapVectors(&offsetVec, &localOffsetVec, 1); - canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop)); + canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft), + SkIntToScalar(srcOffset.fY - bounds.fTop)); canvas.drawBitmap(src, offsetVec.fX, offsetVec.fY, &paint); canvas.drawBitmap(src, 0, 0); *result = device->accessBitmap(false); diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp index 206be1b62d..54bb1c890b 100644 --- a/src/effects/SkLightingImageFilter.cpp +++ b/src/effects/SkLightingImageFilter.cpp @@ -946,19 +946,17 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy, if (src.colorType() != kPMColor_SkColorType) { return false; } - SkAutoLockPixels alp(src); - if (!src.getPixels()) { + SkIRect bounds; + if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { return false; } - SkIRect bounds; - src.getBounds(&bounds); - bounds.offset(srcOffset); - if (!this->applyCropRect(&bounds, ctx.ctm())) { + if (bounds.width() < 2 || bounds.height() < 2) { return false; } - if (bounds.width() < 2 || bounds.height() < 2) { + SkAutoLockPixels alp(src); + if (!src.getPixels()) { return false; } @@ -1039,15 +1037,9 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy, if (src.colorType() != kPMColor_SkColorType) { return false; } - SkAutoLockPixels alp(src); - if (!src.getPixels()) { - return false; - } SkIRect bounds; - src.getBounds(&bounds); - bounds.offset(srcOffset); - if (!this->applyCropRect(&bounds, ctx.ctm())) { + if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { return false; } @@ -1055,6 +1047,11 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy, return false; } + SkAutoLockPixels alp(src); + if (!src.getPixels()) { + return false; + } + dst->setConfig(src.config(), bounds.width(), bounds.height()); dst->allocPixels(); if (!dst->getPixels()) { diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp index 1df1ff9de0..7b9812ddbc 100644 --- a/src/effects/SkMatrixConvolutionImageFilter.cpp +++ b/src/effects/SkMatrixConvolutionImageFilter.cpp @@ -265,9 +265,7 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy, } SkIRect bounds; - src.getBounds(&bounds); - bounds.offset(srcOffset); - if (!this->applyCropRect(&bounds, ctx.ctm())) { + if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { return false; } diff --git a/src/effects/SkMergeImageFilter.cpp b/src/effects/SkMergeImageFilter.cpp index ff36e5b068..adf9afe9b3 100755 --- a/src/effects/SkMergeImageFilter.cpp +++ b/src/effects/SkMergeImageFilter.cpp @@ -73,8 +73,7 @@ bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, } SkIRect bounds; - src.getBounds(&bounds); - if (!this->applyCropRect(&bounds, ctx.ctm())) { + if (!this->applyCropRect(ctx, src, SkIPoint::Make(0, 0), &bounds)) { return false; } diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp index 90940b9452..fb69758edd 100644 --- a/src/effects/SkMorphologyImageFilter.cpp +++ b/src/effects/SkMorphologyImageFilter.cpp @@ -154,9 +154,7 @@ bool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc p } SkIRect bounds; - src.getBounds(&bounds); - bounds.offset(srcOffset); - if (!this->applyCropRect(&bounds, ctx.ctm())) { + if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { return false; } @@ -547,9 +545,7 @@ bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate, return false; } SkIRect bounds; - input.getBounds(&bounds); - bounds.offset(srcOffset); - if (!this->applyCropRect(&bounds, ctx.ctm())) { + if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) { return false; } SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), diff --git a/src/effects/SkOffsetImageFilter.cpp b/src/effects/SkOffsetImageFilter.cpp index 98eb05bf1d..ae35a4ca2f 100644 --- a/src/effects/SkOffsetImageFilter.cpp +++ b/src/effects/SkOffsetImageFilter.cpp @@ -42,10 +42,7 @@ bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, } SkIRect bounds; - src.getBounds(&bounds); - bounds.offset(srcOffset); - - if (!applyCropRect(&bounds, ctx.ctm())) { + if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) { return false; } diff --git a/src/effects/SkRectShaderImageFilter.cpp b/src/effects/SkRectShaderImageFilter.cpp index dad0e02525..13e59c2c27 100644 --- a/src/effects/SkRectShaderImageFilter.cpp +++ b/src/effects/SkRectShaderImageFilter.cpp @@ -56,8 +56,7 @@ bool SkRectShaderImageFilter::onFilterImage(Proxy* proxy, SkBitmap* result, SkIPoint* offset) const { SkIRect bounds; - source.getBounds(&bounds); - if (!this->applyCropRect(&bounds, ctx.ctm())) { + if (!this->applyCropRect(ctx, source, SkIPoint::Make(0, 0), &bounds)) { return false; } diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp index ebfd16c4db..901353fabe 100644 --- a/src/effects/SkXfermodeImageFilter.cpp +++ b/src/effects/SkXfermodeImageFilter.cpp @@ -62,14 +62,13 @@ bool SkXfermodeImageFilter::onFilterImage(Proxy* proxy, } SkIRect bounds, foregroundBounds; - background.getBounds(&bounds); - bounds.offset(backgroundOffset); - foreground.getBounds(&foregroundBounds); - foregroundBounds.offset(foregroundOffset); - bounds.join(foregroundBounds); - if (!applyCropRect(&bounds, ctx.ctm())) { + if (!applyCropRect(ctx, foreground, foregroundOffset, &foregroundBounds)) { + return false; + } + if (!applyCropRect(ctx, background, backgroundOffset, &bounds)) { return false; } + bounds.join(foregroundBounds); SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); if (NULL == device.get()) { |