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 <functional>
      9 #include "SkCanvas.h"
     10 #include "SkDashPathEffect.h"
     11 #include "gm.h"
     12 
     13 constexpr SkScalar kStarts[] = {0.f, 10.f, 30.f, 45.f, 90.f, 165.f, 180.f, 270.f};
     14 constexpr SkScalar kSweeps[] = {1.f, 45.f, 90.f, 130.f, 180.f, 184.f, 300.f, 355.f};
     15 constexpr SkScalar kDiameter = 40.f;
     16 constexpr SkRect kRect = {0.f, 0.f, kDiameter, kDiameter};
     17 constexpr int kW = 1000;
     18 constexpr int kH = 1000;
     19 constexpr SkScalar kPad = 20.f;
     20 
     21 void draw_arcs(SkCanvas* canvas, std::function<void(SkPaint*)> configureStyle) {
     22     // Draws grid of arcs with different start/sweep angles in red and their complement arcs in
     23     // blue.
     24     auto drawGrid = [canvas, &configureStyle] (SkScalar x, SkScalar y, bool useCenter, bool aa) {
     25         SkPaint p0;
     26         p0.setColor(SK_ColorRED);
     27         p0.setAntiAlias(aa);
     28         // Set a reasonable stroke width that configureStyle can override.
     29         p0.setStrokeWidth(15.f);
     30         SkPaint p1 = p0;
     31         p1.setColor(SK_ColorBLUE);
     32         // Use alpha so we see magenta on overlap between arc and its complement.
     33         p0.setAlpha(100);
     34         p1.setAlpha(100);
     35         configureStyle(&p0);
     36         configureStyle(&p1);
     37 
     38         canvas->save();
     39         canvas->translate(kPad + x, kPad + y);
     40         for (auto start : kStarts) {
     41             canvas->save();
     42             for (auto sweep : kSweeps) {
     43                 canvas->drawArc(kRect, start, sweep, useCenter, p0);
     44                 canvas->drawArc(kRect, start, -(360.f - sweep), useCenter, p1);
     45                 canvas->translate(kRect.width() + kPad, 0.f);
     46             }
     47             canvas->restore();
     48             canvas->translate(0, kRect.height() + kPad);
     49         }
     50         canvas->restore();
     51     };
     52     // Draw a grids for combo of enabling/disabling aa and using center.
     53     constexpr SkScalar kGridW = kW / 2.f;
     54     constexpr SkScalar kGridH = kH / 2.f;
     55     drawGrid(0.f   , 0.f   , false, false);
     56     drawGrid(kGridW, 0.f   , true , false);
     57     drawGrid(0.f   , kGridH, false, true );
     58     drawGrid(kGridW, kGridH, true , true );
     59     // Draw separators between the grids.
     60     SkPaint linePaint;
     61     linePaint.setAntiAlias(true);
     62     linePaint.setColor(SK_ColorBLACK);
     63     canvas->drawLine(kGridW, 0.f   , kGridW,            SkIntToScalar(kH), linePaint);
     64     canvas->drawLine(0.f   , kGridH, SkIntToScalar(kW), kGridH,            linePaint);
     65 }
     66 
     67 #define DEF_ARC_GM(name) DEF_SIMPLE_GM(circular_arcs_##name, canvas, kW, kH)
     68 
     69 DEF_ARC_GM(fill) {
     70     auto setFill = [] (SkPaint*p) { p->setStyle(SkPaint::kFill_Style); };
     71     draw_arcs(canvas, setFill);
     72 }
     73 
     74 DEF_ARC_GM(hairline) {
     75     auto setHairline = [] (SkPaint* p) {
     76         p->setStyle(SkPaint::kStroke_Style);
     77         p->setStrokeWidth(0.f);
     78     };
     79     draw_arcs(canvas, setHairline);
     80 }
     81 
     82 DEF_ARC_GM(stroke_butt) {
     83     auto setStroke = [](SkPaint* p) {
     84         p->setStyle(SkPaint::kStroke_Style);
     85         p->setStrokeCap(SkPaint::kButt_Cap);
     86     };
     87     draw_arcs(canvas, setStroke);
     88 }
     89 
     90 DEF_ARC_GM(stroke_square) {
     91     auto setStroke = [] (SkPaint* p) {
     92         p->setStyle(SkPaint::kStroke_Style);
     93         p->setStrokeCap(SkPaint::kSquare_Cap);
     94     };
     95     draw_arcs(canvas, setStroke);
     96 }
     97 
     98 DEF_ARC_GM(stroke_round) {
     99     auto setStroke = [] (SkPaint* p) {
    100         p->setStyle(SkPaint::kStroke_Style);
    101         p->setStrokeCap(SkPaint::kRound_Cap);
    102     };
    103     draw_arcs(canvas, setStroke);
    104 }
    105 
    106 DEF_ARC_GM(stroke_and_fill_butt) {
    107     auto setStroke = [] (SkPaint* p) {
    108         p->setStyle(SkPaint::kStrokeAndFill_Style);
    109         p->setStrokeCap(SkPaint::kButt_Cap);
    110     };
    111     draw_arcs(canvas, setStroke);
    112 }
    113 
    114 DEF_ARC_GM(stroke_and_fill_square) {
    115     auto setStroke = [] (SkPaint* p) {
    116         p->setStyle(SkPaint::kStrokeAndFill_Style);
    117         p->setStrokeCap(SkPaint::kSquare_Cap);
    118     };
    119     draw_arcs(canvas, setStroke);
    120 }
    121 
    122 DEF_ARC_GM(stroke_and_fill_round) {
    123     auto setStroke = [] (SkPaint* p) {
    124         p->setStyle(SkPaint::kStrokeAndFill_Style);
    125         p->setStrokeCap(SkPaint::kRound_Cap);
    126     };
    127     draw_arcs(canvas, setStroke);
    128 }
    129 
    130 DEF_SIMPLE_GM(circular_arcs_weird, canvas, 1000, 400) {
    131     constexpr SkScalar kS = 50;
    132     struct Arc {
    133         SkRect   fOval;
    134         SkScalar fStart;
    135         SkScalar fSweep;
    136     };
    137     const Arc noDrawArcs[] = {
    138         // no sweep
    139         {SkRect::MakeWH(kS, kS),  0,  0},
    140         // empty rect in x
    141         {SkRect::MakeWH(-kS, kS), 0, 90},
    142         // empty rect in y
    143         {SkRect::MakeWH(kS, -kS), 0, 90},
    144         // empty rect in x and y
    145         {SkRect::MakeWH( 0,   0), 0, 90},
    146     };
    147     const Arc arcs[] = {
    148         // large start
    149         {SkRect::MakeWH(kS, kS),   810.f,   90.f},
    150         // large negative start
    151         {SkRect::MakeWH(kS, kS),  -810.f,   90.f},
    152         // exactly 360 sweep
    153         {SkRect::MakeWH(kS, kS),     0.f,  360.f},
    154         // exactly -360 sweep
    155         {SkRect::MakeWH(kS, kS),     0.f, -360.f},
    156         // exactly 540 sweep
    157         {SkRect::MakeWH(kS, kS),     0.f,  540.f},
    158         // exactly -540 sweep
    159         {SkRect::MakeWH(kS, kS),     0.f, -540.f},
    160         // generic large sweep and large start
    161         {SkRect::MakeWH(kS, kS),  1125.f,  990.f},
    162     };
    163     SkTArray<SkPaint> paints;
    164     // fill
    165     paints.push_back();
    166     // stroke
    167     paints.push_back().setStyle(SkPaint::kStroke_Style);
    168     paints.back().setStrokeWidth(kS / 6.f);
    169     // hairline
    170     paints.push_back().setStyle(SkPaint::kStroke_Style);
    171     paints.back().setStrokeWidth(0.f);
    172     // stroke and fill
    173     paints.push_back().setStyle(SkPaint::kStrokeAndFill_Style);
    174     paints.back().setStrokeWidth(kS / 6.f);
    175     // dash effect
    176     paints.push_back().setStyle(SkPaint::kStroke_Style);
    177     paints.back().setStrokeWidth(kS / 6.f);
    178     constexpr SkScalar kDashIntervals[] = {kS / 15, 2 * kS / 15};
    179     paints.back().setPathEffect(SkDashPathEffect::Make(kDashIntervals, 2, 0.f));
    180 
    181     canvas->translate(kPad, kPad);
    182     // This loop should draw nothing.
    183     for (auto arc : noDrawArcs) {
    184         for (auto paint : paints) {
    185             paint.setAntiAlias(true);
    186             canvas->drawArc(arc.fOval, arc.fStart, arc.fSweep, false, paint);
    187             canvas->drawArc(arc.fOval, arc.fStart, arc.fSweep, true, paint);
    188         }
    189     }
    190 
    191     SkPaint linePaint;
    192     linePaint.setAntiAlias(true);
    193     linePaint.setColor(SK_ColorRED);
    194     SkScalar midX   = SK_ARRAY_COUNT(arcs) * (kS + kPad) - kPad/2.f;
    195     SkScalar height = paints.count() * (kS + kPad);
    196     canvas->drawLine(midX, -kPad, midX, height, linePaint);
    197 
    198     for (auto paint : paints) {
    199         paint.setAntiAlias(true);
    200         canvas->save();
    201         for (auto arc : arcs) {
    202             canvas->drawArc(arc.fOval, arc.fStart, arc.fSweep, false, paint);
    203             canvas->translate(kS + kPad, 0.f);
    204         }
    205         for (auto arc : arcs) {
    206             canvas->drawArc(arc.fOval, arc.fStart, arc.fSweep, true, paint);
    207             canvas->translate(kS + kPad, 0.f);
    208         }
    209         canvas->restore();
    210         canvas->translate(0, kS + kPad);
    211     }
    212 }
    213 
    214 DEF_SIMPLE_GM(onebadarc, canvas, 100, 100) {
    215     SkPath path;
    216     path.moveTo(SkBits2Float(0x41a00000), SkBits2Float(0x41a00000));  // 20, 20
    217     path.lineTo(SkBits2Float(0x4208918c), SkBits2Float(0x4208918c));  // 34.1421f, 34.1421f
    218     path.conicTo(SkBits2Float(0x41a00000), SkBits2Float(0x42412318),  // 20, 48.2843f
    219             SkBits2Float(0x40bb73a0), SkBits2Float(0x4208918c),       // 5.85786f, 34.1421f
    220             SkBits2Float(0x3f3504f3));                                // 0.707107f
    221     path.quadTo(SkBits2Float(0x40bb73a0), SkBits2Float(0x4208918c),   // 5.85786f, 34.1421f
    222             SkBits2Float(0x40bb73a2), SkBits2Float(0x4208918c));      // 5.85787f, 34.1421f
    223     path.lineTo(SkBits2Float(0x41a00000), SkBits2Float(0x41a00000));  // 20, 20
    224     path.close();
    225     SkPaint p0;
    226     p0.setColor(SK_ColorRED);
    227     p0.setStrokeWidth(15.f);
    228     p0.setStyle(SkPaint::kStroke_Style);
    229     p0.setAlpha(100);
    230     canvas->translate(20, 0);
    231     canvas->drawPath(path, p0);
    232 
    233     SkRect kRect = { 60, 0, 100, 40};
    234     canvas->drawArc(kRect, 45, 90, true, p0);
    235 }
    236