aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--expectations/gm/ignored-tests.txt4
-rw-r--r--gm/tileimagefilter.cpp33
-rw-r--r--include/effects/SkMatrixConvolutionImageFilter.h2
-rw-r--r--include/effects/SkTileImageFilter.h2
-rw-r--r--src/effects/SkMatrixConvolutionImageFilter.cpp13
-rw-r--r--src/effects/SkTileImageFilter.cpp11
-rw-r--r--tests/ImageFilterTest.cpp111
7 files changed, 172 insertions, 4 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index f02913bc4a..b92e5f77f8 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -60,3 +60,7 @@ peekpixels
# humper: https://codereview.chromium.org/248613004/
# Changed the test in a few ways, will need rebaselining.
simpleblurroundrect
+
+# senorblanco: http://YOUR_CODE_REVIEW_HERE/
+# Added a new test case; reduced the text bitmap size
+tileimagefilter
diff --git a/gm/tileimagefilter.cpp b/gm/tileimagefilter.cpp
index d6c8d4cbfc..c7842ee97c 100644
--- a/gm/tileimagefilter.cpp
+++ b/gm/tileimagefilter.cpp
@@ -6,6 +6,8 @@
*/
#include "gm.h"
+#include "SkColorMatrixFilter.h"
+#include "SkColorFilterImageFilter.h"
#include "SkTileImageFilter.h"
#include "SkBitmapSource.h"
@@ -27,15 +29,15 @@ protected:
}
void make_bitmap() {
- fBitmap.allocN32Pixels(80, 80);
+ fBitmap.allocN32Pixels(50, 50);
SkCanvas canvas(fBitmap);
canvas.clear(0xFF000000);
SkPaint paint;
paint.setAntiAlias(true);
paint.setColor(0xD000D000);
- paint.setTextSize(SkIntToScalar(96));
+ paint.setTextSize(SkIntToScalar(50));
const char* str = "e";
- canvas.drawText(str, strlen(str), SkIntToScalar(15), SkIntToScalar(65), paint);
+ canvas.drawText(str, strlen(str), SkIntToScalar(10), SkIntToScalar(45), paint);
}
void make_checkerboard() {
@@ -70,7 +72,6 @@ protected:
fInitialized = true;
}
canvas->clear(0x00000000);
- SkPaint paint;
int x = 0, y = 0;
for (size_t i = 0; i < 4; i++) {
@@ -88,6 +89,7 @@ protected:
SkTileImageFilter::Create(srcRect, dstRect, tileInput));
canvas->save();
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
+ SkPaint paint;
paint.setImageFilter(filter);
canvas->drawBitmap(fBitmap, 0, 0, &paint);
canvas->restore();
@@ -97,6 +99,29 @@ protected:
y += bitmap->height() + MARGIN;
}
}
+
+ SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
+ 0, SK_Scalar1, 0, 0, 0,
+ 0, 0, SK_Scalar1, 0, 0,
+ 0, 0, 0, SK_Scalar1, 0 };
+
+ SkRect srcRect = SkRect::MakeWH(SkIntToScalar(fBitmap.width()),
+ SkIntToScalar(fBitmap.height()));
+ SkRect dstRect = SkRect::MakeWH(SkIntToScalar(fBitmap.width() * 2),
+ SkIntToScalar(fBitmap.height() * 2));
+ SkAutoTUnref<SkImageFilter> tile(SkTileImageFilter::Create(srcRect, dstRect, NULL));
+ SkAutoTUnref<SkColorFilter> cf(SkColorMatrixFilter::Create(matrix));
+
+ SkAutoTUnref<SkImageFilter> cfif(SkColorFilterImageFilter::Create(cf, tile.get()));
+ SkPaint paint;
+ paint.setImageFilter(cfif);
+ canvas->save();
+ canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
+ canvas->clipRect(dstRect);
+ canvas->saveLayer(&dstRect, &paint);
+ canvas->drawBitmap(fBitmap, 0, 0);
+ canvas->restore();
+ canvas->restore();
}
private:
typedef GM INHERITED;
diff --git a/include/effects/SkMatrixConvolutionImageFilter.h b/include/effects/SkMatrixConvolutionImageFilter.h
index 5b02fbaab5..ee1bfcf3d9 100644
--- a/include/effects/SkMatrixConvolutionImageFilter.h
+++ b/include/effects/SkMatrixConvolutionImageFilter.h
@@ -73,6 +73,8 @@ protected:
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE;
+ virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const SK_OVERRIDE;
+
#if SK_SUPPORT_GPU
virtual bool asNewEffect(GrEffectRef** effect,
diff --git a/include/effects/SkTileImageFilter.h b/include/effects/SkTileImageFilter.h
index 6c0fa68f3c..c26ae9aef8 100644
--- a/include/effects/SkTileImageFilter.h
+++ b/include/effects/SkTileImageFilter.h
@@ -26,6 +26,8 @@ public:
virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const Context& ctx,
SkBitmap* dst, SkIPoint* offset) const SK_OVERRIDE;
+ virtual bool onFilterBounds(const SkIRect& src, const SkMatrix&,
+ SkIRect* dst) const SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTileImageFilter)
diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp
index 878cbae795..3c9fc87787 100644
--- a/src/effects/SkMatrixConvolutionImageFilter.cpp
+++ b/src/effects/SkMatrixConvolutionImageFilter.cpp
@@ -306,6 +306,19 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
return true;
}
+bool SkMatrixConvolutionImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+ SkIRect* dst) const {
+ SkIRect bounds = src;
+ bounds.fRight += fKernelSize.width() - 1;
+ bounds.fBottom += fKernelSize.height() - 1;
+ bounds.offset(-fKernelOffset);
+ if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) {
+ return false;
+ }
+ *dst = bounds;
+ return true;
+}
+
#if SK_SUPPORT_GPU
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/effects/SkTileImageFilter.cpp b/src/effects/SkTileImageFilter.cpp
index f3bad76345..73c0a581e9 100644
--- a/src/effects/SkTileImageFilter.cpp
+++ b/src/effects/SkTileImageFilter.cpp
@@ -75,6 +75,17 @@ bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
return true;
}
+bool SkTileImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+ SkIRect* dst) const {
+ SkRect srcRect;
+ ctm.mapRect(&srcRect, fSrcRect);
+ SkIRect srcIRect;
+ srcRect.roundOut(&srcIRect);
+ srcIRect.join(src);
+ *dst = srcIRect;
+ return true;
+}
+
SkTileImageFilter::SkTileImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
buffer.readRect(&fSrcRect);
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index f968a4e9c5..dac948ef40 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -17,6 +17,7 @@
#include "SkDisplacementMapEffect.h"
#include "SkDropShadowImageFilter.h"
#include "SkFlattenableBuffers.h"
+#include "SkGradientShader.h"
#include "SkLightingImageFilter.h"
#include "SkMatrixConvolutionImageFilter.h"
#include "SkMatrixImageFilter.h"
@@ -261,6 +262,116 @@ static void test_crop_rects(SkBaseDevice* device, skiatest::Reporter* reporter)
}
}
+static SkBitmap make_gradient_circle(int width, int height) {
+ SkBitmap bitmap;
+ SkScalar x = SkIntToScalar(width / 2);
+ SkScalar y = SkIntToScalar(height / 2);
+ SkScalar radius = SkMinScalar(x, y) * 0.8f;
+ bitmap.allocN32Pixels(width, height);
+ SkCanvas canvas(bitmap);
+ 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);
+ return bitmap;
+}
+
+DEF_TEST(ImageFilterDrawTiled, reporter) {
+ // Check that all filters when drawn tiled (with subsequent clip rects) exactly
+ // match the same filters drawn with a single full-canvas bitmap draw.
+ // Tests pass by not asserting.
+
+ 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;
+
+ SkAutoTUnref<SkImageFilter> gradient_source(SkBitmapSource::Create(make_gradient_circle(64, 64)));
+
+ struct {
+ const char* fName;
+ SkImageFilter* fFilter;
+ } filters[] = {
+ { "color filter", SkColorFilterImageFilter::Create(cf.get()) },
+ { "displacement map", SkDisplacementMapEffect::Create(
+ SkDisplacementMapEffect::kR_ChannelSelectorType,
+ SkDisplacementMapEffect::kB_ChannelSelectorType,
+ 40.0f, gradient_source.get()) },
+ { "blur", SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1) },
+ { "drop shadow", SkDropShadowImageFilter::Create(
+ SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN) },
+ { "diffuse lighting", SkLightingImageFilter::CreatePointLitDiffuse(
+ location, SK_ColorGREEN, 0, 0) },
+ { "specular lighting",
+ SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0) },
+ { "matrix convolution",
+ SkMatrixConvolutionImageFilter::Create(
+ kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
+ SkMatrixConvolutionImageFilter::kRepeat_TileMode, false) },
+ { "merge", SkMergeImageFilter::Create(NULL, NULL, SkXfermode::kSrcOver_Mode) },
+ { "offset", SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1) },
+ { "dilate", SkDilateImageFilter::Create(3, 2) },
+ { "erode", SkErodeImageFilter::Create(2, 3) },
+ { "tile", SkTileImageFilter::Create(SkRect::MakeXYWH(0, 0, 50, 50),
+ SkRect::MakeXYWH(0, 0, 100, 100), NULL) },
+ };
+
+ SkBitmap untiledResult, tiledResult;
+ int width = 64, height = 64;
+ untiledResult.allocN32Pixels(width, height);
+ tiledResult.allocN32Pixels(width, height);
+ SkCanvas tiledCanvas(tiledResult);
+ SkCanvas untiledCanvas(untiledResult);
+ tiledCanvas.clear(0);
+ untiledCanvas.clear(0);
+ int tileSize = 16;
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
+ SkPaint paint;
+ paint.setImageFilter(filters[i].fFilter);
+ paint.setTextSize(SkIntToScalar(height));
+ paint.setColor(SK_ColorWHITE);
+ SkString str;
+ const char* text = "ABC";
+ SkScalar ypos = SkIntToScalar(height);
+ untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
+ for (int y = 0; y < height; y += tileSize) {
+ for (int x = 0; x < width; x += tileSize) {
+ tiledCanvas.save();
+ tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
+ tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
+ tiledCanvas.restore();
+ }
+ }
+ untiledCanvas.flush();
+ tiledCanvas.flush();
+ for (int y = 0; y < height; y++) {
+ int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
+ REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName);
+ if (diffs) {
+ break;
+ }
+ }
+ }
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
+ SkSafeUnref(filters[i].fFilter);
+ }
+}
+
DEF_TEST(ImageFilterCropRect, reporter) {
SkBitmap temp;
temp.allocN32Pixels(100, 100);