| Flutter Impeller |

Classes | Public Member Functions | List of all members
impeller::Arc Struct Reference

`#include <arc.h>`

## Classes
struct | Iteration

## Public Member Functions
| Arc (const Rect &bounds, Degrees start, Degrees sweep, bool include_center)
const Rect & | GetOvalBounds () const
| Return the bounds of the oval in which this arc is inscribed. More...
const Point | GetOvalCenter () const
| Returns the center of the oval bounds. More...
const Size | GetOvalSize () const
| Returns the size of the oval bounds. More...
Rect | GetTightArcBounds () const
constexpr Degrees | GetStart () const
constexpr Degrees | GetSweep () const
constexpr bool | IncludeCenter () const
constexpr bool | IsPerfectCircle () const
constexpr bool | IsFullCircle () const
Iteration | ComputeIterations (size_t step_count, bool simplify_360=true) const

## Detailed Description

Definition at line 13 of file arc.h.

## Constructor & Destructor Documentation

## ◆ Arc()

impeller::Arc::Arc | ( | const Rect & | bounds,
|  | Degrees | start,
|  | Degrees | sweep,
|  | bool | include_center
| ) |  |

Definition at line 9 of file arc.cc.

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 }
start
const size_t start
Definition: tessellator_libtess.cc:62

References impeller::Degrees::degrees, impeller::TRect< T >::IsFinite(), impeller::Degrees::IsFinite(), and start.

## Member Function Documentation

## ◆ ComputeIterations()

Arc::Iteration impeller::Arc::ComputeIterations | ( | size_t | step_count,
|  | bool | simplify_360 = `true`
| ) |  | const

Return an |ArcIteration| that explains how to generate vertices for the arc with the indicated number of steps in each full quadrant. The step_count is typically chosen based on the size of the bounds and the scale at which the arc is being drawn and so the computation of the step_count requirements is left to the caller.

If the sweep is more than 360 degrees then the code may simplify the iteration to a simple circle, but only if the simplify_360 parameter is true.

Definition at line 102 of file arc.cc.

103 {
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;
122 iterations.start = impeller::Matrix::CosSin(start);
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 }
impeller::Scalar
float Scalar
Definition: scalar.h:19
impeller::kQuadrantAxes
static constexpr impeller::Vector2 kQuadrantAxes[4]
Definition: point.h:335
impeller::Degrees::degrees
Scalar degrees
Definition: scalar.h:77
impeller::Degrees::GetPositive
constexpr Degrees GetPositive() const
Definition: scalar.h:111
impeller::Matrix::CosSin
static Vector2 CosSin(Radians radians)
Definition: matrix.h:618
end
const size_t end
Definition: tessellator_libtess.cc:63

References impeller::Matrix::CosSin(), impeller::Degrees::degrees, impeller::Arc::Iteration::end, end, impeller::Arc::Iteration::Quadrant::end_index, impeller::Degrees::GetPositive(), impeller::kQuadrantAxes, impeller::Arc::Iteration::quadrant_count, impeller::Arc::Iteration::quadrants, impeller::Arc::Iteration::start, start, and impeller::Arc::Iteration::Quadrant::start_index.

Referenced by impeller::ArcStrokeGeometry::Dispatch(), impeller::Tessellator::FilledArc(), impeller::StrokePathSegmentReceiver::RecordArc(), impeller::Tessellator::StrokedArc(), and impeller::testing::TEST().

## ◆ GetOvalBounds()

const Rect& impeller::Arc::GetOvalBounds | ( |  | ) | const
| inline

Return the bounds of the oval in which this arc is inscribed.

Definition at line 94 of file arc.h.

94 { return bounds_; }

Referenced by impeller::Canvas::DrawArc(), impeller::Tessellator::FilledArc(), std::operator<<(), and impeller::Tessellator::StrokedArc().

## ◆ GetOvalCenter()

const Point impeller::Arc::GetOvalCenter | ( |  | ) | const
| inline

Returns the center of the oval bounds.

Definition at line 97 of file arc.h.

97 { return bounds_.GetCenter(); }
impeller::TRect::GetCenter
constexpr Point GetCenter() const
Get the center point as a |Point|.
Definition: rect.h:386

References impeller::TRect< T >::GetCenter().

Referenced by impeller::ArcStrokeGeometry::Dispatch().

## ◆ GetOvalSize()

const Size impeller::Arc::GetOvalSize | ( |  | ) | const
| inline

Returns the size of the oval bounds.

Definition at line 100 of file arc.h.

100 { return bounds_.GetSize(); }
impeller::TRect::GetSize
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:331

References impeller::TRect< T >::GetSize().

Referenced by impeller::ArcStrokeGeometry::Dispatch(), impeller::Tessellator::FilledArc(), and impeller::Tessellator::StrokedArc().

## ◆ GetStart()

constexpr Degrees impeller::Arc::GetStart | ( |  | ) | const
| inline constexpr

Definition at line 106 of file arc.h.

106 { return start_; }

Referenced by impeller::Canvas::DrawArc(), and std::operator<<().

## ◆ GetSweep()

constexpr Degrees impeller::Arc::GetSweep | ( |  | ) | const
| inline constexpr

Definition at line 108 of file arc.h.

108 { return sweep_; }

Referenced by impeller::Canvas::DrawArc(), and std::operator<<().

## ◆ GetTightArcBounds()

Rect impeller::Arc::GetTightArcBounds | ( |  | ) | const

Return the tight bounds of the arc taking into account its specific geometry such as the start and end angles and the center (if included).

Definition at line 59 of file arc.cc.

59 {
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 }
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:792
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::Size
TSize< Scalar > Size
Definition: size.h:159
impeller::Arc::IsFullCircle
constexpr bool IsFullCircle() const
Definition: arc.h:114
impeller::TRect< Scalar >::MakePointBounds
constexpr static std::optional< TRect > MakePointBounds(const U &value)
Definition: rect.h:165

References impeller::Matrix::CosSin(), impeller::Degrees::degrees, impeller::TRect< T >::GetCenter(), impeller::Degrees::GetPositive(), impeller::TRect< T >::GetSize(), IsFullCircle(), impeller::kQuadrantAxes, and impeller::TRect< Scalar >::MakePointBounds().

Referenced by impeller::ArcStrokeGeometry::GetCoverage().

## ◆ IncludeCenter()

constexpr bool impeller::Arc::IncludeCenter | ( |  | ) | const
| inline constexpr

Definition at line 110 of file arc.h.

110 { return include_center_; }

Referenced by impeller::ArcGeometry::ArcGeometry(), impeller::ArcStrokeGeometry::Dispatch(), impeller::Canvas::DrawArc(), impeller::Tessellator::FilledArc(), std::operator<<(), and impeller::Tessellator::StrokedArc().

## ◆ IsFullCircle()

constexpr bool impeller::Arc::IsFullCircle | ( |  | ) | const
| inline constexpr

Definition at line 114 of file arc.h.

114 { return sweep_.degrees >= 360.0f; }

References impeller::Degrees::degrees.

Referenced by impeller::Canvas::DrawArc(), and GetTightArcBounds().

## ◆ IsPerfectCircle()

constexpr bool impeller::Arc::IsPerfectCircle | ( |  | ) | const
| inline constexpr

Definition at line 112 of file arc.h.

112 { return bounds_.IsSquare(); }
impeller::TRect::IsSquare
constexpr bool IsSquare() const
Returns true if width and height are equal and neither is NaN.
Definition: rect.h:308

References impeller::TRect< T >::IsSquare().

Referenced by impeller::ArcGeometry::ArcGeometry(), and impeller::Tessellator::StrokedArc().

The documentation for this struct was generated from the following files:

- impeller/geometry/arc.h
- impeller/geometry/arc.cc