1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "SampleCode.h"
9#include "SkView.h"
10#include "SkCanvas.h"
11#include "SkBlurMaskFilter.h"
12#include "SkCamera.h"
13#include "SkColorFilter.h"
14#include "SkColorPriv.h"
15#include "SkDevice.h"
16#include "SkGradientShader.h"
17#include "SkImageDecoder.h"
18#include "SkInterpolator.h"
19#include "SkMaskFilter.h"
20#include "SkPath.h"
21#include "SkRegion.h"
22#include "SkShader.h"
23#include "SkTime.h"
24#include "SkTypeface.h"
25#include "SkUtils.h"
26#include "SkKey.h"
27#include "SkXfermode.h"
28#include "SkDrawFilter.h"
29
30static void make_paint(SkPaint* paint, const SkMatrix& localMatrix) {
31    SkColor colors[] = { 0, SK_ColorWHITE };
32    SkPoint pts[] = { { 0, 0 }, { 0, SK_Scalar1*20 } };
33    SkShader* s = SkGradientShader::CreateLinear(pts, colors, nullptr, 2, SkShader::kClamp_TileMode,
34                                                 0, &localMatrix);
35
36    paint->setShader(s)->unref();
37    paint->setXfermodeMode(SkXfermode::kDstIn_Mode);
38}
39
40static void dump_layers(const char label[], SkCanvas* canvas) {
41    SkDebugf("Dump Layers(%s)\n", label);
42
43    SkCanvas::LayerIter iter(canvas, true);
44    int index = 0;
45    while (!iter.done()) {
46        SkImageInfo info = iter.device()->imageInfo();
47        const SkIRect& clip = iter.clip().getBounds();
48        SkDebugf("Layer[%d] bitmap [%d %d] X=%d Y=%d clip=[%d %d %d %d] alpha=%d\n", index++,
49                 info.width(), info.height(), iter.x(), iter.y(),
50                 clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
51                 iter.paint().getAlpha());
52        iter.next();
53    }
54}
55
56// test drawing with strips of fading gradient above and below
57static void test_fade(SkCanvas* canvas) {
58    SkAutoCanvasRestore ar(canvas, true);
59
60    SkRect r;
61
62    SkPaint p;
63    p.setAlpha(0x88);
64
65    SkAutoCanvasRestore ar2(canvas, false);
66
67    // create the layers
68
69    r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
70    canvas->clipRect(r);
71
72    r.fBottom = SkIntToScalar(20);
73    canvas->saveLayer(&r, nullptr);
74
75    r.fTop = SkIntToScalar(80);
76    r.fBottom = SkIntToScalar(100);
77    canvas->saveLayer(&r, nullptr);
78
79    // now draw the "content"
80
81    if (true) {
82        r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
83
84        canvas->saveLayerAlpha(&r, 0x80);
85
86        SkPaint p;
87        p.setColor(SK_ColorRED);
88        p.setAntiAlias(true);
89        canvas->drawOval(r, p);
90
91        dump_layers("inside layer alpha", canvas);
92
93        canvas->restore();
94    } else {
95        r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
96
97        SkPaint p;
98        p.setColor(SK_ColorRED);
99        p.setAntiAlias(true);
100        canvas->drawOval(r, p);
101    }
102
103//    return;
104
105    dump_layers("outside layer alpha", canvas);
106
107    // now apply an effect
108    SkMatrix m;
109    m.setScale(SK_Scalar1, -SK_Scalar1);
110    m.postTranslate(0, SkIntToScalar(100));
111
112    SkPaint paint;
113    make_paint(&paint, m);
114    r.set(0, 0, SkIntToScalar(100), SkIntToScalar(20));
115//    SkDebugf("--------- draw top grad\n");
116    canvas->drawRect(r, paint);
117
118    r.fTop = SkIntToScalar(80);
119    r.fBottom = SkIntToScalar(100);
120//    SkDebugf("--------- draw bot grad\n");
121    canvas->drawRect(r, paint);
122}
123
124class RedFilter : public SkDrawFilter {
125public:
126    bool filter(SkPaint* p, SkDrawFilter::Type) override {
127        fColor = p->getColor();
128        if (fColor == SK_ColorRED) {
129            p->setColor(SK_ColorGREEN);
130        }
131        return true;
132    }
133
134private:
135    SkColor fColor;
136};
137
138class LayersView : public SkView {
139public:
140    LayersView() {}
141
142protected:
143    // overrides from SkEventSink
144    bool onQuery(SkEvent* evt) override {
145        if (SampleCode::TitleQ(*evt)) {
146            SampleCode::TitleR(evt, "Layers");
147            return true;
148        }
149        return this->INHERITED::onQuery(evt);
150    }
151
152    void drawBG(SkCanvas* canvas) {
153        canvas->drawColor(SK_ColorGRAY);
154    }
155
156    void onDraw(SkCanvas* canvas) override {
157        this->drawBG(canvas);
158
159        if (true) {
160            SkRect r;
161            r.set(SkIntToScalar(0), SkIntToScalar(0),
162                  SkIntToScalar(220), SkIntToScalar(120));
163            SkPaint p;
164            canvas->saveLayer(&r, &p);
165            canvas->drawColor(0xFFFF0000);
166            p.setAlpha(0);  // or 0
167            p.setXfermodeMode(SkXfermode::kSrc_Mode);
168            canvas->drawOval(r, p);
169            canvas->restore();
170            return;
171        }
172
173        if (false) {
174            SkRect r;
175            r.set(SkIntToScalar(0), SkIntToScalar(0),
176                  SkIntToScalar(220), SkIntToScalar(120));
177            SkPaint p;
178            p.setAlpha(0x88);
179            p.setAntiAlias(true);
180
181            if (true) {
182                canvas->saveLayer(&r, &p);
183                p.setColor(0xFFFF0000);
184                canvas->drawOval(r, p);
185                canvas->restore();
186            }
187
188            p.setColor(0xFF0000FF);
189            r.offset(SkIntToScalar(20), SkIntToScalar(50));
190            canvas->drawOval(r, p);
191        }
192
193        if (false) {
194            SkPaint p;
195            p.setAlpha(0x88);
196            p.setAntiAlias(true);
197
198            canvas->translate(SkIntToScalar(300), 0);
199
200            SkRect r;
201            r.set(SkIntToScalar(0), SkIntToScalar(0),
202                  SkIntToScalar(220), SkIntToScalar(60));
203
204            canvas->saveLayer(&r, &p);
205
206            r.set(SkIntToScalar(0), SkIntToScalar(0),
207                  SkIntToScalar(220), SkIntToScalar(120));
208            p.setColor(SK_ColorBLUE);
209            canvas->drawOval(r, p);
210            canvas->restore();
211            return;
212        }
213
214        test_fade(canvas);
215    }
216
217    SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
218        this->inval(nullptr);
219
220        return this->INHERITED::onFindClickHandler(x, y, modi);
221    }
222
223    bool onClick(Click* click) override {
224        return this->INHERITED::onClick(click);
225    }
226
227    virtual bool handleKey(SkKey) {
228        this->inval(nullptr);
229        return true;
230    }
231
232private:
233    typedef SkView INHERITED;
234};
235DEF_SAMPLE( return new LayersView; )
236
237//////////////////////////////////////////////////////////////////////////////
238
239#include "SkBlurImageFilter.h"
240#include "SkMatrixConvolutionImageFilter.h"
241#include "SkMorphologyImageFilter.h"
242
243#include "Resources.h"
244#include "SkAnimTimer.h"
245
246class BackdropView : public SampleView {
247    SkPoint fCenter;
248    SkScalar fAngle;
249    SkAutoTUnref<SkImage> fImage;
250    SkAutoTUnref<SkImageFilter> fFilter;
251public:
252    BackdropView() {
253        fCenter.set(200, 150);
254        fAngle = 0;
255        fImage.reset(GetResourceAsImage("mandrill_512.png"));
256        fFilter.reset(SkDilateImageFilter::Create(8, 8));
257    }
258
259protected:
260    // overrides from SkEventSink
261    bool onQuery(SkEvent* evt) override {
262        if (SampleCode::TitleQ(*evt)) {
263            SampleCode::TitleR(evt, "Backdrop");
264            return true;
265        }
266        return this->INHERITED::onQuery(evt);
267    }
268
269    void onDrawContent(SkCanvas* canvas) override {
270        canvas->drawImage(fImage, 0, 0, nullptr);
271
272        const SkScalar w = 250;
273        const SkScalar h = 150;
274        SkPath path;
275        path.addOval(SkRect::MakeXYWH(-w/2, -h/2, w, h));
276        SkMatrix m;
277        m.setRotate(fAngle);
278        m.postTranslate(fCenter.x(), fCenter.y());
279        path.transform(m);
280
281        canvas->clipPath(path, SkRegion::kIntersect_Op, true);
282        const SkRect bounds = path.getBounds();
283
284        SkPaint paint;
285        paint.setAlpha(0xCC);
286        canvas->saveLayer({ &bounds, &paint, fFilter, 0 });
287
288        canvas->restore();
289    }
290
291    bool onAnimate(const SkAnimTimer& timer) override {
292        fAngle = SkDoubleToScalar(fmod(timer.secs() * 360 / 5, 360));
293        return true;
294    }
295
296    SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
297        this->inval(nullptr);
298        return new Click(this);
299    }
300
301    bool onClick(Click* click) override {
302        this->inval(nullptr);
303        fCenter = click->fCurr;
304        return this->INHERITED::onClick(click);
305    }
306
307private:
308    typedef SampleView INHERITED;
309};
310DEF_SAMPLE( return new BackdropView; )
311
312