44
55#pragma once
66
7+ #include < functional>
78#include < vector>
89
910#include " flutter/impeller/geometry/matrix.h"
@@ -22,33 +23,37 @@ struct Trig {
2223
2324 double cos;
2425 double sin;
26+
27+ Vector2 operator *(Scalar radius) const {
28+ return Vector2 (cos * radius, sin * radius);
29+ }
30+
31+ Vector2 interpolate (Vector2 start_vector, Vector2 end_vector) {
32+ return start_vector * cos + end_vector * sin;
33+ }
2534};
2635
36+ using TessellatedPointProc = std::function<void (const Point& p)>;
37+
2738// / @brief A utility class to compute the number of divisions for a circle
2839// / given a transform-adjusted pixel radius and methods for generating
2940// / a tessellated set of triangles for a quarter or full circle.
3041// /
31- // / A helper constructor is provided which can compute the device
32- // / pixel radius size for a geometry-space radius when viewed under
33- // / a specified geometry-to-device transform.
42+ // / The constructor will compute the device pixel radius size for
43+ // / the specified geometry-space | radius| when viewed under
44+ // / a specified geometry-to-device | transform| .
3445// /
35- // / The object should be constructed with the expected radius of the
36- // / circle in pixels , but can then be used to generate a triangular
37- // / tessellation with the indicated number of divisions for any
46+ // / The object should be constructed with the expected transform and
47+ // / radius of the circle , but can then be used to generate a triangular
48+ // / tessellation with the computed number of divisions for any
3849// / radius after that. Since the coordinate space in which the
3950// / circle being tessellated is not necessarily device pixel space,
4051// / the radius supplied during tessellation might not match the
41- // / pixel radius supplied during construction, but the two values
52+ // / pixel radius computed during construction, but the two values
4253// / should be related by the transform in place when the tessellated
4354// / triangles are rendered for maximum tessellation fidelity.
4455class CircleTessellator {
4556 public:
46- // / @brief Constructs a CircleDivider that produces enough segments to
47- // / reasonably approximate a circle with a specified radius
48- // / in pixels.
49- constexpr explicit CircleTessellator (Scalar pixel_radius)
50- : quadrant_divisions_(ComputeQuadrantDivisions(pixel_radius)) {}
51-
5257 // / @brief Constructs a CircleDivider that produces enough segments to
5358 // / reasonably approximate a circle with a specified |radius|
5459 // / when viewed under the specified |transform|.
@@ -62,40 +67,47 @@ class CircleTessellator {
6267 size_t GetQuadrantDivisionCount () const { return quadrant_divisions_; }
6368
6469 // / @brief Return the number of vertices that will be generated to
65- // / tessellate a single quarter circle.
66- size_t GetQuadrantVertexCount () const { return quadrant_divisions_ * 3 ; }
67-
68- // / @brief Return the number of divisions computed by the algorithm for
69- // / a full circle.
70- size_t GetCircleDivisionCount () const { return quadrant_divisions_ * 4 ; }
71-
72- // / @brief Return the number of vertices that will be generated to
73- // / tessellate a full circle.
74- size_t GetCircleVertexCount () const { return quadrant_divisions_ * 12 ; }
75-
76- // / @brief Compute the points of a triangular tesselation of the full
77- // / circle of the given radius and center.
70+ // / tessellate a full circle with a triangle strip.
71+ // /
72+ // / This value can be used to pre-allocate space in a vector
73+ // / to hold the vertices that will be produced by the
74+ // / |GenerateCircleTriangleStrip| and
75+ // / |GenerateRoundCapLineTriangleStrip| methods.
76+ size_t GetCircleVertexCount () const { return (quadrant_divisions_ + 1 ) * 4 ; }
77+
78+ // / @brief Generate the vertices for a triangle strip that covers the
79+ // / circle at a given |radius| from a given |center|, delivering
80+ // / the computed coordinates to the supplied |proc|.
7881 // /
79- // / @return the list of points on the polygonal approximation.
80- std::vector<Point> GetCircleTriangles (const Point& center,
81- Scalar radius) const ;
82-
83- // / @brief Adds entries in an existing vector of |vertices| to represent
84- // / the triangular tessellation of the quarter circle that sweeps
85- // / from the |start_vector| to the |end_vector| around an origin
86- // / specified by |center|. The length of the start and end vectors
87- // / controls the size of the quarter circle.
82+ // / This procedure will generate no more than the number of
83+ // / vertices returned by |GetCircleVertexCount| in an order
84+ // / appropriate for rendering as a triangle strip.
85+ void GenerateCircleTriangleStrip (const TessellatedPointProc& proc,
86+ const Point& center,
87+ Scalar radius) const ;
88+
89+ // / @brief Generate the vertices for a triangle strip that covers the
90+ // / line from |p0| to |p1| with round caps of the specified
91+ // / |radius|, delivering the computed coordinates to the supplied
92+ // / |proc|.
8893 // /
89- // / The axes must be of the same length and perpendicular. The new
90- // / points will be appended to the end of the vector.
91- void FillQuadrantTriangles (std::vector<Point>& vertices,
92- const Point& center,
93- const Point& start_vector,
94- const Point& end_vector) const ;
94+ // / This procedure will generate no more than the number of
95+ // / vertices returned by |GetCircleVertexCount| in an order
96+ // / appropriate for rendering as a triangle strip.
97+ void GenerateRoundCapLineTriangleStrip (const TessellatedPointProc& proc,
98+ const Point& p0,
99+ const Point& p1,
100+ Scalar radius) const ;
95101
96102 private:
97103 const size_t quadrant_divisions_;
98104
105+ // / @brief Constructs a CircleDivider that produces enough segments to
106+ // / reasonably approximate a circle with a specified radius
107+ // / in pixels.
108+ constexpr explicit CircleTessellator (Scalar pixel_radius)
109+ : quadrant_divisions_(ComputeQuadrantDivisions(pixel_radius)) {}
110+
99111 CircleTessellator (const CircleTessellator&) = delete ;
100112
101113 CircleTessellator& operator =(const CircleTessellator&) = delete ;
@@ -116,20 +128,6 @@ class CircleTessellator {
116128 // / @return The vector of (divisions + 1) trig values.
117129 static const std::vector<Trig>& GetTrigForDivisions (size_t divisions);
118130
119- // / @brief Extend a list of |points| in the vector containing relative
120- // / coordinates for the first quadrant (top-center to right-center)
121- // / into the remaining 3 quadrants and adjust them to be relative
122- // / to the supplied |center|.
123- // /
124- // / The incoming coordinates are assumed to be relative to a
125- // / center point of (0, 0) and the method will duplicate and
126- // / reflect them around that origin to fill in the remaining
127- // / 3 quadrants. As the method works, it will also adjust every
128- // / point (including the pre-existing 1st quadrant points) to
129- // / be relative to the new center.
130- static void ExtendRelativeQuadrantToAbsoluteCircle (std::vector<Point>& points,
131- const Point& center = {});
132-
133131 static constexpr int MAX_DIVISIONS_ = 35 ;
134132
135133 static std::vector<Trig> trigs_[MAX_DIVISIONS_ + 1 ];
0 commit comments