blob: 8d2157fbf0de857e6ad1f0878801daacd789ea80 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SampleCode.h"
9#include "SkCanvas.h"
10#include "SkView.h"
11#include "Sk1DPathEffect.h"
12#include "Sk2DPathEffect.h"
13#include "SkAvoidXfermode.h"
14#include "SkBlurMaskFilter.h"
15#include "SkColorFilter.h"
16#include "SkColorPriv.h"
17#include "SkCornerPathEffect.h"
18#include "SkDashPathEffect.h"
19#include "SkDiscretePathEffect.h"
20#include "SkEmbossMaskFilter.h"
21#include "SkGradientShader.h"
22#include "SkImageDecoder.h"
23#include "SkLayerRasterizer.h"
24#include "SkMath.h"
25#include "SkPath.h"
26#include "SkRegion.h"
27#include "SkShader.h"
reed@android.comaa5a7db2009-05-27 01:20:10 +000028#include "SkComposeShader.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000029#include "SkCornerPathEffect.h"
30#include "SkPathMeasure.h"
31#include "SkPicture.h"
32#include "SkRandom.h"
33#include "SkTransparentShader.h"
34#include "SkTypeface.h"
35#include "SkUnitMappers.h"
36#include "SkUtils.h"
37#include "SkXfermode.h"
38
39#include <math.h>
reed@android.com8a1c16f2008-12-17 15:59:43 +000040
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000041static inline SkPMColor rgb2gray(SkPMColor c) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000042 unsigned r = SkGetPackedR32(c);
43 unsigned g = SkGetPackedG32(c);
44 unsigned b = SkGetPackedB32(c);
45
reed@android.comf2b98d62010-12-20 18:26:13 +000046 unsigned x = (r * 5 + g * 7 + b * 4) >> 4;
reed@android.com8a1c16f2008-12-17 15:59:43 +000047
48 return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT));
49}
50
51class SkGrayScaleColorFilter : public SkColorFilter {
52public:
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000053 virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000054 for (int i = 0; i < count; i++)
55 result[i] = rgb2gray(src[i]);
56 }
57};
58
59class SkChannelMaskColorFilter : public SkColorFilter {
60public:
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000061 SkChannelMaskColorFilter(U8CPU redMask, U8CPU greenMask, U8CPU blueMask) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000062 fMask = SkPackARGB32(0xFF, redMask, greenMask, blueMask);
63 }
64
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000065 virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000066 SkPMColor mask = fMask;
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000067 for (int i = 0; i < count; i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000068 result[i] = src[i] & mask;
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000069 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000070 }
71
72private:
73 SkPMColor fMask;
74};
75
76///////////////////////////////////////////////////////////
77
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000078static void r0(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000079 p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
80 SkBlurMaskFilter::kNormal_BlurStyle))->unref();
81 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
82
83 p.setMaskFilter(NULL);
84 p.setStyle(SkPaint::kStroke_Style);
85 p.setStrokeWidth(SK_Scalar1);
86 rast->addLayer(p);
87
88 p.setAlpha(0x11);
89 p.setStyle(SkPaint::kFill_Style);
reed@android.com0baf1932009-06-24 12:41:42 +000090 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +000091 rast->addLayer(p);
92}
93
mike@reedtribe.org5fd92432011-05-05 01:59:48 +000094static void r1(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000095 rast->addLayer(p);
96
97 p.setAlpha(0x40);
reed@android.com0baf1932009-06-24 12:41:42 +000098 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +000099 p.setStyle(SkPaint::kStroke_Style);
100 p.setStrokeWidth(SK_Scalar1*2);
101 rast->addLayer(p);
102}
103
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000104static void r2(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105 p.setStyle(SkPaint::kStrokeAndFill_Style);
106 p.setStrokeWidth(SK_Scalar1*4);
107 rast->addLayer(p);
108
109 p.setStyle(SkPaint::kStroke_Style);
110 p.setStrokeWidth(SK_Scalar1*3/2);
reed@android.com0baf1932009-06-24 12:41:42 +0000111 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112 rast->addLayer(p);
113}
114
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000115static void r3(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116 p.setStyle(SkPaint::kStroke_Style);
117 p.setStrokeWidth(SK_Scalar1*3);
118 rast->addLayer(p);
119
120 p.setAlpha(0x20);
121 p.setStyle(SkPaint::kFill_Style);
reed@android.com0baf1932009-06-24 12:41:42 +0000122 p.setXfermodeMode(SkXfermode::kSrc_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000123 rast->addLayer(p);
124}
125
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000126static void r4(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127 p.setAlpha(0x60);
128 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
129
130 p.setAlpha(0xFF);
reed@android.com0baf1932009-06-24 12:41:42 +0000131 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132 rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
133
134 p.setXfermode(NULL);
135 rast->addLayer(p);
136}
137
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000138static void r5(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139 rast->addLayer(p);
140
141 p.setPathEffect(new SkDiscretePathEffect(SK_Scalar1*4, SK_Scalar1*3))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000142 p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143 rast->addLayer(p);
144}
145
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000146static void r6(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000147 rast->addLayer(p);
148
149 p.setAntiAlias(false);
150 SkLayerRasterizer* rast2 = new SkLayerRasterizer;
151 r5(rast2, p);
152 p.setRasterizer(rast2)->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000153 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154 rast->addLayer(p);
155}
156
157class Dot2DPathEffect : public Sk2DPathEffect {
158public:
159 Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix)
160 : Sk2DPathEffect(matrix), fRadius(radius) {}
161
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000162 virtual void flatten(SkFlattenableWriteBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000163 this->INHERITED::flatten(buffer);
164
165 buffer.writeScalar(fRadius);
166 }
djsollen@google.comba28d032012-03-26 17:57:35 +0000167 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Dot2DPathEffect)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168
169protected:
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000170 virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000171 dst->addCircle(loc.fX, loc.fY, fRadius);
172 }
173
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000174 Dot2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000175 fRadius = buffer.readScalar();
176 }
177private:
178 SkScalar fRadius;
179
reed@android.com8a1c16f2008-12-17 15:59:43 +0000180 typedef Sk2DPathEffect INHERITED;
181};
182
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000183static void r7(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184 SkMatrix lattice;
185 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
186 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
187 p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*4, lattice))->unref();
188 rast->addLayer(p);
189}
190
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000191static void r8(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192 rast->addLayer(p);
193
194 SkMatrix lattice;
195 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
196 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
197 p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*2, lattice))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000198 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000199 rast->addLayer(p);
200
201 p.setPathEffect(NULL);
202 p.setXfermode(NULL);
203 p.setStyle(SkPaint::kStroke_Style);
204 p.setStrokeWidth(SK_Scalar1);
205 rast->addLayer(p);
206}
207
208class Line2DPathEffect : public Sk2DPathEffect {
209public:
210 Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
211 : Sk2DPathEffect(matrix), fWidth(width) {}
212
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000213 virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width) {
214 if (this->INHERITED::filterPath(dst, src, width)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000215 *width = fWidth;
216 return true;
217 }
218 return false;
219 }
220
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000221 virtual void flatten(SkFlattenableWriteBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222 this->INHERITED::flatten(buffer);
223 buffer.writeScalar(fWidth);
224 }
djsollen@google.comba28d032012-03-26 17:57:35 +0000225
226 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Line2DPathEffect)
227
reed@android.com8a1c16f2008-12-17 15:59:43 +0000228protected:
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000229 virtual void nextSpan(int u, int v, int ucount, SkPath* dst) {
230 if (ucount > 1) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000231 SkPoint src[2], dstP[2];
232
233 src[0].set(SkIntToScalar(u) + SK_ScalarHalf,
234 SkIntToScalar(v) + SK_ScalarHalf);
235 src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf,
236 SkIntToScalar(v) + SK_ScalarHalf);
237 this->getMatrix().mapPoints(dstP, src, 2);
238
239 dst->moveTo(dstP[0]);
240 dst->lineTo(dstP[1]);
241 }
242 }
243
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000244 Line2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000245 fWidth = buffer.readScalar();
246 }
247
248private:
249 SkScalar fWidth;
250
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251 typedef Sk2DPathEffect INHERITED;
252};
253
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000254static void r9(SkLayerRasterizer* rast, SkPaint& p) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000255 rast->addLayer(p);
256
257 SkMatrix lattice;
258 lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
259 lattice.postRotate(SkIntToScalar(30), 0, 0);
260 p.setPathEffect(new Line2DPathEffect(SK_Scalar1*2, lattice))->unref();
reed@android.com0baf1932009-06-24 12:41:42 +0000261 p.setXfermodeMode(SkXfermode::kClear_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000262 rast->addLayer(p);
263
264 p.setPathEffect(NULL);
265 p.setXfermode(NULL);
266 p.setStyle(SkPaint::kStroke_Style);
267 p.setStrokeWidth(SK_Scalar1);
268 rast->addLayer(p);
269}
270
271typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
272
273static const raster_proc gRastProcs[] = {
274 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
275};
276
277static const struct {
278 SkColor fMul, fAdd;
279} gLightingColors[] = {
280 { 0x808080, 0x800000 }, // general case
281 { 0x707070, 0x707070 }, // no-pin case
282 { 0xFFFFFF, 0x800000 }, // just-add case
283 { 0x808080, 0x000000 }, // just-mul case
284 { 0xFFFFFF, 0x000000 } // identity case
285};
286
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000287static unsigned color_dist16(uint16_t a, uint16_t b) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000288 unsigned dr = SkAbs32(SkPacked16ToR32(a) - SkPacked16ToR32(b));
289 unsigned dg = SkAbs32(SkPacked16ToG32(a) - SkPacked16ToG32(b));
290 unsigned db = SkAbs32(SkPacked16ToB32(a) - SkPacked16ToB32(b));
291
292 return SkMax32(dr, SkMax32(dg, db));
293}
294
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000295static unsigned scale_dist(unsigned dist, unsigned scale) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000296 dist >>= 6;
297 dist = (dist << 2) | dist;
298 dist = (dist << 4) | dist;
299 return dist;
300
301// return SkAlphaMul(dist, scale);
302}
303
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000304static void apply_shader(SkPaint* paint, int index) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000305 raster_proc proc = gRastProcs[index];
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000306 if (proc) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000307 SkPaint p;
308 SkLayerRasterizer* rast = new SkLayerRasterizer;
309
310 p.setAntiAlias(true);
311 proc(rast, p);
312 paint->setRasterizer(rast)->unref();
313 }
314
315#if 1
316 SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
317 paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref();
318 paint->setColor(SK_ColorBLUE);
319#endif
320}
321
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000322class DemoView : public SampleView {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000323public:
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000324 DemoView() {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000325
326protected:
327 // overrides from SkEventSink
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000328 virtual bool onQuery(SkEvent* evt) {
329 if (SampleCode::TitleQ(*evt)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000330 SampleCode::TitleR(evt, "Demo");
331 return true;
332 }
333 return this->INHERITED::onQuery(evt);
334 }
335
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000336 virtual bool onClick(Click* click) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000337 return this->INHERITED::onClick(click);
338 }
339
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000340 void makePath(SkPath& path) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000341 path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20),
342 SkPath::kCCW_Direction);
343 for (int index = 0; index < 10; index++) {
344 SkScalar x = SkFloatToScalar(cos(index / 10.0f * 2 * 3.1415925358f));
345 SkScalar y = SkFloatToScalar(sin(index / 10.0f * 2 * 3.1415925358f));
346 x *= index & 1 ? 7 : 14;
347 y *= index & 1 ? 7 : 14;
348 x += SkIntToScalar(20);
349 y += SkIntToScalar(20);
350 if (index == 0)
351 path.moveTo(x, y);
352 else
353 path.lineTo(x, y);
354 }
355 path.close();
356 }
357
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000358 virtual void onDrawContent(SkCanvas* canvas) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000359 canvas->save();
360 drawPicture(canvas, 0);
361 canvas->restore();
362
363 {
364 SkPicture picture;
365 SkCanvas* record = picture.beginRecording(320, 480);
366 drawPicture(record, 120);
367 canvas->translate(0, SkIntToScalar(120));
368
369 SkRect clip;
370 clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
371 do {
372 canvas->save();
373 canvas->clipRect(clip);
374 picture.draw(canvas);
375 canvas->restore();
376 if (clip.fRight < SkIntToScalar(320))
377 clip.offset(SkIntToScalar(160), 0);
378 else if (clip.fBottom < SkIntToScalar(480))
379 clip.offset(-SkIntToScalar(320), SkIntToScalar(160));
380 else
381 break;
382 } while (true);
383 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000384 }
385
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000386 void drawPicture(SkCanvas* canvas, int spriteOffset) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000387 SkMatrix matrix; matrix.reset();
388 SkPaint paint;
389 SkPath path;
390 SkPoint start = {0, 0};
391 SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) };
392 SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) };
393 SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) };
394 SkScalar left = 0, top = 0, x = 0, y = 0;
reed@google.com261b8e22011-04-14 17:53:24 +0000395 size_t index;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000396
397 char ascii[] = "ascii...";
398 size_t asciiLength = sizeof(ascii) - 1;
399 char utf8[] = "utf8" "\xe2\x80\xa6";
400 short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 };
401 short utf16simple[] = {'u', 't', 'f', '1', '6', '!' };
402
403 makePath(path);
404 SkTDArray<SkPoint>(pos);
405 pos.setCount(asciiLength);
406 for (index = 0; index < asciiLength; index++)
407 pos[index].set(SkIntToScalar(index * 10), SkIntToScalar(index * 2));
408 SkTDArray<SkPoint>(pos2);
409 pos2.setCount(asciiLength);
410 for (index = 0; index < asciiLength; index++)
411 pos2[index].set(SkIntToScalar(index * 10), SkIntToScalar(20));
412
413 // shaders
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000414 SkPoint linearPoints[] = { { 0, 0, }, { SkIntToScalar(40), SkIntToScalar(40) } };
reed@android.com8a1c16f2008-12-17 15:59:43 +0000415 SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE };
416 SkScalar* linearPos = NULL;
417 int linearCount = 2;
418 SkShader::TileMode linearMode = SkShader::kMirror_TileMode;
419 SkUnitMapper* linearMapper = new SkDiscreteMapper(3);
420 SkAutoUnref unmapLinearMapper(linearMapper);
421 SkShader* linear = SkGradientShader::CreateLinear(linearPoints,
422 linearColors, linearPos, linearCount, linearMode, linearMapper);
423
424 SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) };
425 SkScalar radialRadius = SkIntToScalar(25);
426 SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED };
427 SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)};
428 int radialCount = 3;
429 SkShader::TileMode radialMode = SkShader::kRepeat_TileMode;
430 SkUnitMapper* radialMapper = new SkCosineMapper();
431 SkAutoUnref unmapRadialMapper(radialMapper);
432 SkShader* radial = SkGradientShader::CreateRadial(radialCenter,
433 radialRadius, radialColors, radialPos, radialCount,
434 radialMode, radialMapper);
435
436 SkTransparentShader* transparentShader = new SkTransparentShader();
437 SkEmbossMaskFilter::Light light;
438 light.fDirection[0] = SK_Scalar1/2;
439 light.fDirection[1] = SK_Scalar1/2;
440 light.fDirection[2] = SK_Scalar1/3;
441 light.fAmbient = 0x48;
442 light.fSpecular = 0x80;
443 SkScalar radius = SkIntToScalar(12)/5;
444 SkEmbossMaskFilter* embossFilter = new SkEmbossMaskFilter(light,
445 radius);
446
reed@android.com048522d2009-06-23 12:19:41 +0000447 SkXfermode* xfermode = SkXfermode::Create(SkXfermode::kXor_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000448 SkColorFilter* lightingFilter = SkColorFilter::CreateLightingFilter(
449 0xff89bc45, 0xff112233);
450
451 canvas->save();
452 canvas->translate(SkIntToScalar(0), SkIntToScalar(5));
453 paint.setFlags(SkPaint::kAntiAlias_Flag | SkPaint::kFilterBitmap_Flag);
454 // !!! draw through a clip
455 paint.setColor(SK_ColorLTGRAY);
456 paint.setStyle(SkPaint::kFill_Style);
457 SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)};
458 canvas->clipRect(clip);
459 paint.setShader(SkShader::CreateBitmapShader(fTx,
460 SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode))->unref();
461 canvas->drawPaint(paint);
462 canvas->save();
463
464 // line (exercises xfermode, colorShader, colorFilter, filterShader)
465 paint.setColor(SK_ColorGREEN);
466 paint.setStrokeWidth(SkIntToScalar(10));
467 paint.setStyle(SkPaint::kStroke_Style);
468 paint.setXfermode(xfermode)->unref();
469 paint.setColorFilter(lightingFilter)->unref();
470 canvas->drawLine(start.fX, start.fY, stop.fX, stop.fY, paint); // should not be green
471 paint.setXfermode(NULL);
472 paint.setColorFilter(NULL);
473
474 // rectangle
475 paint.setStyle(SkPaint::kFill_Style);
476 canvas->translate(SkIntToScalar(50), 0);
477 paint.setColor(SK_ColorYELLOW);
478 paint.setShader(linear)->unref();
479 paint.setPathEffect(pathEffectTest())->unref();
480 canvas->drawRect(rect, paint);
481 paint.setPathEffect(NULL);
482
483 // circle w/ emboss & transparent (exercises 3dshader)
484 canvas->translate(SkIntToScalar(50), 0);
485 paint.setMaskFilter(embossFilter)->unref();
486 canvas->drawOval(rect, paint);
487 canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
488 paint.setShader(transparentShader)->unref();
489 canvas->drawOval(rect, paint);
490 canvas->translate(0, SkIntToScalar(-10));
491
492 // path
493 canvas->translate(SkIntToScalar(50), 0);
494 paint.setColor(SK_ColorRED);
495 paint.setStyle(SkPaint::kStroke_Style);
496 paint.setStrokeWidth(SkIntToScalar(5));
497 paint.setShader(radial)->unref();
498 paint.setMaskFilter(NULL);
499 canvas->drawPath(path, paint);
500
501 paint.setShader(NULL);
502 // bitmap, sprite
503 canvas->translate(SkIntToScalar(50), 0);
504 paint.setStyle(SkPaint::kFill_Style);
505 canvas->drawBitmap(fBug, left, top, &paint);
506 canvas->translate(SkIntToScalar(30), 0);
507 canvas->drawSprite(fTb,
508 SkScalarRound(canvas->getTotalMatrix().getTranslateX()),
509 spriteOffset + 10, &paint);
510
511 canvas->translate(-SkIntToScalar(30), SkIntToScalar(30));
512 paint.setShader(shaderTest())->unref(); // test compose shader
513 canvas->drawRect(rect2, paint);
514 paint.setShader(NULL);
515
516 canvas->restore();
517 // text
518 canvas->translate(0, SkIntToScalar(60));
519 canvas->save();
520 paint.setColor(SK_ColorGRAY);
521 canvas->drawPosText(ascii, asciiLength, pos.begin(), paint);
522 canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint);
523
524 canvas->translate(SkIntToScalar(50), 0);
525 paint.setColor(SK_ColorCYAN);
526 canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint);
527
528 canvas->translate(SkIntToScalar(30), 0);
529 paint.setColor(SK_ColorMAGENTA);
530 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
531 matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10));
532 canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint);
533 canvas->translate(0, SkIntToScalar(20));
534 canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint);
535 canvas->restore();
536
537 canvas->translate(0, SkIntToScalar(60));
538 paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
539 canvas->restore();
540 }
541
542 /*
543./SkColorFilter.h:25:class SkColorFilter : public SkFlattenable { -- abstract
544 static SkColorFilter* CreatXfermodeFilter() *** untested ***
545 static SkColorFilter* CreatePorterDuffFilter() *** untested ***
546 static SkColorFilter* CreateLightingFilter() -- tested
547./SkDrawLooper.h:9:class SkDrawLooper : public SkFlattenable { -- virtually abstract
548 ./SkBlurDrawLooper.h:9:class SkBlurDrawLooper : public SkDrawLooper { *** untested ***
549./SkMaskFilter.h:41:class SkMaskFilter : public SkFlattenable { -- abstract chmod +w .h
550 ./SkEmbossMaskFilter.h:27:class SkEmbossMaskFilter : public SkMaskFilter { -- tested
551./SkPathEffect.h:33:class SkPathEffect : public SkFlattenable { -- abstract
552 ./Sk1DPathEffect.h:27:class Sk1DPathEffect : public SkPathEffect { -- abstract
553 ./Sk1DPathEffect.h:48:class SkPath1DPathEffect : public Sk1DPathEffect { -- tested
554 ./Sk2DPathEffect.h:25:class Sk2DPathEffect : public SkPathEffect { *** untested ***
555 ./SkCornerPathEffect.h:28:class SkCornerPathEffect : public SkPathEffect { *** untested ***
556 ./SkDashPathEffect.h:27:class SkDashPathEffect : public SkPathEffect {
557 ./SkDiscretePathEffect.h:27:class SkDiscretePathEffect : public SkPathEffect {
558 ./SkPaint.h:760:class SkStrokePathEffect : public SkPathEffect {
559 ./SkPathEffect.h:58:class SkPairPathEffect : public SkPathEffect {
560 ./SkPathEffect.h:78:class SkComposePathEffect : public SkPairPathEffect {
561 ./SkPathEffect.h:114:class SkSumPathEffect : public SkPairPathEffect {
562./SkRasterizer.h:29:class SkRasterizer : public SkFlattenable {
563 ./SkLayerRasterizer.h:27:class SkLayerRasterizer : public SkRasterizer {
564./SkShader.h:36:class SkShader : public SkFlattenable {
565 ./SkColorFilter.h:59:class SkFilterShader : public SkShader {
566 ./SkColorShader.h:26:class SkColorShader : public SkShader {
567 ./SkShaderExtras.h:31:class SkComposeShader : public SkShader {
568 ./SkTransparentShader.h:23:class SkTransparentShader : public SkShader {
569./SkUnitMapper.h:24:class SkUnitMapper : public SkFlattenable {
570 ./SkUnitMapper.h:33:class SkDiscreteMapper : public SkUnitMapper {
571 ./SkUnitMapper.h:51:class SkFlipCosineMapper : public SkUnitMapper {
572./SkXfermode.h:32:class SkXfermode : public SkFlattenable {
573 ./SkAvoidXfermode.h:28:class SkAvoidXfermode : public SkXfermode { *** not done *** chmod +w .h .cpp
574 ./SkXfermode.h:54:class SkProcXfermode : public SkXfermode {
575 */
576
577 /*
578./SkBlurMaskFilter.h:25:class SkBlurMaskFilter {
579 chmod +w SkBlurMaskFilter.cpp
580./SkGradientShader.h:30:class SkGradientShader {
581 */
582 // save layer, bounder, looper
583 // matrix
584 // clip /path/region
585 // bitmap proc shader ?
586
587/* untested:
588SkCornerPathEffect.h:28:class SkCornerPathEffect : public SkPathEffect {
589*/
590
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000591 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000592 fClickPt.set(x, y);
593 this->inval(NULL);
594 return this->INHERITED::onFindClickHandler(x, y);
595 }
596
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000597 SkPathEffect* pathEffectTest() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000598 static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 };
599 SkScalar gPhase = 0;
600 SkPath path;
601 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
602 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
603 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
604 path.close();
605 path.offset(SkIntToScalar(-6), 0);
606 SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12),
607 gPhase, SkPath1DPathEffect::kRotate_Style);
608 SkPathEffect* inner = new SkDiscretePathEffect(SkIntToScalar(2),
609 SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2));
610 SkPathEffect* result = new SkComposePathEffect(outer, inner);
611 outer->unref();
612 inner->unref();
613 return result;
614 }
615
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000616 SkPathEffect* pathEffectTest2() { // unsure this works (has no visible effect)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000617 SkPathEffect* outer = new SkStrokePathEffect(SkIntToScalar(4),
618 SkPaint::kStroke_Style, SkPaint::kMiter_Join, SkPaint::kButt_Cap);
619 static const SkScalar intervals[] = {SkIntToScalar(1), SkIntToScalar(2),
620 SkIntToScalar(2), SkIntToScalar(1)};
621 SkPathEffect* inner = new SkDashPathEffect(intervals,
622 sizeof(intervals) / sizeof(intervals[0]), 0);
623 SkPathEffect* result = new SkSumPathEffect(outer, inner);
624 outer->unref();
625 inner->unref();
626 return result;
627 }
628
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000629 SkShader* shaderTest() {
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000630 SkPoint pts[] = { { 0, 0, }, { SkIntToScalar(100), 0 } };
reed@android.com8a1c16f2008-12-17 15:59:43 +0000631 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
632 SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL,
633 2, SkShader::kClamp_TileMode);
634 pts[1].set(0, SkIntToScalar(100));
635 SkColor colors2[] = {SK_ColorBLACK, SkColorSetARGB(0x80, 0, 0, 0)};
636 SkShader* shaderB = SkGradientShader::CreateLinear(pts, colors2, NULL,
637 2, SkShader::kClamp_TileMode);
reed@android.com048522d2009-06-23 12:19:41 +0000638 SkXfermode* mode = SkXfermode::Create(SkXfermode::kDstIn_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000639 SkShader* result = new SkComposeShader(shaderA, shaderB, mode);
640 shaderA->unref();
641 shaderB->unref();
642 mode->unref();
643 return result;
644 }
645
646 virtual void startTest() {
647 SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/bugcirc.gif", &fBug);
648 SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/tbcirc.gif", &fTb);
649 SkImageDecoder::DecodeFile("/Users/caryclark/Desktop/05psp04.gif", &fTx);
650 }
651
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000652 void drawRaster(SkCanvas* canvas) {
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000653 for (size_t index = 0; index < SK_ARRAY_COUNT(gRastProcs); index++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000654 drawOneRaster(canvas);
655 }
656
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000657 void drawOneRaster(SkCanvas* canvas) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000658 canvas->save();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000659
660 SkScalar x = SkIntToScalar(20);
661 SkScalar y = SkIntToScalar(40);
662 SkPaint paint;
663
664 paint.setAntiAlias(true);
665 paint.setTextSize(SkIntToScalar(48));
reed@android.comaa5a7db2009-05-27 01:20:10 +0000666 paint.setTypeface(SkTypeface::CreateFromName("sans-serif",
667 SkTypeface::kBold));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000668
669 SkString str("GOOGLE");
670
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000671 for (size_t i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000672 apply_shader(&paint, i);
673
674 // paint.setMaskFilter(NULL);
675 // paint.setColor(SK_ColorBLACK);
676
677#if 01
678 int index = i % SK_ARRAY_COUNT(gLightingColors);
679 paint.setColorFilter(SkColorFilter::CreateLightingFilter(
680 gLightingColors[index].fMul,
681 gLightingColors[index].fAdd))->unref();
682#endif
683
684 canvas->drawText(str.c_str(), str.size(), x, y, paint);
685 SkRect oval = { x, y - SkIntToScalar(40), x + SkIntToScalar(40), y };
686 paint.setStyle(SkPaint::kStroke_Style);
687 canvas->drawOval(oval, paint);
688 paint.setStyle(SkPaint::kFill_Style);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000689
690 y += paint.getFontSpacing();
691 }
692
693 canvas->restore();
694
reed@android.com6b82d1a2009-06-03 02:35:01 +0000695 if (1) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000696 SkAvoidXfermode mode(SK_ColorWHITE, 0xFF,
697 SkAvoidXfermode::kTargetColor_Mode);
698 SkPaint paint;
699 x += SkIntToScalar(20);
700 SkRect r = { x, 0, x + SkIntToScalar(360), SkIntToScalar(700) };
701 paint.setXfermode(&mode);
702 paint.setColor(SK_ColorGREEN);
703 paint.setAntiAlias(true);
704 canvas->drawOval(r, paint);
705 }
706 }
707
708private:
709 SkPoint fClickPt;
710 SkBitmap fBug, fTb, fTx;
mike@reedtribe.org5fd92432011-05-05 01:59:48 +0000711 typedef SampleView INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000712};
713
714//////////////////////////////////////////////////////////////////////////////
715
716static SkView* MyFactory() { return new DemoView; }
717static SkViewRegister reg(MyFactory);
718