Flutter Engine
 
Loading...
Searching...
No Matches
arc.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7namespace impeller {
8
9Arc::Arc(const Rect& bounds, Degrees start, Degrees sweep, bool include_center)
10 : bounds_(bounds), include_center_(include_center) {
11 if (bounds.IsFinite() && start.IsFinite() && sweep.IsFinite()) {
12 if (sweep.degrees < 0) {
13 start = start + sweep;
14 sweep = -sweep;
15 }
16 if (sweep.degrees > 360) {
17 // We need to represent over-sweeping a full circle for the case where
18 // we will be stroking the circle with the center incuded where we
19 // stroke the entire perimeter, but the two segments that connect to
20 // the center are at the proper angles.
21 // Normalize to less than 720.
22 sweep.degrees = 360.0f + std::fmodf(sweep.degrees, 360.0f);
23 }
24 } else {
25 // Don't bother sweeping any distance if anything is non-finite.
26 sweep = Degrees(0);
27 if (!start.IsFinite() || !bounds.IsFinite()) {
28 // We can maintain start if both it and bounds are finite.
29 start = Degrees(0);
30 }
31 }
32 start_ = start;
33 sweep_ = sweep;
34}
35
37 size_t count = 2;
38 for (size_t i = 0; i < quadrant_count; i++) {
39 count += quadrants[i].GetPointCount();
40 }
41 return count;
42}
43
44const Arc::Iteration Arc::ComputeCircleArcIterations(size_t step_count) {
45 return {
46 {1.0f, 0.0f},
47 {1.0f, 0.0f},
48 4u,
49 {
50 {kQuadrantAxes[0], 1u, step_count},
51 {kQuadrantAxes[1], 0u, step_count},
52 {kQuadrantAxes[2], 0u, step_count},
53 {kQuadrantAxes[3], 0u, step_count},
54 {{}, 0u, 0u},
55 },
56 };
57}
58
60 if (IsFullCircle()) {
61 return bounds_;
62 }
63
64 Degrees start_angle = start_.GetPositive();
65 Degrees end_angle = start_angle + sweep_;
66 FML_DCHECK(start_angle.degrees >= 0 && start_angle.degrees < 360);
67 FML_DCHECK(end_angle > start_angle && end_angle.degrees < 720);
68
69 // 1. start vector
70 // 2. end vector
71 // 3. optional center
72 // 4-7. optional quadrant extrema
73 Point extrema[7];
74 int count = 0;
75
76 extrema[count++] = Matrix::CosSin(start_angle);
77 extrema[count++] = Matrix::CosSin(end_angle);
78
79 if (include_center_) {
80 extrema[count++] = {0, 0};
81 }
82
83 // cur_axis will be pre-incremented before recording the following axis
84 int cur_axis = std::floor(start_angle.degrees / 90.0f);
85 // end_axis is a non-inclusive end of the range
86 int end_axis = std::ceil(end_angle.degrees / 90.0f);
87 while (++cur_axis < end_axis) {
88 extrema[count++] = kQuadrantAxes[cur_axis & 3];
89 }
90
91 FML_DCHECK(count <= 7);
92
93 Point center = bounds_.GetCenter();
94 Size radii = bounds_.GetSize() * 0.5f;
95
96 for (int i = 0; i < count; i++) {
97 extrema[i] = center + extrema[i] * radii;
98 }
99 return Rect::MakePointBounds(extrema, extrema + count).value_or(Rect());
100}
101
103 bool simplify_360) const {
104 if (sweep_.degrees == 0) {
105 return {};
106 }
107
108 FML_DCHECK(sweep_.degrees >= 0);
109
110 if (simplify_360 && sweep_.degrees >= 360) {
111 return ComputeCircleArcIterations(step_count);
112 }
113 FML_DCHECK(sweep_.degrees < 720);
114
115 Degrees start = start_.GetPositive();
116 Degrees end = start + sweep_;
117 FML_DCHECK(start.degrees >= 0.0f && start.degrees < 360.0f);
118 FML_DCHECK(end >= start);
119 FML_DCHECK(end.degrees < start.degrees + (simplify_360 ? 360.0f : 720.0f));
120
121 Iteration iterations;
123 iterations.end = impeller::Matrix::CosSin(end);
124
125 // We nudge the start and stop by 1/10th of a step so we don't end
126 // up with degenerately small steps at the start and end of the
127 // arc.
128 Degrees nudge = Degrees((90.0f / step_count) * 0.1f);
129
130 if ((start + nudge) >= (end - nudge)) {
131 iterations.quadrant_count = 0u;
132 return iterations;
133 }
134
135 int cur_quadrant =
136 static_cast<int>(std::floor((start + nudge).degrees / 90.0f));
137 int end_quadrant =
138 static_cast<int>(std::floor((end - nudge).degrees / 90.0f));
139 FML_DCHECK(cur_quadrant >= 0 && //
140 cur_quadrant <= 4);
141 FML_DCHECK(end_quadrant >= cur_quadrant && //
142 end_quadrant <= cur_quadrant + 8);
143 FML_DCHECK(cur_quadrant * 90 <= (start + nudge).degrees);
144 FML_DCHECK(end_quadrant * 90 + 90 >= (end - nudge).degrees);
145
146 auto next_step = [step_count](Degrees angle, int quadrant) -> size_t {
147 Scalar quadrant_fract = angle.degrees / 90.0f - quadrant;
148 return static_cast<size_t>(std::ceil(quadrant_fract * step_count));
149 };
150
151 int i = 0;
152 iterations.quadrants[i] = {
153 kQuadrantAxes[cur_quadrant & 3],
154 next_step(start + nudge, cur_quadrant),
155 step_count,
156 };
157 if (iterations.quadrants[0].end_index > iterations.quadrants[0].start_index) {
158 i++;
159 }
160 while (cur_quadrant < end_quadrant) {
161 iterations.quadrants[i++] = {
162 kQuadrantAxes[(++cur_quadrant) % 4],
163 0u,
164 step_count,
165 };
166 }
167 FML_DCHECK(i <= 9);
168 if (i > 0) {
169 iterations.quadrants[i - 1].end_index =
170 next_step(end - nudge, cur_quadrant);
171 if (iterations.quadrants[i - 1].end_index <=
172 iterations.quadrants[i - 1].start_index) {
173 i--;
174 }
175 }
176 iterations.quadrant_count = i;
177 return iterations;
178}
179
180} // namespace impeller
#define FML_DCHECK(condition)
Definition logging.h:122
float Scalar
Definition scalar.h:19
TRect< Scalar > Rect
Definition rect.h:788
static constexpr impeller::Vector2 kQuadrantAxes[4]
Definition point.h:335
size_t GetPointCount() const
Definition arc.h:50
impeller::Vector2 end
Definition arc.h:59
impeller::Vector2 start
Definition arc.h:58
size_t GetPointCount() const
Definition arc.cc:36
Quadrant quadrants[9]
Definition arc.h:86
size_t quadrant_count
Definition arc.h:63
Iteration ComputeIterations(size_t step_count, bool simplify_360=true) const
Definition arc.cc:102
Arc(const Rect &bounds, Degrees start, Degrees sweep, bool include_center)
Definition arc.cc:9
Rect GetTightArcBounds() const
Definition arc.cc:59
constexpr bool IsFullCircle() const
Definition arc.h:114
Scalar degrees
Definition scalar.h:67
constexpr bool IsFinite() const
Definition scalar.h:77
constexpr Degrees GetPositive() const
Definition scalar.h:91
static Vector2 CosSin(Radians radians)
Definition matrix.h:685
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
Definition rect.h:327
IsFinite() const
Returns true if all of the fields of this floating point rectangle are finite.
Definition rect.h:288
static constexpr std::optional< TRect > MakePointBounds(const U &value)
Definition rect.h:165
constexpr Point GetCenter() const
Get the center point as a |Point|.
Definition rect.h:382
const size_t start
const size_t end