blob: 5fab6825456a8652c64e7fe0b15c83ea860d9c39 [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.com63e34c62009-10-06 21:19:18 +00008#include "SampleCode.h"
9#include "SkView.h"
10#include "SkCanvas.h"
11#include "SkDevice.h"
12#include "SkPaint.h"
13
reed@android.com8af96022009-10-12 17:02:22 +000014#define BG_COLOR 0xFFDDDDDD
15
reed@android.com63e34c62009-10-06 21:19:18 +000016typedef void (*SlideProc)(SkCanvas*);
17
18///////////////////////////////////////////////////////////////////////////////
19
20#include "Sk1DPathEffect.h"
21#include "Sk2DPathEffect.h"
22#include "SkCornerPathEffect.h"
23#include "SkDashPathEffect.h"
24#include "SkDiscretePathEffect.h"
25
26static void compose_pe(SkPaint* paint) {
27 SkPathEffect* pe = paint->getPathEffect();
28 SkPathEffect* corner = new SkCornerPathEffect(25);
29 SkPathEffect* compose;
30 if (pe) {
31 compose = new SkComposePathEffect(pe, corner);
32 corner->unref();
33 } else {
34 compose = corner;
35 }
36 paint->setPathEffect(compose)->unref();
37}
38
39static void hair_pe(SkPaint* paint) {
40 paint->setStrokeWidth(0);
41}
42
43static void hair2_pe(SkPaint* paint) {
44 paint->setStrokeWidth(0);
45 compose_pe(paint);
46}
47
48static void stroke_pe(SkPaint* paint) {
49 paint->setStrokeWidth(12);
50 compose_pe(paint);
51}
52
53static void dash_pe(SkPaint* paint) {
54 SkScalar inter[] = { 20, 10, 10, 10 };
55 paint->setStrokeWidth(12);
56 paint->setPathEffect(new SkDashPathEffect(inter, SK_ARRAY_COUNT(inter),
57 0))->unref();
58 compose_pe(paint);
59}
60
61static const int gXY[] = {
624, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
63};
64
65static void scale(SkPath* path, SkScalar scale) {
66 SkMatrix m;
67 m.setScale(scale, scale);
68 path->transform(m);
69}
70
71static void one_d_pe(SkPaint* paint) {
72 SkPath path;
73 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
74 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
75 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
76 path.close();
77 path.offset(SkIntToScalar(-6), 0);
78 scale(&path, 1.5);
79
80 paint->setPathEffect(new SkPath1DPathEffect(path, SkIntToScalar(21), 0,
81 SkPath1DPathEffect::kRotate_Style))->unref();
82 compose_pe(paint);
83}
84
85typedef void (*PE_Proc)(SkPaint*);
86static const PE_Proc gPE[] = { hair_pe, hair2_pe, stroke_pe, dash_pe, one_d_pe };
87
88static void fill_pe(SkPaint* paint) {
89 paint->setStyle(SkPaint::kFill_Style);
90 paint->setPathEffect(NULL);
91}
92
93static void discrete_pe(SkPaint* paint) {
94 paint->setPathEffect(new SkDiscretePathEffect(10, 4))->unref();
95}
96
97class TilePathEffect : public Sk2DPathEffect {
98 static SkMatrix make_mat() {
99 SkMatrix m;
100 m.setScale(12, 12);
101 return m;
102 }
103public:
104 TilePathEffect() : Sk2DPathEffect(make_mat()) {}
105
106protected:
107 virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) {
108 dst->addCircle(loc.fX, loc.fY, 5);
109 }
110};
111
112static void tile_pe(SkPaint* paint) {
113 paint->setPathEffect(new TilePathEffect)->unref();
114}
115
116static const PE_Proc gPE2[] = { fill_pe, discrete_pe, tile_pe };
117
118static void patheffect_slide(SkCanvas* canvas) {
119 SkPaint paint;
120 paint.setAntiAlias(true);
121 paint.setStyle(SkPaint::kStroke_Style);
122
123 SkPath path;
124 path.moveTo(20, 20);
125 path.lineTo(70, 120);
126 path.lineTo(120, 30);
127 path.lineTo(170, 80);
128 path.lineTo(240, 50);
129
130 size_t i;
131 canvas->save();
132 for (i = 0; i < SK_ARRAY_COUNT(gPE); i++) {
133 gPE[i](&paint);
134 canvas->drawPath(path, paint);
135 canvas->translate(0, 75);
136 }
137 canvas->restore();
138
139 path.reset();
140 SkRect r = { 0, 0, 250, 120 };
141 path.addOval(r, SkPath::kCW_Direction);
142 r.inset(50, 50);
143 path.addRect(r, SkPath::kCCW_Direction);
144
145 canvas->translate(320, 20);
146 for (i = 0; i < SK_ARRAY_COUNT(gPE2); i++) {
147 gPE2[i](&paint);
148 canvas->drawPath(path, paint);
149 canvas->translate(0, 160);
150 }
151}
152
153///////////////////////////////////////////////////////////////////////////////
154
155#include "SkGradientShader.h"
156
157struct GradData {
158 int fCount;
159 const SkColor* fColors;
160 const SkScalar* fPos;
161};
162
163static const SkColor gColors[] = {
164SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
165};
166static const SkScalar gPos0[] = { 0, SK_Scalar1 };
167static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
168static const SkScalar gPos2[] = {
1690, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
170};
171
172static const GradData gGradData[] = {
173{ 2, gColors, NULL },
174{ 2, gColors, gPos0 },
175{ 2, gColors, gPos1 },
176{ 5, gColors, NULL },
177{ 5, gColors, gPos2 }
178};
179
180static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
181 SkShader::TileMode tm, SkUnitMapper* mapper) {
182 return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
183 data.fCount, tm, mapper);
184}
185
186static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
187 SkShader::TileMode tm, SkUnitMapper* mapper) {
188 SkPoint center;
189 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
190 SkScalarAve(pts[0].fY, pts[1].fY));
191 return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
192 data.fPos, data.fCount, tm, mapper);
193}
194
195static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
196 SkShader::TileMode tm, SkUnitMapper* mapper) {
197 SkPoint center;
198 center.set(SkScalarAve(pts[0].fX, pts[1].fX),
199 SkScalarAve(pts[0].fY, pts[1].fY));
200 return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
201 data.fPos, data.fCount, mapper);
202}
203
204static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
205 SkShader::TileMode tm, SkUnitMapper* mapper) {
206 SkPoint center0, center1;
207 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
208 SkScalarAve(pts[0].fY, pts[1].fY));
209 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
210 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
211 return SkGradientShader::CreateTwoPointRadial(
212 center1, (pts[1].fX - pts[0].fX) / 7,
213 center0, (pts[1].fX - pts[0].fX) / 2,
214 data.fColors, data.fPos, data.fCount, tm, mapper);
215}
216
217typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
218 SkShader::TileMode tm, SkUnitMapper* mapper);
219static const GradMaker gGradMakers[] = {
220 MakeLinear, MakeRadial, MakeSweep, Make2Radial
221};
222
223static void gradient_slide(SkCanvas* canvas) {
224 SkPoint pts[2] = {
225 { 0, 0 },
226 { SkIntToScalar(100), SkIntToScalar(100) }
227 };
228 SkShader::TileMode tm = SkShader::kClamp_TileMode;
229 SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
230 SkPaint paint;
231 paint.setAntiAlias(true);
232 paint.setDither(true);
233
234 canvas->translate(SkIntToScalar(20), SkIntToScalar(10));
235 for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
236 canvas->save();
237 for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
238 SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL);
239 paint.setShader(shader);
240 canvas->drawRect(r, paint);
241 shader->unref();
242 canvas->translate(0, SkIntToScalar(120));
243 }
244 canvas->restore();
245 canvas->translate(SkIntToScalar(120), 0);
246 }
247}
248
249///////////////////////////////////////////////////////////////////////////////
250
251#include "SkPathMeasure.h"
252
253static SkScalar getpathlen(const SkPath& path) {
254 SkPathMeasure meas(path, false);
255 return meas.getLength();
256}
257
258static void textonpath_slide(SkCanvas* canvas) {
259 const char* text = "Displacement";
260 size_t len =strlen(text);
261 SkPath path;
262 path.moveTo(100, 300);
263 path.quadTo(300, 100, 500, 300);
264 path.offset(0, -100);
265
266 SkPaint paint;
267 paint.setAntiAlias(true);
268 paint.setTextSize(40);
269
270 paint.setStyle(SkPaint::kStroke_Style);
271 canvas->drawPath(path, paint);
272 paint.setStyle(SkPaint::kFill_Style);
273
274 SkScalar x = 50;
275 paint.setColor(0xFF008800);
276 canvas->drawTextOnPathHV(text, len, path,
277 x, paint.getTextSize()*2/3, paint);
278 paint.setColor(SK_ColorRED);
279 canvas->drawTextOnPathHV(text, len, path,
280 x + 60, 0, paint);
281 paint.setColor(SK_ColorBLUE);
282 canvas->drawTextOnPathHV(text, len, path,
283 x + 120, -paint.getTextSize()*2/3, paint);
284
285 path.offset(0, 200);
286 paint.setTextAlign(SkPaint::kRight_Align);
287
288 text = "Matrices";
289 len = strlen(text);
290 SkScalar pathLen = getpathlen(path);
291 SkMatrix matrix;
292
293 paint.setColor(SK_ColorBLACK);
294 paint.setStyle(SkPaint::kStroke_Style);
295 canvas->drawPath(path, paint);
296 paint.setStyle(SkPaint::kFill_Style);
297
298 paint.setTextSize(50);
299 canvas->drawTextOnPath(text, len, path, NULL, paint);
300
301 paint.setColor(SK_ColorRED);
302 matrix.setScale(-SK_Scalar1, SK_Scalar1);
303 matrix.postTranslate(pathLen, 0);
304 canvas->drawTextOnPath(text, len, path, &matrix, paint);
305
306 paint.setColor(SK_ColorBLUE);
307 matrix.setScale(SK_Scalar1, -SK_Scalar1);
308 canvas->drawTextOnPath(text, len, path, &matrix, paint);
309
310 paint.setColor(0xFF008800);
311 matrix.setScale(-SK_Scalar1, -SK_Scalar1);
312 matrix.postTranslate(pathLen, 0);
313 canvas->drawTextOnPath(text, len, path, &matrix, paint);
314}
315
316///////////////////////////////////////////////////////////////////////////////
317
318#include "SkImageDecoder.h"
319#include "SkOSFile.h"
320#include "SkRandom.h"
321#include "SkStream.h"
322#include "SkNinePatch.h"
323
324static SkShader* make_shader0(SkIPoint* size) {
325 SkBitmap bm;
326
327 SkImageDecoder::DecodeFile("/skimages/logo.gif", &bm);
328 size->set(bm.width(), bm.height());
329 return SkShader::CreateBitmapShader(bm, SkShader::kClamp_TileMode,
330 SkShader::kClamp_TileMode);
331}
332
333static SkShader* make_shader1(const SkIPoint& size) {
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000334 SkPoint pts[] = { { 0, 0 },
335 { SkIntToScalar(size.fX), SkIntToScalar(size.fY) } };
reed@android.com63e34c62009-10-06 21:19:18 +0000336 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED };
337 return SkGradientShader::CreateLinear(pts, colors, NULL,
338 SK_ARRAY_COUNT(colors), SkShader::kMirror_TileMode, NULL);
339}
340
reed@android.comf2b98d62010-12-20 18:26:13 +0000341class Rec {
342public:
reed@android.com63e34c62009-10-06 21:19:18 +0000343 SkCanvas::VertexMode fMode;
344 int fCount;
345 SkPoint* fVerts;
346 SkPoint* fTexs;
347
348 Rec() : fCount(0), fVerts(NULL), fTexs(NULL) {}
349 ~Rec() { delete[] fVerts; delete[] fTexs; }
350};
351
352void make_tris(Rec* rec) {
353 int n = 10;
354 SkRandom rand;
355
356 rec->fMode = SkCanvas::kTriangles_VertexMode;
357 rec->fCount = n * 3;
358 rec->fVerts = new SkPoint[rec->fCount];
359
360 for (int i = 0; i < n; i++) {
361 SkPoint* v = &rec->fVerts[i*3];
362 for (int j = 0; j < 3; j++) {
363 v[j].set(rand.nextUScalar1() * 250, rand.nextUScalar1() * 250);
364 }
365 }
366}
367
368void make_fan(Rec* rec, int texWidth, int texHeight) {
369 const SkScalar tx = SkIntToScalar(texWidth);
370 const SkScalar ty = SkIntToScalar(texHeight);
371 const int n = 24;
372
373 rec->fMode = SkCanvas::kTriangleFan_VertexMode;
374 rec->fCount = n + 2;
375 rec->fVerts = new SkPoint[rec->fCount];
376 rec->fTexs = new SkPoint[rec->fCount];
377
378 SkPoint* v = rec->fVerts;
379 SkPoint* t = rec->fTexs;
380
381 v[0].set(0, 0);
382 t[0].set(0, 0);
383 for (int i = 0; i < n; i++) {
384 SkScalar cos;
385 SkScalar sin = SkScalarSinCos(SK_ScalarPI * 2 * i / n, &cos);
386 v[i+1].set(cos, sin);
387 t[i+1].set(i*tx/n, ty);
388 }
389 v[n+1] = v[1];
390 t[n+1].set(tx, ty);
391
392 SkMatrix m;
393 m.setScale(SkIntToScalar(100), SkIntToScalar(100));
394 m.postTranslate(SkIntToScalar(110), SkIntToScalar(110));
395 m.mapPoints(v, rec->fCount);
396}
397
398void make_strip(Rec* rec, int texWidth, int texHeight) {
399 const SkScalar tx = SkIntToScalar(texWidth);
400 const SkScalar ty = SkIntToScalar(texHeight);
401 const int n = 24;
402
403 rec->fMode = SkCanvas::kTriangleStrip_VertexMode;
404 rec->fCount = 2 * (n + 1);
405 rec->fVerts = new SkPoint[rec->fCount];
406 rec->fTexs = new SkPoint[rec->fCount];
407
408 SkPoint* v = rec->fVerts;
409 SkPoint* t = rec->fTexs;
410
411 for (int i = 0; i < n; i++) {
412 SkScalar cos;
413 SkScalar sin = SkScalarSinCos(SK_ScalarPI * 2 * i / n, &cos);
414 v[i*2 + 0].set(cos/2, sin/2);
415 v[i*2 + 1].set(cos, sin);
416
417 t[i*2 + 0].set(tx * i / n, ty);
418 t[i*2 + 1].set(tx * i / n, 0);
419 }
420 v[2*n + 0] = v[0];
421 v[2*n + 1] = v[1];
422
423 t[2*n + 0].set(tx, ty);
424 t[2*n + 1].set(tx, 0);
425
426 SkMatrix m;
427 m.setScale(SkIntToScalar(100), SkIntToScalar(100));
428 m.postTranslate(SkIntToScalar(110), SkIntToScalar(110));
429 m.mapPoints(v, rec->fCount);
430}
431
432static void mesh_slide(SkCanvas* canvas) {
433 Rec fRecs[3];
434 SkIPoint size;
435
436 SkShader* fShader0 = make_shader0(&size);
437 SkShader* fShader1 = make_shader1(size);
reed@android.comf2b98d62010-12-20 18:26:13 +0000438
439 SkAutoUnref aur0(fShader0);
440 SkAutoUnref aur1(fShader1);
441
reed@android.com63e34c62009-10-06 21:19:18 +0000442 make_strip(&fRecs[0], size.fX, size.fY);
443 make_fan(&fRecs[1], size.fX, size.fY);
444 make_tris(&fRecs[2]);
445
reed@android.com63e34c62009-10-06 21:19:18 +0000446 SkPaint paint;
447 paint.setDither(true);
448 paint.setFilterBitmap(true);
449
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000450 for (size_t i = 0; i < SK_ARRAY_COUNT(fRecs); i++) {
reed@android.com63e34c62009-10-06 21:19:18 +0000451 canvas->save();
452
453 paint.setShader(NULL);
454 canvas->drawVertices(fRecs[i].fMode, fRecs[i].fCount,
455 fRecs[i].fVerts, fRecs[i].fTexs,
456 NULL, NULL, NULL, 0, paint);
457
458 canvas->translate(SkIntToScalar(210), 0);
459
460 paint.setShader(fShader0);
461 canvas->drawVertices(fRecs[i].fMode, fRecs[i].fCount,
462 fRecs[i].fVerts, fRecs[i].fTexs,
463 NULL, NULL, NULL, 0, paint);
464
465 canvas->translate(SkIntToScalar(210), 0);
466
467 paint.setShader(fShader1);
468 canvas->drawVertices(fRecs[i].fMode, fRecs[i].fCount,
469 fRecs[i].fVerts, fRecs[i].fTexs,
470 NULL, NULL, NULL, 0, paint);
471 canvas->restore();
472
473 canvas->translate(0, SkIntToScalar(250));
474 }
475}
476
477///////////////////////////////////////////////////////////////////////////////
478
reed@android.com8af96022009-10-12 17:02:22 +0000479#include "SkGradientShader.h"
480#include "SkLayerRasterizer.h"
481#include "SkBlurMaskFilter.h"
482
483static void r0(SkLayerRasterizer* rast, SkPaint& p)
484{
485 p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
486 SkBlurMaskFilter::kNormal_BlurStyle))->unref();
487 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
488
489 p.setMaskFilter(NULL);
490 p.setStyle(SkPaint::kStroke_Style);
491 p.setStrokeWidth(SK_Scalar1);
492 rast->addLayer(p);
493
494 p.setAlpha(0x11);
495 p.setStyle(SkPaint::kFill_Style);
496 p.setXfermodeMode(SkXfermode::kSrc_Mode);
497 rast->addLayer(p);
498}
499
500static void r1(SkLayerRasterizer* rast, SkPaint& p)
501{
502 rast->addLayer(p);
503
504 p.setAlpha(0x40);
505 p.setXfermodeMode(SkXfermode::kSrc_Mode);
506 p.setStyle(SkPaint::kStroke_Style);
507 p.setStrokeWidth(SK_Scalar1*2);
508 rast->addLayer(p);
509}
510
511static void r2(SkLayerRasterizer* rast, SkPaint& p)
512{
513 p.setStyle(SkPaint::kStrokeAndFill_Style);
514 p.setStrokeWidth(SK_Scalar1*4);
515 rast->addLayer(p);
516
517 p.setStyle(SkPaint::kStroke_Style);
518 p.setStrokeWidth(SK_Scalar1*3/2);
519 p.setXfermodeMode(SkXfermode::kClear_Mode);
520 rast->addLayer(p);
521}
522
523static void r3(SkLayerRasterizer* rast, SkPaint& p)
524{
525 p.setStyle(SkPaint::kStroke_Style);
526 p.setStrokeWidth(SK_Scalar1*3);
527 rast->addLayer(p);
528
529 p.setAlpha(0x20);
530 p.setStyle(SkPaint::kFill_Style);
531 p.setXfermodeMode(SkXfermode::kSrc_Mode);
532 rast->addLayer(p);
533}
534
535static void r4(SkLayerRasterizer* rast, SkPaint& p)
536{
537 p.setAlpha(0x60);
538 rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
539
540 p.setAlpha(0xFF);
541 p.setXfermodeMode(SkXfermode::kClear_Mode);
542 rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
543
544 p.setXfermode(NULL);
545 rast->addLayer(p);
546}
547
548#include "SkDiscretePathEffect.h"
549
550static void r5(SkLayerRasterizer* rast, SkPaint& p)
551{
552 rast->addLayer(p);
553
554 p.setPathEffect(new SkDiscretePathEffect(SK_Scalar1*4, SK_Scalar1*3))->unref();
555 p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
556 rast->addLayer(p);
557}
558
559static void r6(SkLayerRasterizer* rast, SkPaint& p)
560{
561 rast->addLayer(p);
562
563 p.setAntiAlias(false);
564 SkLayerRasterizer* rast2 = new SkLayerRasterizer;
565 r5(rast2, p);
566 p.setRasterizer(rast2)->unref();
567 p.setXfermodeMode(SkXfermode::kClear_Mode);
568 rast->addLayer(p);
569}
570
571#include "Sk2DPathEffect.h"
572
reed@google.com18dc4772011-08-09 18:47:40 +0000573static SkPathEffect* MakeDotEffect(SkScalar radius, const SkMatrix& matrix) {
574 SkPath path;
575 path.addCircle(0, 0, radius);
576 return new SkPath2DPathEffect(matrix, path);
577}
reed@android.com8af96022009-10-12 17:02:22 +0000578
579static void r7(SkLayerRasterizer* rast, SkPaint& p)
580{
581 SkMatrix lattice;
582 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
583 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
reed@google.com18dc4772011-08-09 18:47:40 +0000584 p.setPathEffect(MakeDotEffect(SK_Scalar1*4, lattice))->unref();
reed@android.com8af96022009-10-12 17:02:22 +0000585 rast->addLayer(p);
586}
587
588static void r8(SkLayerRasterizer* rast, SkPaint& p)
589{
590 rast->addLayer(p);
591
592 SkMatrix lattice;
593 lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
594 lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
reed@google.com18dc4772011-08-09 18:47:40 +0000595 p.setPathEffect(MakeDotEffect(SK_Scalar1*2, lattice))->unref();
reed@android.com8af96022009-10-12 17:02:22 +0000596 p.setXfermodeMode(SkXfermode::kClear_Mode);
597 rast->addLayer(p);
598
599 p.setPathEffect(NULL);
600 p.setXfermode(NULL);
601 p.setStyle(SkPaint::kStroke_Style);
602 p.setStrokeWidth(SK_Scalar1);
603 rast->addLayer(p);
604}
605
606class Line2DPathEffect : public Sk2DPathEffect {
607public:
608 Line2DPathEffect(SkScalar width, const SkMatrix& matrix)
609 : Sk2DPathEffect(matrix), fWidth(width) {}
610
611 virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width)
612 {
613 if (this->INHERITED::filterPath(dst, src, width))
614 {
615 *width = fWidth;
616 return true;
617 }
618 return false;
619 }
620
621 virtual Factory getFactory() { return CreateProc; }
622 virtual void flatten(SkFlattenableWriteBuffer& buffer)
623 {
624 this->INHERITED::flatten(buffer);
625 buffer.writeScalar(fWidth);
626 }
627protected:
628 virtual void nextSpan(int u, int v, int ucount, SkPath* dst)
629 {
630 if (ucount > 1)
631 {
632 SkPoint src[2], dstP[2];
633
634 src[0].set(SkIntToScalar(u) + SK_ScalarHalf,
635 SkIntToScalar(v) + SK_ScalarHalf);
636 src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf,
637 SkIntToScalar(v) + SK_ScalarHalf);
638 this->getMatrix().mapPoints(dstP, src, 2);
639
640 dst->moveTo(dstP[0]);
641 dst->lineTo(dstP[1]);
642 }
643 }
644
645 Line2DPathEffect(SkFlattenableReadBuffer& buffer) : Sk2DPathEffect(buffer)
646 {
647 fWidth = buffer.readScalar();
648 }
649
650private:
651 SkScalar fWidth;
652
653 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)
654 {
655 return new Line2DPathEffect(buffer);
656 }
657
658 typedef Sk2DPathEffect INHERITED;
659};
660
661static void r9(SkLayerRasterizer* rast, SkPaint& p)
662{
663 rast->addLayer(p);
664
665 SkMatrix lattice;
666 lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
667 lattice.postRotate(SkIntToScalar(30), 0, 0);
668 p.setPathEffect(new Line2DPathEffect(SK_Scalar1*2, lattice))->unref();
669 p.setXfermodeMode(SkXfermode::kClear_Mode);
670 rast->addLayer(p);
671
672 p.setPathEffect(NULL);
673 p.setXfermode(NULL);
674 p.setStyle(SkPaint::kStroke_Style);
675 p.setStrokeWidth(SK_Scalar1);
676 rast->addLayer(p);
677}
678
679typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
680
681static const raster_proc gRastProcs[] = {
682 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
683};
684
685static void apply_shader(SkPaint* paint, int index) {
686 raster_proc proc = gRastProcs[index];
687 SkPaint p;
688 SkLayerRasterizer* rast = new SkLayerRasterizer;
689
690 p.setAntiAlias(true);
691 proc(rast, p);
692 paint->setRasterizer(rast)->unref();
693 paint->setColor(SK_ColorBLUE);
694}
695
696#include "SkTypeface.h"
697
698static void texteffect_slide(SkCanvas* canvas) {
699 const char* str = "Google";
700 size_t len = strlen(str);
701 SkScalar x = 20;
702 SkScalar y = 80;
703 SkPaint paint;
704 paint.setTypeface(SkTypeface::CreateFromName("Georgia", SkTypeface::kItalic));
705 paint.setTextSize(75);
706 paint.setAntiAlias(true);
707 paint.setColor(SK_ColorBLUE);
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000708 for (size_t i = 0; i < SK_ARRAY_COUNT(gRastProcs); i++) {
reed@android.com8af96022009-10-12 17:02:22 +0000709 apply_shader(&paint, i);
710 canvas->drawText(str, len, x, y, paint);
711 y += 80;
712 if (i == 4) {
713 x += 320;
714 y = 80;
715 }
716 }
717}
718
719///////////////////////////////////////////////////////////////////////////////
720
reed@android.com63e34c62009-10-06 21:19:18 +0000721#include "SkImageEncoder.h"
722
723static const SlideProc gProc[] = {
724 patheffect_slide,
725 gradient_slide,
726 textonpath_slide,
reed@android.com8af96022009-10-12 17:02:22 +0000727 mesh_slide,
728 texteffect_slide
reed@android.com63e34c62009-10-06 21:19:18 +0000729};
730
reed@google.com81e3d7f2011-06-01 12:42:36 +0000731class SlideView : public SampleView {
reed@android.com63e34c62009-10-06 21:19:18 +0000732 int fIndex;
733public:
734 SlideView() {
735 fIndex = 0;
736
737 SkBitmap bm;
738 bm.setConfig(SkBitmap::kARGB_8888_Config, 1024, 768);
739 bm.allocPixels();
740 SkCanvas canvas(bm);
741 SkScalar s = SkIntToScalar(1024) / 640;
742 canvas.scale(s, s);
743 for (size_t i = 0; i < SK_ARRAY_COUNT(gProc); i++) {
744 canvas.save();
reed@android.com8af96022009-10-12 17:02:22 +0000745 canvas.drawColor(BG_COLOR);
reed@android.com63e34c62009-10-06 21:19:18 +0000746 gProc[i](&canvas);
747 canvas.restore();
748 SkString str;
749 str.printf("/skimages/slide_%d.png", i);
750 SkImageEncoder::EncodeFile(str.c_str(), bm, SkImageEncoder::kPNG_Type, 100);
751 }
reed@google.com81e3d7f2011-06-01 12:42:36 +0000752 this->setBGColor(BG_COLOR);
reed@android.com63e34c62009-10-06 21:19:18 +0000753 }
754
755protected:
756 // overrides from SkEventSink
757 virtual bool onQuery(SkEvent* evt) {
758 if (SampleCode::TitleQ(*evt)) {
759 SampleCode::TitleR(evt, "Slides");
760 return true;
761 }
762 return this->INHERITED::onQuery(evt);
763 }
764
reed@google.com81e3d7f2011-06-01 12:42:36 +0000765 virtual void onDrawContent(SkCanvas* canvas) {
reed@android.com63e34c62009-10-06 21:19:18 +0000766 gProc[fIndex](canvas);
767 }
768
769 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
770 fIndex = (fIndex + 1) % SK_ARRAY_COUNT(gProc);
771 this->inval(NULL);
772 return NULL;
773 }
774
775private:
reed@google.com81e3d7f2011-06-01 12:42:36 +0000776 typedef SampleView INHERITED;
reed@android.com63e34c62009-10-06 21:19:18 +0000777};
778
779//////////////////////////////////////////////////////////////////////////////
780
781static SkView* MyFactory() { return new SlideView; }
782static SkViewRegister reg(MyFactory);
783