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