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