Home | History | Annotate | Download | only in gm
      1 /*
      2  * Copyright 2016 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 
      8 #include "gm.h"
      9 #include "sk_tool_utils.h"
     10 #include "SkBlurMaskFilter.h"
     11 #include "SkDashPathEffect.h"
     12 #include "SkGradientShader.h"
     13 #include "SkPaint.h"
     14 #include "SkPath.h"
     15 #include "SkPoint3.h"
     16 
     17 constexpr int kNumColumns = 6;
     18 constexpr int kNumRows = 8;
     19 constexpr int kRadius = 40;  // radius of the snowflake
     20 constexpr int kPad = 5;      // padding on both sides of the snowflake
     21 constexpr int kNumSpokes = 6;
     22 constexpr SkScalar kStrokeWidth = 5.0f;
     23 
     24 static void draw_fins(SkCanvas* canvas, const SkPoint& offset, float angle, const SkPaint& paint) {
     25     SkScalar cos, sin;
     26 
     27     // first fin
     28     sin = SkScalarSinCos(angle + (SK_ScalarPI/4), &cos);
     29     sin *= kRadius / 2.0f;
     30     cos *= kRadius / 2.0f;
     31 
     32     SkPath p;
     33     p.moveTo(offset.fX, offset.fY);
     34     p.lineTo(offset.fX + cos, offset.fY + sin);
     35     canvas->drawPath(p, paint);
     36 
     37     // second fin
     38     sin = SkScalarSinCos(angle - (SK_ScalarPI/4), &cos);
     39     sin *= kRadius / 2.0f;
     40     cos *= kRadius / 2.0f;
     41 
     42     p.reset();
     43     p.moveTo(offset.fX, offset.fY);
     44     p.lineTo(offset.fX + cos, offset.fY + sin);
     45     canvas->drawPath(p, paint);
     46 }
     47 
     48 // draw a snowflake centered at the origin
     49 static void draw_snowflake(SkCanvas* canvas, const SkPaint& paint) {
     50 
     51     canvas->clipRect(SkRect::MakeLTRB(-kRadius-kPad, -kRadius-kPad, kRadius+kPad, kRadius+kPad));
     52 
     53     SkScalar sin, cos, angle = 0.0f;
     54     for (int i = 0; i < kNumSpokes/2; ++i, angle += SK_ScalarPI/(kNumSpokes/2)) {
     55         sin = SkScalarSinCos(angle, &cos);
     56         sin *= kRadius;
     57         cos *= kRadius;
     58 
     59         // main spoke
     60         SkPath p;
     61         p.moveTo(-cos, -sin);
     62         p.lineTo(cos, sin);
     63         canvas->drawPath(p, paint);
     64 
     65         // fins on positive side
     66         const SkPoint posOffset = SkPoint::Make(0.5f * cos, 0.5f * sin);
     67         draw_fins(canvas, posOffset, angle, paint);
     68 
     69         // fins on negative side
     70         const SkPoint negOffset = SkPoint::Make(-0.5f * cos, -0.5f * sin);
     71         draw_fins(canvas, negOffset, angle+SK_ScalarPI, paint);
     72     }
     73 }
     74 
     75 static void draw_row(SkCanvas* canvas, const SkPaint& paint, const SkMatrix& localMatrix) {
     76     canvas->translate(kRadius+kPad, 0.0f);
     77 
     78     for (auto cap : { SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap }) {
     79         for (auto isAA : { true, false }) {
     80             SkPaint tmp(paint);
     81             tmp.setStrokeWidth(kStrokeWidth);
     82             tmp.setStyle(SkPaint::kStroke_Style);
     83             tmp.setStrokeCap(cap);
     84             tmp.setAntiAlias(isAA);
     85 
     86             int saveCount = canvas->save();
     87             canvas->concat(localMatrix);
     88             draw_snowflake(canvas, tmp);
     89             canvas->restoreToCount(saveCount);
     90 
     91             canvas->translate(2*(kRadius+kPad), 0.0f);
     92         }
     93     }
     94 }
     95 
     96 namespace skiagm {
     97 
     98 // This GM exercises the special case of a stroked lines.
     99 // Various shaders are applied to ensure the coordinate spaces work out right.
    100 class StrokedLinesGM : public GM {
    101 public:
    102     StrokedLinesGM() {
    103         this->setBGColor(sk_tool_utils::color_to_565(0xFF1A65D7));
    104     }
    105 
    106 protected:
    107     SkString onShortName() override {
    108         return SkString("strokedlines");
    109     }
    110 
    111     SkISize onISize() override {
    112         return SkISize::Make(kNumColumns * (2*kRadius+2*kPad), kNumRows * (2*kRadius+2*kPad));
    113     }
    114 
    115     void onOnceBeforeDraw() override {
    116         // paints
    117         {
    118             // basic white
    119             SkPaint p;
    120             p.setColor(SK_ColorWHITE);
    121             fPaints.push_back(p);
    122         }
    123         {
    124             // gradient
    125             SkColor colors[] = { SK_ColorRED, SK_ColorGREEN };
    126             SkPoint pts[] = { {-kRadius-kPad, -kRadius-kPad }, { kRadius+kPad, kRadius+kPad } };
    127 
    128             SkPaint p;
    129             p.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
    130                                                      SkShader::kClamp_TileMode, 0, nullptr));
    131 
    132             fPaints.push_back(p);
    133         }
    134         {
    135             // dashing
    136             SkScalar intervals[] = { kStrokeWidth, kStrokeWidth };
    137             int intervalCount = (int) SK_ARRAY_COUNT(intervals);
    138             SkPaint p;
    139             p.setColor(SK_ColorWHITE);
    140             p.setPathEffect(SkDashPathEffect::Make(intervals, intervalCount, kStrokeWidth));
    141 
    142             fPaints.push_back(p);
    143         }
    144         {
    145             // Bitmap shader
    146             SkBitmap bm;
    147             bm.allocN32Pixels(2, 2);
    148             *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
    149             *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = 0x0;
    150 
    151             SkMatrix m;
    152             m.setRotate(12.0f);
    153             m.preScale(3.0f, 3.0f);;
    154 
    155             SkPaint p;
    156             p.setShader(SkShader::MakeBitmapShader(bm,
    157                                                    SkShader::kRepeat_TileMode,
    158                                                    SkShader::kRepeat_TileMode,
    159                                                    &m));
    160             fPaints.push_back(p);
    161         }
    162         {
    163             // blur
    164             SkPaint p;
    165             p.setColor(SK_ColorWHITE);
    166             p.setMaskFilter(SkBlurMaskFilter::Make(kOuter_SkBlurStyle, 3.0f,
    167                                                    SkBlurMaskFilter::kHighQuality_BlurFlag));
    168             fPaints.push_back(p);
    169         }
    170 
    171         // matrices
    172         {
    173             // rotation
    174             SkMatrix m;
    175             m.setRotate(12.0f);
    176 
    177             fMatrices.push_back(m);
    178         }
    179         {
    180             // skew
    181             SkMatrix m;
    182             m.setSkew(0.3f, 0.5f);
    183 
    184             fMatrices.push_back(m);
    185         }
    186         {
    187             // perspective
    188             SkMatrix m;
    189             m.reset();
    190             m.setPerspX(-SK_Scalar1 / 300);
    191             m.setPerspY(SK_Scalar1 / 300);
    192 
    193             fMatrices.push_back(m);
    194         }
    195 
    196         SkASSERT(kNumRows == fPaints.count() + fMatrices.count());
    197     }
    198 
    199     void onDraw(SkCanvas* canvas) override {
    200         canvas->translate(0, kRadius+kPad);
    201 
    202         for (int i = 0; i < fPaints.count(); ++i) {
    203             int saveCount = canvas->save();
    204             draw_row(canvas, fPaints[i], SkMatrix::I());
    205             canvas->restoreToCount(saveCount);
    206 
    207             canvas->translate(0, 2*(kRadius+kPad));
    208         }
    209 
    210         for (int i = 0; i < fMatrices.count(); ++i) {
    211             int saveCount = canvas->save();
    212             draw_row(canvas, fPaints[0], fMatrices[i]);
    213             canvas->restoreToCount(saveCount);
    214 
    215             canvas->translate(0, 2*(kRadius+kPad));
    216         }
    217     }
    218 
    219 private:
    220     SkTArray<SkPaint> fPaints;
    221     SkTArray<SkMatrix> fMatrices;
    222 
    223     typedef GM INHERITED;
    224 };
    225 
    226 //////////////////////////////////////////////////////////////////////////////
    227 
    228 DEF_GM(return new StrokedLinesGM;)
    229 }
    230