Home | History | Annotate | Download | only in gm
      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 
      8 #include "gm.h"
      9 #include "SkPath.h"
     10 
     11 typedef SkScalar (*MakePathProc)(SkPath*);
     12 
     13 static SkScalar make_frame(SkPath* path) {
     14     SkRect r = { SkIntToScalar(10), SkIntToScalar(10),
     15                  SkIntToScalar(630), SkIntToScalar(470) };
     16     path->addRoundRect(r, SkIntToScalar(15), SkIntToScalar(15));
     17 
     18     SkPaint paint;
     19     paint.setStyle(SkPaint::kStroke_Style);
     20     paint.setStrokeWidth(SkIntToScalar(5));
     21     paint.getFillPath(*path, path);
     22     return SkIntToScalar(15);
     23 }
     24 
     25 static SkScalar make_triangle(SkPath* path) {
     26     static const int gCoord[] = {
     27         10, 20, 15, 5, 30, 30
     28     };
     29     path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1]));
     30     path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3]));
     31     path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5]));
     32     path->close();
     33     path->offset(SkIntToScalar(10), SkIntToScalar(0));
     34     return SkIntToScalar(30);
     35 }
     36 
     37 static SkScalar make_rect(SkPath* path) {
     38     SkRect r = { SkIntToScalar(10), SkIntToScalar(10),
     39                  SkIntToScalar(30), SkIntToScalar(30) };
     40     path->addRect(r);
     41     path->offset(SkIntToScalar(10), SkIntToScalar(0));
     42     return SkIntToScalar(30);
     43 }
     44 
     45 static SkScalar make_oval(SkPath* path) {
     46     SkRect r = { SkIntToScalar(10), SkIntToScalar(10),
     47                  SkIntToScalar(30), SkIntToScalar(30) };
     48     path->addOval(r);
     49     path->offset(SkIntToScalar(10), SkIntToScalar(0));
     50     return SkIntToScalar(30);
     51 }
     52 
     53 static SkScalar make_sawtooth(SkPath* path) {
     54     SkScalar x = SkIntToScalar(20);
     55     SkScalar y = SkIntToScalar(20);
     56     const SkScalar x0 = x;
     57     const SkScalar dx = SK_Scalar1 * 5;
     58     const SkScalar dy = SK_Scalar1 * 10;
     59 
     60     path->moveTo(x, y);
     61     for (int i = 0; i < 32; i++) {
     62         x += dx;
     63         path->lineTo(x, y - dy);
     64         x += dx;
     65         path->lineTo(x, y + dy);
     66     }
     67     path->lineTo(x, y + (2 * dy));
     68     path->lineTo(x0, y + (2 * dy));
     69     path->close();
     70     return SkIntToScalar(30);
     71 }
     72 
     73 static SkScalar make_star(SkPath* path, int n) {
     74     const SkScalar c = SkIntToScalar(45);
     75     const SkScalar r = SkIntToScalar(20);
     76 
     77     SkScalar rad = -SK_ScalarPI / 2;
     78     const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n;
     79 
     80     path->moveTo(c, c - r);
     81     for (int i = 1; i < n; i++) {
     82         rad += drad;
     83         SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV);
     84         path->lineTo(c + SkScalarMul(cosV, r), c + SkScalarMul(sinV, r));
     85     }
     86     path->close();
     87     return r * 2 * 6 / 5;
     88 }
     89 
     90 static SkScalar make_star_5(SkPath* path) { return make_star(path, 5); }
     91 static SkScalar make_star_13(SkPath* path) { return make_star(path, 13); }
     92 
     93 // We don't expect any output from this path.
     94 static SkScalar make_line(SkPath* path) {
     95     path->moveTo(SkIntToScalar(30), SkIntToScalar(30));
     96     path->lineTo(SkIntToScalar(120), SkIntToScalar(40));
     97     path->close();
     98     path->moveTo(SkIntToScalar(150), SkIntToScalar(30));
     99     path->lineTo(SkIntToScalar(150), SkIntToScalar(30));
    100     path->lineTo(SkIntToScalar(300), SkIntToScalar(40));
    101     path->close();
    102     return SkIntToScalar(40);
    103 }
    104 
    105 static const MakePathProc gProcs[] = {
    106     make_frame,
    107     make_triangle,
    108     make_rect,
    109     make_oval,
    110     make_sawtooth,
    111     make_star_5,
    112     make_star_13,
    113     make_line,
    114 };
    115 
    116 #define N   SK_ARRAY_COUNT(gProcs)
    117 
    118 class PathFillGM : public skiagm::GM {
    119     SkPath  fPath[N];
    120     SkScalar fDY[N];
    121 protected:
    122     void onOnceBeforeDraw() override {
    123         for (size_t i = 0; i < N; i++) {
    124             fDY[i] = gProcs[i](&fPath[i]);
    125         }
    126     }
    127 
    128 
    129     SkString onShortName() override {
    130         return SkString("pathfill");
    131     }
    132 
    133     SkISize onISize() override {
    134         return SkISize::Make(640, 480);
    135     }
    136 
    137     void onDraw(SkCanvas* canvas) override {
    138         SkPaint paint;
    139         paint.setAntiAlias(true);
    140 
    141         for (size_t i = 0; i < N; i++) {
    142             canvas->drawPath(fPath[i], paint);
    143             canvas->translate(SkIntToScalar(0), fDY[i]);
    144         }
    145     }
    146 
    147 private:
    148     typedef skiagm::GM INHERITED;
    149 };
    150 
    151 // test inverse-fill w/ a clip that completely excludes the geometry
    152 class PathInverseFillGM : public skiagm::GM {
    153     SkPath  fPath[N];
    154     SkScalar fDY[N];
    155 protected:
    156     void onOnceBeforeDraw() override {
    157         for (size_t i = 0; i < N; i++) {
    158             fDY[i] = gProcs[i](&fPath[i]);
    159         }
    160     }
    161 
    162     SkString onShortName() override {
    163         return SkString("pathinvfill");
    164     }
    165 
    166     SkISize onISize() override {
    167         return SkISize::Make(450, 220);
    168     }
    169 
    170     static void show(SkCanvas* canvas, const SkPath& path, const SkPaint& paint,
    171                      const SkRect* clip, SkScalar top, const SkScalar bottom) {
    172         canvas->save();
    173         if (clip) {
    174             SkRect r = *clip;
    175             r.fTop = top;
    176             r.fBottom = bottom;
    177             canvas->clipRect(r);
    178         }
    179         canvas->drawPath(path, paint);
    180         canvas->restore();
    181     }
    182 
    183     void onDraw(SkCanvas* canvas) override {
    184         SkPath path;
    185 
    186         path.addCircle(SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(40));
    187         path.toggleInverseFillType();
    188 
    189         SkRect clipR = { 0, 0, SkIntToScalar(100), SkIntToScalar(200) };
    190 
    191         canvas->translate(SkIntToScalar(10), SkIntToScalar(10));
    192 
    193         for (int doclip = 0; doclip <= 1; ++doclip) {
    194             for (int aa = 0; aa <= 1; ++aa) {
    195                 SkPaint paint;
    196                 paint.setAntiAlias(SkToBool(aa));
    197 
    198                 canvas->save();
    199                 canvas->clipRect(clipR);
    200 
    201                 const SkRect* clipPtr = doclip ? &clipR : nullptr;
    202 
    203                 show(canvas, path, paint, clipPtr, clipR.fTop, clipR.centerY());
    204                 show(canvas, path, paint, clipPtr, clipR.centerY(), clipR.fBottom);
    205 
    206                 canvas->restore();
    207                 canvas->translate(SkIntToScalar(110), 0);
    208             }
    209         }
    210     }
    211 
    212 private:
    213     typedef skiagm::GM INHERITED;
    214 };
    215 
    216 ///////////////////////////////////////////////////////////////////////////////
    217 
    218 DEF_GM( return new PathFillGM; )
    219 DEF_GM( return new PathInverseFillGM; )
    220