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 "SkCanvas.h"
10#include "SkColorFilter.h"
11#include "SkColorPriv.h"
12#include "SkShader.h"
13
14#include "SkBlurImageFilter.h"
15#include "SkColorFilterImageFilter.h"
16#include "SkDropShadowImageFilter.h"
17#include "SkTestImageFilters.h"
18
19class FailImageFilter : public SkImageFilter {
20public:
21    class Registrar {
22    public:
23        Registrar() {
24            SkFlattenable::Register("FailImageFilter",
25#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
26                                    FailImageFilter::DeepCreateProc,
27#else
28                                    FailImageFilter::CreateProc,
29#endif
30                                    FailImageFilter::GetFlattenableType());
31        }
32    };
33    static FailImageFilter* Create() {
34        return SkNEW(FailImageFilter);
35    }
36
37    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(FailImageFilter)
38
39protected:
40    FailImageFilter() : INHERITED(0, NULL) {}
41
42    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
43                               SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE {
44        return false;
45    }
46
47#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
48    FailImageFilter(SkReadBuffer& buffer) : INHERITED(0, buffer) {}
49#endif
50
51private:
52    typedef SkImageFilter INHERITED;
53};
54
55static FailImageFilter::Registrar gReg0;
56
57SkFlattenable* FailImageFilter::CreateProc(SkReadBuffer& buffer) {
58    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
59    return FailImageFilter::Create();
60}
61
62class IdentityImageFilter : public SkImageFilter {
63public:
64    class Registrar {
65    public:
66        Registrar() {
67            SkFlattenable::Register("IdentityImageFilter",
68#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
69                                    IdentityImageFilter::DeepCreateProc,
70#else
71                                    IdentityImageFilter::CreateProc,
72#endif
73                                    IdentityImageFilter::GetFlattenableType());
74        }
75    };
76    static IdentityImageFilter* Create(SkImageFilter* input = NULL) {
77        return SkNEW_ARGS(IdentityImageFilter, (input));
78    }
79
80    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(IdentityImageFilter)
81protected:
82    IdentityImageFilter(SkImageFilter* input) : INHERITED(1, &input) {}
83
84    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
85                               SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE {
86        *result = src;
87        offset->set(0, 0);
88        return true;
89    }
90
91#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
92    IdentityImageFilter(SkReadBuffer& buffer) : INHERITED(1, buffer) {}
93#endif
94
95private:
96    typedef SkImageFilter INHERITED;
97};
98
99static IdentityImageFilter::Registrar gReg1;
100
101SkFlattenable* IdentityImageFilter::CreateProc(SkReadBuffer& buffer) {
102    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
103    return IdentityImageFilter::Create(common.getInput(0));
104}
105
106///////////////////////////////////////////////////////////////////////////////
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);
148    sk_tool_utils::set_portable_typeface(&paint);
149    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);
157
158    SkIRect bounds;
159    r.roundOut(&bounds);
160
161    SkBitmap bm;
162    bm.allocN32Pixels(bounds.width(), bounds.height());
163    bm.eraseColor(SK_ColorTRANSPARENT);
164    SkCanvas c(bm);
165    draw_path(&c, r, NULL);
166
167    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);
173
174    SkIRect bounds;
175    r.roundOut(&bounds);
176
177    SkBitmap bm;
178    bm.allocN32Pixels(bounds.width(), bounds.height());
179    bm.eraseColor(SK_ColorTRANSPARENT);
180    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:
197    virtual SkString onShortName() {
198        return SkString("imagefiltersbase");
199    }
200
201    virtual SkISize onISize() { return SkISize::Make(700, 500); }
202
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
210    virtual uint32_t onGetFlags() const {
211        // Because of the use of drawSprite, this test is excluded
212        // from scaled replay tests because drawSprite ignores the
213        // reciprocal scale that is applied at record time, which is
214        // the intended behavior of drawSprite.
215        return kSkipScaledReplay_Flag | kSkipTiled_Flag;
216    }
217
218    virtual void onDraw(SkCanvas* canvas) {
219        void (*drawProc[])(SkCanvas*, const SkRect&, SkImageFilter*) = {
220            draw_paint,
221            draw_line, draw_rect, draw_path, draw_text,
222            draw_bitmap,
223            draw_sprite
224        };
225
226        SkColorFilter* cf = SkColorFilter::CreateModeFilter(SK_ColorRED,
227                                                     SkXfermode::kSrcIn_Mode);
228        SkImageFilter* filters[] = {
229            NULL,
230            IdentityImageFilter::Create(),
231            FailImageFilter::Create(),
232            SkColorFilterImageFilter::Create(cf),
233            SkBlurImageFilter::Create(12.0f, 0.0f),
234            SkDropShadowImageFilter::Create(10.0f, 5.0f, 3.0f, 3.0f, SK_ColorBLUE),
235        };
236        cf->unref();
237
238        SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64));
239        SkScalar MARGIN = SkIntToScalar(16);
240        SkScalar DX = r.width() + MARGIN;
241        SkScalar DY = r.height() + MARGIN;
242
243        canvas->translate(MARGIN, MARGIN);
244        for (size_t i = 0; i < SK_ARRAY_COUNT(drawProc); ++i) {
245            canvas->save();
246            for (size_t j = 0; j < SK_ARRAY_COUNT(filters); ++j) {
247                drawProc[i](canvas, r, filters[j]);
248
249                draw_frame(canvas, r);
250                canvas->translate(0, DY);
251            }
252            canvas->restore();
253            canvas->translate(DX, 0);
254        }
255
256        for(size_t j = 0; j < SK_ARRAY_COUNT(filters); ++j) {
257            SkSafeUnref(filters[j]);
258        }
259    }
260
261private:
262    typedef GM INHERITED;
263};
264
265///////////////////////////////////////////////////////////////////////////////
266
267static skiagm::GM* MyFactory(void*) { return new ImageFiltersBaseGM; }
268static skiagm::GMRegistry reg(MyFactory);
269