blob: 6e8ac29dea0b3ae1d98b20065a9c2b6b12ad922b [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"
9#include "SkCanvas.h"
10#include "SkColorFilter.h"
11#include "SkColorPriv.h"
12#include "SkShader.h"
13
14#include "SkBlurImageFilter.h"
senorblanco@chromium.org44888c62012-08-20 19:23:24 +000015#include "SkColorFilterImageFilter.h"
junov@chromium.orgf44fcdc2013-08-07 20:00:55 +000016#include "SkDropShadowImageFilter.h"
reed@google.com8926b162012-03-23 15:36:36 +000017#include "SkTestImageFilters.h"
18
19class FailImageFilter : public SkImageFilter {
20public:
reed7daaaa42014-08-21 10:53:34 -070021 class Registrar {
22 public:
23 Registrar() {
24 SkFlattenable::Register("FailImageFilter",
reed7daaaa42014-08-21 10:53:34 -070025 FailImageFilter::CreateProc,
reed7daaaa42014-08-21 10:53:34 -070026 FailImageFilter::GetFlattenableType());
27 }
28 };
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000029 static FailImageFilter* Create() {
30 return SkNEW(FailImageFilter);
31 }
djsollen@google.comba28d032012-03-26 17:57:35 +000032
robertphillipsf3f5bad2014-12-19 13:49:15 -080033 SK_TO_STRING_OVERRIDE()
djsollen@google.comba28d032012-03-26 17:57:35 +000034 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(FailImageFilter)
reed9fa60da2014-08-21 07:59:51 -070035
reed@google.com8926b162012-03-23 15:36:36 +000036protected:
reed7daaaa42014-08-21 10:53:34 -070037 FailImageFilter() : INHERITED(0, NULL) {}
reed9fa60da2014-08-21 07:59:51 -070038
reed8dc0ccb2015-03-20 06:32:52 -070039 bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
mtklein36352bf2015-03-25 18:17:31 -070040 SkBitmap* result, SkIPoint* offset) const override {
reed@google.com8926b162012-03-23 15:36:36 +000041 return false;
42 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000043
reed@google.com8926b162012-03-23 15:36:36 +000044private:
reed@google.com8926b162012-03-23 15:36:36 +000045 typedef SkImageFilter INHERITED;
46};
47
reed7daaaa42014-08-21 10:53:34 -070048static FailImageFilter::Registrar gReg0;
49
reed9fa60da2014-08-21 07:59:51 -070050SkFlattenable* FailImageFilter::CreateProc(SkReadBuffer& buffer) {
51 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
52 return FailImageFilter::Create();
53}
djsollen@google.comba28d032012-03-26 17:57:35 +000054
robertphillipsf3f5bad2014-12-19 13:49:15 -080055#ifndef SK_IGNORE_TO_STRING
56void FailImageFilter::toString(SkString* str) const {
57 str->appendf("FailImageFilter: (");
58 str->append(")");
59}
60#endif
61
reed@google.com8926b162012-03-23 15:36:36 +000062class IdentityImageFilter : public SkImageFilter {
63public:
reed7daaaa42014-08-21 10:53:34 -070064 class Registrar {
65 public:
66 Registrar() {
67 SkFlattenable::Register("IdentityImageFilter",
reed7daaaa42014-08-21 10:53:34 -070068 IdentityImageFilter::CreateProc,
reed7daaaa42014-08-21 10:53:34 -070069 IdentityImageFilter::GetFlattenableType());
70 }
71 };
senorblanco9ea3d572014-07-08 09:16:22 -070072 static IdentityImageFilter* Create(SkImageFilter* input = NULL) {
73 return SkNEW_ARGS(IdentityImageFilter, (input));
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000074 }
reed@google.com8926b162012-03-23 15:36:36 +000075
robertphillipsf3f5bad2014-12-19 13:49:15 -080076 SK_TO_STRING_OVERRIDE()
djsollen@google.comba28d032012-03-26 17:57:35 +000077 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(IdentityImageFilter)
reed@google.com8926b162012-03-23 15:36:36 +000078protected:
reed7daaaa42014-08-21 10:53:34 -070079 IdentityImageFilter(SkImageFilter* input) : INHERITED(1, &input) {}
reed9fa60da2014-08-21 07:59:51 -070080
reed8dc0ccb2015-03-20 06:32:52 -070081 bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
mtklein36352bf2015-03-25 18:17:31 -070082 SkBitmap* result, SkIPoint* offset) const override {
reed@google.com8926b162012-03-23 15:36:36 +000083 *result = src;
commit-bot@chromium.orgf7efa502014-04-11 18:57:00 +000084 offset->set(0, 0);
reed@google.com8926b162012-03-23 15:36:36 +000085 return true;
86 }
87
reed@google.com8926b162012-03-23 15:36:36 +000088private:
reed@google.com8926b162012-03-23 15:36:36 +000089 typedef SkImageFilter INHERITED;
90};
91
reed7daaaa42014-08-21 10:53:34 -070092static IdentityImageFilter::Registrar gReg1;
93
reed9fa60da2014-08-21 07:59:51 -070094SkFlattenable* IdentityImageFilter::CreateProc(SkReadBuffer& buffer) {
95 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
96 return IdentityImageFilter::Create(common.getInput(0));
97}
djsollen@google.comba28d032012-03-26 17:57:35 +000098
robertphillipsf3f5bad2014-12-19 13:49:15 -080099#ifndef SK_IGNORE_TO_STRING
100void IdentityImageFilter::toString(SkString* str) const {
101 str->appendf("IdentityImageFilter: (");
102 str->append(")");
103}
104#endif
105
reed@google.com8926b162012-03-23 15:36:36 +0000106///////////////////////////////////////////////////////////////////////////////
107
108static void draw_paint(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
109 SkPaint paint;
110 paint.setImageFilter(imf);
111 paint.setColor(SK_ColorGREEN);
112 canvas->save();
113 canvas->clipRect(r);
114 canvas->drawPaint(paint);
115 canvas->restore();
116}
117
118static void draw_line(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
119 SkPaint paint;
120 paint.setColor(SK_ColorBLUE);
121 paint.setImageFilter(imf);
122 paint.setStrokeWidth(r.width()/10);
123 canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
124}
125
126static void draw_rect(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
127 SkPaint paint;
128 paint.setColor(SK_ColorYELLOW);
129 paint.setImageFilter(imf);
130 SkRect rr(r);
131 rr.inset(r.width()/10, r.height()/10);
132 canvas->drawRect(rr, paint);
133}
134
135static void draw_path(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
136 SkPaint paint;
137 paint.setColor(SK_ColorMAGENTA);
138 paint.setImageFilter(imf);
139 paint.setAntiAlias(true);
140 canvas->drawCircle(r.centerX(), r.centerY(), r.width()*2/5, paint);
141}
142
143static void draw_text(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
144 SkPaint paint;
145 paint.setImageFilter(imf);
146 paint.setColor(SK_ColorCYAN);
147 paint.setAntiAlias(true);
Cary Clark992c7b02014-07-31 08:58:44 -0400148 sk_tool_utils::set_portable_typeface(&paint);
reed@google.com8926b162012-03-23 15:36:36 +0000149 paint.setTextSize(r.height()/2);
150 paint.setTextAlign(SkPaint::kCenter_Align);
151 canvas->drawText("Text", 4, r.centerX(), r.centerY(), paint);
152}
153
154static void draw_bitmap(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
155 SkPaint paint;
156 paint.setImageFilter(imf);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000157
reed@google.com8926b162012-03-23 15:36:36 +0000158 SkIRect bounds;
159 r.roundOut(&bounds);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000160
reed@google.com8926b162012-03-23 15:36:36 +0000161 SkBitmap bm;
reed@google.comeb9a46c2014-01-25 16:46:20 +0000162 bm.allocN32Pixels(bounds.width(), bounds.height());
junov@google.comdbfac8a2012-12-06 21:47:40 +0000163 bm.eraseColor(SK_ColorTRANSPARENT);
reed@google.com8926b162012-03-23 15:36:36 +0000164 SkCanvas c(bm);
165 draw_path(&c, r, NULL);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000166
reed@google.com8926b162012-03-23 15:36:36 +0000167 canvas->drawBitmap(bm, 0, 0, &paint);
168}
169
170static void draw_sprite(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
171 SkPaint paint;
172 paint.setImageFilter(imf);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000173
reed@google.com8926b162012-03-23 15:36:36 +0000174 SkIRect bounds;
175 r.roundOut(&bounds);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000176
reed@google.com8926b162012-03-23 15:36:36 +0000177 SkBitmap bm;
reed@google.comeb9a46c2014-01-25 16:46:20 +0000178 bm.allocN32Pixels(bounds.width(), bounds.height());
junov@google.comdbfac8a2012-12-06 21:47:40 +0000179 bm.eraseColor(SK_ColorTRANSPARENT);
reed@google.com8926b162012-03-23 15:36:36 +0000180 SkCanvas c(bm);
181 draw_path(&c, r, NULL);
182
183 SkPoint loc = { r.fLeft, r.fTop };
184 canvas->getTotalMatrix().mapPoints(&loc, 1);
185 canvas->drawSprite(bm,
186 SkScalarRoundToInt(loc.fX), SkScalarRoundToInt(loc.fY),
187 &paint);
188}
189
190///////////////////////////////////////////////////////////////////////////////
191
192class ImageFiltersBaseGM : public skiagm::GM {
193public:
194 ImageFiltersBaseGM () {}
195
196protected:
mtklein36352bf2015-03-25 18:17:31 -0700197 SkString onShortName() override {
reed@google.com8926b162012-03-23 15:36:36 +0000198 return SkString("imagefiltersbase");
199 }
200
mtklein36352bf2015-03-25 18:17:31 -0700201 SkISize onISize() override { return SkISize::Make(700, 500); }
reed@google.com8926b162012-03-23 15:36:36 +0000202
203 void draw_frame(SkCanvas* canvas, const SkRect& r) {
204 SkPaint paint;
205 paint.setStyle(SkPaint::kStroke_Style);
206 paint.setColor(SK_ColorRED);
207 canvas->drawRect(r, paint);
208 }
209
mtklein36352bf2015-03-25 18:17:31 -0700210 void onDraw(SkCanvas* canvas) override {
reed@google.com8926b162012-03-23 15:36:36 +0000211 void (*drawProc[])(SkCanvas*, const SkRect&, SkImageFilter*) = {
212 draw_paint,
213 draw_line, draw_rect, draw_path, draw_text,
214 draw_bitmap,
215 draw_sprite
216 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000217
reed@google.com8926b162012-03-23 15:36:36 +0000218 SkColorFilter* cf = SkColorFilter::CreateModeFilter(SK_ColorRED,
219 SkXfermode::kSrcIn_Mode);
220 SkImageFilter* filters[] = {
reed@google.com8926b162012-03-23 15:36:36 +0000221 NULL,
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000222 IdentityImageFilter::Create(),
223 FailImageFilter::Create(),
senorblanco@chromium.orgcd9f5592012-10-26 19:37:00 +0000224 SkColorFilterImageFilter::Create(cf),
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000225 SkBlurImageFilter::Create(12.0f, 0.0f),
sugoi234f0362014-10-23 13:59:52 -0700226 SkDropShadowImageFilter::Create(10.0f, 5.0f, 3.0f, 3.0f, SK_ColorBLUE,
227 SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode),
reed@google.com8926b162012-03-23 15:36:36 +0000228 };
229 cf->unref();
230
231 SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64));
232 SkScalar MARGIN = SkIntToScalar(16);
233 SkScalar DX = r.width() + MARGIN;
234 SkScalar DY = r.height() + MARGIN;
235
236 canvas->translate(MARGIN, MARGIN);
237 for (size_t i = 0; i < SK_ARRAY_COUNT(drawProc); ++i) {
238 canvas->save();
239 for (size_t j = 0; j < SK_ARRAY_COUNT(filters); ++j) {
240 drawProc[i](canvas, r, filters[j]);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000241
reed@google.com8926b162012-03-23 15:36:36 +0000242 draw_frame(canvas, r);
243 canvas->translate(0, DY);
244 }
245 canvas->restore();
246 canvas->translate(DX, 0);
247 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000248
reed@google.com4bca84d2012-06-27 14:00:06 +0000249 for(size_t j = 0; j < SK_ARRAY_COUNT(filters); ++j) {
250 SkSafeUnref(filters[j]);
251 }
reed@google.com8926b162012-03-23 15:36:36 +0000252 }
253
254private:
255 typedef GM INHERITED;
256};
reed8dc0ccb2015-03-20 06:32:52 -0700257DEF_GM( return new ImageFiltersBaseGM; )
reed@google.com8926b162012-03-23 15:36:36 +0000258
259///////////////////////////////////////////////////////////////////////////////
260
reed8dc0ccb2015-03-20 06:32:52 -0700261/*
262 * Want to test combos of filter and LCD text, to be sure we disable LCD in the presence of
263 * a filter.
264 */
265class ImageFiltersTextBaseGM : public skiagm::GM {
266 SkString fSuffix;
267public:
268 ImageFiltersTextBaseGM(const char suffix[]) : fSuffix(suffix) {}
269
270protected:
mtklein36352bf2015-03-25 18:17:31 -0700271 SkString onShortName() override {
reed8dc0ccb2015-03-20 06:32:52 -0700272 SkString name;
273 name.printf("%s_%s", "textfilter", fSuffix.c_str());
274 return name;
275 }
276
mtklein36352bf2015-03-25 18:17:31 -0700277 SkISize onISize() override { return SkISize::Make(512, 342); }
reed8dc0ccb2015-03-20 06:32:52 -0700278
279 void drawWaterfall(SkCanvas* canvas, const SkPaint& origPaint) {
280 const uint32_t flags[] = {
281 0,
282 SkPaint::kAntiAlias_Flag,
283 SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag,
284 };
285 SkPaint paint(origPaint);
286 paint.setTextSize(30);
287
288 SkAutoCanvasRestore acr(canvas, true);
289 for (size_t i = 0; i < SK_ARRAY_COUNT(flags); ++i) {
290 paint.setFlags(flags[i]);
291 canvas->drawText("Hamburgefons", 11, 0, 0, paint);
292 canvas->translate(0, 40);
293 }
294 }
295
296 virtual void installFilter(SkPaint* paint) = 0;
297
mtklein36352bf2015-03-25 18:17:31 -0700298 void onDraw(SkCanvas* canvas) override {
reed8dc0ccb2015-03-20 06:32:52 -0700299 SkPaint paint;
300
301 canvas->translate(20, 40);
302
303 for (int doSaveLayer = 0; doSaveLayer <= 1; ++doSaveLayer) {
304 SkAutoCanvasRestore acr(canvas, true);
305 for (int useFilter = 0; useFilter <= 1; ++useFilter) {
306 SkAutoCanvasRestore acr2(canvas, true);
307
308 SkPaint paint;
309 if (useFilter) {
310 this->installFilter(&paint);
311 }
312 if (doSaveLayer) {
313 canvas->saveLayer(NULL, &paint);
314 paint.setImageFilter(NULL);
315 }
316 this->drawWaterfall(canvas, paint);
317
318 acr2.restore();
319 canvas->translate(250, 0);
320 }
321 acr.restore();
322 canvas->translate(0, 200);
323 }
324 }
325
326private:
327 typedef GM INHERITED;
328};
329
330class ImageFiltersText_IF : public ImageFiltersTextBaseGM {
331public:
332 ImageFiltersText_IF() : ImageFiltersTextBaseGM("image") {}
333
mtklein36352bf2015-03-25 18:17:31 -0700334 void installFilter(SkPaint* paint) override {
reed8dc0ccb2015-03-20 06:32:52 -0700335 paint->setImageFilter(SkBlurImageFilter::Create(1.5f, 1.5f))->unref();
336 }
337};
338DEF_GM( return new ImageFiltersText_IF; )
339
340class ImageFiltersText_CF : public ImageFiltersTextBaseGM {
341public:
342 ImageFiltersText_CF() : ImageFiltersTextBaseGM("color") {}
343
mtklein36352bf2015-03-25 18:17:31 -0700344 void installFilter(SkPaint* paint) override {
reed8dc0ccb2015-03-20 06:32:52 -0700345 paint->setColorFilter(SkColorFilter::CreateModeFilter(SK_ColorBLUE, SkXfermode::kSrcIn_Mode))->unref();
346 }
347};
348DEF_GM( return new ImageFiltersText_CF; )
349