aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-03 21:48:22 +0000
committerGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-03 21:48:22 +0000
commit6776b82d466fa93ccffd251fdf556fe058395444 (patch)
treeeec73f3d3613a5a9dffd40c8f899c73f283749b0
parent927138977fa256a6719baf74221882555b24008f (diff)
Make SkImageFilter crop rects relative to the primitive origin, instead of relative to their parent's crop rect. This is required by SVG semantics, and is more sane anyway.
To do this, this patch changes the "offset/loc" parameter in filterImage() / onFilterImage() from an inout-param to an out-param only, so that the calling filter can know how much the input filter wants its result offset (and doesn't include the original primitive position). This offset can then be applied to the current filter's crop rect. (I've renamed the parameter "offset" in all cases to make this clear.) This makes the call sites in SkCanvas/SkGpuDevice responsible for applying the resulting offset to the primitive's position, which is actually a fairly small change. This change also fixes SkTileImageFilter and SkOffsetImageFilter to correctly handle an input offset, which they weren't before. This required modifying the GM's, since they assumed the broken behaviour. NOTE: this will require rebaselining the imagefiltersgraph test, since it has a new test case. NOTE: this will "break" the Blink layout tests css3/filters/effect-reference-subregion-chained-hw.html and css3/filters/effect-reference-subregion-hw.html, but it actually makes them give correct results. It should be suppressed on the skia roll, and I'll rebaseline it. R=reed@google.com Review URL: https://codereview.chromium.org/112803004 git-svn-id: http://skia.googlecode.com/svn/trunk@12895 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--expectations/gm/ignored-tests.txt3
-rw-r--r--gm/imagefiltersgraph.cpp19
-rw-r--r--gm/offsetimagefilter.cpp9
-rw-r--r--gm/tileimagefilter.cpp21
-rw-r--r--include/core/SkImageFilter.h19
-rw-r--r--src/core/SkCanvas.cpp11
-rw-r--r--src/core/SkImageFilter.cpp8
-rw-r--r--src/core/SkImageFilterUtils.cpp1
-rw-r--r--src/effects/SkBicubicImageFilter.cpp8
-rw-r--r--src/effects/SkBitmapSource.cpp5
-rw-r--r--src/effects/SkBlurImageFilter.cpp15
-rwxr-xr-xsrc/effects/SkColorFilterImageFilter.cpp12
-rw-r--r--src/effects/SkComposeImageFilter.cpp8
-rw-r--r--src/effects/SkDisplacementMapEffect.cpp8
-rw-r--r--src/effects/SkDropShadowImageFilter.cpp10
-rw-r--r--src/effects/SkLightingImageFilter.cpp18
-rw-r--r--src/effects/SkMatrixConvolutionImageFilter.cpp11
-rwxr-xr-xsrc/effects/SkMergeImageFilter.cpp6
-rw-r--r--src/effects/SkMorphologyImageFilter.cpp42
-rw-r--r--src/effects/SkOffsetImageFilter.cpp19
-rw-r--r--src/effects/SkPictureImageFilter.cpp6
-rw-r--r--src/effects/SkRectShaderImageFilter.cpp4
-rw-r--r--src/effects/SkTileImageFilter.cpp21
-rw-r--r--src/effects/SkXfermodeImageFilter.cpp8
-rw-r--r--src/gpu/SkGpuDevice.cpp8
-rw-r--r--tests/ImageFilterTest.cpp69
26 files changed, 260 insertions, 109 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index fba1f9a22e..fe85535741 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -60,3 +60,6 @@ filterbitmap_text_10.00pt
# Added by sugoi for added test in https://codereview.chromium.org/104853005
displacement
+
+# Added by senorblanco for new test case in https://codereview.chromium.org/112803004/
+imagefiltersgraph
diff --git a/gm/imagefiltersgraph.cpp b/gm/imagefiltersgraph.cpp
index 01ca5edad6..a8aa5fb416 100644
--- a/gm/imagefiltersgraph.cpp
+++ b/gm/imagefiltersgraph.cpp
@@ -182,6 +182,25 @@ protected:
drawClippedBitmap(canvas, fBitmap, paint);
canvas->translate(SkIntToScalar(100), 0);
}
+ {
+ // Test that crop offsets are absolute, not relative to the parent's crop rect.
+ SkAutoTUnref<SkColorFilter> cf1(SkColorFilter::CreateModeFilter(SK_ColorBLUE,
+ SkXfermode::kSrcIn_Mode));
+ SkAutoTUnref<SkColorFilter> cf2(SkColorFilter::CreateModeFilter(SK_ColorGREEN,
+ SkXfermode::kSrcIn_Mode));
+ SkImageFilter::CropRect outerRect(SkRect::MakeXYWH(SkIntToScalar(10), SkIntToScalar(10),
+ SkIntToScalar(80), SkIntToScalar(80)));
+ SkImageFilter::CropRect innerRect(SkRect::MakeXYWH(SkIntToScalar(20), SkIntToScalar(20),
+ SkIntToScalar(60), SkIntToScalar(60)));
+ SkAutoTUnref<SkImageFilter> color1(SkColorFilterImageFilter::Create(cf1, NULL, &outerRect));
+ SkAutoTUnref<SkImageFilter> color2(SkColorFilterImageFilter::Create(cf2, color1, &innerRect));
+
+ SkPaint paint;
+ paint.setImageFilter(color2);
+ paint.setColor(0xFFFF0000);
+ canvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
+ canvas->translate(SkIntToScalar(100), 0);
+ }
}
private:
diff --git a/gm/offsetimagefilter.cpp b/gm/offsetimagefilter.cpp
index 2d77bbd243..95f1a31fe5 100644
--- a/gm/offsetimagefilter.cpp
+++ b/gm/offsetimagefilter.cpp
@@ -70,9 +70,10 @@ protected:
void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint,
SkScalar x, SkScalar y) {
canvas->save();
- canvas->clipRect(SkRect::MakeXYWH(x, y,
+ canvas->translate(x, y);
+ canvas->clipRect(SkRect::MakeXYWH(0, 0,
SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())));
- canvas->drawBitmap(bitmap, x, y, &paint);
+ canvas->drawBitmap(bitmap, 0, 0, &paint);
canvas->restore();
}
@@ -88,8 +89,8 @@ protected:
int x = 0, y = 0;
for (size_t i = 0; i < 4; i++) {
SkBitmap* bitmap = (i & 0x01) ? &fCheckerboard : &fBitmap;
- SkIRect cropRect = SkIRect::MakeXYWH(x + i * 12,
- y + i * 8,
+ SkIRect cropRect = SkIRect::MakeXYWH(i * 12,
+ i * 8,
bitmap->width() - i * 8,
bitmap->height() - i * 12);
SkImageFilter::CropRect rect(SkRect::Make(cropRect));
diff --git a/gm/tileimagefilter.cpp b/gm/tileimagefilter.cpp
index 48d65ca073..2d6160fe82 100644
--- a/gm/tileimagefilter.cpp
+++ b/gm/tileimagefilter.cpp
@@ -31,7 +31,7 @@ protected:
fBitmap.allocPixels();
SkBitmapDevice device(fBitmap);
SkCanvas canvas(&device);
- canvas.clear(0x00000000);
+ canvas.clear(0xFF000000);
SkPaint paint;
paint.setAntiAlias(true);
paint.setColor(0xD000D000);
@@ -67,16 +67,6 @@ protected:
return make_isize(WIDTH, HEIGHT);
}
- void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint,
- SkScalar x, SkScalar y) {
- canvas->save();
- canvas->translate(x, y);
- canvas->clipRect(SkRect::MakeXYWH(0, 0,
- SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())));
- canvas->drawBitmap(bitmap, 0, 0, &paint);
- canvas->restore();
- }
-
virtual void onDraw(SkCanvas* canvas) {
if (!fInitialized) {
make_bitmap();
@@ -95,13 +85,16 @@ protected:
SkIntToScalar(bitmap->height()/(i+1)));
SkRect dstRect = SkRect::MakeXYWH(SkIntToScalar(i * 8),
SkIntToScalar(i * 4),
- SkIntToScalar(bitmap->width() - i * 4),
- SkIntToScalar(bitmap->height()) - i * 8);
+ SkIntToScalar(bitmap->width() - i * 12),
+ SkIntToScalar(bitmap->height()) - i * 12);
SkAutoTUnref<SkImageFilter> tileInput(SkNEW_ARGS(SkBitmapSource, (*bitmap)));
SkAutoTUnref<SkImageFilter> filter(SkNEW_ARGS(
SkTileImageFilter, (srcRect, dstRect, tileInput)));
+ canvas->save();
+ canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
paint.setImageFilter(filter);
- drawClippedBitmap(canvas, *bitmap, paint, SkIntToScalar(x), SkIntToScalar(y));
+ canvas->drawBitmap(fBitmap, 0, 0, &paint);
+ canvas->restore();
x += bitmap->width() + MARGIN;
if (x + bitmap->width() > WIDTH) {
x = 0;
diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h
index 4c372a413d..398af90ca0 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -71,7 +71,7 @@ public:
* The matrix is the current matrix on the canvas.
*
* Offset is the amount to translate the resulting image relative to the
- * src when it is drawn.
+ * src when it is drawn. This is an out-param.
*
* If the result image cannot be created, return false, in which case both
* the result and offset parameters will be ignored by the caller.
@@ -167,7 +167,22 @@ protected:
virtual void flatten(SkFlattenableWriteBuffer& wb) const SK_OVERRIDE;
- // Default impl returns false
+ /**
+ * This is the virtual which should be overridden by the derived class
+ * to perform image filtering.
+ *
+ * src is the original primitive bitmap. If the filter has a connected
+ * input, it should recurse on that input and use that in place of src.
+ *
+ * The matrix is the current matrix on the canvas.
+ *
+ * Offset is the amount to translate the resulting image relative to the
+ * src when it is drawn. This is an out-param.
+ *
+ * If the result image cannot be created, this should false, in which
+ * case both the result and offset parameters will be ignored by the
+ * caller.
+ */
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* offset);
// Default impl copies src into dst and returns true
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 62021cb535..29c09d1e7a 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -998,13 +998,15 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
if (filter && !dstDev->canHandleImageFilter(filter)) {
SkDeviceImageFilterProxy proxy(dstDev);
SkBitmap dst;
+ SkIPoint offset = SkIPoint::Make(0, 0);
const SkBitmap& src = srcDev->accessBitmap(false);
SkMatrix matrix = *iter.fMatrix;
matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
- if (filter->filterImage(&proxy, src, matrix, &dst, &pos)) {
+ if (filter->filterImage(&proxy, src, matrix, &dst, &offset)) {
SkPaint tmpUnfiltered(*paint);
tmpUnfiltered.setImageFilter(NULL);
- dstDev->drawSprite(iter, dst, pos.x(), pos.y(), tmpUnfiltered);
+ dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
+ tmpUnfiltered);
}
} else {
dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
@@ -1036,12 +1038,13 @@ void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
SkDeviceImageFilterProxy proxy(iter.fDevice);
SkBitmap dst;
+ SkIPoint offset = SkIPoint::Make(0, 0);
SkMatrix matrix = *iter.fMatrix;
matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
- if (filter->filterImage(&proxy, bitmap, matrix, &dst, &pos)) {
+ if (filter->filterImage(&proxy, bitmap, matrix, &dst, &offset)) {
SkPaint tmpUnfiltered(*paint);
tmpUnfiltered.setImageFilter(NULL);
- iter.fDevice->drawSprite(iter, dst, pos.x(), pos.y(),
+ iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
tmpUnfiltered);
}
} else {
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index cda635b4fb..d62685a17c 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -93,15 +93,15 @@ void SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* loc) {
+ SkBitmap* result, SkIPoint* offset) {
SkASSERT(result);
- SkASSERT(loc);
+ SkASSERT(offset);
/*
* Give the proxy first shot at the filter. If it returns false, ask
* the filter to do it.
*/
- return (proxy && proxy->filterImage(this, src, ctm, result, loc)) ||
- this->onFilterImage(proxy, src, ctm, result, loc);
+ return (proxy && proxy->filterImage(this, src, ctm, result, offset)) ||
+ this->onFilterImage(proxy, src, ctm, result, offset);
}
bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
diff --git a/src/core/SkImageFilterUtils.cpp b/src/core/SkImageFilterUtils.cpp
index a59cf7bbbd..92fe67e84c 100644
--- a/src/core/SkImageFilterUtils.cpp
+++ b/src/core/SkImageFilterUtils.cpp
@@ -35,6 +35,7 @@ bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter:
GrContext* context = src.getTexture()->getContext();
GrContext::AutoWideOpenIdentityDraw awoid(context, NULL);
if (!filter) {
+ offset->fX = offset->fY = 0;
*result = src;
return true;
} else if (filter->canFilterImageGPU()) {
diff --git a/src/effects/SkBicubicImageFilter.cpp b/src/effects/SkBicubicImageFilter.cpp
index 87ff046fc1..96d46aa7ce 100644
--- a/src/effects/SkBicubicImageFilter.cpp
+++ b/src/effects/SkBicubicImageFilter.cpp
@@ -84,9 +84,10 @@ bool SkBicubicImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source,
const SkMatrix& matrix,
SkBitmap* result,
- SkIPoint* loc) {
+ SkIPoint* offset) {
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, loc)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, &srcOffset)) {
return false;
}
@@ -114,6 +115,7 @@ bool SkBicubicImageFilter::onFilterImage(Proxy* proxy,
SkRect srcRect;
src.getBounds(&srcRect);
+ srcRect.offset(SkPoint::Make(SkIntToScalar(srcOffset.fX), SkIntToScalar(srcOffset.fY)));
SkMatrix inverse;
inverse.setRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit);
inverse.postTranslate(-0.5f, -0.5f);
@@ -158,6 +160,8 @@ bool SkBicubicImageFilter::onFilterImage(Proxy* proxy,
*dptr++ = cubicBlend(fCoefficients, fracty, s0, s1, s2, s3);
}
}
+ offset->fX = dstIRect.fLeft;
+ offset->fY = dstIRect.fTop;
return true;
}
diff --git a/src/effects/SkBitmapSource.cpp b/src/effects/SkBitmapSource.cpp
index b5ee1dd834..daf4fb08b3 100644
--- a/src/effects/SkBitmapSource.cpp
+++ b/src/effects/SkBitmapSource.cpp
@@ -49,6 +49,7 @@ bool SkBitmapSource::onFilterImage(Proxy* proxy, const SkBitmap&, const SkMatrix
if (fSrcRect == bounds && dstRect == bounds) {
// No regions cropped out or resized; return entire bitmap.
*result = fBitmap;
+ offset->fX = offset->fY = 0;
return true;
}
SkIRect dstIRect;
@@ -73,7 +74,7 @@ bool SkBitmapSource::onFilterImage(Proxy* proxy, const SkBitmap&, const SkMatrix
canvas.drawBitmapRectToRect(fBitmap, &fSrcRect, dstRect, &paint);
*result = device.get()->accessBitmap(false);
- offset->fX += dstIRect.fLeft;
- offset->fY += dstIRect.fTop;
+ offset->fX = dstIRect.fLeft;
+ offset->fY = dstIRect.fTop;
return true;
}
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp
index 2795f3a872..5efef0ba50 100644
--- a/src/effects/SkBlurImageFilter.cpp
+++ b/src/effects/SkBlurImageFilter.cpp
@@ -137,7 +137,8 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source, const SkMatrix& ctm,
SkBitmap* dst, SkIPoint* offset) {
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, offset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, &srcOffset)) {
return false;
}
@@ -152,6 +153,7 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
SkIRect srcBounds, dstBounds;
src.getBounds(&srcBounds);
+ srcBounds.offset(srcOffset);
if (!this->applyCropRect(&srcBounds, ctm)) {
return false;
}
@@ -174,6 +176,8 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
if (kernelSizeX == 0 && kernelSizeY == 0) {
src.copyTo(dst, dst->config());
+ offset->fX = srcBounds.fLeft;
+ offset->fY = srcBounds.fTop;
return true;
}
@@ -183,6 +187,9 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
return false;
}
+ offset->fX = srcBounds.fLeft;
+ offset->fY = srcBounds.fTop;
+ srcBounds.offset(-srcOffset);
const SkPMColor* s = src.getAddr32(srcBounds.left(), srcBounds.top());
SkPMColor* t = temp.getAddr32(0, 0);
SkPMColor* d = dst->getAddr32(0, 0);
@@ -212,8 +219,6 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
boxBlurX(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h, w);
boxBlurXY(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h, w);
}
- offset->fX += srcBounds.fLeft;
- offset->fY += srcBounds.fTop;
return true;
}
@@ -237,8 +242,8 @@ bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const
true,
fSigma.width(),
fSigma.height()));
- offset->fX += rect.fLeft;
- offset->fY += rect.fTop;
+ offset->fX = rect.fLeft;
+ offset->fY = rect.fTop;
return SkImageFilterUtils::WrapTexture(tex, rect.width(), rect.height(), result);
#else
SkDEBUGFAIL("Should not call in GPU-less build");
diff --git a/src/effects/SkColorFilterImageFilter.cpp b/src/effects/SkColorFilterImageFilter.cpp
index 8b7b390ea8..d648b6c4a7 100755
--- a/src/effects/SkColorFilterImageFilter.cpp
+++ b/src/effects/SkColorFilterImageFilter.cpp
@@ -100,14 +100,16 @@ SkColorFilterImageFilter::~SkColorFilterImageFilter() {
bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
const SkMatrix& matrix,
SkBitmap* result,
- SkIPoint* loc) {
+ SkIPoint* offset) {
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, loc)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, &srcOffset)) {
return false;
}
SkIRect bounds;
src.getBounds(&bounds);
+ bounds.offset(srcOffset);
if (!this->applyCropRect(&bounds, matrix)) {
return false;
}
@@ -121,11 +123,11 @@ bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& sourc
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
paint.setColorFilter(fColorFilter);
- canvas.drawSprite(src, -bounds.fLeft, -bounds.fTop, &paint);
+ canvas.drawSprite(src, srcOffset.fX - bounds.fLeft, srcOffset.fY - bounds.fTop, &paint);
*result = device.get()->accessBitmap(false);
- loc->fX += bounds.fLeft;
- loc->fY += bounds.fTop;
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
return true;
}
diff --git a/src/effects/SkComposeImageFilter.cpp b/src/effects/SkComposeImageFilter.cpp
index 2412d9fe87..7445bdfe91 100644
--- a/src/effects/SkComposeImageFilter.cpp
+++ b/src/effects/SkComposeImageFilter.cpp
@@ -16,7 +16,7 @@ bool SkComposeImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& src,
const SkMatrix& ctm,
SkBitmap* result,
- SkIPoint* loc) {
+ SkIPoint* offset) {
SkImageFilter* outer = getInput(0);
SkImageFilter* inner = getInput(1);
@@ -25,12 +25,12 @@ bool SkComposeImageFilter::onFilterImage(Proxy* proxy,
}
if (!outer || !inner) {
- return (outer ? outer : inner)->filterImage(proxy, src, ctm, result, loc);
+ return (outer ? outer : inner)->filterImage(proxy, src, ctm, result, offset);
}
SkBitmap tmp;
- return inner->filterImage(proxy, src, ctm, &tmp, loc) &&
- outer->filterImage(proxy, tmp, ctm, result, loc);
+ return inner->filterImage(proxy, src, ctm, &tmp, offset) &&
+ outer->filterImage(proxy, tmp, ctm, result, offset);
}
bool SkComposeImageFilter::onFilterBounds(const SkIRect& src,
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 3087b63c7a..e9a9acb4ce 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -221,8 +221,8 @@ bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy,
computeDisplacement(fXChannelSelector, fYChannelSelector, fScale, dst, &displ, &color, bounds);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
@@ -356,8 +356,8 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
SkRect srcRect = SkRect::Make(bounds);
SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
context->drawRectToRect(paint, dstRect, srcRect);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return SkImageFilterUtils::WrapTexture(dst, bounds.width(), bounds.height(), result);
}
diff --git a/src/effects/SkDropShadowImageFilter.cpp b/src/effects/SkDropShadowImageFilter.cpp
index 24a910d0b6..60294e4f02 100644
--- a/src/effects/SkDropShadowImageFilter.cpp
+++ b/src/effects/SkDropShadowImageFilter.cpp
@@ -57,14 +57,16 @@ void SkDropShadowImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const
buffer.writeColor(fColor);
}
-bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, const SkMatrix& matrix, SkBitmap* result, SkIPoint* loc)
+bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, const SkMatrix& matrix, SkBitmap* result, SkIPoint* offset)
{
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, loc))
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, &srcOffset))
return false;
SkIRect bounds;
src.getBounds(&bounds);
+ bounds.offset(srcOffset);
if (!this->applyCropRect(&bounds, matrix)) {
return false;
}
@@ -85,7 +87,7 @@ bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source
canvas.drawBitmap(src, fDx, fDy, &paint);
canvas.drawBitmap(src, 0, 0);
*result = device->accessBitmap(false);
- loc->fX += bounds.fLeft;
- loc->fY += bounds.fTop;
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
return true;
}
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index 50cca07dfd..b24a91eb44 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -927,7 +927,8 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
SkIPoint* offset) {
SkImageFilter* input = getInput(0);
SkBitmap src = source;
- if (input && !input->filterImage(proxy, source, ctm, &src, offset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (input && !input->filterImage(proxy, source, ctm, &src, &srcOffset)) {
return false;
}
@@ -941,6 +942,7 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
SkIRect bounds;
src.getBounds(&bounds);
+ bounds.offset(srcOffset);
if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
@@ -958,6 +960,9 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
SkAutoTUnref<SkLight> transformedLight(light()->transform(ctm));
DiffuseLightingType lightingType(fKD);
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
+ bounds.offset(-srcOffset);
switch (transformedLight->type()) {
case SkLight::kDistant_LightType:
lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
@@ -970,8 +975,6 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
break;
}
- offset->fX += bounds.left();
- offset->fY += bounds.top();
return true;
}
@@ -1018,7 +1021,8 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
SkIPoint* offset) {
SkImageFilter* input = getInput(0);
SkBitmap src = source;
- if (input && !input->filterImage(proxy, source, ctm, &src, offset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (input && !input->filterImage(proxy, source, ctm, &src, &srcOffset)) {
return false;
}
@@ -1032,6 +1036,7 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
SkIRect bounds;
src.getBounds(&bounds);
+ bounds.offset(srcOffset);
if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
@@ -1047,6 +1052,9 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
}
SpecularLightingType lightingType(fKS, fShininess);
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
+ bounds.offset(-srcOffset);
SkAutoTUnref<SkLight> transformedLight(light()->transform(ctm));
switch (transformedLight->type()) {
case SkLight::kDistant_LightType:
@@ -1059,8 +1067,6 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
break;
}
- offset->fX += bounds.left();
- offset->fY += bounds.top();
return true;
}
diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp
index 3da27cef26..a450040000 100644
--- a/src/effects/SkMatrixConvolutionImageFilter.cpp
+++ b/src/effects/SkMatrixConvolutionImageFilter.cpp
@@ -252,9 +252,10 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source,
const SkMatrix& matrix,
SkBitmap* result,
- SkIPoint* loc) {
+ SkIPoint* offset) {
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, loc)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, &srcOffset)) {
return false;
}
@@ -264,6 +265,7 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
SkIRect bounds;
src.getBounds(&bounds);
+ bounds.offset(srcOffset);
if (!this->applyCropRect(&bounds, matrix)) {
return false;
}
@@ -283,6 +285,9 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
return false;
}
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
+ bounds.offset(-srcOffset);
SkIRect interior = SkIRect::MakeXYWH(bounds.left() + fTarget.fX,
bounds.top() + fTarget.fY,
bounds.width() - fKernelSize.fWidth + 1,
@@ -299,8 +304,6 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
filterInteriorPixels(src, result, interior, bounds);
filterBorderPixels(src, result, right, bounds);
filterBorderPixels(src, result, bottom, bounds);
- loc->fX += bounds.fLeft;
- loc->fY += bounds.fTop;
return true;
}
diff --git a/src/effects/SkMergeImageFilter.cpp b/src/effects/SkMergeImageFilter.cpp
index 528fe823eb..9c0fa92a2b 100755
--- a/src/effects/SkMergeImageFilter.cpp
+++ b/src/effects/SkMergeImageFilter.cpp
@@ -98,7 +98,7 @@ bool SkMergeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* loc) {
+ SkBitmap* result, SkIPoint* offset) {
if (countInputs() < 1) {
return false;
}
@@ -142,8 +142,8 @@ bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint);
}
- loc->fX += bounds.left();
- loc->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
*result = dst->accessBitmap(false);
return true;
}
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index 0d00c359d8..1f8bca111f 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -167,7 +167,8 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source, const SkMatrix& ctm,
SkBitmap* dst, SkIPoint* offset) {
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, offset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, &srcOffset)) {
return false;
}
@@ -177,6 +178,7 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
SkIRect bounds;
src.getBounds(&bounds);
+ bounds.offset(srcOffset);
if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
@@ -201,8 +203,8 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
if (width == 0 && height == 0) {
src.extractSubset(dst, bounds);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
@@ -212,6 +214,9 @@ 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());
@@ -221,8 +226,6 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
} else if (height > 0) {
erodeY(src, dst, height, bounds);
}
- offset->fX += bounds.left();
- offset->fY += bounds.top();
return true;
}
@@ -230,7 +233,8 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source, const SkMatrix& ctm,
SkBitmap* dst, SkIPoint* offset) {
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, offset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, &srcOffset)) {
return false;
}
if (src.config() != SkBitmap::kARGB_8888_Config) {
@@ -239,6 +243,7 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
SkIRect bounds;
src.getBounds(&bounds);
+ bounds.offset(srcOffset);
if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
@@ -263,8 +268,8 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
if (width == 0 && height == 0) {
src.extractSubset(dst, bounds);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
@@ -274,6 +279,9 @@ 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());
@@ -283,8 +291,6 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
} else if (height > 0) {
dilateY(src, dst, height, bounds);
}
- offset->fX += bounds.left();
- offset->fY += bounds.top();
return true;
}
@@ -580,16 +586,16 @@ bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, cons
if (width == 0 && height == 0) {
src.extractSubset(result, bounds);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
if (!apply_morphology(input, bounds, GrMorphologyEffect::kDilate_MorphologyType, radius(), result)) {
return false;
}
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
@@ -613,16 +619,16 @@ bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const
if (width == 0 && height == 0) {
src.extractSubset(result, bounds);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
if (!apply_morphology(input, bounds, GrMorphologyEffect::kErode_MorphologyType, radius(), result)) {
return false;
}
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
diff --git a/src/effects/SkOffsetImageFilter.cpp b/src/effects/SkOffsetImageFilter.cpp
index 59318e3915..61f68f7afe 100644
--- a/src/effects/SkOffsetImageFilter.cpp
+++ b/src/effects/SkOffsetImageFilter.cpp
@@ -16,32 +16,33 @@
bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
const SkMatrix& matrix,
SkBitmap* result,
- SkIPoint* loc) {
+ SkIPoint* offset) {
SkImageFilter* input = getInput(0);
SkBitmap src = source;
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
#ifdef SK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION
if (false) {
#else
if (!cropRectIsSet()) {
#endif
- if (input && !input->filterImage(proxy, source, matrix, &src, loc)) {
+ if (input && !input->filterImage(proxy, source, matrix, &src, &srcOffset)) {
return false;
}
SkVector vec;
matrix.mapVectors(&vec, &fOffset, 1);
- loc->fX += SkScalarRoundToInt(vec.fX);
- loc->fY += SkScalarRoundToInt(vec.fY);
+ offset->fX = srcOffset.fX + SkScalarRoundToInt(vec.fX);
+ offset->fY = srcOffset.fY + SkScalarRoundToInt(vec.fY);
*result = src;
} else {
- SkIPoint srcOffset = SkIPoint::Make(0, 0);
if (input && !input->filterImage(proxy, source, matrix, &src, &srcOffset)) {
return false;
}
SkIRect bounds;
src.getBounds(&bounds);
+ bounds.offset(srcOffset);
if (!applyCropRect(&bounds, matrix)) {
return false;
@@ -54,10 +55,12 @@ bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
SkCanvas canvas(device);
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- canvas.drawBitmap(src, fOffset.fX - bounds.left(), fOffset.fY - bounds.top(), &paint);
+ canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
+ SkIntToScalar(srcOffset.fY - bounds.fTop));
+ canvas.drawBitmap(src, fOffset.x(), fOffset.y(), &paint);
*result = device->accessBitmap(false);
- loc->fX += bounds.left();
- loc->fY += bounds.top();
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
}
return true;
}
diff --git a/src/effects/SkPictureImageFilter.cpp b/src/effects/SkPictureImageFilter.cpp
index 5b4af6548c..b054ee21a8 100644
--- a/src/effects/SkPictureImageFilter.cpp
+++ b/src/effects/SkPictureImageFilter.cpp
@@ -46,6 +46,7 @@ void SkPictureImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
bool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const SkMatrix& matrix,
SkBitmap* result, SkIPoint* offset) {
if (!fPicture) {
+ offset->fX = offset->fY = 0;
return true;
}
@@ -55,6 +56,7 @@ bool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const Sk
floatBounds.roundOut(&bounds);
if (bounds.isEmpty()) {
+ offset->fX = offset->fY = 0;
return true;
}
@@ -71,7 +73,7 @@ bool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const Sk
canvas.drawPicture(*fPicture);
*result = device.get()->accessBitmap(false);
- offset->fX += bounds.fLeft;
- offset->fY += bounds.fTop;
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
return true;
}
diff --git a/src/effects/SkRectShaderImageFilter.cpp b/src/effects/SkRectShaderImageFilter.cpp
index 5c34547cb3..f55df2c577 100644
--- a/src/effects/SkRectShaderImageFilter.cpp
+++ b/src/effects/SkRectShaderImageFilter.cpp
@@ -74,7 +74,7 @@ bool SkRectShaderImageFilter::onFilterImage(Proxy* proxy,
SkRect rect = SkRect::MakeWH(SkIntToScalar(bounds.width()), SkIntToScalar(bounds.height()));
canvas.drawRect(rect, paint);
*result = device.get()->accessBitmap(false);
- offset->fX += bounds.fLeft;
- offset->fY += bounds.fTop;
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
return true;
}
diff --git a/src/effects/SkTileImageFilter.cpp b/src/effects/SkTileImageFilter.cpp
index 73e5304adb..08dfec4493 100644
--- a/src/effects/SkTileImageFilter.cpp
+++ b/src/effects/SkTileImageFilter.cpp
@@ -19,15 +19,17 @@ bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const S
SkBitmap* dst, SkIPoint* offset) {
SkBitmap source = src;
SkImageFilter* input = getInput(0);
- SkIPoint localOffset = SkIPoint::Make(0, 0);
- if (input && !input->filterImage(proxy, src, ctm, &source, &localOffset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (input && !input->filterImage(proxy, src, ctm, &source, &srcOffset)) {
return false;
}
SkRect dstRect;
ctm.mapRect(&dstRect, fDstRect);
- int w = SkScalarCeilToInt(dstRect.width());
- int h = SkScalarCeilToInt(dstRect.height());
+ SkIRect dstIRect;
+ dstRect.roundOut(&dstIRect);
+ int w = dstIRect.width();
+ int h = dstIRect.height();
if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) {
return false;
}
@@ -36,10 +38,13 @@ bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const S
ctm.mapRect(&srcRect, fSrcRect);
SkIRect srcIRect;
srcRect.roundOut(&srcIRect);
+ srcIRect.offset(-srcOffset);
SkBitmap subset;
SkIRect bounds;
source.getBounds(&bounds);
+
if (!srcIRect.intersect(bounds)) {
+ offset->fX = offset->fY = 0;
return true;
} else if (!source.extractSubset(&subset, srcIRect)) {
return false;
@@ -55,10 +60,16 @@ bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const S
SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
+ SkMatrix shaderMatrix;
+ shaderMatrix.setTranslate(SkIntToScalar(srcOffset.fX),
+ SkIntToScalar(srcOffset.fY));
+ shader->setLocalMatrix(shaderMatrix);
paint.setShader(shader);
- dstRect.offset(SkIntToScalar(localOffset.fX), SkIntToScalar(localOffset.fY));
+ canvas.translate(-dstRect.fLeft, -dstRect.fTop);
canvas.drawRect(dstRect, paint);
*dst = device->accessBitmap(false);
+ offset->fX = dstIRect.fLeft;
+ offset->fY = dstIRect.fTop;
return true;
}
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index 4674ff44ab..beb1de211c 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -88,8 +88,8 @@ bool SkXfermodeImageFilter::onFilterImage(Proxy* proxy,
paint.setColor(SK_ColorTRANSPARENT);
canvas.drawPaint(paint);
*dst = device->accessBitmap(false);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
@@ -157,8 +157,8 @@ bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
foregroundPaint.addColorTextureEffect(foregroundTex, foregroundMatrix);
context->drawRect(foregroundPaint, srcRect);
}
- offset->fX += backgroundOffset.fX;
- offset->fY += backgroundOffset.fY;
+ offset->fX = backgroundOffset.fX;
+ offset->fY = backgroundOffset.fY;
return SkImageFilterUtils::WrapTexture(dst, src.width(), src.height(), result);
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index b18f54b595..680dd89984 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1494,11 +1494,11 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
SkAutoCachedTexture act(this, bitmap, NULL, &texture);
SkImageFilter* filter = paint.getImageFilter();
- SkIPoint offset = SkIPoint::Make(left, top);
// This bitmap will own the filtered result as a texture.
SkBitmap filteredBitmap;
if (NULL != filter) {
+ SkIPoint offset = SkIPoint::Make(0, 0);
SkMatrix matrix(*draw.fMatrix);
matrix.postTranslate(SkIntToScalar(-left), SkIntToScalar(-top));
if (filter_texture(this, fContext, texture, filter, w, h, matrix, &filteredBitmap,
@@ -1506,6 +1506,8 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
texture = (GrTexture*) filteredBitmap.getTexture();
w = filteredBitmap.width();
h = filteredBitmap.height();
+ left += offset.x();
+ top += offset.y();
} else {
return;
}
@@ -1519,8 +1521,8 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
}
fContext->drawRectToRect(grPaint,
- SkRect::MakeXYWH(SkIntToScalar(offset.fX),
- SkIntToScalar(offset.fY),
+ SkRect::MakeXYWH(SkIntToScalar(left),
+ SkIntToScalar(top),
SkIntToScalar(w),
SkIntToScalar(h)),
SkRect::MakeXYWH(0,
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index 4301fc3967..44b917c205 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -15,7 +15,16 @@
#include "SkColorMatrixFilter.h"
#include "SkColorFilterImageFilter.h"
#include "SkDeviceImageFilterProxy.h"
+#include "SkBlurImageFilter.h"
+#include "SkDisplacementMapEffect.h"
+#include "SkDropShadowImageFilter.h"
#include "SkLightingImageFilter.h"
+#include "SkMergeImageFilter.h"
+#include "SkMorphologyImageFilter.h"
+#include "SkMatrixConvolutionImageFilter.h"
+#include "SkOffsetImageFilter.h"
+#include "SkTileImageFilter.h"
+#include "SkXfermodeImageFilter.h"
#include "SkRect.h"
static const int kBitmapSize = 4;
@@ -148,4 +157,64 @@ DEF_TEST(ImageFilter, reporter) {
!bicubic->filterImage(&proxy, bitmap, SkMatrix::I(), &result, &loc));
}
}
+
+ {
+ // Check that all filters offset to their absolute crop rect,
+ // unaffected by the input crop rect.
+ // Tests pass by not asserting.
+ SkBitmap bitmap, temp;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
+ temp.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
+ bitmap.allocPixels();
+ temp.allocPixels();
+ bitmap.eraseARGB(0, 0, 0, 0);
+ SkBitmapDevice device(temp);
+ SkDeviceImageFilterProxy proxy(&device);
+
+ SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
+ SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
+ SkAutoTUnref<SkImageFilter> input(make_grayscale(NULL, &inputCropRect));
+
+ SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
+ SkPoint3 location(0, 0, SK_Scalar1);
+ SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
+ SkScalar kernel[9] = {
+ SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
+ SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
+ SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
+ };
+ SkISize kernelSize = SkISize::Make(3, 3);
+ SkScalar gain = SK_Scalar1, bias = 0;
+
+ SkImageFilter* filters[] = {
+ SkColorFilterImageFilter::Create(cf.get(), input.get(), &cropRect),
+ new SkDisplacementMapEffect(SkDisplacementMapEffect::kR_ChannelSelectorType,
+ SkDisplacementMapEffect::kB_ChannelSelectorType,
+ 40.0f, input.get(), input.get(), &cropRect),
+ new SkBlurImageFilter(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
+ new SkDropShadowImageFilter(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN, input.get(), &cropRect),
+ SkLightingImageFilter::CreatePointLitDiffuse(location, SK_ColorGREEN, 0, 0, input.get(), &cropRect),
+ SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input.get(), &cropRect),
+ new SkMatrixConvolutionImageFilter(kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), SkMatrixConvolutionImageFilter::kRepeat_TileMode, false, input.get(), &cropRect),
+ new SkMergeImageFilter(input.get(), input.get(), SkXfermode::kSrcOver_Mode, &cropRect),
+ new SkOffsetImageFilter(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
+ new SkOffsetImageFilter(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
+ new SkDilateImageFilter(3, 2, input.get(), &cropRect),
+ new SkErodeImageFilter(2, 3, input.get(), &cropRect),
+ new SkTileImageFilter(inputCropRect.rect(), cropRect.rect(), input.get()),
+ new SkXfermodeImageFilter(SkXfermode::Create(SkXfermode::kSrcOver_Mode), input.get(), input.get(), &cropRect),
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
+ SkImageFilter* filter = filters[i];
+ SkBitmap result;
+ SkIPoint offset;
+ REPORTER_ASSERT(reporter, filter->filterImage(&proxy, bitmap, SkMatrix::I(), &result, &offset));
+ REPORTER_ASSERT(reporter, offset.fX == 20 && offset.fY == 30);
+ }
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
+ SkSafeUnref(filters[i]);
+ }
+ }
}