blob: 40bb8104425387fa18cfbedd4d452d52982297f0 [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"
Mike Reed71f5a0b2018-10-25 16:12:39 -040015#include "SkTextUtils.h"
reed@google.com8926b162012-03-23 15:36:36 +000016
17#include "SkBlurImageFilter.h"
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000018#include "SkColorFilterImageFilter.h"
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000019#include "SkDropShadowImageFilter.h"
robertphillips4ba94e22016-04-04 12:07:47 -070020#include "SkSpecialImage.h"
reed@google.com8926b162012-03-23 15:36:36 +000021
22class FailImageFilter : public SkImageFilter {
23public:
robertphillips43c2ad42016-04-04 05:05:11 -070024 static sk_sp<SkImageFilter> Make() {
25 return sk_sp<SkImageFilter>(new FailImageFilter);
26 }
djsollen@google.comba28d032012-03-26 17:57:35 +000027
Mike Kleina3d40992018-10-20 07:54:41 -040028 SK_FLATTENABLE_HOOKS(FailImageFilter)
reed@google.com8926b162012-03-23 15:36:36 +000029protected:
robertphillips43c2ad42016-04-04 05:05:11 -070030 FailImageFilter() : INHERITED(nullptr, 0, nullptr) {}
reed9fa60da2014-08-21 07:59:51 -070031
robertphillips4ba94e22016-04-04 12:07:47 -070032 sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
33 SkIPoint* offset) const override {
34 return nullptr;
reed@google.com8926b162012-03-23 15:36:36 +000035 }
Matt Sarett62745a82017-04-17 11:57:29 -040036 sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override {
Brian Osmanf83cacb2018-08-03 16:13:13 -040037 return sk_ref_sp(this);
Matt Sarett62745a82017-04-17 11:57:29 -040038 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000039
reed@google.com8926b162012-03-23 15:36:36 +000040private:
Mike Klein4fee3232018-10-18 17:27:16 -040041
reed@google.com8926b162012-03-23 15:36:36 +000042 typedef SkImageFilter INHERITED;
43};
44
reed60c9b582016-04-03 09:11:13 -070045sk_sp<SkFlattenable> FailImageFilter::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -070046 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
robertphillips43c2ad42016-04-04 05:05:11 -070047 return FailImageFilter::Make();
reed9fa60da2014-08-21 07:59:51 -070048}
djsollen@google.comba28d032012-03-26 17:57:35 +000049
reed@google.com8926b162012-03-23 15:36:36 +000050class IdentityImageFilter : public SkImageFilter {
51public:
robertphillips43c2ad42016-04-04 05:05:11 -070052 static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilter> input) {
53 return sk_sp<SkImageFilter>(new IdentityImageFilter(std::move(input)));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000054 }
reed@google.com8926b162012-03-23 15:36:36 +000055
reed9fa60da2014-08-21 07:59:51 -070056
Mike Kleina3d40992018-10-20 07:54:41 -040057 SK_FLATTENABLE_HOOKS(IdentityImageFilter)
robertphillips43c2ad42016-04-04 05:05:11 -070058protected:
robertphillips4ba94e22016-04-04 12:07:47 -070059 sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
60 SkIPoint* offset) const override {
commit-bot@chromium.orgf7efa502014-04-11 18:57:00 +000061 offset->set(0, 0);
robertphillips4ba94e22016-04-04 12:07:47 -070062 return sk_ref_sp<SkSpecialImage>(source);
reed@google.com8926b162012-03-23 15:36:36 +000063 }
Matt Sarett62745a82017-04-17 11:57:29 -040064 sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override {
65 return sk_ref_sp(const_cast<IdentityImageFilter*>(this));
66 }
reed@google.com8926b162012-03-23 15:36:36 +000067
reed@google.com8926b162012-03-23 15:36:36 +000068private:
robertphillips43c2ad42016-04-04 05:05:11 -070069 IdentityImageFilter(sk_sp<SkImageFilter> input) : INHERITED(&input, 1, nullptr) {}
70
reed@google.com8926b162012-03-23 15:36:36 +000071 typedef SkImageFilter INHERITED;
72};
73
Mike Kleina3d40992018-10-20 07:54:41 -040074// Register these image filters as deserializable before main().
75namespace {
76 static struct Initializer {
77 Initializer() {
Mike Kleinfa5f6ce2018-10-20 08:21:31 -040078 SK_REGISTER_FLATTENABLE(IdentityImageFilter);
79 SK_REGISTER_FLATTENABLE(FailImageFilter);
Mike Kleina3d40992018-10-20 07:54:41 -040080 }
81 } initializer;
82}
reed7daaaa42014-08-21 10:53:34 -070083
reed60c9b582016-04-03 09:11:13 -070084sk_sp<SkFlattenable> IdentityImageFilter::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -070085 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
robertphillips43c2ad42016-04-04 05:05:11 -070086 return IdentityImageFilter::Make(common.getInput(0));
reed9fa60da2014-08-21 07:59:51 -070087}
djsollen@google.comba28d032012-03-26 17:57:35 +000088
reed@google.com8926b162012-03-23 15:36:36 +000089///////////////////////////////////////////////////////////////////////////////
90
robertphillips5605b562016-04-05 11:50:42 -070091static void draw_paint(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +000092 SkPaint paint;
robertphillips5605b562016-04-05 11:50:42 -070093 paint.setImageFilter(std::move(imf));
reed@google.com8926b162012-03-23 15:36:36 +000094 paint.setColor(SK_ColorGREEN);
95 canvas->save();
96 canvas->clipRect(r);
97 canvas->drawPaint(paint);
98 canvas->restore();
99}
100
robertphillips5605b562016-04-05 11:50:42 -0700101static void draw_line(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +0000102 SkPaint paint;
103 paint.setColor(SK_ColorBLUE);
104 paint.setImageFilter(imf);
105 paint.setStrokeWidth(r.width()/10);
106 canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
107}
108
robertphillips5605b562016-04-05 11:50:42 -0700109static void draw_rect(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +0000110 SkPaint paint;
111 paint.setColor(SK_ColorYELLOW);
112 paint.setImageFilter(imf);
113 SkRect rr(r);
114 rr.inset(r.width()/10, r.height()/10);
115 canvas->drawRect(rr, paint);
116}
117
robertphillips5605b562016-04-05 11:50:42 -0700118static void draw_path(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +0000119 SkPaint paint;
120 paint.setColor(SK_ColorMAGENTA);
121 paint.setImageFilter(imf);
122 paint.setAntiAlias(true);
123 canvas->drawCircle(r.centerX(), r.centerY(), r.width()*2/5, paint);
124}
125
robertphillips5605b562016-04-05 11:50:42 -0700126static void draw_text(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +0000127 SkPaint paint;
128 paint.setImageFilter(imf);
129 paint.setColor(SK_ColorCYAN);
Mike Reeddc5863c2018-12-23 23:19:14 -0500130 SkFont font(sk_tool_utils::create_portable_typeface(), r.height()/2);
131 SkTextUtils::DrawString(canvas, "Text", r.centerX(), r.centerY(), font, paint,
Mike Reed3a42ec02018-10-30 12:53:21 -0400132 SkTextUtils::kCenter_Align);
reed@google.com8926b162012-03-23 15:36:36 +0000133}
134
robertphillips5605b562016-04-05 11:50:42 -0700135static void draw_bitmap(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
reed@google.com8926b162012-03-23 15:36:36 +0000136 SkPaint paint;
robertphillips5605b562016-04-05 11:50:42 -0700137 paint.setImageFilter(std::move(imf));
rmistry@google.comd6176b02012-08-23 18:14:13 +0000138
reed@google.com8926b162012-03-23 15:36:36 +0000139 SkIRect bounds;
140 r.roundOut(&bounds);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000141
reed@google.com8926b162012-03-23 15:36:36 +0000142 SkBitmap bm;
reed@google.comeb9a46c2014-01-25 16:46:20 +0000143 bm.allocN32Pixels(bounds.width(), bounds.height());
junov@google.comdbfac8a2012-12-06 21:47:40 +0000144 bm.eraseColor(SK_ColorTRANSPARENT);
reed@google.com8926b162012-03-23 15:36:36 +0000145 SkCanvas c(bm);
halcanary96fcdcc2015-08-27 07:41:13 -0700146 draw_path(&c, r, nullptr);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000147
reed@google.com8926b162012-03-23 15:36:36 +0000148 canvas->drawBitmap(bm, 0, 0, &paint);
149}
150
reed@google.com8926b162012-03-23 15:36:36 +0000151///////////////////////////////////////////////////////////////////////////////
152
153class ImageFiltersBaseGM : public skiagm::GM {
154public:
155 ImageFiltersBaseGM () {}
156
157protected:
mtklein36352bf2015-03-25 18:17:31 -0700158 SkString onShortName() override {
reed@google.com8926b162012-03-23 15:36:36 +0000159 return SkString("imagefiltersbase");
160 }
161
mtklein36352bf2015-03-25 18:17:31 -0700162 SkISize onISize() override { return SkISize::Make(700, 500); }
reed@google.com8926b162012-03-23 15:36:36 +0000163
164 void draw_frame(SkCanvas* canvas, const SkRect& r) {
165 SkPaint paint;
166 paint.setStyle(SkPaint::kStroke_Style);
167 paint.setColor(SK_ColorRED);
168 canvas->drawRect(r, paint);
169 }
170
mtklein36352bf2015-03-25 18:17:31 -0700171 void onDraw(SkCanvas* canvas) override {
robertphillips5605b562016-04-05 11:50:42 -0700172 void (*drawProc[])(SkCanvas*, const SkRect&, sk_sp<SkImageFilter>) = {
reed@google.com8926b162012-03-23 15:36:36 +0000173 draw_paint,
174 draw_line, draw_rect, draw_path, draw_text,
175 draw_bitmap,
reed@google.com8926b162012-03-23 15:36:36 +0000176 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000177
Mike Reed7d954ad2016-10-28 15:42:34 -0400178 auto cf = SkColorFilter::MakeModeFilter(SK_ColorRED, SkBlendMode::kSrcIn);
robertphillips5605b562016-04-05 11:50:42 -0700179 sk_sp<SkImageFilter> filters[] = {
halcanary96fcdcc2015-08-27 07:41:13 -0700180 nullptr,
robertphillips5605b562016-04-05 11:50:42 -0700181 IdentityImageFilter::Make(nullptr),
182 FailImageFilter::Make(),
183 SkColorFilterImageFilter::Make(std::move(cf), nullptr),
Herb Derby4fafedd2017-12-18 15:06:29 -0500184 // The strage 0.29 value tickles an edge case where crop rect calculates
185 // a small border, but the blur really needs no border. This tickels
186 // an msan uninitialized value bug.
187 SkBlurImageFilter::Make(12.0f, 0.29f, nullptr),
robertphillipsc4169122016-04-06 08:40:59 -0700188 SkDropShadowImageFilter::Make(
robertphillips5605b562016-04-05 11:50:42 -0700189 10.0f, 5.0f, 3.0f, 3.0f, SK_ColorBLUE,
robertphillipsc4169122016-04-06 08:40:59 -0700190 SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
191 nullptr),
reed@google.com8926b162012-03-23 15:36:36 +0000192 };
reed@google.com8926b162012-03-23 15:36:36 +0000193
194 SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64));
195 SkScalar MARGIN = SkIntToScalar(16);
196 SkScalar DX = r.width() + MARGIN;
197 SkScalar DY = r.height() + MARGIN;
198
199 canvas->translate(MARGIN, MARGIN);
200 for (size_t i = 0; i < SK_ARRAY_COUNT(drawProc); ++i) {
201 canvas->save();
202 for (size_t j = 0; j < SK_ARRAY_COUNT(filters); ++j) {
203 drawProc[i](canvas, r, filters[j]);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000204
reed@google.com8926b162012-03-23 15:36:36 +0000205 draw_frame(canvas, r);
206 canvas->translate(0, DY);
207 }
208 canvas->restore();
209 canvas->translate(DX, 0);
210 }
reed@google.com8926b162012-03-23 15:36:36 +0000211 }
212
213private:
214 typedef GM INHERITED;
215};
reed8dc0ccb2015-03-20 06:32:52 -0700216DEF_GM( return new ImageFiltersBaseGM; )
reed@google.com8926b162012-03-23 15:36:36 +0000217
218///////////////////////////////////////////////////////////////////////////////
219
reed8dc0ccb2015-03-20 06:32:52 -0700220/*
221 * Want to test combos of filter and LCD text, to be sure we disable LCD in the presence of
222 * a filter.
223 */
224class ImageFiltersTextBaseGM : public skiagm::GM {
225 SkString fSuffix;
226public:
227 ImageFiltersTextBaseGM(const char suffix[]) : fSuffix(suffix) {}
228
229protected:
mtklein36352bf2015-03-25 18:17:31 -0700230 SkString onShortName() override {
reed8dc0ccb2015-03-20 06:32:52 -0700231 SkString name;
232 name.printf("%s_%s", "textfilter", fSuffix.c_str());
233 return name;
234 }
235
mtklein36352bf2015-03-25 18:17:31 -0700236 SkISize onISize() override { return SkISize::Make(512, 342); }
reed8dc0ccb2015-03-20 06:32:52 -0700237
Hal Canary6ac0df82019-01-07 16:01:22 -0500238 void drawWaterfall(SkCanvas* canvas, const SkPaint& paint) {
239 static const SkFont::Edging kEdgings[3] = {
240 SkFont::Edging::kAlias,
241 SkFont::Edging::kAntiAlias,
242 SkFont::Edging::kSubpixelAntiAlias,
reed8dc0ccb2015-03-20 06:32:52 -0700243 };
Hal Canary6ac0df82019-01-07 16:01:22 -0500244 SkFont font(sk_tool_utils::create_portable_typeface(), 30);
reed8dc0ccb2015-03-20 06:32:52 -0700245
246 SkAutoCanvasRestore acr(canvas, true);
Hal Canary6ac0df82019-01-07 16:01:22 -0500247 for (SkFont::Edging edging : kEdgings) {
248 font.setEdging(edging);
249 canvas->drawString("Hamburgefon", 0, 0, font, paint);
reed8dc0ccb2015-03-20 06:32:52 -0700250 canvas->translate(0, 40);
251 }
252 }
253
254 virtual void installFilter(SkPaint* paint) = 0;
255
mtklein36352bf2015-03-25 18:17:31 -0700256 void onDraw(SkCanvas* canvas) override {
reed8dc0ccb2015-03-20 06:32:52 -0700257 SkPaint paint;
258
259 canvas->translate(20, 40);
260
261 for (int doSaveLayer = 0; doSaveLayer <= 1; ++doSaveLayer) {
262 SkAutoCanvasRestore acr(canvas, true);
263 for (int useFilter = 0; useFilter <= 1; ++useFilter) {
264 SkAutoCanvasRestore acr2(canvas, true);
265
266 SkPaint paint;
267 if (useFilter) {
268 this->installFilter(&paint);
269 }
270 if (doSaveLayer) {
halcanary96fcdcc2015-08-27 07:41:13 -0700271 canvas->saveLayer(nullptr, &paint);
272 paint.setImageFilter(nullptr);
reed8dc0ccb2015-03-20 06:32:52 -0700273 }
274 this->drawWaterfall(canvas, paint);
275
276 acr2.restore();
277 canvas->translate(250, 0);
278 }
279 acr.restore();
280 canvas->translate(0, 200);
281 }
282 }
halcanary9d524f22016-03-29 09:03:52 -0700283
reed8dc0ccb2015-03-20 06:32:52 -0700284private:
285 typedef GM INHERITED;
286};
287
288class ImageFiltersText_IF : public ImageFiltersTextBaseGM {
289public:
290 ImageFiltersText_IF() : ImageFiltersTextBaseGM("image") {}
291
mtklein36352bf2015-03-25 18:17:31 -0700292 void installFilter(SkPaint* paint) override {
robertphillips6e7025a2016-04-04 04:31:25 -0700293 paint->setImageFilter(SkBlurImageFilter::Make(1.5f, 1.5f, nullptr));
reed8dc0ccb2015-03-20 06:32:52 -0700294 }
295};
296DEF_GM( return new ImageFiltersText_IF; )
297
298class ImageFiltersText_CF : public ImageFiltersTextBaseGM {
299public:
300 ImageFiltersText_CF() : ImageFiltersTextBaseGM("color") {}
301
mtklein36352bf2015-03-25 18:17:31 -0700302 void installFilter(SkPaint* paint) override {
Mike Reed7d954ad2016-10-28 15:42:34 -0400303 paint->setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorBLUE, SkBlendMode::kSrcIn));
reed8dc0ccb2015-03-20 06:32:52 -0700304 }
305};
306DEF_GM( return new ImageFiltersText_CF; )