blob: 4f221d49fc71d808d0d932bb30d4973b174f4d52 [file] [log] [blame]
reed@google.com12fa9ba2013-01-16 18:54:15 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
9#include "SkCanvas.h"
10#include "SkBlurImageFilter.h"
reed71c3c762015-06-24 10:29:17 -070011#include "SkRSXform.h"
12#include "SkSurface.h"
reed@google.com12fa9ba2013-01-16 18:54:15 +000013
14static void make_bm(SkBitmap* bm) {
reed@google.comeb9a46c2014-01-25 16:46:20 +000015 bm->allocN32Pixels(100, 100);
reed@google.com12fa9ba2013-01-16 18:54:15 +000016 bm->eraseColor(SK_ColorBLUE);
17
18 SkCanvas canvas(*bm);
19 SkPaint paint;
20 paint.setAntiAlias(true);
21 paint.setColor(SK_ColorRED);
22 canvas.drawCircle(50, 50, 50, paint);
23}
24
reedda420b92015-12-16 08:38:15 -080025static void draw_1_bitmap(SkCanvas* canvas, const SkBitmap& bm, bool doClip,
26 int dx, int dy, SkImageFilter* filter = nullptr) {
reed@google.com12fa9ba2013-01-16 18:54:15 +000027 SkAutoCanvasRestore acr(canvas, true);
28 SkPaint paint;
29
skia.committer@gmail.com4d28d982013-01-17 07:06:06 +000030 SkRect clipR = SkRect::MakeXYWH(SkIntToScalar(dx),
robertphillips@google.com914a2f22013-01-16 19:57:02 +000031 SkIntToScalar(dy),
reed@google.com1c711ca2013-01-16 19:24:15 +000032 SkIntToScalar(bm.width()),
33 SkIntToScalar(bm.height()));
reed@google.com12fa9ba2013-01-16 18:54:15 +000034
35 paint.setImageFilter(filter);
36 clipR.inset(5, 5);
37
reed@google.com1c711ca2013-01-16 19:24:15 +000038 canvas->translate(SkIntToScalar(bm.width() + 20), 0);
reed@google.com12fa9ba2013-01-16 18:54:15 +000039
40 if (doClip) {
41 canvas->save();
42 canvas->clipRect(clipR);
43 }
reed@google.com1c711ca2013-01-16 19:24:15 +000044 canvas->drawBitmap(bm, SkIntToScalar(dx), SkIntToScalar(dy), &paint);
reed@google.com12fa9ba2013-01-16 18:54:15 +000045 if (doClip) {
46 canvas->restore();
47 }
48}
49
50/**
51 * Compare output of drawSprite and drawBitmap (esp. clipping and imagefilters)
52 */
53class SpriteBitmapGM : public skiagm::GM {
54public:
55 SpriteBitmapGM() {}
56
57protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +000058
mtklein36352bf2015-03-25 18:17:31 -070059 SkString onShortName() override {
reed@google.com12fa9ba2013-01-16 18:54:15 +000060 return SkString("spritebitmap");
61 }
62
mtklein36352bf2015-03-25 18:17:31 -070063 SkISize onISize() override {
reed@google.com12fa9ba2013-01-16 18:54:15 +000064 return SkISize::Make(640, 480);
65 }
66
mtklein36352bf2015-03-25 18:17:31 -070067 void onDraw(SkCanvas* canvas) override {
reed@google.com12fa9ba2013-01-16 18:54:15 +000068 SkBitmap bm;
69 make_bm(&bm);
70
71 int dx = 10;
72 int dy = 10;
73
74 SkScalar sigma = 8;
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000075 SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(sigma, sigma));
reed@google.com12fa9ba2013-01-16 18:54:15 +000076
reedda420b92015-12-16 08:38:15 -080077 draw_1_bitmap(canvas, bm, false, dx, dy);
reed@google.com12fa9ba2013-01-16 18:54:15 +000078 dy += bm.height() + 20;
reedda420b92015-12-16 08:38:15 -080079 draw_1_bitmap(canvas, bm, false, dx, dy, filter);
reed@google.com12fa9ba2013-01-16 18:54:15 +000080 dy += bm.height() + 20;
reedda420b92015-12-16 08:38:15 -080081 draw_1_bitmap(canvas, bm, true, dx, dy);
reed@google.com12fa9ba2013-01-16 18:54:15 +000082 dy += bm.height() + 20;
reedda420b92015-12-16 08:38:15 -080083 draw_1_bitmap(canvas, bm, true, dx, dy, filter);
reed@google.com12fa9ba2013-01-16 18:54:15 +000084 }
85
86private:
87 typedef GM INHERITED;
88};
reed@google.com12fa9ba2013-01-16 18:54:15 +000089DEF_GM( return new SpriteBitmapGM; )
reed71c3c762015-06-24 10:29:17 -070090
reed88d064d2015-10-12 11:30:02 -070091///////////////////////////////////////////////////////////////////////////////////////////////////
92
93#include "SkColorFilterImageFilter.h"
94#include "SkModeColorFilter.h"
95#include "SkMorphologyImageFilter.h"
96#include "SkOffsetImageFilter.h"
97
98static SkImage* make_image(SkCanvas* rootCanvas) {
99 SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
100 SkAutoTUnref<SkSurface> surface(rootCanvas->newSurface(info));
101 if (!surface) {
102 surface.reset(SkSurface::NewRaster(info));
103 }
104
105 SkPaint paint;
106 paint.setAntiAlias(true);
107 paint.setColor(SK_ColorRED);
108 surface->getCanvas()->drawCircle(50, 50, 50, paint);
109 return surface->newImageSnapshot();
110}
111
112static void show_image(SkCanvas* canvas, SkImage* image, const SkIPoint& offset) {
113 SkScalar x = SkIntToScalar(offset.x());
114 SkScalar y = SkIntToScalar(offset.y());
115
116 SkPaint paint;
117 paint.setStyle(SkPaint::kStroke_Style);
118
119 SkRect r = SkRect::MakeIWH(image->width(), image->height());
120 r.offset(x, y);
121 // get on pixel-centers to make the hairline land on a numerical stable boundary
122 r.outset(SK_ScalarHalf, SK_ScalarHalf);
123 canvas->drawRect(r, paint);
124
125 canvas->drawImage(image, x, y, nullptr);
126}
127
128typedef SkImageFilter* (*ImageFilterFactory)();
129
130// +[]{...} did not work on windows (VS)
131// (ImageFilterFactory)[]{...} did not work on linux (gcc)
132// hence this cast function
133template <typename T> ImageFilterFactory IFCCast(T arg) { return arg; }
134
reed59dc0d22015-10-19 08:24:21 -0700135// We expect that applying the filter will keep us in the same domain (raster or gpu)
136static void check_same_domain(SkImage* a, SkImage* b) {
137 SkASSERT(a->isTextureBacked() == b->isTextureBacked());
138}
139
reed88d064d2015-10-12 11:30:02 -0700140/**
141 * Compare output of drawSprite and drawBitmap (esp. clipping and imagefilters)
142 */
143class ApplyFilterGM : public skiagm::GM {
144public:
145 ApplyFilterGM() {}
146
147protected:
148 SkString onShortName() override {
149 return SkString("apply-filter");
150 }
151
152 SkISize onISize() override {
reedc837d8f2015-10-12 14:38:34 -0700153 return SkISize::Make(780, 780);
reed88d064d2015-10-12 11:30:02 -0700154 }
155
156 void onDraw(SkCanvas* canvas) override {
157 SkAutoTUnref<SkImage> image0(make_image(canvas));
158
159 const ImageFilterFactory factories[] = {
160 IFCCast([]{ return SkBlurImageFilter::Create(8, 8); }),
161 IFCCast([]{ SkAutoTUnref<SkColorFilter> cf(SkModeColorFilter::Create(SK_ColorBLUE,
162 SkXfermode::kSrcIn_Mode));
163 return SkColorFilterImageFilter::Create(cf);
164 }),
165 IFCCast([]{ return SkDilateImageFilter::Create(8, 8); }),
166 IFCCast([]{ return SkErodeImageFilter::Create(8, 8); }),
167 IFCCast([]{ return SkOffsetImageFilter::Create(8, 8); }),
168 };
169
170 const SkScalar spacer = image0->width() * 3.0f / 2;
171
172 for (auto&& factory : factories) {
173 SkAutoTUnref<SkImageFilter> filter(factory());
174
175 SkIPoint offset1, offset2;
176 SkAutoTUnref<SkImage> image1(image0->applyFilter(filter, &offset1, true));
177 SkAutoTUnref<SkImage> image2(image0->applyFilter(filter, &offset2, false));
178
reed59dc0d22015-10-19 08:24:21 -0700179 check_same_domain(image0, image1);
180 check_same_domain(image0, image2);
181
reed88d064d2015-10-12 11:30:02 -0700182 canvas->save();
183 canvas->translate(30, 30);
184 show_image(canvas, image0, SkIPoint::Make(0, 0)); // original
185 canvas->translate(spacer, 0);
186 show_image(canvas, image1, offset1); // snug
187 canvas->translate(spacer, 0);
188 show_image(canvas, image2, offset2); // not snug
189
reed88d064d2015-10-12 11:30:02 -0700190 canvas->restore();
191
192 canvas->translate(0, spacer);
193 }
194 }
195
196private:
197 typedef GM INHERITED;
198};
199DEF_GM( return new ApplyFilterGM; )