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 "SkDashPathEffect.h"
     11 #include "SkGradientShader.h"
     12 #include "SkMaskFilter.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(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3.0f));
    167             fPaints.push_back(p);
    168         }
    169 
    170         // matrices
    171         {
    172             // rotation
    173             SkMatrix m;
    174             m.setRotate(12.0f);
    175 
    176             fMatrices.push_back(m);
    177         }
    178         {
    179             // skew
    180             SkMatrix m;
    181             m.setSkew(0.3f, 0.5f);
    182 
    183             fMatrices.push_back(m);
    184         }
    185         {
    186             // perspective
    187             SkMatrix m;
    188             m.reset();
    189             m.setPerspX(-SK_Scalar1 / 300);
    190             m.setPerspY(SK_Scalar1 / 300);
    191 
    192             fMatrices.push_back(m);
    193         }
    194 
    195         SkASSERT(kNumRows == fPaints.count() + fMatrices.count());
    196     }
    197 
    198     void onDraw(SkCanvas* canvas) override {
    199         canvas->translate(0, kRadius+kPad);
    200 
    201         for (int i = 0; i < fPaints.count(); ++i) {
    202             int saveCount = canvas->save();
    203             draw_row(canvas, fPaints[i], SkMatrix::I());
    204             canvas->restoreToCount(saveCount);
    205 
    206             canvas->translate(0, 2*(kRadius+kPad));
    207         }
    208 
    209         for (int i = 0; i < fMatrices.count(); ++i) {
    210             int saveCount = canvas->save();
    211             draw_row(canvas, fPaints[0], fMatrices[i]);
    212             canvas->restoreToCount(saveCount);
    213 
    214             canvas->translate(0, 2*(kRadius+kPad));
    215         }
    216     }
    217 
    218 private:
    219     SkTArray<SkPaint> fPaints;
    220     SkTArray<SkMatrix> fMatrices;
    221 
    222     typedef GM INHERITED;
    223 };
    224 
    225 //////////////////////////////////////////////////////////////////////////////
    226 
    227 DEF_GM(return new StrokedLinesGM;)
    228 }
    229