Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
addarc.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2015 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/gm.h"
15#include "include/core/SkRect.h"
17#include "include/core/SkSize.h"
21#include "src/base/SkRandom.h"
22#include "tools/ToolUtils.h"
24
25class AddArcGM : public skiagm::GM {
26public:
27 AddArcGM() : fRotate(0) {}
28
29protected:
30 SkString getName() const override { return SkString("addarc"); }
31
32 SkISize getISize() override { return SkISize::Make(1040, 1040); }
33
34 void onDraw(SkCanvas* canvas) override {
35 canvas->translate(20, 20);
36
37 SkRect r = SkRect::MakeWH(1000, 1000);
38
40 paint.setAntiAlias(true);
41 paint.setStroke(true);
42 paint.setStrokeWidth(15);
43
44 const SkScalar inset = paint.getStrokeWidth() + 4;
45 const SkScalar sweepAngle = 345;
46 SkRandom rand;
47
48 SkScalar sign = 1;
49 while (r.width() > paint.getStrokeWidth() * 3) {
50 paint.setColor(ToolUtils::color_to_565(rand.nextU() | (0xFF << 24)));
51 SkScalar startAngle = rand.nextUScalar1() * 360;
52
53 SkScalar speed = SkScalarSqrt(16 / r.width()) * 0.5f;
54 startAngle += fRotate * 360 * speed * sign;
55
56 SkPathBuilder path;
57 path.addArc(r, startAngle, sweepAngle);
58 canvas->drawPath(path.detach().setIsVolatile(true), paint);
59
60 r.inset(inset, inset);
61 sign = -sign;
62 }
63 }
64
65 bool onAnimate(double nanos) override {
66 fRotate = TimeUtils::Scaled(1e-9 * nanos, 1, 360);
67 return true;
68 }
69
70private:
71 SkScalar fRotate;
72 using INHERITED = skiagm::GM;
73};
74DEF_GM( return new AddArcGM; )
75
76///////////////////////////////////////////////////
77
78#define R 400
79
80DEF_SIMPLE_GM(addarc_meas, canvas, 2*R + 40, 2*R + 40) {
81 canvas->translate(R + 20, R + 20);
82
84 paint.setAntiAlias(true);
85 paint.setStroke(true);
86
87 SkPaint measPaint;
88 measPaint.setAntiAlias(true);
89 measPaint.setColor(SK_ColorRED);
90
91 const SkRect oval = SkRect::MakeLTRB(-R, -R, R, R);
92 canvas->drawOval(oval, paint);
93
94 for (SkScalar deg = 0; deg < 360; deg += 10) {
95 const SkScalar rad = SkDegreesToRadians(deg);
96 SkScalar rx = SkScalarCos(rad) * R;
97 SkScalar ry = SkScalarSin(rad) * R;
98
99 canvas->drawLine(0, 0, rx, ry, paint);
100
101 SkPathMeasure meas(SkPathBuilder().addArc(oval, 0, deg).detach(), false);
102 SkScalar arcLen = rad * R;
103 SkPoint pos;
104 if (meas.getPosTan(arcLen, &pos, nullptr)) {
105 canvas->drawLine({0, 0}, pos, measPaint);
106 }
107 }
108}
109
110///////////////////////////////////////////////////
111
112// Emphasize drawing a stroked oval (containing conics) and then scaling the results up,
113// to ensure that we compute the stroke taking the CTM into account
114//
116public:
117 StrokeCircleGM() : fRotate(0) {}
118
119protected:
120 SkString getName() const override { return SkString("strokecircle"); }
121
122 SkISize getISize() override { return SkISize::Make(520, 520); }
123
124 void onDraw(SkCanvas* canvas) override {
125 canvas->scale(20, 20);
126 canvas->translate(13, 13);
127
129 paint.setAntiAlias(true);
130 paint.setStroke(true);
131 paint.setStrokeWidth(SK_Scalar1 / 2);
132
133 const SkScalar delta = paint.getStrokeWidth() * 3 / 2;
134 SkRect r = SkRect::MakeXYWH(-12, -12, 24, 24);
135 SkRandom rand;
136
137 SkScalar sign = 1;
138 while (r.width() > paint.getStrokeWidth() * 2) {
139 SkAutoCanvasRestore acr(canvas, true);
140 canvas->rotate(fRotate * sign);
141
142 paint.setColor(ToolUtils::color_to_565(rand.nextU() | (0xFF << 24)));
143 canvas->drawOval(r, paint);
144 r.inset(delta, delta);
145 sign = -sign;
146 }
147 }
148
149 bool onAnimate(double nanos) override {
150 fRotate = TimeUtils::Scaled(1e-9 * nanos, 60, 360);
151 return true;
152 }
153
154private:
155 SkScalar fRotate;
156
157 using INHERITED = skiagm::GM;
158};
159DEF_GM( return new StrokeCircleGM; )
160
161//////////////////////
162
163// Fill circles and rotate them to test our Analytic Anti-Aliasing.
164// This test is based on StrokeCircleGM.
165class FillCircleGM : public skiagm::GM {
166public:
167 FillCircleGM() : fRotate(0) {}
168
169protected:
170 SkString getName() const override { return SkString("fillcircle"); }
171
172 SkISize getISize() override { return SkISize::Make(520, 520); }
173
174 void onDraw(SkCanvas* canvas) override {
175 canvas->scale(20, 20);
176 canvas->translate(13, 13);
177
179 paint.setAntiAlias(true);
180 paint.setStroke(true);
181 paint.setStrokeWidth(SK_Scalar1 / 2);
182
183 const SkScalar strokeWidth = paint.getStrokeWidth();
184 const SkScalar delta = strokeWidth * 3 / 2;
185 SkRect r = SkRect::MakeXYWH(-12, -12, 24, 24);
186 SkRandom rand;
187
188 // Reset style to fill. We only need stroke stype for producing delta and strokeWidth
189 paint.setStroke(false);
190
191 SkScalar sign = 1;
192 while (r.width() > strokeWidth * 2) {
193 SkAutoCanvasRestore acr(canvas, true);
194 canvas->rotate(fRotate * sign);
195 paint.setColor(ToolUtils::color_to_565(rand.nextU() | (0xFF << 24)));
196 canvas->drawOval(r, paint);
197 r.inset(delta, delta);
198 sign = -sign;
199 }
200 }
201
202 bool onAnimate(double nanos) override {
203 fRotate = TimeUtils::Scaled(1e-9 * nanos, 60, 360);
204 return true;
205 }
206
207private:
208 SkScalar fRotate;
209
210 using INHERITED = skiagm::GM;
211};
212DEF_GM( return new FillCircleGM; )
213
214//////////////////////
215
217 SkScalar end, bool ccw, bool callArcTo) {
218 SkRect bounds = { x - r, y - r, x + r, y + r };
219 SkScalar sweep = ccw ? end - start : start - end;
220 if (callArcTo)
221 path->arcTo(bounds, start, sweep, false);
222 else
223 path->addArc(bounds, start, sweep);
224}
225
226// Lifted from canvas-arc-circumference-fill-diffs.html
227DEF_SIMPLE_GM(manyarcs, canvas, 620, 330) {
229 paint.setAntiAlias(true);
230 paint.setStroke(true);
231
232 canvas->translate(10, 10);
233
234 // 20 angles.
235 SkScalar sweepAngles[] = {
236 -123.7f, -2.3f, -2, -1, -0.3f, -0.000001f, 0, 0.000001f, 0.3f, 0.7f,
237 1, 1.3f, 1.5f, 1.7f, 1.99999f, 2, 2.00001f, 2.3f, 4.3f, 3934723942837.3f
238 };
239 for (size_t i = 0; i < std::size(sweepAngles); ++i) {
240 sweepAngles[i] *= 180;
241 }
242
243 SkScalar startAngles[] = { -1, -0.5f, 0, 0.5f };
244 for (size_t i = 0; i < std::size(startAngles); ++i) {
245 startAngles[i] *= 180;
246 }
247
248 bool anticlockwise = false;
249 SkScalar sign = 1;
250 for (size_t i = 0; i < std::size(startAngles) * 2; ++i) {
251 if (i == std::size(startAngles)) {
252 anticlockwise = true;
253 sign = -1;
254 }
255 SkScalar startAngle = startAngles[i % std::size(startAngles)] * sign;
256 canvas->save();
257 for (size_t j = 0; j < std::size(sweepAngles); ++j) {
258 SkPathBuilder path;
259 path.moveTo(0, 2);
260 html_canvas_arc(&path, 18, 15, 10, startAngle, startAngle + (sweepAngles[j] * sign),
261 anticlockwise, true);
262 path.lineTo(0, 28);
263 canvas->drawPath(path.detach().setIsVolatile(true), paint);
264 canvas->translate(30, 0);
265 }
266 canvas->restore();
267 canvas->translate(0, 40);
268 }
269}
270
271// Lifted from https://bugs.chromium.org/p/chromium/issues/detail?id=640031
272DEF_SIMPLE_GM(tinyanglearcs, canvas, 620, 330) {
274 paint.setAntiAlias(true);
275 paint.setStroke(true);
276
277 canvas->translate(50, 50);
278
279 SkScalar outerRadius = 100000.0f;
280 SkScalar innerRadius = outerRadius - 20.0f;
281 SkScalar centerX = 50;
282 SkScalar centerY = outerRadius;
283 SkScalar startAngles[] = { 1.5f * SK_ScalarPI , 1.501f * SK_ScalarPI };
284 SkScalar sweepAngle = 10.0f / outerRadius;
285
286 for (size_t i = 0; i < std::size(startAngles); ++i) {
287 SkPathBuilder path;
288 SkScalar endAngle = startAngles[i] + sweepAngle;
289 path.moveTo(centerX + innerRadius * std::cos(startAngles[i]),
290 centerY + innerRadius * std::sin(startAngles[i]));
291 path.lineTo(centerX + outerRadius * std::cos(startAngles[i]),
292 centerY + outerRadius * std::sin(startAngles[i]));
293 // A combination of tiny sweepAngle + large radius, we should draw a line.
294 html_canvas_arc(&path, centerX, outerRadius, outerRadius,
295 startAngles[i] * 180 / SK_ScalarPI, endAngle * 180 / SK_ScalarPI,
296 true, true);
297 path.lineTo(centerX + innerRadius * std::cos(endAngle),
298 centerY + innerRadius * std::sin(endAngle));
299 html_canvas_arc(&path, centerX, outerRadius, innerRadius,
300 endAngle * 180 / SK_ScalarPI, startAngles[i] * 180 / SK_ScalarPI,
301 true, false);
302 canvas->drawPath(path.detach(), paint);
303 canvas->translate(20, 0);
304 }
305}
static const int strokeWidth
Definition BlurTest.cpp:60
SkPoint pos
constexpr SkColor SK_ColorRED
Definition SkColor.h:126
static int sign(SkScalar x)
Definition SkPath.cpp:2141
#define INHERITED(method,...)
#define SkDegreesToRadians(degrees)
Definition SkScalar.h:77
#define SkScalarSin(radians)
Definition SkScalar.h:45
#define SK_Scalar1
Definition SkScalar.h:18
#define SkScalarCos(radians)
Definition SkScalar.h:46
#define SkScalarSqrt(x)
Definition SkScalar.h:42
#define SK_ScalarPI
Definition SkScalar.h:21
#define R
Definition addarc.cpp:78
static void html_canvas_arc(SkPathBuilder *path, SkScalar x, SkScalar y, SkScalar r, SkScalar start, SkScalar end, bool ccw, bool callArcTo)
Definition addarc.cpp:216
AddArcGM()
Definition addarc.cpp:27
SkString getName() const override
Definition addarc.cpp:30
bool onAnimate(double nanos) override
Definition addarc.cpp:65
void onDraw(SkCanvas *canvas) override
Definition addarc.cpp:34
SkISize getISize() override
Definition addarc.cpp:32
bool onAnimate(double nanos) override
Definition addarc.cpp:202
void onDraw(SkCanvas *canvas) override
Definition addarc.cpp:174
SkString getName() const override
Definition addarc.cpp:170
SkISize getISize() override
Definition addarc.cpp:172
void drawOval(const SkRect &oval, const SkPaint &paint)
void translate(SkScalar dx, SkScalar dy)
void rotate(SkScalar degrees)
void drawPath(const SkPath &path, const SkPaint &paint)
void scale(SkScalar sx, SkScalar sy)
void setColor(SkColor color)
Definition SkPaint.cpp:119
void setAntiAlias(bool aa)
Definition SkPaint.h:170
bool getPosTan(SkScalar distance, SkPoint *position, SkVector *tangent)
uint32_t nextU()
Definition SkRandom.h:42
SkScalar nextUScalar1()
Definition SkRandom.h:101
SkString getName() const override
Definition addarc.cpp:120
void onDraw(SkCanvas *canvas) override
Definition addarc.cpp:124
bool onAnimate(double nanos) override
Definition addarc.cpp:149
SkISize getISize() override
Definition addarc.cpp:122
const Paint & paint
float SkScalar
Definition extension.cpp:12
glong glong end
#define DEF_GM(CODE)
Definition gm.h:40
#define DEF_SIMPLE_GM(NAME, CANVAS, W, H)
Definition gm.h:50
double y
double x
static float Scaled(float time, float speed, float period=0)
Definition TimeUtils.h:27
SkColor color_to_565(SkColor color)
static SkRect inset(const SkRect &r)
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
void inset(float dx, float dy)
Definition SkRect.h:1060
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659
constexpr float width() const
Definition SkRect.h:762
static constexpr SkRect MakeWH(float w, float h)
Definition SkRect.h:609
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646