Flutter Engine
 
Loading...
Searching...
No Matches
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 RectGetOvalBounds () const
 Return the bounds of the oval in which this arc is inscribed.
 
const Point GetOvalCenter () const
 Returns the center of the oval bounds.
 
const Size GetOvalSize () const
 Returns the size of the oval bounds.
 
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}
const size_t start

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}
#define FML_DCHECK(condition)
Definition logging.h:122
float Scalar
Definition scalar.h:19
static constexpr impeller::Vector2 kQuadrantAxes[4]
Definition point.h:335
Scalar degrees
Definition scalar.h:67
constexpr Degrees GetPositive() const
Definition scalar.h:91
static Vector2 CosSin(Radians radians)
Definition matrix.h:685
const size_t end

References impeller::Matrix::CosSin(), impeller::Degrees::degrees, impeller::Arc::Iteration::end, end, impeller::Arc::Iteration::Quadrant::end_index, FML_DCHECK, impeller::Degrees::GetPositive(), i, 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(), impeller::testing::TEST(), impeller::testing::TEST(), 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(); }
constexpr Point GetCenter() const
Get the center point as a |Point|.
Definition rect.h:382

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(); }
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

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

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

◆ GetStart()

constexpr Degrees impeller::Arc::GetStart ( ) const
inlineconstexpr

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
inlineconstexpr

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

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

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

◆ IncludeCenter()

constexpr bool impeller::Arc::IncludeCenter ( ) const
inlineconstexpr

◆ IsFullCircle()

constexpr bool impeller::Arc::IsFullCircle ( ) const
inlineconstexpr

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
inlineconstexpr

Definition at line 112 of file arc.h.

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

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: