aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-20 19:58:28 +0000
committerGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-20 19:58:28 +0000
commit2bfe36b68d11d05c114a33d62f9f45427e316916 (patch)
treebe03a85b8403ad5671ced41860df6a3041884264
parent29f351a86790fc2f996c01b996db9ef032134d90 (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.cpp152
-rw-r--r--gyp/gmslides.gypi1
-rw-r--r--src/effects/SkBlurImageFilter.cpp13
-rw-r--r--src/effects/SkDisplacementMapEffect.cpp133
-rw-r--r--src/effects/SkDropShadowImageFilter.cpp8
-rw-r--r--src/effects/SkMorphologyImageFilter.cpp96
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();