Fix for partially-specified crop rects.
When only the left or top edge of a crop rect is given, the
right and bottom should be computed based on the incoming width
and height, not based on the crop rect's width & height. This
complies more accurately with SVG semantics.
BUG=240827
Review URL: https://codereview.chromium.org/1232873002
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index 8a3fbb4..178d892 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -302,10 +302,18 @@
ctx.ctm().mapRect(&cropRect, fCropRect.rect());
const SkIRect cropRectI = cropRect.roundOut();
uint32_t flags = fCropRect.flags();
- if (flags & CropRect::kHasLeft_CropEdge) srcBounds.fLeft = cropRectI.fLeft;
- if (flags & CropRect::kHasTop_CropEdge) srcBounds.fTop = cropRectI.fTop;
- if (flags & CropRect::kHasRight_CropEdge) srcBounds.fRight = cropRectI.fRight;
- if (flags & CropRect::kHasBottom_CropEdge) srcBounds.fBottom = cropRectI.fBottom;
+ if (flags & CropRect::kHasLeft_CropEdge) {
+ srcBounds.fLeft = cropRectI.fLeft;
+ }
+ if (flags & CropRect::kHasTop_CropEdge) {
+ srcBounds.fTop = cropRectI.fTop;
+ }
+ if (flags & CropRect::kHasRight_CropEdge) {
+ srcBounds.fRight = srcBounds.fLeft + cropRectI.width();
+ }
+ if (flags & CropRect::kHasBottom_CropEdge) {
+ srcBounds.fBottom = srcBounds.fTop + cropRectI.height();
+ }
if (!srcBounds.intersect(ctx.clipBounds())) {
return false;
}
@@ -323,10 +331,18 @@
const SkIRect cropRectI = cropRect.roundOut();
uint32_t flags = fCropRect.flags();
*bounds = srcBounds;
- if (flags & CropRect::kHasLeft_CropEdge) bounds->fLeft = cropRectI.fLeft;
- if (flags & CropRect::kHasTop_CropEdge) bounds->fTop = cropRectI.fTop;
- if (flags & CropRect::kHasRight_CropEdge) bounds->fRight = cropRectI.fRight;
- if (flags & CropRect::kHasBottom_CropEdge) bounds->fBottom = cropRectI.fBottom;
+ if (flags & CropRect::kHasLeft_CropEdge) {
+ bounds->fLeft = cropRectI.fLeft;
+ }
+ if (flags & CropRect::kHasTop_CropEdge) {
+ bounds->fTop = cropRectI.fTop;
+ }
+ if (flags & CropRect::kHasRight_CropEdge) {
+ bounds->fRight = bounds->fLeft + cropRectI.width();
+ }
+ if (flags & CropRect::kHasBottom_CropEdge) {
+ bounds->fBottom = bounds->fTop + cropRectI.height();
+ }
if (!bounds->intersect(ctx.clipBounds())) {
return false;
}
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index 480a75f..dc35332 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -1139,6 +1139,27 @@
REPORTER_ASSERT(reporter, offset.fX == 1 && offset.fY == 0);
}
+DEF_TEST(PartialCropRect, reporter) {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(100, 100);
+ bitmap.eraseARGB(0, 0, 0, 0);
+ const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
+ SkBitmapDevice device(bitmap, props);
+ SkImageFilter::Proxy proxy(&device);
+
+ SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(100, 0, 20, 30),
+ SkImageFilter::CropRect::kHasRight_CropEdge | SkImageFilter::CropRect::kHasBottom_CropEdge);
+ SkAutoTUnref<SkImageFilter> filter(make_grayscale(NULL, &cropRect));
+ SkBitmap result;
+ SkIPoint offset;
+ SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeLargest(), NULL);
+ REPORTER_ASSERT(reporter, filter->filterImage(&proxy, bitmap, ctx, &result, &offset));
+ REPORTER_ASSERT(reporter, offset.fX == 0);
+ REPORTER_ASSERT(reporter, offset.fY == 0);
+ REPORTER_ASSERT(reporter, result.width() == 20);
+ REPORTER_ASSERT(reporter, result.height() == 30);
+}
+
#if SK_SUPPORT_GPU
DEF_GPUTEST(ImageFilterCropRectGPU, reporter, factory) {