blob: b31c839facbd4cbb03e9bd90130b14cef1c9b6f5 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +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 */
reed8a21c9f2016-03-08 18:50:00 -08007
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#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"
msarettd15750c2016-03-18 15:48:49 -070017#include "SkImage.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000018#include "SkInterpolator.h"
19#include "SkMaskFilter.h"
20#include "SkPath.h"
21#include "SkRegion.h"
22#include "SkShader.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000023#include "SkTime.h"
24#include "SkTypeface.h"
25#include "SkUtils.h"
26#include "SkKey.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000027#include "SkXfermode.h"
28#include "SkDrawFilter.h"
29
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +000030static void make_paint(SkPaint* paint, const SkMatrix& localMatrix) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000031 SkColor colors[] = { 0, SK_ColorWHITE };
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +000032 SkPoint pts[] = { { 0, 0 }, { 0, SK_Scalar1*20 } };
reed8a21c9f2016-03-08 18:50:00 -080033 paint->setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
34 SkShader::kClamp_TileMode, 0, &localMatrix));
reed@android.com0baf1932009-06-24 12:41:42 +000035 paint->setXfermodeMode(SkXfermode::kDstIn_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +000036}
37
38static void dump_layers(const char label[], SkCanvas* canvas) {
39 SkDebugf("Dump Layers(%s)\n", label);
40
41 SkCanvas::LayerIter iter(canvas, true);
42 int index = 0;
43 while (!iter.done()) {
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +000044 SkImageInfo info = iter.device()->imageInfo();
reed@android.com8a1c16f2008-12-17 15:59:43 +000045 const SkIRect& clip = iter.clip().getBounds();
46 SkDebugf("Layer[%d] bitmap [%d %d] X=%d Y=%d clip=[%d %d %d %d] alpha=%d\n", index++,
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +000047 info.width(), info.height(), iter.x(), iter.y(),
reed@android.com8a1c16f2008-12-17 15:59:43 +000048 clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
49 iter.paint().getAlpha());
50 iter.next();
51 }
52}
53
54// test drawing with strips of fading gradient above and below
55static void test_fade(SkCanvas* canvas) {
56 SkAutoCanvasRestore ar(canvas, true);
57
58 SkRect r;
rmistry@google.comae933ce2012-08-23 18:19:56 +000059
reed@android.com8a1c16f2008-12-17 15:59:43 +000060 SkPaint p;
61 p.setAlpha(0x88);
62
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +000063 SkAutoCanvasRestore ar2(canvas, false);
reed@android.com8a1c16f2008-12-17 15:59:43 +000064
65 // create the layers
66
67 r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
68 canvas->clipRect(r);
rmistry@google.comae933ce2012-08-23 18:19:56 +000069
reed@android.com8a1c16f2008-12-17 15:59:43 +000070 r.fBottom = SkIntToScalar(20);
halcanary96fcdcc2015-08-27 07:41:13 -070071 canvas->saveLayer(&r, nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +000072
73 r.fTop = SkIntToScalar(80);
74 r.fBottom = SkIntToScalar(100);
halcanary96fcdcc2015-08-27 07:41:13 -070075 canvas->saveLayer(&r, nullptr);
rmistry@google.comae933ce2012-08-23 18:19:56 +000076
77 // now draw the "content"
reed@android.com8a1c16f2008-12-17 15:59:43 +000078
79 if (true) {
80 r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
81
82 canvas->saveLayerAlpha(&r, 0x80);
83
84 SkPaint p;
85 p.setColor(SK_ColorRED);
86 p.setAntiAlias(true);
87 canvas->drawOval(r, p);
rmistry@google.comae933ce2012-08-23 18:19:56 +000088
reed@android.com8a1c16f2008-12-17 15:59:43 +000089 dump_layers("inside layer alpha", canvas);
rmistry@google.comae933ce2012-08-23 18:19:56 +000090
reed@android.com8a1c16f2008-12-17 15:59:43 +000091 canvas->restore();
92 } else {
93 r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100));
rmistry@google.comae933ce2012-08-23 18:19:56 +000094
reed@android.com8a1c16f2008-12-17 15:59:43 +000095 SkPaint p;
96 p.setColor(SK_ColorRED);
97 p.setAntiAlias(true);
98 canvas->drawOval(r, p);
99 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000100
reed@android.com8a1c16f2008-12-17 15:59:43 +0000101// return;
102
103 dump_layers("outside layer alpha", canvas);
104
105 // now apply an effect
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +0000106 SkMatrix m;
107 m.setScale(SK_Scalar1, -SK_Scalar1);
108 m.postTranslate(0, SkIntToScalar(100));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109
110 SkPaint paint;
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +0000111 make_paint(&paint, m);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112 r.set(0, 0, SkIntToScalar(100), SkIntToScalar(20));
113// SkDebugf("--------- draw top grad\n");
114 canvas->drawRect(r, paint);
115
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116 r.fTop = SkIntToScalar(80);
117 r.fBottom = SkIntToScalar(100);
118// SkDebugf("--------- draw bot grad\n");
119 canvas->drawRect(r, paint);
120}
121
122class RedFilter : public SkDrawFilter {
123public:
mtklein36352bf2015-03-25 18:17:31 -0700124 bool filter(SkPaint* p, SkDrawFilter::Type) override {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125 fColor = p->getColor();
126 if (fColor == SK_ColorRED) {
127 p->setColor(SK_ColorGREEN);
128 }
reed@google.com971aca72012-11-26 20:26:54 +0000129 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000131
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132private:
133 SkColor fColor;
134};
135
136class LayersView : public SkView {
137public:
rmistry@google.comae933ce2012-08-23 18:19:56 +0000138 LayersView() {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139
140protected:
141 // overrides from SkEventSink
mtkleinf0599002015-07-13 06:18:39 -0700142 bool onQuery(SkEvent* evt) override {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143 if (SampleCode::TitleQ(*evt)) {
144 SampleCode::TitleR(evt, "Layers");
145 return true;
146 }
147 return this->INHERITED::onQuery(evt);
148 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000149
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150 void drawBG(SkCanvas* canvas) {
reed@android.com149e2f62009-05-22 14:39:03 +0000151 canvas->drawColor(SK_ColorGRAY);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000153
mtkleinf0599002015-07-13 06:18:39 -0700154 void onDraw(SkCanvas* canvas) override {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000155 this->drawBG(canvas);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000156
reed@android.com149e2f62009-05-22 14:39:03 +0000157 if (true) {
158 SkRect r;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000159 r.set(SkIntToScalar(0), SkIntToScalar(0),
160 SkIntToScalar(220), SkIntToScalar(120));
reed@android.com149e2f62009-05-22 14:39:03 +0000161 SkPaint p;
162 canvas->saveLayer(&r, &p);
163 canvas->drawColor(0xFFFF0000);
reed@android.comf2b98d62010-12-20 18:26:13 +0000164 p.setAlpha(0); // or 0
reed@android.com0baf1932009-06-24 12:41:42 +0000165 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com149e2f62009-05-22 14:39:03 +0000166 canvas->drawOval(r, p);
167 canvas->restore();
168 return;
169 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000170
reed@android.com8a1c16f2008-12-17 15:59:43 +0000171 if (false) {
172 SkRect r;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000173 r.set(SkIntToScalar(0), SkIntToScalar(0),
174 SkIntToScalar(220), SkIntToScalar(120));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000175 SkPaint p;
176 p.setAlpha(0x88);
177 p.setAntiAlias(true);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000178
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179 if (true) {
180 canvas->saveLayer(&r, &p);
181 p.setColor(0xFFFF0000);
182 canvas->drawOval(r, p);
183 canvas->restore();
184 }
185
186 p.setColor(0xFF0000FF);
187 r.offset(SkIntToScalar(20), SkIntToScalar(50));
188 canvas->drawOval(r, p);
189 }
190
191 if (false) {
192 SkPaint p;
193 p.setAlpha(0x88);
194 p.setAntiAlias(true);
195
196 canvas->translate(SkIntToScalar(300), 0);
197
198 SkRect r;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000199 r.set(SkIntToScalar(0), SkIntToScalar(0),
200 SkIntToScalar(220), SkIntToScalar(60));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000201
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000202 canvas->saveLayer(&r, &p);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000203
rmistry@google.comae933ce2012-08-23 18:19:56 +0000204 r.set(SkIntToScalar(0), SkIntToScalar(0),
205 SkIntToScalar(220), SkIntToScalar(120));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000206 p.setColor(SK_ColorBLUE);
207 canvas->drawOval(r, p);
208 canvas->restore();
209 return;
210 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000211
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212 test_fade(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000213 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000214
mtkleinf0599002015-07-13 06:18:39 -0700215 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
halcanary96fcdcc2015-08-27 07:41:13 -0700216 this->inval(nullptr);
rmistry@google.comae933ce2012-08-23 18:19:56 +0000217
reed@google.com4d5c26d2013-01-08 16:17:50 +0000218 return this->INHERITED::onFindClickHandler(x, y, modi);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000219 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000220
mtkleinf0599002015-07-13 06:18:39 -0700221 bool onClick(Click* click) override {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222 return this->INHERITED::onClick(click);
223 }
224
sugoi@google.com93c7ee32013-03-12 14:36:57 +0000225 virtual bool handleKey(SkKey) {
halcanary96fcdcc2015-08-27 07:41:13 -0700226 this->inval(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000227 return true;
228 }
229
230private:
231 typedef SkView INHERITED;
232};
reedbfd5f172016-01-07 11:28:08 -0800233DEF_SAMPLE( return new LayersView; )
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234
235//////////////////////////////////////////////////////////////////////////////
236
reedbfd5f172016-01-07 11:28:08 -0800237#include "SkBlurImageFilter.h"
238#include "SkMatrixConvolutionImageFilter.h"
239#include "SkMorphologyImageFilter.h"
240
241#include "Resources.h"
242#include "SkAnimTimer.h"
243
244class BackdropView : public SampleView {
245 SkPoint fCenter;
246 SkScalar fAngle;
reed9ce9d672016-03-17 10:51:11 -0700247 sk_sp<SkImage> fImage;
reedbfd5f172016-01-07 11:28:08 -0800248 SkAutoTUnref<SkImageFilter> fFilter;
249public:
250 BackdropView() {
251 fCenter.set(200, 150);
252 fAngle = 0;
reed9ce9d672016-03-17 10:51:11 -0700253 fImage = GetResourceAsImage("mandrill_512.png");
reedbfd5f172016-01-07 11:28:08 -0800254 fFilter.reset(SkDilateImageFilter::Create(8, 8));
255 }
256
257protected:
258 // overrides from SkEventSink
259 bool onQuery(SkEvent* evt) override {
260 if (SampleCode::TitleQ(*evt)) {
261 SampleCode::TitleR(evt, "Backdrop");
262 return true;
263 }
264 return this->INHERITED::onQuery(evt);
265 }
266
267 void onDrawContent(SkCanvas* canvas) override {
reed9ce9d672016-03-17 10:51:11 -0700268 canvas->drawImage(fImage.get(), 0, 0, nullptr);
reedbfd5f172016-01-07 11:28:08 -0800269
270 const SkScalar w = 250;
271 const SkScalar h = 150;
272 SkPath path;
273 path.addOval(SkRect::MakeXYWH(-w/2, -h/2, w, h));
274 SkMatrix m;
275 m.setRotate(fAngle);
276 m.postTranslate(fCenter.x(), fCenter.y());
277 path.transform(m);
278
279 canvas->clipPath(path, SkRegion::kIntersect_Op, true);
280 const SkRect bounds = path.getBounds();
281
282 SkPaint paint;
283 paint.setAlpha(0xCC);
284 canvas->saveLayer({ &bounds, &paint, fFilter, 0 });
285
286 canvas->restore();
287 }
288
289 bool onAnimate(const SkAnimTimer& timer) override {
290 fAngle = SkDoubleToScalar(fmod(timer.secs() * 360 / 5, 360));
291 return true;
292 }
293
294 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
295 this->inval(nullptr);
296 return new Click(this);
297 }
298
299 bool onClick(Click* click) override {
300 this->inval(nullptr);
301 fCenter = click->fCurr;
302 return this->INHERITED::onClick(click);
303 }
304
305private:
306 typedef SampleView INHERITED;
307};
308DEF_SAMPLE( return new BackdropView; )
309