Index: gm/spritebitmap.cpp |
diff --git a/gm/spritebitmap.cpp b/gm/spritebitmap.cpp |
index ceed50acaac31504488fe44486733171073709e1..0d467ea01ad4922a42ecd4f5085da2e11e980609 100644 |
--- a/gm/spritebitmap.cpp |
+++ b/gm/spritebitmap.cpp |
@@ -97,3 +97,121 @@ private: |
}; |
DEF_GM( return new SpriteBitmapGM; ) |
+/////////////////////////////////////////////////////////////////////////////////////////////////// |
+ |
+#include "SkColorFilterImageFilter.h" |
+#include "SkModeColorFilter.h" |
+#include "SkMorphologyImageFilter.h" |
+#include "SkOffsetImageFilter.h" |
+ |
+static SkImage* make_image(SkCanvas* rootCanvas) { |
+ SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100); |
+ SkAutoTUnref<SkSurface> surface(rootCanvas->newSurface(info)); |
+ if (!surface) { |
+ surface.reset(SkSurface::NewRaster(info)); |
+ } |
+ |
+ SkPaint paint; |
+ paint.setAntiAlias(true); |
+ paint.setColor(SK_ColorRED); |
+ surface->getCanvas()->drawCircle(50, 50, 50, paint); |
+ return surface->newImageSnapshot(); |
+} |
+ |
+static void show_image(SkCanvas* canvas, SkImage* image, const SkIPoint& offset) { |
+ SkScalar x = SkIntToScalar(offset.x()); |
+ SkScalar y = SkIntToScalar(offset.y()); |
+ |
+ SkPaint paint; |
+ paint.setStyle(SkPaint::kStroke_Style); |
+ |
+ SkRect r = SkRect::MakeIWH(image->width(), image->height()); |
+ r.offset(x, y); |
+ // get on pixel-centers to make the hairline land on a numerical stable boundary |
+ r.outset(SK_ScalarHalf, SK_ScalarHalf); |
+ canvas->drawRect(r, paint); |
+ |
+ canvas->drawImage(image, x, y, nullptr); |
+} |
+ |
+typedef SkImageFilter* (*ImageFilterFactory)(); |
+ |
+// +[]{...} did not work on windows (VS) |
+// (ImageFilterFactory)[]{...} did not work on linux (gcc) |
+// hence this cast function |
+template <typename T> ImageFilterFactory IFCCast(T arg) { return arg; } |
+ |
+/** |
+ * Compare output of drawSprite and drawBitmap (esp. clipping and imagefilters) |
+ */ |
+class ApplyFilterGM : public skiagm::GM { |
+public: |
+ ApplyFilterGM() {} |
+ |
+protected: |
+ SkString onShortName() override { |
+ return SkString("apply-filter"); |
+ } |
+ |
+ SkISize onISize() override { |
+ return SkISize::Make(640, 480); |
+ } |
+ |
+ void onDraw(SkCanvas* canvas) override { |
+ SkAutoTUnref<SkImage> image0(make_image(canvas)); |
+ |
+ const ImageFilterFactory factories[] = { |
+ IFCCast([]{ return SkBlurImageFilter::Create(8, 8); }), |
+ IFCCast([]{ SkAutoTUnref<SkColorFilter> cf(SkModeColorFilter::Create(SK_ColorBLUE, |
+ SkXfermode::kSrcIn_Mode)); |
+ return SkColorFilterImageFilter::Create(cf); |
+ }), |
+ IFCCast([]{ return SkDilateImageFilter::Create(8, 8); }), |
+ IFCCast([]{ return SkErodeImageFilter::Create(8, 8); }), |
+ IFCCast([]{ return SkOffsetImageFilter::Create(8, 8); }), |
+ }; |
+ |
+ const SkScalar spacer = image0->width() * 3.0f / 2; |
+ |
+ for (auto&& factory : factories) { |
+ SkAutoTUnref<SkImageFilter> filter(factory()); |
+ |
+ SkIPoint offset1, offset2; |
+ SkAutoTUnref<SkImage> image1(image0->applyFilter(filter, &offset1, true)); |
+ SkAutoTUnref<SkImage> image2(image0->applyFilter(filter, &offset2, false)); |
+ |
+ canvas->save(); |
+ canvas->translate(30, 30); |
+ show_image(canvas, image0, SkIPoint::Make(0, 0)); // original |
+ canvas->translate(spacer, 0); |
+ show_image(canvas, image1, offset1); // snug |
+ canvas->translate(spacer, 0); |
+ show_image(canvas, image2, offset2); // not snug |
+ |
+ // Try drawing the original w/ the filter, to see that it "draws" the same as |
+ // when we have manually applied the filter (above). |
+ { |
+ SkPaint paint; |
+ paint.setImageFilter(filter); |
+ |
+ SkBitmap bm; |
+ image0->asLegacyBitmap(&bm, SkImage::kRO_LegacyBitmapMode); |
+ SkPoint loc = { 0, 0 }; |
+ canvas->translate(spacer, 0); |
+ canvas->getTotalMatrix().mapPoints(&loc, 1); |
+ canvas->drawSprite(bm, (int)loc.x(), (int)loc.y(), &paint); // like snug |
+ |
+ canvas->translate(spacer, 0); |
+ canvas->drawImage(image0, 0, 0, &paint); // like not snug |
+ } |
+ canvas->restore(); |
+ |
+ canvas->translate(0, spacer); |
+ } |
+ } |
+ |
+private: |
+ typedef GM INHERITED; |
+}; |
+DEF_GM( return new ApplyFilterGM; ) |
+ |