diff options
author | 2014-01-20 19:58:28 +0000 | |
---|---|---|
committer | 2014-01-20 19:58:28 +0000 | |
commit | 2bfe36b68d11d05c114a33d62f9f45427e316916 (patch) | |
tree | be03a85b8403ad5671ced41860df6a3041884264 | |
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
-rw-r--r-- | gm/imagefiltersscaled.cpp | 152 | ||||
-rw-r--r-- | gyp/gmslides.gypi | 1 | ||||
-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 |
6 files changed, 319 insertions, 84 deletions
diff --git a/gm/imagefiltersscaled.cpp b/gm/imagefiltersscaled.cpp new file mode 100644 index 0000000000..f5275caae1 --- /dev/null +++ b/gm/imagefiltersscaled.cpp @@ -0,0 +1,152 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gm.h" +#include "SkColor.h" +#include "SkBitmapSource.h" +#include "SkBlurImageFilter.h" +#include "SkDisplacementMapEffect.h" +#include "SkDropShadowImageFilter.h" +#include "SkGradientShader.h" +#include "SkMorphologyImageFilter.h" +#include "SkScalar.h" + +namespace skiagm { + +class ImageFiltersScaledGM : public GM { +public: + ImageFiltersScaledGM() : fInitialized(false) { + this->setBGColor(0x00000000); + } + +protected: + virtual SkString onShortName() { + return SkString("imagefiltersscaled"); + } + + virtual SkISize onISize() { + return make_isize(860, 500); + } + + void make_checkerboard() { + fCheckerboard.setConfig(SkBitmap::kARGB_8888_Config, 64, 64); + fCheckerboard.allocPixels(); + SkBitmapDevice device(fCheckerboard); + SkCanvas canvas(&device); + canvas.clear(0x00000000); + SkPaint darkPaint; + darkPaint.setColor(0xFF404040); + SkPaint lightPaint; + lightPaint.setColor(0xFFA0A0A0); + for (int y = 0; y < 64; y += 16) { + for (int x = 0; x < 64; x += 16) { + canvas.save(); + canvas.translate(SkIntToScalar(x), SkIntToScalar(y)); + canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint); + canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint); + canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint); + canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint); + canvas.restore(); + } + } + } + + void make_gradient_circle(int width, int height) { + SkScalar x = SkIntToScalar(width / 2); + SkScalar y = SkIntToScalar(height / 2); + SkScalar radius = SkScalarMul(SkMinScalar(x, y), SkIntToScalar(4) / SkIntToScalar(5)); + fGradientCircle.setConfig(SkBitmap::kARGB_8888_Config, width, height); + fGradientCircle.allocPixels(); + SkBitmapDevice device(fGradientCircle); + SkCanvas canvas(&device); + canvas.clear(0x00000000); + SkColor colors[2]; + colors[0] = SK_ColorWHITE; + colors[1] = SK_ColorBLACK; + SkAutoTUnref<SkShader> shader( + SkGradientShader::CreateRadial(SkPoint::Make(x, y), radius, colors, NULL, 2, + SkShader::kClamp_TileMode) + ); + SkPaint paint; + paint.setShader(shader); + canvas.drawCircle(x, y, radius, paint); + } + + virtual void onDraw(SkCanvas* canvas) { + if (!fInitialized) { + this->make_checkerboard(); + this->make_gradient_circle(64, 64); + fInitialized = true; + } + canvas->clear(0x00000000); + + SkAutoTUnref<SkImageFilter> gradient(new SkBitmapSource(fGradientCircle)); + SkAutoTUnref<SkImageFilter> checkerboard(new SkBitmapSource(fCheckerboard)); + + SkImageFilter* filters[] = { + new SkBlurImageFilter(SkIntToScalar(4), SkIntToScalar(4)), + new SkDropShadowImageFilter(SkIntToScalar(5), SkIntToScalar(10), SkIntToScalar(3), + SK_ColorYELLOW), + new SkDisplacementMapEffect(SkDisplacementMapEffect::kR_ChannelSelectorType, + SkDisplacementMapEffect::kR_ChannelSelectorType, + SkIntToScalar(12), + gradient.get(), + checkerboard.get()), + new SkDilateImageFilter(1, 1, checkerboard.get()), + new SkErodeImageFilter(1, 1, checkerboard.get()), + }; + + SkVector scales[] = { + SkVector::Make(SkScalarInvert(2), SkScalarInvert(2)), + SkVector::Make(SkIntToScalar(1), SkIntToScalar(1)), + SkVector::Make(SkIntToScalar(1), SkIntToScalar(2)), + SkVector::Make(SkIntToScalar(2), SkIntToScalar(1)), + SkVector::Make(SkIntToScalar(2), SkIntToScalar(2)), + }; + + SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64)); + SkScalar margin = SkIntToScalar(16); + SkRect bounds = r; + bounds.outset(margin, margin); + + for (size_t j = 0; j < SK_ARRAY_COUNT(scales); ++j) { + canvas->save(); + for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) { + SkPaint paint; + paint.setColor(SK_ColorBLUE); + paint.setImageFilter(filters[i]); + paint.setAntiAlias(true); + canvas->save(); + canvas->scale(scales[j].fX, scales[j].fY); + canvas->clipRect(bounds); + canvas->drawCircle(r.centerX(), r.centerY(), + SkScalarDiv(r.width()*2, SkIntToScalar(5)), paint); + canvas->restore(); + canvas->translate(r.width() * scales[j].fX + margin, 0); + } + canvas->restore(); + canvas->translate(0, r.height() * scales[j].fY + margin); + } + + for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) { + filters[i]->unref(); + } + } + +private: + bool fInitialized; + SkBitmap fCheckerboard; + SkBitmap fGradientCircle; + typedef GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new ImageFiltersScaledGM; } +static GMRegistry reg(MyFactory); + +} diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi index 8069419de3..0e53fb9f50 100644 --- a/gyp/gmslides.gypi +++ b/gyp/gmslides.gypi @@ -84,6 +84,7 @@ '../gm/imagefiltersbase.cpp', '../gm/imagefilterscropped.cpp', '../gm/imagefiltersgraph.cpp', + '../gm/imagefiltersscaled.cpp', '../gm/internal_links.cpp', '../gm/lcdtext.cpp', '../gm/linepaths.cpp', 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(); |