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    FailImageFilter() : INHERITED(0) {}
22
23    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(FailImageFilter)
24protected:
25    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
26                               SkBitmap* result, SkIPoint* offset) {
27        return false;
28    }
29
30    FailImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
31
32private:
33    typedef SkImageFilter INHERITED;
34};
35
36// register the filter with the flattenable registry
37static SkFlattenable::Registrar gFailImageFilterReg("FailImageFilter",
38                                                    FailImageFilter::CreateProc);
39
40class IdentityImageFilter : public SkImageFilter {
41public:
42    IdentityImageFilter() : INHERITED(0) {}
43
44    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(IdentityImageFilter)
45protected:
46    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
47                               SkBitmap* result, SkIPoint* offset) {
48        *result = src;
49        return true;
50    }
51
52    IdentityImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
53
54private:
55    typedef SkImageFilter INHERITED;
56};
57
58// register the filter with the flattenable registry
59static SkFlattenable::Registrar gIdentityImageFilterReg("IdentityImageFilter",
60                                                        IdentityImageFilter::CreateProc);
61
62
63///////////////////////////////////////////////////////////////////////////////
64
65static void draw_paint(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
66    SkPaint paint;
67    paint.setImageFilter(imf);
68    paint.setColor(SK_ColorGREEN);
69    canvas->save();
70    canvas->clipRect(r);
71    canvas->drawPaint(paint);
72    canvas->restore();
73}
74
75static void draw_line(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
76    SkPaint paint;
77    paint.setColor(SK_ColorBLUE);
78    paint.setImageFilter(imf);
79    paint.setStrokeWidth(r.width()/10);
80    canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
81}
82
83static void draw_rect(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
84    SkPaint paint;
85    paint.setColor(SK_ColorYELLOW);
86    paint.setImageFilter(imf);
87    SkRect rr(r);
88    rr.inset(r.width()/10, r.height()/10);
89    canvas->drawRect(rr, paint);
90}
91
92static void draw_path(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
93    SkPaint paint;
94    paint.setColor(SK_ColorMAGENTA);
95    paint.setImageFilter(imf);
96    paint.setAntiAlias(true);
97    canvas->drawCircle(r.centerX(), r.centerY(), r.width()*2/5, paint);
98}
99
100static void draw_text(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
101    SkPaint paint;
102    paint.setImageFilter(imf);
103    paint.setColor(SK_ColorCYAN);
104    paint.setAntiAlias(true);
105    paint.setTextSize(r.height()/2);
106    paint.setTextAlign(SkPaint::kCenter_Align);
107    canvas->drawText("Text", 4, r.centerX(), r.centerY(), paint);
108}
109
110static void draw_bitmap(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
111    SkPaint paint;
112    paint.setImageFilter(imf);
113
114    SkIRect bounds;
115    r.roundOut(&bounds);
116
117    SkBitmap bm;
118    bm.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), bounds.height());
119    bm.allocPixels();
120    bm.eraseColor(SK_ColorTRANSPARENT);
121    SkCanvas c(bm);
122    draw_path(&c, r, NULL);
123
124    canvas->drawBitmap(bm, 0, 0, &paint);
125}
126
127static void draw_sprite(SkCanvas* canvas, const SkRect& r, SkImageFilter* imf) {
128    SkPaint paint;
129    paint.setImageFilter(imf);
130
131    SkIRect bounds;
132    r.roundOut(&bounds);
133
134    SkBitmap bm;
135    bm.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), bounds.height());
136    bm.allocPixels();
137    bm.eraseColor(SK_ColorTRANSPARENT);
138    SkCanvas c(bm);
139    draw_path(&c, r, NULL);
140
141    SkPoint loc = { r.fLeft, r.fTop };
142    canvas->getTotalMatrix().mapPoints(&loc, 1);
143    canvas->drawSprite(bm,
144                       SkScalarRoundToInt(loc.fX), SkScalarRoundToInt(loc.fY),
145                       &paint);
146}
147
148///////////////////////////////////////////////////////////////////////////////
149
150class ImageFiltersBaseGM : public skiagm::GM {
151public:
152    ImageFiltersBaseGM () {}
153
154protected:
155
156    virtual SkString onShortName() {
157        return SkString("imagefiltersbase");
158    }
159
160    virtual SkISize onISize() { return SkISize::Make(700, 500); }
161
162    void draw_frame(SkCanvas* canvas, const SkRect& r) {
163        SkPaint paint;
164        paint.setStyle(SkPaint::kStroke_Style);
165        paint.setColor(SK_ColorRED);
166        canvas->drawRect(r, paint);
167    }
168
169    virtual uint32_t onGetFlags() const {
170        // Because of the use of drawSprite, this test is excluded
171        // from scaled replay tests because drawSprite ignores the
172        // reciprocal scale that is applied at record time, which is
173        // the intended behavior of drawSprite.
174        return kSkipScaledReplay_Flag;
175    }
176
177    virtual void onDraw(SkCanvas* canvas) {
178        void (*drawProc[])(SkCanvas*, const SkRect&, SkImageFilter*) = {
179            draw_paint,
180            draw_line, draw_rect, draw_path, draw_text,
181            draw_bitmap,
182            draw_sprite
183        };
184
185        SkColorFilter* cf = SkColorFilter::CreateModeFilter(SK_ColorRED,
186                                                     SkXfermode::kSrcIn_Mode);
187        SkImageFilter* filters[] = {
188            NULL,
189            new IdentityImageFilter,
190            new FailImageFilter,
191            SkColorFilterImageFilter::Create(cf),
192            new SkBlurImageFilter(12.0f, 0.0f),
193            new SkDropShadowImageFilter(10.0f, 5.0f, 3.0f, SK_ColorBLUE),
194        };
195        cf->unref();
196
197        SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64));
198        SkScalar MARGIN = SkIntToScalar(16);
199        SkScalar DX = r.width() + MARGIN;
200        SkScalar DY = r.height() + MARGIN;
201
202        canvas->translate(MARGIN, MARGIN);
203        for (size_t i = 0; i < SK_ARRAY_COUNT(drawProc); ++i) {
204            canvas->save();
205            for (size_t j = 0; j < SK_ARRAY_COUNT(filters); ++j) {
206                drawProc[i](canvas, r, filters[j]);
207
208                draw_frame(canvas, r);
209                canvas->translate(0, DY);
210            }
211            canvas->restore();
212            canvas->translate(DX, 0);
213        }
214
215        for(size_t j = 0; j < SK_ARRAY_COUNT(filters); ++j) {
216            SkSafeUnref(filters[j]);
217        }
218    }
219
220private:
221    typedef GM INHERITED;
222};
223
224///////////////////////////////////////////////////////////////////////////////
225
226static skiagm::GM* MyFactory(void*) { return new ImageFiltersBaseGM; }
227static skiagm::GMRegistry reg(MyFactory);
228