diff options
author | senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-01-20 19:58:28 +0000 |
---|---|---|
committer | senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-01-20 19:58:28 +0000 |
commit | 2bfe36b68d11d05c114a33d62f9f45427e316916 (patch) | |
tree | be03a85b8403ad5671ced41860df6a3041884264 /src | |
parent | 29f351a86790fc2f996c01b996db9ef032134d90 (diff) |
Apply the CTM to filter parameters for SkBlurImageFilter, SkDropShadowImageFilter, SkDisplacementMapEffect and SkMorphologyImageFilter. I had resisted this (and may later put in an assert that the CTM contains no rotation, skew or perspective), but it just makes the filters play better with Skia generally.
This revealed that the displacement map was not handling clipping or upstream cropping at all well (the color would "swim" through the displacement at the edge of the clip rect). Fixed by passing through the correct offsets to the bitmap accesses in both raster and GPU paths. Same for morphology.
R=sugoi@google.com
Review URL: https://codereview.chromium.org/137053003
git-svn-id: http://skia.googlecode.com/svn/trunk@13127 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/effects/SkBlurImageFilter.cpp | 13 | ||||
-rw-r--r-- | src/effects/SkDisplacementMapEffect.cpp | 133 | ||||
-rw-r--r-- | src/effects/SkDropShadowImageFilter.cpp | 8 | ||||
-rw-r--r-- | src/effects/SkMorphologyImageFilter.cpp | 96 |
4 files changed, 166 insertions, 84 deletions
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp index 5efef0ba50..7f3f532079 100644 --- a/src/effects/SkBlurImageFilter.cpp +++ b/src/effects/SkBlurImageFilter.cpp @@ -165,10 +165,13 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy, return false; } + SkVector sigma, localSigma = SkVector::Make(fSigma.width(), fSigma.height()); + ctm.mapVectors(&sigma, &localSigma, 1); + int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX; int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY; - getBox3Params(fSigma.width(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX); - getBox3Params(fSigma.height(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY); + getBox3Params(sigma.x(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX); + getBox3Params(sigma.y(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY); if (kernelSizeX < 0 || kernelSizeY < 0) { return false; @@ -235,13 +238,15 @@ bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const if (!this->applyCropRect(&rect, ctm)) { return false; } + SkVector sigma, localSigma = SkVector::Make(fSigma.width(), fSigma.height()); + ctm.mapVectors(&sigma, &localSigma, 1); SkAutoTUnref<GrTexture> tex(SkGpuBlurUtils::GaussianBlur(source->getContext(), source, false, SkRect::Make(rect), true, - fSigma.width(), - fSigma.height())); + sigma.x(), + sigma.y())); offset->fX = rect.fLeft; offset->fY = rect.fTop; return SkImageFilterUtils::WrapTexture(tex, rect.width(), rect.height(), result); diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp index e9a9acb4ce..8264ec8e06 100644 --- a/src/effects/SkDisplacementMapEffect.cpp +++ b/src/effects/SkDisplacementMapEffect.cpp @@ -47,22 +47,28 @@ template<> uint32_t getValue<SkDisplacementMapEffect::kA_ChannelSelectorType>( template<SkDisplacementMapEffect::ChannelSelectorType typeX, SkDisplacementMapEffect::ChannelSelectorType typeY> -void computeDisplacement(SkScalar scale, SkBitmap* dst, SkBitmap* displ, SkBitmap* src, const SkIRect& bounds) +void computeDisplacement(const SkVector& scale, SkBitmap* dst, + SkBitmap* displ, const SkIPoint& offset, + SkBitmap* src, + const SkIRect& bounds) { static const SkScalar Inv8bit = SkScalarDiv(SK_Scalar1, 255.0f); const int srcW = src->width(); const int srcH = src->height(); - const SkScalar scaleForColor = SkScalarMul(scale, Inv8bit); - const SkScalar scaleAdj = SK_ScalarHalf - SkScalarMul(scale, SK_ScalarHalf); + const SkVector scaleForColor = SkVector::Make(SkScalarMul(scale.fX, Inv8bit), + SkScalarMul(scale.fY, Inv8bit)); + const SkVector scaleAdj = SkVector::Make(SK_ScalarHalf - SkScalarMul(scale.fX, SK_ScalarHalf), + SK_ScalarHalf - SkScalarMul(scale.fY, SK_ScalarHalf)); const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); SkPMColor* dstPtr = dst->getAddr32(0, 0); for (int y = bounds.top(); y < bounds.bottom(); ++y) { - const SkPMColor* displPtr = displ->getAddr32(bounds.left(), y); + const SkPMColor* displPtr = displ->getAddr32(bounds.left() + offset.fX, + y + offset.fY); for (int x = bounds.left(); x < bounds.right(); ++x, ++displPtr) { - const SkScalar displX = SkScalarMul(scaleForColor, - SkIntToScalar(getValue<typeX>(*displPtr, table))) + scaleAdj; - const SkScalar displY = SkScalarMul(scaleForColor, - SkIntToScalar(getValue<typeY>(*displPtr, table))) + scaleAdj; + const SkScalar displX = SkScalarMul(scaleForColor.fX, + SkIntToScalar(getValue<typeX>(*displPtr, table))) + scaleAdj.fX; + const SkScalar displY = SkScalarMul(scaleForColor.fY, + SkIntToScalar(getValue<typeY>(*displPtr, table))) + scaleAdj.fY; // Truncate the displacement values const int srcX = x + SkScalarTruncToInt(displX); const int srcY = y + SkScalarTruncToInt(displY); @@ -74,24 +80,27 @@ void computeDisplacement(SkScalar scale, SkBitmap* dst, SkBitmap* displ, SkBitma template<SkDisplacementMapEffect::ChannelSelectorType typeX> void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, - SkScalar scale, SkBitmap* dst, SkBitmap* displ, SkBitmap* src, const SkIRect& bounds) + const SkVector& scale, SkBitmap* dst, + SkBitmap* displ, const SkIPoint& offset, + SkBitmap* src, + const SkIRect& bounds) { switch (yChannelSelector) { case SkDisplacementMapEffect::kR_ChannelSelectorType: computeDisplacement<typeX, SkDisplacementMapEffect::kR_ChannelSelectorType>( - scale, dst, displ, src, bounds); + scale, dst, displ, offset, src, bounds); break; case SkDisplacementMapEffect::kG_ChannelSelectorType: computeDisplacement<typeX, SkDisplacementMapEffect::kG_ChannelSelectorType>( - scale, dst, displ, src, bounds); + scale, dst, displ, offset, src, bounds); break; case SkDisplacementMapEffect::kB_ChannelSelectorType: computeDisplacement<typeX, SkDisplacementMapEffect::kB_ChannelSelectorType>( - scale, dst, displ, src, bounds); + scale, dst, displ, offset, src, bounds); break; case SkDisplacementMapEffect::kA_ChannelSelectorType: computeDisplacement<typeX, SkDisplacementMapEffect::kA_ChannelSelectorType>( - scale, dst, displ, src, bounds); + scale, dst, displ, offset, src, bounds); break; case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: default: @@ -101,24 +110,27 @@ void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSe void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, - SkScalar scale, SkBitmap* dst, SkBitmap* displ, SkBitmap* src, const SkIRect& bounds) + const SkVector& scale, SkBitmap* dst, + SkBitmap* displ, const SkIPoint& offset, + SkBitmap* src, + const SkIRect& bounds) { switch (xChannelSelector) { case SkDisplacementMapEffect::kR_ChannelSelectorType: computeDisplacement<SkDisplacementMapEffect::kR_ChannelSelectorType>( - yChannelSelector, scale, dst, displ, src, bounds); + yChannelSelector, scale, dst, displ, offset, src, bounds); break; case SkDisplacementMapEffect::kG_ChannelSelectorType: computeDisplacement<SkDisplacementMapEffect::kG_ChannelSelectorType>( - yChannelSelector, scale, dst, displ, src, bounds); + yChannelSelector, scale, dst, displ, offset, src, bounds); break; case SkDisplacementMapEffect::kB_ChannelSelectorType: computeDisplacement<SkDisplacementMapEffect::kB_ChannelSelectorType>( - yChannelSelector, scale, dst, displ, src, bounds); + yChannelSelector, scale, dst, displ, offset, src, bounds); break; case SkDisplacementMapEffect::kA_ChannelSelectorType: computeDisplacement<SkDisplacementMapEffect::kA_ChannelSelectorType>( - yChannelSelector, scale, dst, displ, src, bounds); + yChannelSelector, scale, dst, displ, offset, src, bounds); break; case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: default: @@ -185,9 +197,10 @@ bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy, SkIPoint* offset) { SkBitmap displ = src, color = src; SkImageFilter* colorInput = getColorInput(); - SkImageFilter* displacementInput = getDisplacementInput(); - if ((colorInput && !colorInput->filterImage(proxy, src, ctm, &color, offset)) || - (displacementInput && !displacementInput->filterImage(proxy, src, ctm, &displ, offset))) { + SkImageFilter* displInput = getDisplacementInput(); + SkIPoint colorOffset = SkIPoint::Make(0, 0), displOffset = SkIPoint::Make(0, 0); + if ((colorInput && !colorInput->filterImage(proxy, src, ctm, &color, &colorOffset)) || + (displInput && !displInput->filterImage(proxy, src, ctm, &displ, &displOffset))) { return false; } if ((displ.config() != SkBitmap::kARGB_8888_Config) || @@ -201,11 +214,13 @@ bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy, } SkIRect bounds; color.getBounds(&bounds); + bounds.offset(colorOffset); if (!this->applyCropRect(&bounds, ctm)) { return false; } SkIRect displBounds; displ.getBounds(&displBounds); + displBounds.offset(displOffset); if (!this->applyCropRect(&displBounds, ctm)) { return false; } @@ -219,7 +234,13 @@ bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy, return false; } - computeDisplacement(fXChannelSelector, fYChannelSelector, fScale, dst, &displ, &color, bounds); + SkVector scale = SkVector::Make(fScale, fScale); + ctm.mapVectors(&scale, 1); + SkIRect colorBounds = bounds; + colorBounds.offset(-colorOffset); + + computeDisplacement(fXChannelSelector, fYChannelSelector, scale, dst, + &displ, colorOffset - displOffset, &color, colorBounds); offset->fX = bounds.left(); offset->fY = bounds.top(); @@ -261,11 +282,14 @@ class GrDisplacementMapEffect : public GrEffect { public: static GrEffectRef* Create(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, - SkScalar scale, GrTexture* displacement, GrTexture* color) { + SkVector scale, + GrTexture* displacement, const SkMatrix& offsetMatrix, + GrTexture* color) { AutoEffectUnref effect(SkNEW_ARGS(GrDisplacementMapEffect, (xChannelSelector, yChannelSelector, scale, displacement, + offsetMatrix, color))); return CreateEffectRef(effect); } @@ -277,7 +301,7 @@ public: { return fXChannelSelector; } SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const { return fYChannelSelector; } - SkScalar scale() const { return fScale; } + const SkVector& scale() const { return fScale; } typedef GrGLDisplacementMapEffect GLEffect; static const char* Name() { return "DisplacementMap"; } @@ -289,7 +313,9 @@ private: GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, - SkScalar scale, GrTexture* displacement, GrTexture* color); + const SkVector& scale, + GrTexture* displacement, const SkMatrix& offsetMatrix, + GrTexture* color); GR_DECLARE_EFFECT_TEST; @@ -299,7 +325,7 @@ private: GrTextureAccess fColorAccess; SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector; SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector; - SkScalar fScale; + SkVector fScale; typedef GrEffect INHERITED; }; @@ -324,8 +350,8 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, GrTextureDesc desc; desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; - desc.fWidth = src.width(); - desc.fHeight = src.height(); + desc.fWidth = colorBM.width(); + desc.fHeight = colorBM.height(); desc.fConfig = kSkia8888_GrPixelConfig; GrAutoScratchTexture ast(context, desc); @@ -333,29 +359,43 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, GrContext::AutoRenderTarget art(context, dst->asRenderTarget()); - GrPaint paint; - paint.addColorEffect( - GrDisplacementMapEffect::Create(fXChannelSelector, - fYChannelSelector, - fScale, - displacement, - color))->unref(); + SkVector scale = SkVector::Make(fScale, fScale); + ctm.mapVectors(&scale, 1); SkIRect bounds; - src.getBounds(&bounds); + colorBM.getBounds(&bounds); + bounds.offset(colorOffset); if (!this->applyCropRect(&bounds, ctm)) { return false; } SkIRect displBounds; displacementBM.getBounds(&displBounds); + displBounds.offset(displacementOffset); if (!this->applyCropRect(&displBounds, ctm)) { return false; } if (!bounds.intersect(displBounds)) { return false; } - SkRect srcRect = SkRect::Make(bounds); - SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); - context->drawRectToRect(paint, dstRect, srcRect); + + GrPaint paint; + SkMatrix offsetMatrix = GrEffect::MakeDivByTextureWHMatrix(displacement); + offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX), + SkIntToScalar(colorOffset.fY - displacementOffset.fY)); + + paint.addColorEffect( + GrDisplacementMapEffect::Create(fXChannelSelector, + fYChannelSelector, + scale, + displacement, + offsetMatrix, + color))->unref(); + SkIRect colorBounds = bounds; + colorBounds.offset(-colorOffset); + SkMatrix matrix; + matrix.setTranslate(-SkIntToScalar(colorBounds.x()), + -SkIntToScalar(colorBounds.y())); + context->concatMatrix(matrix); + context->drawRect(paint, SkRect::Make(colorBounds)); offset->fX = bounds.left(); offset->fY = bounds.top(); return SkImageFilterUtils::WrapTexture(dst, bounds.width(), bounds.height(), result); @@ -366,10 +406,11 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, GrDisplacementMapEffect::GrDisplacementMapEffect( SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, - SkScalar scale, + const SkVector& scale, GrTexture* displacement, + const SkMatrix& offsetMatrix, GrTexture* color) - : fDisplacementTransform(kLocal_GrCoordSet, displacement) + : fDisplacementTransform(kLocal_GrCoordSet, offsetMatrix, displacement) , fDisplacementAccess(displacement) , fColorTransform(kLocal_GrCoordSet, color) , fColorAccess(color) @@ -428,10 +469,12 @@ GrEffectRef* GrDisplacementMapEffect::TestCreate(SkRandom* random, SkDisplacementMapEffect::ChannelSelectorType yChannelSelector = static_cast<SkDisplacementMapEffect::ChannelSelectorType>( random->nextRangeU(1, kMaxComponent)); - SkScalar scale = random->nextRangeScalar(0, 100.0f); + SkVector scale = SkVector::Make(random->nextRangeScalar(0, 100.0f), + random->nextRangeScalar(0, 100.0f)); return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, scale, - textures[texIdxDispl], textures[texIdxColor]); + textures[texIdxDispl], SkMatrix::I(), + textures[texIdxColor]); } /////////////////////////////////////////////////////////////////////////////// @@ -528,8 +571,8 @@ void GrGLDisplacementMapEffect::setData(const GrGLUniformManager& uman, const GrDisplacementMapEffect& displacementMap = drawEffect.castEffect<GrDisplacementMapEffect>(); GrTexture* colorTex = displacementMap.texture(1); - SkScalar scaleX = SkScalarDiv(displacementMap.scale(), SkIntToScalar(colorTex->width())); - SkScalar scaleY = SkScalarDiv(displacementMap.scale(), SkIntToScalar(colorTex->height())); + SkScalar scaleX = SkScalarDiv(displacementMap.scale().fX, SkIntToScalar(colorTex->width())); + SkScalar scaleY = SkScalarDiv(displacementMap.scale().fY, SkIntToScalar(colorTex->height())); uman.set2f(fScaleUni, SkScalarToFloat(scaleX), colorTex->origin() == kTopLeft_GrSurfaceOrigin ? SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY)); diff --git a/src/effects/SkDropShadowImageFilter.cpp b/src/effects/SkDropShadowImageFilter.cpp index 60294e4f02..61093784fa 100644 --- a/src/effects/SkDropShadowImageFilter.cpp +++ b/src/effects/SkDropShadowImageFilter.cpp @@ -77,14 +77,18 @@ bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source } SkCanvas canvas(device.get()); - SkAutoTUnref<SkImageFilter> blurFilter(new SkBlurImageFilter(fSigmaX, fSigmaY)); + SkVector sigma, localSigma = SkVector::Make(fSigmaX, fSigmaY); + matrix.mapVectors(&sigma, &localSigma, 1); + SkAutoTUnref<SkImageFilter> blurFilter(new SkBlurImageFilter(sigma.fX, sigma.fY)); SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(fColor, SkXfermode::kSrcIn_Mode)); SkPaint paint; paint.setImageFilter(blurFilter.get()); paint.setColorFilter(colorFilter.get()); paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); + SkVector offsetVec, localOffsetVec = SkVector::Make(fDx, fDy); + matrix.mapVectors(&offsetVec, &localOffsetVec, 1); canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop)); - canvas.drawBitmap(src, fDx, fDy, &paint); + canvas.drawBitmap(src, offsetVec.fX, offsetVec.fY, &paint); canvas.drawBitmap(src, 0, 0); *result = device->accessBitmap(false); offset->fX = bounds.fLeft; diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp index 1f8bca111f..09d9f5de4a 100644 --- a/src/effects/SkMorphologyImageFilter.cpp +++ b/src/effects/SkMorphologyImageFilter.cpp @@ -28,7 +28,10 @@ SkMorphologyImageFilter::SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer (fRadius.fHeight >= 0)); } -SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const CropRect* cropRect) +SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, + int radiusY, + SkImageFilter* input, + const CropRect* cropRect) : INHERITED(input, cropRect), fRadius(SkISize::Make(radiusX, radiusY)) { } @@ -194,15 +197,21 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy, return false; } - int width = radius().width(); - int height = radius().height(); + SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), + SkIntToScalar(this->radius().height())); + ctm.mapVectors(&radius, 1); + int width = SkScalarFloorToInt(radius.fX); + int height = SkScalarFloorToInt(radius.fY); if (width < 0 || height < 0) { return false; } + SkIRect srcBounds = bounds; + srcBounds.offset(-srcOffset); + if (width == 0 && height == 0) { - src.extractSubset(dst, bounds); + src.extractSubset(dst, srcBounds); offset->fX = bounds.left(); offset->fY = bounds.top(); return true; @@ -214,18 +223,17 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy, return false; } - offset->fX = bounds.left(); - offset->fY = bounds.top(); - bounds.offset(-srcOffset); if (width > 0 && height > 0) { - erodeX(src, &temp, width, bounds); - SkIRect tmpBounds = SkIRect::MakeWH(bounds.width(), bounds.height()); + erodeX(src, &temp, width, srcBounds); + SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height()); erodeY(temp, dst, height, tmpBounds); } else if (width > 0) { - erodeX(src, dst, width, bounds); + erodeX(src, dst, width, srcBounds); } else if (height > 0) { - erodeY(src, dst, height, bounds); + erodeY(src, dst, height, srcBounds); } + offset->fX = bounds.left(); + offset->fY = bounds.top(); return true; } @@ -259,15 +267,21 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy, return false; } - int width = radius().width(); - int height = radius().height(); + SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), + SkIntToScalar(this->radius().height())); + ctm.mapVectors(&radius, 1); + int width = SkScalarFloorToInt(radius.fX); + int height = SkScalarFloorToInt(radius.fY); if (width < 0 || height < 0) { return false; } + SkIRect srcBounds = bounds; + srcBounds.offset(-srcOffset); + if (width == 0 && height == 0) { - src.extractSubset(dst, bounds); + src.extractSubset(dst, srcBounds); offset->fX = bounds.left(); offset->fY = bounds.top(); return true; @@ -279,18 +293,17 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy, return false; } - offset->fX = bounds.left(); - offset->fY = bounds.top(); - bounds.offset(-srcOffset); if (width > 0 && height > 0) { - dilateX(src, &temp, width, bounds); - SkIRect tmpBounds = SkIRect::MakeWH(bounds.width(), bounds.height()); + dilateX(src, &temp, width, srcBounds); + SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height()); dilateY(temp, dst, height, tmpBounds); } else if (width > 0) { - dilateX(src, dst, width, bounds); + dilateX(src, dst, width, srcBounds); } else if (height > 0) { - dilateY(src, dst, height, bounds); + dilateY(src, dst, height, srcBounds); } + offset->fX = bounds.left(); + offset->fY = bounds.top(); return true; } @@ -569,29 +582,37 @@ bool apply_morphology(const SkBitmap& input, bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, SkBitmap* result, SkIPoint* offset) { SkBitmap input; - if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, offset)) { + SkIPoint srcOffset = SkIPoint::Make(0, 0); + if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, &srcOffset)) { return false; } SkIRect bounds; - src.getBounds(&bounds); + input.getBounds(&bounds); + bounds.offset(srcOffset); if (!this->applyCropRect(&bounds, ctm)) { return false; } - int width = radius().width(); - int height = radius().height(); + SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), + SkIntToScalar(this->radius().height())); + ctm.mapVectors(&radius, 1); + int width = SkScalarFloorToInt(radius.fX); + int height = SkScalarFloorToInt(radius.fY); if (width < 0 || height < 0) { return false; } + SkIRect srcBounds = bounds; + srcBounds.offset(-srcOffset); if (width == 0 && height == 0) { - src.extractSubset(result, bounds); + input.extractSubset(result, srcBounds); offset->fX = bounds.left(); offset->fY = bounds.top(); return true; } - if (!apply_morphology(input, bounds, GrMorphologyEffect::kDilate_MorphologyType, radius(), result)) { + if (!apply_morphology(input, srcBounds, GrMorphologyEffect::kDilate_MorphologyType, + SkISize::Make(width, height), result)) { return false; } offset->fX = bounds.left(); @@ -602,29 +623,38 @@ bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, cons bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, SkBitmap* result, SkIPoint* offset) { SkBitmap input; - if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, offset)) { + SkIPoint srcOffset = SkIPoint::Make(0, 0); + if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, &srcOffset)) { return false; } SkIRect bounds; - src.getBounds(&bounds); + input.getBounds(&bounds); + bounds.offset(srcOffset); if (!this->applyCropRect(&bounds, ctm)) { return false; } - int width = radius().width(); - int height = radius().height(); + SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), + SkIntToScalar(this->radius().height())); + ctm.mapVectors(&radius, 1); + int width = SkScalarFloorToInt(radius.fX); + int height = SkScalarFloorToInt(radius.fY); if (width < 0 || height < 0) { return false; } + SkIRect srcBounds = bounds; + srcBounds.offset(-srcOffset); + if (width == 0 && height == 0) { - src.extractSubset(result, bounds); + input.extractSubset(result, srcBounds); offset->fX = bounds.left(); offset->fY = bounds.top(); return true; } - if (!apply_morphology(input, bounds, GrMorphologyEffect::kErode_MorphologyType, radius(), result)) { + if (!apply_morphology(input, srcBounds, GrMorphologyEffect::kErode_MorphologyType, + SkISize::Make(width, height), result)) { return false; } offset->fX = bounds.left(); |