• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "sk_tool_utils.h"
10 #include "SkCanvas.h"
11 #include "SkColorFilter.h"
12 #include "SkColorPriv.h"
13 #include "SkImageFilterPriv.h"
14 #include "SkShader.h"
15 
16 #include "SkBlurImageFilter.h"
17 #include "SkColorFilterImageFilter.h"
18 #include "SkDropShadowImageFilter.h"
19 #include "SkSpecialImage.h"
20 
21 class FailImageFilter : public SkImageFilter {
22 public:
23     class Registrar {
24     public:
Registrar()25         Registrar() {
26             SkFlattenable::Register("FailImageFilter",
27                                     FailImageFilter::CreateProc,
28                                     FailImageFilter::GetFlattenableType());
29         }
30     };
Make()31     static sk_sp<SkImageFilter> Make() {
32         return sk_sp<SkImageFilter>(new FailImageFilter);
33     }
34 
35     SK_TO_STRING_OVERRIDE()
36     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(FailImageFilter)
37 
38 protected:
FailImageFilter()39     FailImageFilter() : INHERITED(nullptr, 0, nullptr) {}
40 
onFilterImage(SkSpecialImage * source,const Context &,SkIPoint * offset) const41     sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
42                                         SkIPoint* offset) const override {
43         return nullptr;
44     }
onMakeColorSpace(SkColorSpaceXformer *) const45     sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override {
46         return nullptr;
47     }
48 
49 private:
50     typedef SkImageFilter INHERITED;
51 };
52 
53 static FailImageFilter::Registrar gReg0;
54 
CreateProc(SkReadBuffer & buffer)55 sk_sp<SkFlattenable> FailImageFilter::CreateProc(SkReadBuffer& buffer) {
56     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
57     return FailImageFilter::Make();
58 }
59 
60 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const61 void FailImageFilter::toString(SkString* str) const {
62     str->appendf("FailImageFilter: (");
63     str->append(")");
64 }
65 #endif
66 
67 class IdentityImageFilter : public SkImageFilter {
68 public:
69     class Registrar {
70     public:
Registrar()71         Registrar() {
72             SkFlattenable::Register("IdentityImageFilter",
73                                     IdentityImageFilter::CreateProc,
74                                     IdentityImageFilter::GetFlattenableType());
75         }
76     };
Make(sk_sp<SkImageFilter> input)77     static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilter> input) {
78         return sk_sp<SkImageFilter>(new IdentityImageFilter(std::move(input)));
79     }
80 
81     SK_TO_STRING_OVERRIDE()
82     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(IdentityImageFilter)
83 
84 protected:
onFilterImage(SkSpecialImage * source,const Context &,SkIPoint * offset) const85     sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
86                                         SkIPoint* offset) const override {
87         offset->set(0, 0);
88         return sk_ref_sp<SkSpecialImage>(source);
89     }
onMakeColorSpace(SkColorSpaceXformer *) const90     sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override {
91         return sk_ref_sp(const_cast<IdentityImageFilter*>(this));
92     }
93 
94 private:
IdentityImageFilter(sk_sp<SkImageFilter> input)95     IdentityImageFilter(sk_sp<SkImageFilter> input) : INHERITED(&input, 1, nullptr) {}
96 
97     typedef SkImageFilter INHERITED;
98 };
99 
100 static IdentityImageFilter::Registrar gReg1;
101 
CreateProc(SkReadBuffer & buffer)102 sk_sp<SkFlattenable> IdentityImageFilter::CreateProc(SkReadBuffer& buffer) {
103     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
104     return IdentityImageFilter::Make(common.getInput(0));
105 }
106 
107 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const108 void IdentityImageFilter::toString(SkString* str) const {
109     str->appendf("IdentityImageFilter: (");
110     str->append(")");
111 }
112 #endif
113 
114 ///////////////////////////////////////////////////////////////////////////////
115 
draw_paint(SkCanvas * canvas,const SkRect & r,sk_sp<SkImageFilter> imf)116 static void draw_paint(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
117     SkPaint paint;
118     paint.setImageFilter(std::move(imf));
119     paint.setColor(SK_ColorGREEN);
120     canvas->save();
121     canvas->clipRect(r);
122     canvas->drawPaint(paint);
123     canvas->restore();
124 }
125 
draw_line(SkCanvas * canvas,const SkRect & r,sk_sp<SkImageFilter> imf)126 static void draw_line(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
127     SkPaint paint;
128     paint.setColor(SK_ColorBLUE);
129     paint.setImageFilter(imf);
130     paint.setStrokeWidth(r.width()/10);
131     canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
132 }
133 
draw_rect(SkCanvas * canvas,const SkRect & r,sk_sp<SkImageFilter> imf)134 static void draw_rect(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
135     SkPaint paint;
136     paint.setColor(SK_ColorYELLOW);
137     paint.setImageFilter(imf);
138     SkRect rr(r);
139     rr.inset(r.width()/10, r.height()/10);
140     canvas->drawRect(rr, paint);
141 }
142 
draw_path(SkCanvas * canvas,const SkRect & r,sk_sp<SkImageFilter> imf)143 static void draw_path(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
144     SkPaint paint;
145     paint.setColor(SK_ColorMAGENTA);
146     paint.setImageFilter(imf);
147     paint.setAntiAlias(true);
148     canvas->drawCircle(r.centerX(), r.centerY(), r.width()*2/5, paint);
149 }
150 
draw_text(SkCanvas * canvas,const SkRect & r,sk_sp<SkImageFilter> imf)151 static void draw_text(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
152     SkPaint paint;
153     paint.setImageFilter(imf);
154     paint.setColor(SK_ColorCYAN);
155     paint.setAntiAlias(true);
156     sk_tool_utils::set_portable_typeface(&paint);
157     paint.setTextSize(r.height()/2);
158     paint.setTextAlign(SkPaint::kCenter_Align);
159     canvas->drawString("Text", r.centerX(), r.centerY(), paint);
160 }
161 
draw_bitmap(SkCanvas * canvas,const SkRect & r,sk_sp<SkImageFilter> imf)162 static void draw_bitmap(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
163     SkPaint paint;
164     paint.setImageFilter(std::move(imf));
165 
166     SkIRect bounds;
167     r.roundOut(&bounds);
168 
169     SkBitmap bm;
170     bm.allocN32Pixels(bounds.width(), bounds.height());
171     bm.eraseColor(SK_ColorTRANSPARENT);
172     SkCanvas c(bm);
173     draw_path(&c, r, nullptr);
174 
175     canvas->drawBitmap(bm, 0, 0, &paint);
176 }
177 
178 ///////////////////////////////////////////////////////////////////////////////
179 
180 class ImageFiltersBaseGM : public skiagm::GM {
181 public:
ImageFiltersBaseGM()182     ImageFiltersBaseGM () {}
183 
184 protected:
onShortName()185     SkString onShortName() override {
186         return SkString("imagefiltersbase");
187     }
188 
onISize()189     SkISize onISize() override { return SkISize::Make(700, 500); }
190 
draw_frame(SkCanvas * canvas,const SkRect & r)191     void draw_frame(SkCanvas* canvas, const SkRect& r) {
192         SkPaint paint;
193         paint.setStyle(SkPaint::kStroke_Style);
194         paint.setColor(SK_ColorRED);
195         canvas->drawRect(r, paint);
196     }
197 
onDraw(SkCanvas * canvas)198     void onDraw(SkCanvas* canvas) override {
199         void (*drawProc[])(SkCanvas*, const SkRect&, sk_sp<SkImageFilter>) = {
200             draw_paint,
201             draw_line, draw_rect, draw_path, draw_text,
202             draw_bitmap,
203         };
204 
205         auto cf = SkColorFilter::MakeModeFilter(SK_ColorRED, SkBlendMode::kSrcIn);
206         sk_sp<SkImageFilter> filters[] = {
207             nullptr,
208             IdentityImageFilter::Make(nullptr),
209             FailImageFilter::Make(),
210             SkColorFilterImageFilter::Make(std::move(cf), nullptr),
211             // The strage 0.29 value tickles an edge case where crop rect calculates
212             // a small border, but the blur really needs no border. This tickels
213             // an msan uninitialized value bug.
214             SkBlurImageFilter::Make(12.0f, 0.29f, nullptr),
215             SkDropShadowImageFilter::Make(
216                                     10.0f, 5.0f, 3.0f, 3.0f, SK_ColorBLUE,
217                                     SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
218                                     nullptr),
219         };
220 
221         SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64));
222         SkScalar MARGIN = SkIntToScalar(16);
223         SkScalar DX = r.width() + MARGIN;
224         SkScalar DY = r.height() + MARGIN;
225 
226         canvas->translate(MARGIN, MARGIN);
227         for (size_t i = 0; i < SK_ARRAY_COUNT(drawProc); ++i) {
228             canvas->save();
229             for (size_t j = 0; j < SK_ARRAY_COUNT(filters); ++j) {
230                 drawProc[i](canvas, r, filters[j]);
231 
232                 draw_frame(canvas, r);
233                 canvas->translate(0, DY);
234             }
235             canvas->restore();
236             canvas->translate(DX, 0);
237         }
238     }
239 
240 private:
241     typedef GM INHERITED;
242 };
243 DEF_GM( return new ImageFiltersBaseGM; )
244 
245 ///////////////////////////////////////////////////////////////////////////////
246 
247 /*
248  *  Want to test combos of filter and LCD text, to be sure we disable LCD in the presence of
249  *  a filter.
250  */
251 class ImageFiltersTextBaseGM : public skiagm::GM {
252     SkString fSuffix;
253 public:
ImageFiltersTextBaseGM(const char suffix[])254     ImageFiltersTextBaseGM(const char suffix[]) : fSuffix(suffix) {}
255 
256 protected:
onShortName()257     SkString onShortName() override {
258         SkString name;
259         name.printf("%s_%s", "textfilter", fSuffix.c_str());
260         return name;
261     }
262 
onISize()263     SkISize onISize() override { return SkISize::Make(512, 342); }
264 
drawWaterfall(SkCanvas * canvas,const SkPaint & origPaint)265     void drawWaterfall(SkCanvas* canvas, const SkPaint& origPaint) {
266         const uint32_t flags[] = {
267             0,
268             SkPaint::kAntiAlias_Flag,
269             SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag,
270         };
271         SkPaint paint(origPaint);
272         sk_tool_utils::set_portable_typeface(&paint);
273         paint.setTextSize(30);
274 
275         SkAutoCanvasRestore acr(canvas, true);
276         for (size_t i = 0; i < SK_ARRAY_COUNT(flags); ++i) {
277             paint.setFlags(flags[i]);
278             canvas->drawString("Hamburgefon", 0, 0, paint);
279             canvas->translate(0, 40);
280         }
281     }
282 
283     virtual void installFilter(SkPaint* paint) = 0;
284 
onDraw(SkCanvas * canvas)285     void onDraw(SkCanvas* canvas) override {
286         SkPaint paint;
287 
288         canvas->translate(20, 40);
289 
290         for (int doSaveLayer = 0; doSaveLayer <= 1; ++doSaveLayer) {
291             SkAutoCanvasRestore acr(canvas, true);
292             for (int useFilter = 0; useFilter <= 1; ++useFilter) {
293                 SkAutoCanvasRestore acr2(canvas, true);
294 
295                 SkPaint paint;
296                 if (useFilter) {
297                     this->installFilter(&paint);
298                 }
299                 if (doSaveLayer) {
300                     canvas->saveLayer(nullptr, &paint);
301                     paint.setImageFilter(nullptr);
302                 }
303                 this->drawWaterfall(canvas, paint);
304 
305                 acr2.restore();
306                 canvas->translate(250, 0);
307             }
308             acr.restore();
309             canvas->translate(0, 200);
310         }
311     }
312 
313 private:
314     typedef GM INHERITED;
315 };
316 
317 class ImageFiltersText_IF : public ImageFiltersTextBaseGM {
318 public:
ImageFiltersText_IF()319     ImageFiltersText_IF() : ImageFiltersTextBaseGM("image") {}
320 
installFilter(SkPaint * paint)321     void installFilter(SkPaint* paint) override {
322         paint->setImageFilter(SkBlurImageFilter::Make(1.5f, 1.5f, nullptr));
323     }
324 };
325 DEF_GM( return new ImageFiltersText_IF; )
326 
327 class ImageFiltersText_CF : public ImageFiltersTextBaseGM {
328 public:
ImageFiltersText_CF()329     ImageFiltersText_CF() : ImageFiltersTextBaseGM("color") {}
330 
installFilter(SkPaint * paint)331     void installFilter(SkPaint* paint) override {
332         paint->setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorBLUE, SkBlendMode::kSrcIn));
333     }
334 };
335 DEF_GM( return new ImageFiltersText_CF; )
336