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 "Sample.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 "SkPaint.h"
     15 #include "SkVertices.h"
     16 
     17 #include "sk_tool_utils.h"
     18 
     19 #define BG_COLOR    0xFFDDDDDD
     20 
     21 typedef void (*SlideProc)(SkCanvas*);
     22 
     23 ///////////////////////////////////////////////////////////////////////////////
     24 
     25 #include "Sk1DPathEffect.h"
     26 #include "Sk2DPathEffect.h"
     27 #include "SkCornerPathEffect.h"
     28 #include "SkDashPathEffect.h"
     29 #include "SkDiscretePathEffect.h"
     30 
     31 static void compose_pe(SkPaint* paint) {
     32     SkPathEffect* pe = paint->getPathEffect();
     33     sk_sp<SkPathEffect> corner = SkCornerPathEffect::Make(25);
     34     sk_sp<SkPathEffect> compose;
     35     if (pe) {
     36         compose = SkPathEffect::MakeCompose(sk_ref_sp(pe), corner);
     37     } else {
     38         compose = corner;
     39     }
     40     paint->setPathEffect(compose);
     41 }
     42 
     43 static void hair_pe(SkPaint* paint) {
     44     paint->setStrokeWidth(0);
     45 }
     46 
     47 static void hair2_pe(SkPaint* paint) {
     48     paint->setStrokeWidth(0);
     49     compose_pe(paint);
     50 }
     51 
     52 static void stroke_pe(SkPaint* paint) {
     53     paint->setStrokeWidth(12);
     54     compose_pe(paint);
     55 }
     56 
     57 static void dash_pe(SkPaint* paint) {
     58     SkScalar inter[] = { 20, 10, 10, 10 };
     59     paint->setStrokeWidth(12);
     60     paint->setPathEffect(SkDashPathEffect::Make(inter, SK_ARRAY_COUNT(inter), 0));
     61     compose_pe(paint);
     62 }
     63 
     64 static const int gXY[] = {
     65 4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
     66 };
     67 
     68 static void scale(SkPath* path, SkScalar scale) {
     69     SkMatrix m;
     70     m.setScale(scale, scale);
     71     path->transform(m);
     72 }
     73 
     74 static void one_d_pe(SkPaint* paint) {
     75     SkPath  path;
     76     path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
     77     for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
     78         path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
     79     path.close();
     80     path.offset(SkIntToScalar(-6), 0);
     81     scale(&path, 1.5f);
     82 
     83     paint->setPathEffect(SkPath1DPathEffect::Make(path, SkIntToScalar(21), 0,
     84                                                   SkPath1DPathEffect::kRotate_Style));
     85     compose_pe(paint);
     86 }
     87 
     88 typedef void (*PE_Proc)(SkPaint*);
     89 static const PE_Proc gPE[] = { hair_pe, hair2_pe, stroke_pe, dash_pe, one_d_pe };
     90 
     91 static void fill_pe(SkPaint* paint) {
     92     paint->setStyle(SkPaint::kFill_Style);
     93     paint->setPathEffect(nullptr);
     94 }
     95 
     96 static void discrete_pe(SkPaint* paint) {
     97     paint->setPathEffect(SkDiscretePathEffect::Make(10, 4));
     98 }
     99 
    100 static sk_sp<SkPathEffect> MakeTileEffect() {
    101     SkMatrix m;
    102     m.setScale(SkIntToScalar(12), SkIntToScalar(12));
    103 
    104     SkPath path;
    105     path.addCircle(0, 0, SkIntToScalar(5));
    106 
    107     return SkPath2DPathEffect::Make(m, path);
    108 }
    109 
    110 static void tile_pe(SkPaint* paint) {
    111     paint->setPathEffect(MakeTileEffect());
    112 }
    113 
    114 static const PE_Proc gPE2[] = { fill_pe, discrete_pe, tile_pe };
    115 
    116 static void patheffect_slide(SkCanvas* canvas) {
    117     SkPaint paint;
    118     paint.setAntiAlias(true);
    119     paint.setStyle(SkPaint::kStroke_Style);
    120 
    121     SkPath path;
    122     path.moveTo(20, 20);
    123     path.lineTo(70, 120);
    124     path.lineTo(120, 30);
    125     path.lineTo(170, 80);
    126     path.lineTo(240, 50);
    127 
    128     size_t i;
    129     canvas->save();
    130     for (i = 0; i < SK_ARRAY_COUNT(gPE); i++) {
    131         gPE[i](&paint);
    132         canvas->drawPath(path, paint);
    133         canvas->translate(0, 75);
    134     }
    135     canvas->restore();
    136 
    137     path.reset();
    138     SkRect r = { 0, 0, 250, 120 };
    139     path.addOval(r, SkPath::kCW_Direction);
    140     r.inset(50, 50);
    141     path.addRect(r, SkPath::kCCW_Direction);
    142 
    143     canvas->translate(320, 20);
    144     for (i = 0; i < SK_ARRAY_COUNT(gPE2); i++) {
    145         gPE2[i](&paint);
    146         canvas->drawPath(path, paint);
    147         canvas->translate(0, 160);
    148     }
    149 }
    150 
    151 ///////////////////////////////////////////////////////////////////////////////
    152 
    153 #include "SkGradientShader.h"
    154 
    155 struct GradData {
    156     int             fCount;
    157     const SkColor*  fColors;
    158     const SkScalar* fPos;
    159 };
    160 
    161 static const SkColor gColors[] = {
    162 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
    163 };
    164 static const SkScalar gPos0[] = { 0, SK_Scalar1 };
    165 static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
    166 static const SkScalar gPos2[] = {
    167 0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
    168 };
    169 
    170 static const GradData gGradData[] = {
    171 { 2, gColors, nullptr },
    172 { 2, gColors, gPos0 },
    173 { 2, gColors, gPos1 },
    174 { 5, gColors, nullptr },
    175 { 5, gColors, gPos2 }
    176 };
    177 
    178 static sk_sp<SkShader> MakeLinear(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
    179     return SkGradientShader::MakeLinear(pts, data.fColors, data.fPos, data.fCount, tm);
    180 }
    181 
    182 static sk_sp<SkShader> MakeRadial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
    183     SkPoint center;
    184     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
    185                SkScalarAve(pts[0].fY, pts[1].fY));
    186     return SkGradientShader::MakeRadial(center, center.fX, data.fColors,
    187                                           data.fPos, data.fCount, tm);
    188 }
    189 
    190 static sk_sp<SkShader> MakeSweep(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
    191     SkPoint center;
    192     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
    193                SkScalarAve(pts[0].fY, pts[1].fY));
    194     return SkGradientShader::MakeSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount);
    195 }
    196 
    197 static sk_sp<SkShader> Make2Conical(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
    198     SkPoint center0, center1;
    199     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
    200                 SkScalarAve(pts[0].fY, pts[1].fY));
    201     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
    202                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
    203     return SkGradientShader::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
    204                                                   center0, (pts[1].fX - pts[0].fX) / 2,
    205                                                   data.fColors, data.fPos, data.fCount, tm);
    206 }
    207 
    208 typedef sk_sp<SkShader> (*GradMaker)(const SkPoint pts[2], const GradData&, SkShader::TileMode);
    209 static const GradMaker gGradMakers[] = {
    210     MakeLinear, MakeRadial, MakeSweep, Make2Conical
    211 };
    212 
    213 static void gradient_slide(SkCanvas* canvas) {
    214     SkPoint pts[2] = {
    215         { 0, 0 },
    216         { SkIntToScalar(100), SkIntToScalar(100) }
    217     };
    218     SkShader::TileMode tm = SkShader::kClamp_TileMode;
    219     SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
    220     SkPaint paint;
    221     paint.setAntiAlias(true);
    222     paint.setDither(true);
    223 
    224     canvas->translate(SkIntToScalar(20), SkIntToScalar(10));
    225     for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
    226         canvas->save();
    227         for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
    228             paint.setShader(gGradMakers[j](pts, gGradData[i], tm));
    229             canvas->drawRect(r, paint);
    230             canvas->translate(0, SkIntToScalar(120));
    231         }
    232         canvas->restore();
    233         canvas->translate(SkIntToScalar(120), 0);
    234     }
    235 }
    236 
    237 ///////////////////////////////////////////////////////////////////////////////
    238 
    239 #include "DecodeFile.h"
    240 #include "SkOSFile.h"
    241 #include "SkRandom.h"
    242 #include "SkStream.h"
    243 
    244 static sk_sp<SkShader> make_shader0(SkIPoint* size) {
    245     SkBitmap    bm;
    246 
    247     decode_file("/skimages/logo.gif", &bm);
    248     size->set(bm.width(), bm.height());
    249     return SkShader::MakeBitmapShader(bm, SkShader::kClamp_TileMode,
    250                                         SkShader::kClamp_TileMode);
    251 }
    252 
    253 static sk_sp<SkShader> make_shader1(const SkIPoint& size) {
    254     SkPoint pts[] = { { 0, 0 },
    255                       { SkIntToScalar(size.fX), SkIntToScalar(size.fY) } };
    256     SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED };
    257     return SkGradientShader::MakeLinear(pts, colors, nullptr,
    258                                           SK_ARRAY_COUNT(colors), SkShader::kMirror_TileMode);
    259 }
    260 
    261 class Rec {
    262 public:
    263     SkVertices::VertexMode  fMode;
    264     int                     fCount;
    265     SkPoint*                fVerts;
    266     SkPoint*                fTexs;
    267 
    268     Rec() : fCount(0), fVerts(nullptr), fTexs(nullptr) {}
    269     ~Rec() { delete[] fVerts; delete[] fTexs; }
    270 };
    271 
    272 static void make_tris(Rec* rec) {
    273     int n = 10;
    274     SkRandom    rand;
    275 
    276     rec->fMode = SkVertices::kTriangles_VertexMode;
    277     rec->fCount = n * 3;
    278     rec->fVerts = new SkPoint[rec->fCount];
    279 
    280     for (int i = 0; i < n; i++) {
    281         SkPoint* v = &rec->fVerts[i*3];
    282         for (int j = 0; j < 3; j++) {
    283             v[j].set(rand.nextUScalar1() * 250, rand.nextUScalar1() * 250);
    284         }
    285     }
    286 }
    287 
    288 static void make_fan(Rec* rec, int texWidth, int texHeight) {
    289     const SkScalar tx = SkIntToScalar(texWidth);
    290     const SkScalar ty = SkIntToScalar(texHeight);
    291     const int n = 24;
    292 
    293     rec->fMode = SkVertices::kTriangleFan_VertexMode;
    294     rec->fCount = n + 2;
    295     rec->fVerts = new SkPoint[rec->fCount];
    296     rec->fTexs  = new SkPoint[rec->fCount];
    297 
    298     SkPoint* v = rec->fVerts;
    299     SkPoint* t = rec->fTexs;
    300 
    301     v[0].set(0, 0);
    302     t[0].set(0, 0);
    303     for (int i = 0; i < n; i++) {
    304         SkScalar cos;
    305         SkScalar sin = SkScalarSinCos(SK_ScalarPI * 2 * i / n, &cos);
    306         v[i+1].set(cos, sin);
    307         t[i+1].set(i*tx/n, ty);
    308     }
    309     v[n+1] = v[1];
    310     t[n+1].set(tx, ty);
    311 
    312     SkMatrix m;
    313     m.setScale(SkIntToScalar(100), SkIntToScalar(100));
    314     m.postTranslate(SkIntToScalar(110), SkIntToScalar(110));
    315     m.mapPoints(v, rec->fCount);
    316 }
    317 
    318 static void make_strip(Rec* rec, int texWidth, int texHeight) {
    319     const SkScalar tx = SkIntToScalar(texWidth);
    320     const SkScalar ty = SkIntToScalar(texHeight);
    321     const int n = 24;
    322 
    323     rec->fMode = SkVertices::kTriangleStrip_VertexMode;
    324     rec->fCount = 2 * (n + 1);
    325     rec->fVerts = new SkPoint[rec->fCount];
    326     rec->fTexs  = new SkPoint[rec->fCount];
    327 
    328     SkPoint* v = rec->fVerts;
    329     SkPoint* t = rec->fTexs;
    330 
    331     for (int i = 0; i < n; i++) {
    332         SkScalar cos;
    333         SkScalar sin = SkScalarSinCos(SK_ScalarPI * 2 * i / n, &cos);
    334         v[i*2 + 0].set(cos/2, sin/2);
    335         v[i*2 + 1].set(cos, sin);
    336 
    337         t[i*2 + 0].set(tx * i / n, ty);
    338         t[i*2 + 1].set(tx * i / n, 0);
    339     }
    340     v[2*n + 0] = v[0];
    341     v[2*n + 1] = v[1];
    342 
    343     t[2*n + 0].set(tx, ty);
    344     t[2*n + 1].set(tx, 0);
    345 
    346     SkMatrix m;
    347     m.setScale(SkIntToScalar(100), SkIntToScalar(100));
    348     m.postTranslate(SkIntToScalar(110), SkIntToScalar(110));
    349     m.mapPoints(v, rec->fCount);
    350 }
    351 
    352 static void mesh_slide(SkCanvas* canvas) {
    353     Rec fRecs[3];
    354     SkIPoint    size;
    355 
    356     auto fShader0 = make_shader0(&size);
    357     auto fShader1 = make_shader1(size);
    358 
    359     make_strip(&fRecs[0], size.fX, size.fY);
    360     make_fan(&fRecs[1], size.fX, size.fY);
    361     make_tris(&fRecs[2]);
    362 
    363     SkPaint paint;
    364     paint.setDither(true);
    365     paint.setFilterQuality(kLow_SkFilterQuality);
    366 
    367     for (size_t i = 0; i < SK_ARRAY_COUNT(fRecs); i++) {
    368         auto verts = SkVertices::MakeCopy(fRecs[i].fMode, fRecs[i].fCount,
    369                                           fRecs[i].fVerts, fRecs[i].fTexs, nullptr);
    370         canvas->save();
    371 
    372         paint.setShader(nullptr);
    373         canvas->drawVertices(verts, SkBlendMode::kModulate, paint);
    374 
    375         canvas->translate(SkIntToScalar(210), 0);
    376 
    377         paint.setShader(fShader0);
    378         canvas->drawVertices(verts, SkBlendMode::kModulate, paint);
    379 
    380         canvas->translate(SkIntToScalar(210), 0);
    381 
    382         paint.setShader(fShader1);
    383         canvas->drawVertices(verts, SkBlendMode::kModulate, paint);
    384         canvas->restore();
    385 
    386         canvas->translate(0, SkIntToScalar(250));
    387     }
    388 }
    389 
    390 ///////////////////////////////////////////////////////////////////////////////
    391 
    392 #include "SkTypeface.h"
    393 
    394 ///////////////////////////////////////////////////////////////////////////////
    395 
    396 #include "SkImageEncoder.h"
    397 
    398 static const SlideProc gProc[] = {
    399     patheffect_slide,
    400     gradient_slide,
    401     mesh_slide,
    402 };
    403 
    404 class SlideView : public Sample {
    405     int fIndex;
    406     bool fOnce;
    407 public:
    408     SlideView() {
    409         fOnce = false;
    410     }
    411 
    412     void init() {
    413         if (fOnce) {
    414             return;
    415         }
    416         fOnce = true;
    417 
    418         fIndex = 0;
    419 
    420         SkBitmap bm;
    421         bm.allocN32Pixels(1024, 768);
    422         SkCanvas canvas(bm);
    423         SkScalar s = SkIntToScalar(1024) / 640;
    424         canvas.scale(s, s);
    425         for (size_t i = 0; i < SK_ARRAY_COUNT(gProc); i++) {
    426             canvas.save();
    427             canvas.drawColor(BG_COLOR);
    428             gProc[i](&canvas);
    429             canvas.restore();
    430             SkString str;
    431             str.printf("/skimages/slide_" SK_SIZE_T_SPECIFIER ".png", i);
    432             sk_tool_utils::EncodeImageToFile(str.c_str(), bm, SkEncodedImageFormat::kPNG, 100);
    433         }
    434         this->setBGColor(BG_COLOR);
    435     }
    436 
    437 protected:
    438     bool onQuery(Sample::Event* evt) override {
    439         if (Sample::TitleQ(*evt)) {
    440             Sample::TitleR(evt, "Slides");
    441             return true;
    442         }
    443         return this->INHERITED::onQuery(evt);
    444     }
    445 
    446     void onDrawContent(SkCanvas* canvas) override {
    447         this->init();
    448         gProc[fIndex](canvas);
    449     }
    450 
    451     Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override {
    452         this->init();
    453         fIndex = (fIndex + 1) % SK_ARRAY_COUNT(gProc);
    454         return nullptr;
    455     }
    456 
    457 private:
    458     typedef Sample INHERITED;
    459 };
    460 
    461 //////////////////////////////////////////////////////////////////////////////
    462 
    463 DEF_SAMPLE( return new SlideView(); )
    464