13static constexpr int kPrecomputedDivisionCount = 1024;
15static int kPrecomputedDivisions[kPrecomputedDivisionCount] = {
17 1, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7,
18 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
19 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13,
20 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14,
21 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16,
22 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18,
23 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19,
24 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
25 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
26 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23,
27 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24,
28 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25,
29 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26,
30 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27,
31 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28,
32 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29,
33 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
34 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
35 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
36 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32,
37 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33,
38 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
39 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
40 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35,
41 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36,
42 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
43 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
44 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38,
45 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
46 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
47 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40,
48 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
49 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41,
50 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
51 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
52 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43,
53 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
54 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44,
55 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
56 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
57 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
58 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
59 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47,
60 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
61 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48,
62 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
63 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49,
64 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
65 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50,
66 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
67 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51,
68 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
69 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52,
70 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
71 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53,
72 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
73 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54,
74 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
75 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
76 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
77 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
78 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
79 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
80 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57,
85 if (pixel_radius <= 0.0) {
88 int radius_index = ceil(pixel_radius);
89 if (radius_index < kPrecomputedDivisionCount) {
90 return kPrecomputedDivisions[radius_index];
145 uint16_t* index_buffer)
146 : point_buffer_(point_buffer), index_buffer_(index_buffer) {}
148 ~FanPathVertexWriter() =
default;
150 size_t GetIndexCount()
const {
return index_count_; }
151 size_t GetPointCount()
const {
return count_; }
157 index_buffer_[index_count_++] = 0xFFFF;
161 index_buffer_[index_count_++] = count_;
162 point_buffer_[count_++] = point;
167 size_t index_count_ = 0;
169 uint16_t* index_buffer_ =
nullptr;
177 uint16_t* index_buffer)
178 : point_buffer_(point_buffer), index_buffer_(index_buffer) {}
180 ~StripPathVertexWriter() =
default;
182 size_t GetIndexCount()
const {
return index_count_; }
183 size_t GetPointCount()
const {
return count_; }
186 if (count_ == 0u || contour_start_ == count_ - 1) {
191 size_t start = contour_start_;
192 size_t end = count_ - 1;
194 index_buffer_[index_count_++] =
start;
196 size_t a =
start + 1;
199 index_buffer_[index_count_++] = a;
200 index_buffer_[index_count_++] =
b;
205 index_buffer_[index_count_++] = a;
208 contour_start_ = count_;
209 index_buffer_[index_count_++] = 0xFFFF;
213 point_buffer_[count_++] = point;
218 size_t index_count_ = 0;
219 size_t contour_start_ = 0;
221 uint16_t* index_buffer_ =
nullptr;
227 explicit GLESPathVertexWriter(std::vector<impeller::Point>&
points,
228 std::vector<uint16_t>& indices)
229 : points_(
points), indices_(indices) {}
231 ~GLESPathVertexWriter() =
default;
234 if (points_.size() == 0u || contour_start_ == points_.size() - 1) {
239 auto start = contour_start_;
240 auto end = points_.size() - 1;
245 if (points_[
end] == points_[start]) {
250 if (contour_start_ != 0) {
251 auto back = indices_.back();
252 indices_.push_back(back);
253 indices_.push_back(start);
254 indices_.push_back(start);
259 if (previous_contour_odd_points_) {
260 indices_.push_back(start);
263 indices_.push_back(start);
266 size_t a =
start + 1;
269 indices_.push_back(a);
270 indices_.push_back(b);
275 indices_.push_back(a);
276 previous_contour_odd_points_ =
false;
278 previous_contour_odd_points_ =
true;
280 contour_start_ = points_.size();
283 void Write(
impeller::Point point)
override { points_.push_back(point); }
286 bool previous_contour_odd_points_ =
false;
287 size_t contour_start_ = 0u;
288 std::vector<impeller::Point>& points_;
289 std::vector<uint16_t>& indices_;
297 : point_buffer_(
std::make_unique<
std::vector<
Point>>()),
298 index_buffer_(
std::make_unique<
std::vector<uint16_t>>()),
311 return GetTrigsForDivisions(ComputeQuadrantDivisions(pixel_radius));
318 bool supports_primitive_restart,
319 bool supports_triangle_fan) {
320 if (supports_primitive_restart) {
322 const auto [point_count, contour_count] =
325 nullptr,
sizeof(
Point) * point_count,
alignof(
Point));
327 nullptr,
sizeof(uint16_t) * (point_count + contour_count),
330 if (supports_triangle_fan) {
331 FanPathVertexWriter writer(
334 reinterpret_cast<uint16_t*
>(
338 FML_DCHECK(writer.GetPointCount() <= point_count);
339 FML_DCHECK(writer.GetIndexCount() <= (point_count + contour_count));
345 .index_buffer = std::move(index_buffer),
346 .vertex_count = writer.GetIndexCount(),
350 StripPathVertexWriter writer(
353 reinterpret_cast<uint16_t*
>(
357 FML_DCHECK(writer.GetPointCount() <= point_count);
358 FML_DCHECK(writer.GetIndexCount() <= (point_count + contour_count));
364 .index_buffer = std::move(index_buffer),
365 .vertex_count = writer.GetIndexCount(),
394 .index_buffer = std::move(index_buffer),
401 std::vector<Point>& point_buffer,
402 std::vector<uint16_t>& index_buffer,
404 point_buffer.clear();
405 index_buffer.clear();
407 GLESPathVertexWriter writer(point_buffer, index_buffer);
415void Tessellator::Trigs::init(
size_t divisions) {
416 if (!trigs_.empty()) {
421 trigs_.reserve(divisions + 1);
423 double angle_scale =
kPiOver2 / divisions;
425 trigs_.emplace_back(1.0, 0.0);
426 for (
size_t i = 1;
i < divisions;
i++) {
427 trigs_.emplace_back(
Radians(
i * angle_scale));
429 trigs_.emplace_back(0.0, 1.0);
432Tessellator::Trigs Tessellator::GetTrigsForDivisions(
size_t divisions) {
433 return divisions < Tessellator::kCachedTrigCount
434 ? Trigs(precomputed_trigs_[divisions], divisions)
439using EllipticalVertexGenerator = Tessellator::EllipticalVertexGenerator;
440using ArcVertexGenerator = Tessellator::ArcVertexGenerator;
442EllipticalVertexGenerator::EllipticalVertexGenerator(
443 EllipticalVertexGenerator::GeneratorProc& generator,
446 size_t vertices_per_trig,
449 trigs_(
std::move(trigs)),
451 vertices_per_trig_(vertices_per_trig) {}
454 const Matrix& view_transform,
460 GetTrigsForDivisions(divisions),
463 .reference_centers = {center, center},
464 .radii = {radius, radius},
470 const Matrix& view_transform,
474 if (half_width > 0) {
475 auto divisions = ComputeQuadrantDivisions(
478 GetTrigsForDivisions(divisions),
481 .reference_centers = {center, center},
482 .radii = {radius, radius},
483 .half_width = half_width,
490ArcVertexGenerator::ArcVertexGenerator(
const Arc::Iteration& iteration,
492 const Rect& oval_bounds,
494 bool supports_triangle_fans)
495 : iteration_(iteration),
496 trigs_(
std::move(trigs)),
497 oval_bounds_(oval_bounds),
501 supports_triangle_fans_(supports_triangle_fans) {}
503ArcVertexGenerator::ArcVertexGenerator(
const Arc::Iteration& iteration,
505 const Rect& oval_bounds,
508 : iteration_(iteration),
509 trigs_(
std::move(trigs)),
510 oval_bounds_(oval_bounds),
512 half_width_(half_width),
514 supports_triangle_fans_(false) {}
517 return (half_width_ < 0 && supports_triangle_fans_)
524 if (half_width_ > 0) {
531 }
else if (supports_triangle_fans_) {
537 count += (count + 1) / 2;
544 if (half_width_ > 0) {
546 Tessellator::GenerateStrokedArc(trigs_, iteration_, oval_bounds_,
547 half_width_, cap_, proc);
548 }
else if (supports_triangle_fans_) {
549 Tessellator::GenerateFilledArcFan(trigs_, iteration_, oval_bounds_,
552 Tessellator::GenerateFilledArcStrip(trigs_, iteration_, oval_bounds_,
559 bool supports_triangle_fans) {
560 size_t divisions = ComputeQuadrantDivisions(
580 GetTrigsForDivisions(divisions),
585 const Matrix& view_transform,
589 auto along = p1 - p0;
595 GetTrigsForDivisions(divisions),
598 .reference_centers = {p0, p1},
599 .radii = {radius, radius},
608 const Matrix& view_transform,
609 const Rect& bounds) {
614 auto max_radius = bounds.
GetSize().MaxDimension();
615 auto divisions = ComputeQuadrantDivisions(
619 GetTrigsForDivisions(divisions),
622 .reference_centers = {center, center},
623 .radii = bounds.
GetSize() * 0.5f,
629 const Matrix& view_transform,
635 auto divisions = ComputeQuadrantDivisions(
637 auto upper_left = bounds.
GetLeftTop() + radii;
640 GetTrigsForDivisions(divisions),
656void Tessellator::GenerateFilledCircle(
658 const EllipticalVertexGenerator::Data&
data,
659 const TessellatedVertexProc& proc) {
660 auto center =
data.reference_centers[0];
661 auto radius =
data.radii.width;
668 for (
auto& trig : trigs) {
669 auto offset = trig * radius;
670 proc({center.x - offset.x, center.y + offset.y});
671 proc({center.x - offset.x, center.y - offset.y});
679 for (
auto& trig : trigs) {
680 auto offset = trig * radius;
686void Tessellator::GenerateStrokedCircle(
688 const EllipticalVertexGenerator::Data&
data,
696 auto outer_radius =
data.radii.width +
data.half_width;
697 auto inner_radius =
data.radii.width -
data.half_width;
705 for (
auto& trig : trigs) {
706 auto outer = trig * outer_radius;
707 auto inner = trig * inner_radius;
717 for (
auto& trig : trigs) {
718 auto outer = trig * outer_radius;
719 auto inner = trig * inner_radius;
725 for (
auto& trig : trigs) {
726 auto outer = trig * outer_radius;
727 auto inner = trig * inner_radius;
733 for (
auto& trig : trigs) {
734 auto outer = trig * outer_radius;
735 auto inner = trig * inner_radius;
741void Tessellator::GenerateFilledArcFan(
const Trigs& trigs,
742 const Arc::Iteration& iteration,
743 const Rect& oval_bounds,
747 Size radii = oval_bounds.GetSize() * 0.5f;
752 proc(center + iteration.start * radii);
753 for (
size_t i = 0;
i < iteration.quadrant_count;
i++) {
754 auto quadrant = iteration.quadrants[
i];
755 for (
size_t j = quadrant.start_index; j < quadrant.end_index; j++) {
756 proc(center + trigs[j] * quadrant.axis * radii);
759 proc(center + iteration.end * radii);
762void Tessellator::GenerateFilledArcStrip(
const Trigs& trigs,
763 const Arc::Iteration& iteration,
764 const Rect& oval_bounds,
768 Size radii = oval_bounds.GetSize() * 0.5f;
774 Point midpoint = (iteration.start + iteration.end) * 0.5f;
775 origin =
center + midpoint * radii;
779 proc(center + iteration.start * radii);
780 bool insert_origin =
false;
781 for (
size_t i = 0;
i < iteration.quadrant_count;
i++) {
782 auto quadrant = iteration.quadrants[
i];
783 for (
size_t j = quadrant.start_index; j < quadrant.end_index; j++) {
787 insert_origin = !insert_origin;
788 proc(center + trigs[j] * quadrant.axis * radii);
794 proc(center + iteration.end * radii);
797void Tessellator::GenerateStrokedArc(
const Trigs& trigs,
798 const Arc::Iteration& iteration,
799 const Rect& oval_bounds,
804 Size base_radii = oval_bounds.GetSize() * 0.5f;
805 Size inner_radii = base_radii -
Size(half_width, half_width);
806 Size outer_radii = base_radii +
Size(half_width, half_width);
811 Vector2{iteration.start.
y, -iteration.start.x} * half_width;
812 proc(center + iteration.start * inner_radii + offset);
813 proc(center + iteration.start * outer_radii + offset);
815 proc(center + iteration.start * inner_radii);
816 proc(center + iteration.start * outer_radii);
817 for (
size_t i = 0;
i < iteration.quadrant_count;
i++) {
818 auto quadrant = iteration.quadrants[
i];
819 for (
size_t j = quadrant.start_index; j < quadrant.end_index; j++) {
820 proc(center + trigs[j] * quadrant.axis * inner_radii);
821 proc(center + trigs[j] * quadrant.axis * outer_radii);
824 proc(center + iteration.end * inner_radii);
825 proc(center + iteration.end * outer_radii);
827 Vector2 offset =
Vector2{-iteration.end.
y, iteration.end.x} * half_width;
828 proc(center + iteration.end * inner_radii + offset);
829 proc(center + iteration.end * outer_radii + offset);
833void Tessellator::GenerateRoundCapLine(
835 const EllipticalVertexGenerator::Data&
data,
837 auto p0 =
data.reference_centers[0];
838 auto p1 =
data.reference_centers[1];
839 auto radius =
data.radii.width;
844 auto along = p1 - p0;
845 along *= radius / along.GetLength();
846 auto across =
Point(-along.y, along.x);
848 for (
auto& trig : trigs) {
849 auto relative_along = along * trig.cos;
850 auto relative_across = across * trig.sin;
851 proc(p0 - relative_along + relative_across);
852 proc(p0 - relative_along - relative_across);
858 for (
auto& trig : trigs) {
859 auto relative_along = along * trig.sin;
860 auto relative_across = across * trig.cos;
861 proc(p1 + relative_along + relative_across);
862 proc(p1 + relative_along - relative_across);
866void Tessellator::GenerateFilledEllipse(
868 const EllipticalVertexGenerator::Data&
data,
871 auto radii =
data.radii;
877 for (
auto& trig : trigs) {
878 auto offset = trig * radii;
888 for (
auto& trig : trigs) {
889 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);
895void Tessellator::GenerateFilledRoundRect(
897 const EllipticalVertexGenerator::Data&
data,
903 auto radii =
data.radii;
908 for (
auto& trig : trigs) {
909 auto offset = trig * radii;
910 proc({
left - offset.x, bottom + offset.y});
911 proc({
left - offset.x, top - offset.y});
919 for (
auto& trig : trigs) {
920 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);
921 proc({
right + offset.x, bottom + offset.y});
922 proc({
right + offset.x, top - offset.y});
virtual void Flush(std::optional< Range > range=std::nullopt) const
virtual uint8_t * OnGetContents() const =0
BufferView Emplace(const BufferType &buffer, size_t alignment=0)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
An interface for generating a multi contour polyline as a triangle strip.
virtual void EndContour()=0
static void PathToFilledVertices(const PathSource &source, VertexWriter &writer, Scalar scale)
static std::pair< size_t, size_t > CountFillStorage(const PathSource &source, Scalar scale)
The |VertexGenerator| implementation common to all shapes that are based on a polygonal representatio...
size_t GetVertexCount() const override
|VertexGenerator|
PrimitiveType GetTriangleType() const override
|VertexGenerator|
void GenerateVertices(const TessellatedVertexProc &proc) const override
|VertexGenerator|
The |VertexGenerator| implementation common to all shapes that are based on a polygonal representatio...
Trigs(Scalar pixel_radius)
A utility that generates triangles of the specified fill type given a polyline. This happens on the C...
Trigs GetTrigsForDeviceRadius(Scalar pixel_radius)
std::vector< Point > stroke_points_
Used for stroke path generation.
EllipticalVertexGenerator RoundCapLine(const Matrix &view_transform, const Point &p0, const Point &p1, Scalar radius)
Create a |VertexGenerator| that can produce vertices for a line with round end caps of the given radi...
std::vector< Point > & GetStrokePointCache()
Retrieve a pre-allocated arena of kPointArenaSize points.
EllipticalVertexGenerator FilledRoundRect(const Matrix &view_transform, const Rect &bounds, const Size &radii)
Create a |VertexGenerator| that can produce vertices for a filled round rect within the given bounds ...
static constexpr Scalar kCircleTolerance
The pixel tolerance used by the algorighm to determine how many divisions to create for a circle.
VertexBuffer TessellateConvex(const PathSource &path, HostBuffer &data_host_buffer, HostBuffer &indexes_host_buffer, Scalar tolerance, bool supports_primitive_restart=false, bool supports_triangle_fan=false)
Given a convex path, create a triangle fan structure.
EllipticalVertexGenerator FilledCircle(const Matrix &view_transform, const Point ¢er, Scalar radius)
Create a |VertexGenerator| that can produce vertices for a filled circle of the given radius around t...
ArcVertexGenerator StrokedArc(const Matrix &view_transform, const Arc &arc, Cap cap, Scalar half_width)
Create a |VertexGenerator| that can produce vertices for a stroked arc inscribed within the given ova...
static void TessellateConvexInternal(const PathSource &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
EllipticalVertexGenerator StrokedCircle(const Matrix &view_transform, const Point ¢er, Scalar radius, Scalar half_width)
Create a |VertexGenerator| that can produce vertices for a stroked circle of the given radius and hal...
std::unique_ptr< std::vector< Point > > point_buffer_
Used for polyline generation.
std::unique_ptr< std::vector< uint16_t > > index_buffer_
EllipticalVertexGenerator FilledEllipse(const Matrix &view_transform, const Rect &bounds)
Create a |VertexGenerator| that can produce vertices for a filled ellipse inscribed within the given ...
std::function< void(const Point &p)> TessellatedVertexProc
A callback function for a |VertexGenerator| to deliver the vertices it computes as |Point| objects.
ArcVertexGenerator FilledArc(const Matrix &view_transform, const Arc &arc, bool supports_triangle_fans)
Create a |VertexGenerator| that can produce vertices for a stroked arc inscribed within the given ova...
#define FML_DCHECK(condition)
PrimitiveType
Decides how backend draws pixels based on input vertices.
constexpr float kEhCloseEnough
Cap
An enum that describes ways to decorate the end of a path contour.
static constexpr size_t kPointArenaSize
The size of the point arena buffer stored on the tessellator.
size_t GetPointCount() const
Iteration ComputeIterations(size_t step_count, bool simplify_360=true) const
constexpr bool IncludeCenter() const
const Size GetOvalSize() const
Returns the size of the oval bounds.
constexpr bool IsPerfectCircle() const
const Rect & GetOvalBounds() const
Return the bounds of the oval in which this arc is inscribed.
const DeviceBuffer * GetBuffer() const
A 4x4 matrix using column-major storage.
Scalar GetMaxBasisLengthXY() const
Return the maximum scale applied specifically to either the X axis or Y axis unit vectors (the bases)...
constexpr Type GetLength() const
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...
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
constexpr TPoint< T > GetLeftTop() const
constexpr bool IsSquare() const
Returns true if width and height are equal and neither is NaN.
constexpr TPoint< T > GetRightBottom() const
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
constexpr Point GetCenter() const
Get the center point as a |Point|.
constexpr Type MaxDimension() const
std::vector< Point > points
std::shared_ptr< const fml::Mapping > data