blob: 91172e2e797a9287f1c7b953cacebce60c974f3d [file] [log] [blame]
reed@google.com8926b162012-03-23 15:36:36 +00001/*
2 * Copyright 2011 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"
Mike Klein33d20552017-03-22 13:47:51 -04009#include "sk_tool_utils.h"
reed@google.com8926b162012-03-23 15:36:36 +000010#include "SkCanvas.h"
11#include "SkColorFilter.h"
12#include "SkColorPriv.h"
Cary Clark60aaeb22017-11-03 08:06:09 -040013#include "SkImageFilterPriv.h"
reed@google.com8926b162012-03-23 15:36:36 +000014#include "SkShader.h"
15
16#include "SkBlurImageFilter.h"
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000017#include "SkColorFilterImageFilter.h"
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000018#include "SkDropShadowImageFilter.h"
robertphillips4ba94e22016-04-04 12:07:47 -070019#include "SkSpecialImage.h"
reed@google.com8926b162012-03-23 15:36:36 +000020
21class FailImageFilter : public SkImageFilter {
22public:
reed7daaaa42014-08-21 10:53:34 -070023 class Registrar {
24 public:
25 Registrar() {
26 SkFlattenable::Register("FailImageFilter",
mtklein3b375452016-04-04 14:57:19 -070027 FailImageFilter::CreateProc,
28 FailImageFilter::GetFlattenableType());
reed7daaaa42014-08-21 10:53:34 -070029 }
30 };
robertphillips43c2ad42016-04-04 05:05:11 -070031 static sk_sp<SkImageFilter> Make() {
32 return sk_sp<SkImageFilter>(new FailImageFilter);
33 }
djsollen@google.comba28d032012-03-26 17:57:35 +000034
reed@google.com8926b162012-03-23 15:36:36 +000035protected:
robertphillips43c2ad42016-04-04 05:05:11 -070036 FailImageFilter() : INHERITED(nullptr, 0, nullptr) {}
reed9fa60da2014-08-21 07:59:51 -070037
robertphillips4ba94e22016-04-04 12:07:47 -070038 sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
39 SkIPoint* offset) const override {
40 return nullptr;
reed@google.com8926b162012-03-23 15:36:36 +000041 }
Matt Sarett62745a82017-04-17 11:57:29 -040042 sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override {
Brian Osmanf83cacb2018-08-03 16:13:13 -040043 return sk_ref_sp(this);
Matt Sarett62745a82017-04-17 11:57:29 -040044 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000045
reed@google.com8926b162012-03-23 15:36:36 +000046private:
Mike Klein4fee3232018-10-18 17:27:16 -040047 SK_FLATTENABLE_HOOKS(FailImageFilter)
48
reed@google.com8926b162012-03-23 15:36:36 +000049 typedef SkImageFilter INHERITED;
50};
51
reed7daaaa42014-08-21 10:53:34 -070052static FailImageFilter::Registrar gReg0;
53
reed60c9b582016-04-03 09:11:13 -070054sk_sp<SkFlattenable> FailImageFilter::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -070055 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
robertphillips43c2ad42016-04-04 05:05:11 -070056 return FailImageFilter::Make();
reed9fa60da2014-08-21 07:59:51 -070057}
djsollen@google.comba28d032012-03-26 17:57:35 +000058
reed@google.com8926b162012-03-23 15:36:36 +000059class IdentityImageFilter : public SkImageFilter {
60public:
reed7daaaa42014-08-21 10:53:34 -070061 class Registrar {
62 public:
63 Registrar() {
64 SkFlattenable::Register("IdentityImageFilter",
mtklein3b375452016-04-04 14:57:19 -070065 IdentityImageFilter::CreateProc,
66 IdentityImageFilter::GetFlattenableType());
reed7daaaa42014-08-21 10:53:34 -070067 }
68 };
robertphillips43c2ad42016-04-04 05:05:11 -070069 static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilter> input) {
70 return sk_sp<SkImageFilter>(new IdentityImageFilter(std::move(input)));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000071 }
reed@google.com8926b162012-03-23 15:36:36 +000072
reed9fa60da2014-08-21 07:59:51 -070073
robertphillips43c2ad42016-04-04 05:05:11 -070074protected:
robertphillips4ba94e22016-04-04 12:07:47 -070075 sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
76 SkIPoint* offset) const override {
commit-bot@chromium.orgf7efa502014-04-11 18:57:00 +000077 offset->set(0, 0);
robertphillips4ba94e22016-04-04 12:07:47 -070078 return sk_ref_sp<SkSpecialImage>(source);
reed@google.com8926b162012-03-23 15:36:36 +000079 }
Matt Sarett62745a82017-04-17 11:57:29 -040080 sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override {
81 return sk_ref_sp(const_cast<IdentityImageFilter*>(this));
82 }
reed@google.com8926b162012-03-23 15:36:36 +000083
reed@google.com8926b162012-03-23 15:36:36 +000084private:
Mike Klein4fee3232018-10-18 17:27:16 -040085 SK_FLATTENABLE_HOOKS(IdentityImageFilter)
robertphillips43c2ad42016-04-04 05:05:11 -070086 IdentityImageFilter(sk_sp<SkImageFilter> input) : INHERITED(&input, 1, nullptr) {}
87
reed@google.com8926b162012-03-23 15:36:36 +000088 typedef SkImageFilter INHERITED;
89};
90
reed7daaaa42014-08-21 10:53:34 -070091static IdentityImageFilter::Registrar gReg1;
92
reed60c9b582016-04-03 09:11:13 -070093sk_sp<SkFlattenable> IdentityImageFilter::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -070094 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
robertphillips43c2ad42016-04-04 05:05:11 -070095 return IdentityImageFilter::Make(common.getInput(0));
reed9fa60da2014-08-21 07:59:51 -070096}
djsollen@google.comba28d032012-03-26 17:57:35 +000097
reed@google.com8926b162012-03-23 15:36:36 +000098///////////////////////////////////////////////////////////////////////////////
99
robertphillips5605b562016-04-05 11:50:42 -0700100static void draw_paint(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +0000101 SkPaint paint;
robertphillips5605b562016-04-05 11:50:42 -0700102 paint.setImageFilter(std::move(imf));
reed@google.com8926b162012-03-23 15:36:36 +0000103 paint.setColor(SK_ColorGREEN);
104 canvas->save();
105 canvas->clipRect(r);
106 canvas->drawPaint(paint);
107 canvas->restore();
108}
109
robertphillips5605b562016-04-05 11:50:42 -0700110static void draw_line(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +0000111 SkPaint paint;
112 paint.setColor(SK_ColorBLUE);
113 paint.setImageFilter(imf);
114 paint.setStrokeWidth(r.width()/10);
115 canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
116}
117
robertphillips5605b562016-04-05 11:50:42 -0700118static void draw_rect(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +0000119 SkPaint paint;
120 paint.setColor(SK_ColorYELLOW);
121 paint.setImageFilter(imf);
122 SkRect rr(r);
123 rr.inset(r.width()/10, r.height()/10);
124 canvas->drawRect(rr, paint);
125}
126
robertphillips5605b562016-04-05 11:50:42 -0700127static void draw_path(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +0000128 SkPaint paint;
129 paint.setColor(SK_ColorMAGENTA);
130 paint.setImageFilter(imf);
131 paint.setAntiAlias(true);
132 canvas->drawCircle(r.centerX(), r.centerY(), r.width()*2/5, paint);
133}
134
robertphillips5605b562016-04-05 11:50:42 -0700135static void draw_text(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +0000136 SkPaint paint;
137 paint.setImageFilter(imf);
138 paint.setColor(SK_ColorCYAN);
139 paint.setAntiAlias(true);
caryclark1818acb2015-07-24 12:09:25 -0700140 sk_tool_utils::set_portable_typeface(&paint);
reed@google.com8926b162012-03-23 15:36:36 +0000141 paint.setTextSize(r.height()/2);
142 paint.setTextAlign(SkPaint::kCenter_Align);
Cary Clark2a475ea2017-04-28 15:35:12 -0400143 canvas->drawString("Text", r.centerX(), r.centerY(), paint);
reed@google.com8926b162012-03-23 15:36:36 +0000144}
145
robertphillips5605b562016-04-05 11:50:42 -0700146static void draw_bitmap(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +0000147 SkPaint paint;
robertphillips5605b562016-04-05 11:50:42 -0700148 paint.setImageFilter(std::move(imf));
rmistry@google.comd6176b02012-08-23 18:14:13 +0000149
reed@google.com8926b162012-03-23 15:36:36 +0000150 SkIRect bounds;
151 r.roundOut(&bounds);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000152
reed@google.com8926b162012-03-23 15:36:36 +0000153 SkBitmap bm;
reed@google.comeb9a46c2014-01-25 16:46:20 +0000154 bm.allocN32Pixels(bounds.width(), bounds.height());
junov@google.comdbfac8a2012-12-06 21:47:40 +0000155 bm.eraseColor(SK_ColorTRANSPARENT);
reed@google.com8926b162012-03-23 15:36:36 +0000156 SkCanvas c(bm);
halcanary96fcdcc2015-08-27 07:41:13 -0700157 draw_path(&c, r, nullptr);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000158
reed@google.com8926b162012-03-23 15:36:36 +0000159 canvas->drawBitmap(bm, 0, 0, &paint);
160}
161
reed@google.com8926b162012-03-23 15:36:36 +0000162///////////////////////////////////////////////////////////////////////////////
163
164class ImageFiltersBaseGM : public skiagm::GM {
165public:
166 ImageFiltersBaseGM () {}
167
168protected:
mtklein36352bf2015-03-25 18:17:31 -0700169 SkString onShortName() override {
reed@google.com8926b162012-03-23 15:36:36 +0000170 return SkString("imagefiltersbase");
171 }
172
mtklein36352bf2015-03-25 18:17:31 -0700173 SkISize onISize() override { return SkISize::Make(700, 500); }
reed@google.com8926b162012-03-23 15:36:36 +0000174
175 void draw_frame(SkCanvas* canvas, const SkRect& r) {
176 SkPaint paint;
177 paint.setStyle(SkPaint::kStroke_Style);
178 paint.setColor(SK_ColorRED);
179 canvas->drawRect(r, paint);
180 }
181
mtklein36352bf2015-03-25 18:17:31 -0700182 void onDraw(SkCanvas* canvas) override {
robertphillips5605b562016-04-05 11:50:42 -0700183 void (*drawProc[])(SkCanvas*, const SkRect&, sk_sp<SkImageFilter>) = {
reed@google.com8926b162012-03-23 15:36:36 +0000184 draw_paint,
185 draw_line, draw_rect, draw_path, draw_text,
186 draw_bitmap,
reed@google.com8926b162012-03-23 15:36:36 +0000187 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000188
Mike Reed7d954ad2016-10-28 15:42:34 -0400189 auto cf = SkColorFilter::MakeModeFilter(SK_ColorRED, SkBlendMode::kSrcIn);
robertphillips5605b562016-04-05 11:50:42 -0700190 sk_sp<SkImageFilter> filters[] = {
halcanary96fcdcc2015-08-27 07:41:13 -0700191 nullptr,
robertphillips5605b562016-04-05 11:50:42 -0700192 IdentityImageFilter::Make(nullptr),
193 FailImageFilter::Make(),
194 SkColorFilterImageFilter::Make(std::move(cf), nullptr),
Herb Derby4fafedd2017-12-18 15:06:29 -0500195 // The strage 0.29 value tickles an edge case where crop rect calculates
196 // a small border, but the blur really needs no border. This tickels
197 // an msan uninitialized value bug.
198 SkBlurImageFilter::Make(12.0f, 0.29f, nullptr),
robertphillipsc4169122016-04-06 08:40:59 -0700199 SkDropShadowImageFilter::Make(
robertphillips5605b562016-04-05 11:50:42 -0700200 10.0f, 5.0f, 3.0f, 3.0f, SK_ColorBLUE,
robertphillipsc4169122016-04-06 08:40:59 -0700201 SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
202 nullptr),
reed@google.com8926b162012-03-23 15:36:36 +0000203 };
reed@google.com8926b162012-03-23 15:36:36 +0000204
205 SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64));
206 SkScalar MARGIN = SkIntToScalar(16);
207 SkScalar DX = r.width() + MARGIN;
208 SkScalar DY = r.height() + MARGIN;
209
210 canvas->translate(MARGIN, MARGIN);
211 for (size_t i = 0; i < SK_ARRAY_COUNT(drawProc); ++i) {
212 canvas->save();
213 for (size_t j = 0; j < SK_ARRAY_COUNT(filters); ++j) {
214 drawProc[i](canvas, r, filters[j]);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000215
reed@google.com8926b162012-03-23 15:36:36 +0000216 draw_frame(canvas, r);
217 canvas->translate(0, DY);
218 }
219 canvas->restore();
220 canvas->translate(DX, 0);
221 }
reed@google.com8926b162012-03-23 15:36:36 +0000222 }
223
224private:
225 typedef GM INHERITED;
226};
reed8dc0ccb2015-03-20 06:32:52 -0700227DEF_GM( return new ImageFiltersBaseGM; )
reed@google.com8926b162012-03-23 15:36:36 +0000228
229///////////////////////////////////////////////////////////////////////////////
230
reed8dc0ccb2015-03-20 06:32:52 -0700231/*
232 * Want to test combos of filter and LCD text, to be sure we disable LCD in the presence of
233 * a filter.
234 */
235class ImageFiltersTextBaseGM : public skiagm::GM {
236 SkString fSuffix;
237public:
238 ImageFiltersTextBaseGM(const char suffix[]) : fSuffix(suffix) {}
239
240protected:
mtklein36352bf2015-03-25 18:17:31 -0700241 SkString onShortName() override {
reed8dc0ccb2015-03-20 06:32:52 -0700242 SkString name;
243 name.printf("%s_%s", "textfilter", fSuffix.c_str());
244 return name;
245 }
246
mtklein36352bf2015-03-25 18:17:31 -0700247 SkISize onISize() override { return SkISize::Make(512, 342); }
reed8dc0ccb2015-03-20 06:32:52 -0700248
249 void drawWaterfall(SkCanvas* canvas, const SkPaint& origPaint) {
250 const uint32_t flags[] = {
251 0,
252 SkPaint::kAntiAlias_Flag,
253 SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag,
254 };
255 SkPaint paint(origPaint);
caryclark1818acb2015-07-24 12:09:25 -0700256 sk_tool_utils::set_portable_typeface(&paint);
reed8dc0ccb2015-03-20 06:32:52 -0700257 paint.setTextSize(30);
258
259 SkAutoCanvasRestore acr(canvas, true);
260 for (size_t i = 0; i < SK_ARRAY_COUNT(flags); ++i) {
261 paint.setFlags(flags[i]);
Cary Clark2a475ea2017-04-28 15:35:12 -0400262 canvas->drawString("Hamburgefon", 0, 0, paint);
reed8dc0ccb2015-03-20 06:32:52 -0700263 canvas->translate(0, 40);
264 }
265 }
266
267 virtual void installFilter(SkPaint* paint) = 0;
268
mtklein36352bf2015-03-25 18:17:31 -0700269 void onDraw(SkCanvas* canvas) override {
reed8dc0ccb2015-03-20 06:32:52 -0700270 SkPaint paint;
271
272 canvas->translate(20, 40);
273
274 for (int doSaveLayer = 0; doSaveLayer <= 1; ++doSaveLayer) {
275 SkAutoCanvasRestore acr(canvas, true);
276 for (int useFilter = 0; useFilter <= 1; ++useFilter) {
277 SkAutoCanvasRestore acr2(canvas, true);
278
279 SkPaint paint;
280 if (useFilter) {
281 this->installFilter(&paint);
282 }
283 if (doSaveLayer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700284 canvas->saveLayer(nullptr, &paint);
285 paint.setImageFilter(nullptr);
reed8dc0ccb2015-03-20 06:32:52 -0700286 }
287 this->drawWaterfall(canvas, paint);
288
289 acr2.restore();
290 canvas->translate(250, 0);
291 }
292 acr.restore();
293 canvas->translate(0, 200);
294 }
295 }
halcanary9d524f22016-03-29 09:03:52 -0700296
reed8dc0ccb2015-03-20 06:32:52 -0700297private:
298 typedef GM INHERITED;
299};
300
301class ImageFiltersText_IF : public ImageFiltersTextBaseGM {
302public:
303 ImageFiltersText_IF() : ImageFiltersTextBaseGM("image") {}
304
mtklein36352bf2015-03-25 18:17:31 -0700305 void installFilter(SkPaint* paint) override {
robertphillips6e7025a2016-04-04 04:31:25 -0700306 paint->setImageFilter(SkBlurImageFilter::Make(1.5f, 1.5f, nullptr));
reed8dc0ccb2015-03-20 06:32:52 -0700307 }
308};
309DEF_GM( return new ImageFiltersText_IF; )
310
311class ImageFiltersText_CF : public ImageFiltersTextBaseGM {
312public:
313 ImageFiltersText_CF() : ImageFiltersTextBaseGM("color") {}
314
mtklein36352bf2015-03-25 18:17:31 -0700315 void installFilter(SkPaint* paint) override {
Mike Reed7d954ad2016-10-28 15:42:34 -0400316 paint->setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorBLUE, SkBlendMode::kSrcIn));
reed8dc0ccb2015-03-20 06:32:52 -0700317 }
318};
319DEF_GM( return new ImageFiltersText_CF; )