Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
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) {
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) {
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:2205
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
#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
DEF_SIMPLE_GM(addarc_meas, canvas, 2 *R+40, 2 *R+40)
Definition: addarc.cpp:80
#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)
Definition: SkCanvas.cpp:1698
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void rotate(SkScalar degrees)
Definition: SkCanvas.cpp:1300
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
void scale(SkScalar sx, SkScalar sy)
Definition: SkCanvas.cpp:1289
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
Definition: gm.h:110
const Paint & paint
Definition: color_source.cc:38
float SkScalar
Definition: extension.cpp:12
glong glong end
#define DEF_GM(CODE)
Definition: gm.h:40
double y
double x
Optional< SkRect > bounds
Definition: SkRecords.h:189
SkRect oval
Definition: SkRecords.h:249
SkScalar startAngle
Definition: SkRecords.h:250
SkScalar sweepAngle
Definition: SkRecords.h:251
static float Scaled(float time, float speed, float period=0)
Definition: TimeUtils.h:27
SkColor color_to_565(SkColor color)
Definition: ToolUtils.cpp:139
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
static SkRect inset(const SkRect &r)
Definition: SkSize.h:16
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