diff options
-rw-r--r-- | expectations/gm/ignored-tests.txt | 4 | ||||
-rw-r--r-- | gm/tileimagefilter.cpp | 33 | ||||
-rw-r--r-- | include/effects/SkMatrixConvolutionImageFilter.h | 2 | ||||
-rw-r--r-- | include/effects/SkTileImageFilter.h | 2 | ||||
-rw-r--r-- | src/effects/SkMatrixConvolutionImageFilter.cpp | 13 | ||||
-rw-r--r-- | src/effects/SkTileImageFilter.cpp | 11 | ||||
-rw-r--r-- | tests/ImageFilterTest.cpp | 111 |
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); |