blob: 3d6a56d94adde572771d6412545df9d59103f1be [file] [log] [blame]
bsalomon71c5eee2016-08-19 10:53:13 -07001/*
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"
bsalomon21af9ca2016-08-25 12:29:23 -070010#include "SkDashPathEffect.h"
bsalomon71c5eee2016-08-19 10:53:13 -070011#include "gm.h"
12
mtkleindbfd7ab2016-09-01 11:24:54 -070013constexpr SkScalar kStarts[] = {0.f, 10.f, 30.f, 45.f, 90.f, 165.f, 180.f, 270.f};
14constexpr SkScalar kSweeps[] = {1.f, 45.f, 90.f, 130.f, 180.f, 184.f, 300.f, 355.f};
15constexpr SkScalar kDiameter = 40.f;
16constexpr SkRect kRect = {0.f, 0.f, kDiameter, kDiameter};
17constexpr int kW = 1000;
18constexpr int kH = 1000;
19constexpr SkScalar kPad = 20.f;
bsalomon71c5eee2016-08-19 10:53:13 -070020
21void 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);
bsalomon71c5eee2016-08-19 10:53:13 -070030 SkPaint p1 = p0;
31 p1.setColor(SK_ColorBLUE);
bsalomon4c547882016-08-19 13:41:28 -070032 // Use alpha so we see magenta on overlap between arc and its complement.
33 p0.setAlpha(100);
34 p1.setAlpha(100);
bsalomon71c5eee2016-08-19 10:53:13 -070035 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.
mtkleindbfd7ab2016-09-01 11:24:54 -070053 constexpr SkScalar kGridW = kW / 2.f;
54 constexpr SkScalar kGridH = kH / 2.f;
bsalomon71c5eee2016-08-19 10:53:13 -070055 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
bsalomon4c547882016-08-19 13:41:28 -070069DEF_ARC_GM(fill) {
bsalomon71c5eee2016-08-19 10:53:13 -070070 auto setFill = [] (SkPaint*p) { p->setStyle(SkPaint::kFill_Style); };
71 draw_arcs(canvas, setFill);
72}
73
74DEF_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
82DEF_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
90DEF_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
98DEF_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}
bsalomonac1d0ab2016-08-22 10:00:14 -0700105
bsalomon4c261d02016-08-22 13:10:46 -0700106DEF_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
114DEF_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
122DEF_ARC_GM(stroke_and_fill_round) {
bsalomonac1d0ab2016-08-22 10:00:14 -0700123 auto setStroke = [] (SkPaint* p) {
124 p->setStyle(SkPaint::kStrokeAndFill_Style);
125 p->setStrokeCap(SkPaint::kRound_Cap);
126 };
127 draw_arcs(canvas, setStroke);
128}
bsalomon21af9ca2016-08-25 12:29:23 -0700129
130DEF_SIMPLE_GM(circular_arcs_weird, canvas, 1000, 400) {
mtkleindbfd7ab2016-09-01 11:24:54 -0700131 constexpr SkScalar kS = 50;
bsalomon21af9ca2016-08-25 12:29:23 -0700132 struct Arc {
133 SkRect fOval;
134 SkScalar fStart;
135 SkScalar fSweep;
136 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700137 const Arc noDrawArcs[] = {
bsalomon21af9ca2016-08-25 12:29:23 -0700138 // 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 };
mtkleindbfd7ab2016-09-01 11:24:54 -0700147 const Arc arcs[] = {
bsalomon21af9ca2016-08-25 12:29:23 -0700148 // 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);
mtkleindbfd7ab2016-09-01 11:24:54 -0700178 constexpr SkScalar kDashIntervals[] = {kS / 15, 2 * kS / 15};
bsalomon21af9ca2016-08-25 12:29:23 -0700179 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}
caryclarkf71ab8f2016-08-26 09:54:25 -0700213
214DEF_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}