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];
140template <
typename IndexT>
153template <
typename IndexT>
157 IndexT* index_buffer)
158 : point_buffer_(point_buffer), index_buffer_(index_buffer) {}
160 ~FanPathVertexWriter() =
default;
162 size_t GetIndexCount()
const {
return index_count_; }
163 size_t GetPointCount()
const {
return count_; }
169 index_buffer_[index_count_++] =
static_cast<IndexT
>(-1);
173 index_buffer_[index_count_++] = count_;
174 point_buffer_[count_++] = point;
179 size_t index_count_ = 0;
181 IndexT* index_buffer_ =
nullptr;
186template <
typename IndexT>
190 IndexT* index_buffer)
191 : point_buffer_(point_buffer), index_buffer_(index_buffer) {}
193 ~StripPathVertexWriter() =
default;
195 size_t GetIndexCount()
const {
return index_count_; }
196 size_t GetPointCount()
const {
return count_; }
199 if (count_ == 0u || contour_start_ == count_ - 1) {
204 size_t start = contour_start_;
205 size_t end = count_ - 1;
207 index_buffer_[index_count_++] =
start;
209 size_t a =
start + 1;
212 index_buffer_[index_count_++] = a;
213 index_buffer_[index_count_++] =
b;
218 index_buffer_[index_count_++] = a;
221 contour_start_ = count_;
222 index_buffer_[index_count_++] =
static_cast<IndexT
>(-1);
226 point_buffer_[count_++] = point;
231 size_t index_count_ = 0;
232 size_t contour_start_ = 0;
234 IndexT* index_buffer_ =
nullptr;
238template <
typename IndexT>
241 explicit GLESPathVertexWriter(std::vector<impeller::Point>&
points,
242 std::vector<IndexT>& indices)
243 : points_(
points), indices_(indices) {}
245 ~GLESPathVertexWriter() =
default;
248 if (points_.size() == 0u || contour_start_ == points_.size() - 1) {
253 auto start = contour_start_;
254 auto end = points_.size() - 1;
259 if (points_[
end] == points_[start]) {
264 if (contour_start_ != 0) {
265 auto back = indices_.back();
266 indices_.push_back(back);
267 indices_.push_back(start);
268 indices_.push_back(start);
273 if (previous_contour_odd_points_) {
274 indices_.push_back(start);
277 indices_.push_back(start);
280 size_t a =
start + 1;
283 indices_.push_back(a);
284 indices_.push_back(b);
289 indices_.push_back(a);
290 previous_contour_odd_points_ =
false;
292 previous_contour_odd_points_ =
true;
294 contour_start_ = points_.size();
297 void Write(
impeller::Point point)
override { points_.push_back(point); }
300 bool previous_contour_odd_points_ =
false;
301 size_t contour_start_ = 0u;
302 std::vector<impeller::Point>& points_;
303 std::vector<IndexT>& indices_;
306template <
typename IndexT>
308 std::vector<impeller::Point>& point_buffer,
309 std::vector<IndexT>& index_buffer,
311 point_buffer.clear();
312 index_buffer.clear();
314 GLESPathVertexWriter writer(point_buffer, index_buffer);
323template <
typename IndexT>
324class ConvexTessellatorImpl :
public Tessellator::ConvexTessellator {
326 ConvexTessellatorImpl() {
327 point_buffer_.reserve(2048);
328 index_buffer_.reserve(2048);
331 VertexBuffer TessellateConvex(
const PathSource& path,
332 HostBuffer& data_host_buffer,
333 HostBuffer& indexes_host_buffer,
335 bool supports_primitive_restart,
336 bool supports_triangle_fan)
override {
337 if (supports_primitive_restart) {
339 const auto [point_count, contour_count] =
341 BufferView point_buffer = data_host_buffer.Emplace(
342 nullptr,
sizeof(
Point) * point_count,
alignof(
Point));
343 BufferView index_buffer = indexes_host_buffer.Emplace(
344 nullptr,
sizeof(IndexT) * (point_count + contour_count),
348 reinterpret_cast<Point*
>(point_buffer.GetBuffer()->OnGetContents() +
349 point_buffer.GetRange().offset);
351 reinterpret_cast<IndexT*
>(index_buffer.GetBuffer()->OnGetContents() +
352 index_buffer.GetRange().offset);
354 auto tessellate_path = [&](
auto& writer) {
356 FML_DCHECK(writer.GetPointCount() <= point_count);
357 FML_DCHECK(writer.GetIndexCount() <= (point_count + contour_count));
358 point_buffer.GetBuffer()->Flush(point_buffer.GetRange());
359 index_buffer.GetBuffer()->Flush(index_buffer.GetRange());
362 .vertex_buffer = std::move(point_buffer),
363 .index_buffer = std::move(index_buffer),
364 .vertex_count = writer.GetIndexCount(),
365 .index_type = IndexTypeFor<IndexT>(),
369 if (supports_triangle_fan) {
370 FanPathVertexWriter writer(points_ptr, indices_ptr);
371 return tessellate_path(writer);
373 StripPathVertexWriter writer(points_ptr, indices_ptr);
374 return tessellate_path(writer);
378 DoTessellateConvexInternal(path, point_buffer_, index_buffer_, tolerance);
380 if (point_buffer_.empty()) {
385 .index_type = IndexTypeFor<IndexT>(),
389 BufferView vertex_buffer = data_host_buffer.Emplace(
390 point_buffer_.data(),
sizeof(
Point) * point_buffer_.size(),
393 BufferView index_buffer = indexes_host_buffer.Emplace(
394 index_buffer_.data(),
sizeof(IndexT) * index_buffer_.size(),
398 .vertex_buffer = std::move(vertex_buffer),
399 .index_buffer = std::move(index_buffer),
400 .vertex_count = index_buffer_.size(),
401 .index_type = IndexTypeFor<IndexT>(),
406 std::vector<Point> point_buffer_;
407 std::vector<IndexT> index_buffer_;
412 if (supports_32bit_primitive_indices) {
413 convex_tessellator_ = std::make_unique<ConvexTessellatorImpl<uint32_t>>();
415 convex_tessellator_ = std::make_unique<ConvexTessellatorImpl<uint16_t>>();
422 return stroke_points_;
426 return GetTrigsForDivisions(ComputeQuadrantDivisions(pixel_radius));
433 bool supports_primitive_restart,
434 bool supports_triangle_fan) {
435 return convex_tessellator_->TessellateConvex(
436 path, data_host_buffer, indexes_host_buffer, tolerance,
437 supports_primitive_restart, supports_triangle_fan);
441 std::vector<Point>& point_buffer,
442 std::vector<uint16_t>& index_buffer,
444 DoTessellateConvexInternal(path, point_buffer, index_buffer, tolerance);
450void Tessellator::Trigs::init(
size_t divisions) {
451 if (!trigs_.empty()) {
456 trigs_.reserve(divisions + 1);
458 double angle_scale =
kPiOver2 / divisions;
460 trigs_.emplace_back(1.0, 0.0);
461 for (
size_t i = 1;
i < divisions;
i++) {
462 trigs_.emplace_back(
Radians(
i * angle_scale));
464 trigs_.emplace_back(0.0, 1.0);
467Tessellator::Trigs Tessellator::GetTrigsForDivisions(
size_t divisions) {
468 return divisions < Tessellator::kCachedTrigCount
469 ? Trigs(precomputed_trigs_[divisions], divisions)
474using EllipticalVertexGenerator = Tessellator::EllipticalVertexGenerator;
475using ArcVertexGenerator = Tessellator::ArcVertexGenerator;
477EllipticalVertexGenerator::EllipticalVertexGenerator(
478 EllipticalVertexGenerator::GeneratorProc& generator,
481 size_t vertices_per_trig,
484 trigs_(
std::move(trigs)),
486 vertices_per_trig_(vertices_per_trig) {}
489 const Matrix& view_transform,
495 GetTrigsForDivisions(divisions),
498 .reference_centers = {center, center},
499 .radii = {radius, radius},
505 const Matrix& view_transform,
509 if (half_width > 0) {
510 auto divisions = ComputeQuadrantDivisions(
513 GetTrigsForDivisions(divisions),
516 .reference_centers = {center, center},
517 .radii = {radius, radius},
518 .half_width = half_width,
528 const Rect& oval_bounds,
530 bool supports_triangle_fans) {
539 const Rect& oval_bounds,
542 std::unique_ptr<Trigs> round_cap_trigs) {
544 false, half_width, cap, std::move(round_cap_trigs));
547ArcVertexGenerator::ArcVertexGenerator(
const Arc::Iteration& iteration,
549 const Rect& oval_bounds,
551 bool supports_triangle_fans,
554 std::unique_ptr<Trigs> round_cap_trigs)
555 : iteration_(iteration),
556 trigs_(
std::move(trigs)),
557 oval_bounds_(oval_bounds),
559 supports_triangle_fans_(supports_triangle_fans),
560 half_width_(half_width),
562 round_cap_trigs_(
std::move(round_cap_trigs)) {}
565 return (half_width_ < 0 && supports_triangle_fans_)
572 if (half_width_ > 0) {
583 count += round_cap_trigs_->size() * 4 - 4;
585 }
else if (supports_triangle_fans_) {
592 count = (2 * count) - 1;
599 if (half_width_ > 0) {
601 Tessellator::GenerateStrokedArc(trigs_, iteration_, oval_bounds_,
602 half_width_, cap_, round_cap_trigs_, proc);
603 }
else if (supports_triangle_fans_) {
604 Tessellator::GenerateFilledArcFan(trigs_, iteration_, oval_bounds_,
607 Tessellator::GenerateFilledArcStrip(trigs_, iteration_, oval_bounds_,
614 bool supports_triangle_fans) {
615 size_t divisions = ComputeQuadrantDivisions(
634 std::unique_ptr<Trigs> round_cap_trigs;
642 arc.
GetOvalBounds(), half_width, cap, std::move(round_cap_trigs));
646 const Matrix& view_transform,
650 auto along = p1 - p0;
656 GetTrigsForDivisions(divisions),
659 .reference_centers = {p0, p1},
660 .radii = {radius, radius},
669 const Matrix& view_transform,
670 const Rect& bounds) {
675 auto max_radius = bounds.
GetSize().MaxDimension();
676 auto divisions = ComputeQuadrantDivisions(
680 GetTrigsForDivisions(divisions),
683 .reference_centers = {center, center},
684 .radii = bounds.
GetSize() * 0.5f,
690 const Matrix& view_transform,
696 auto divisions = ComputeQuadrantDivisions(
698 auto upper_left = bounds.
GetLeftTop() + radii;
701 GetTrigsForDivisions(divisions),
717void Tessellator::GenerateFilledCircle(
719 const EllipticalVertexGenerator::Data&
data,
720 const TessellatedVertexProc& proc) {
721 auto center =
data.reference_centers[0];
722 auto radius =
data.radii.width;
729 for (
auto& trig : trigs) {
730 auto offset = trig * radius;
731 proc({center.x - offset.x, center.y + offset.y});
732 proc({center.x - offset.x, center.y - offset.y});
740 for (
auto& trig : trigs) {
741 auto offset = trig * radius;
747void Tessellator::GenerateStrokedCircle(
749 const EllipticalVertexGenerator::Data&
data,
757 auto outer_radius =
data.radii.width +
data.half_width;
758 auto inner_radius =
data.radii.width -
data.half_width;
766 for (
auto& trig : trigs) {
767 auto outer = trig * outer_radius;
768 auto inner = trig * inner_radius;
778 for (
auto& trig : trigs) {
779 auto outer = trig * outer_radius;
780 auto inner = trig * inner_radius;
786 for (
auto& trig : trigs) {
787 auto outer = trig * outer_radius;
788 auto inner = trig * inner_radius;
794 for (
auto& trig : trigs) {
795 auto outer = trig * outer_radius;
796 auto inner = trig * inner_radius;
802void Tessellator::GenerateFilledArcFan(
const Trigs& trigs,
803 const Arc::Iteration& iteration,
804 const Rect& oval_bounds,
808 Size radii = oval_bounds.GetSize() * 0.5f;
813 proc(center + iteration.start * radii);
814 for (
size_t i = 0;
i < iteration.quadrant_count;
i++) {
815 auto quadrant = iteration.quadrants[
i];
816 for (
size_t j = quadrant.start_index; j < quadrant.end_index; j++) {
817 proc(center + trigs[j] * quadrant.axis * radii);
820 proc(center + iteration.end * radii);
823void Tessellator::GenerateFilledArcStrip(
const Trigs& trigs,
824 const Arc::Iteration& iteration,
825 const Rect& oval_bounds,
829 Size radii = oval_bounds.GetSize() * 0.5f;
835 Point midpoint = (iteration.start + iteration.end) * 0.5f;
836 origin =
center + midpoint * radii;
839 proc(center + iteration.start * radii);
840 for (
size_t i = 0;
i < iteration.quadrant_count;
i++) {
841 auto quadrant = iteration.quadrants[
i];
842 for (
size_t j = quadrant.start_index; j < quadrant.end_index; j++) {
844 proc(center + trigs[j] * quadrant.axis * radii);
848 proc(center + iteration.end * radii);
851void Tessellator::GenerateStrokedArc(
853 const Arc::Iteration& iteration,
854 const Rect& oval_bounds,
857 const std::unique_ptr<Trigs>& round_cap_trigs,
860 Size base_radii = oval_bounds.GetSize() * 0.5f;
861 Size inner_radii = base_radii -
Size(half_width, half_width);
862 Size outer_radii = base_radii +
Size(half_width, half_width);
867 proc(center + iteration.start * inner_radii);
868 proc(center + iteration.start * outer_radii);
872 Tessellator::GenerateStartRoundCap(center + iteration.start * base_radii,
873 -iteration.start * half_width,
874 *round_cap_trigs, proc);
878 Vector2{iteration.start.
y, -iteration.start.x} * half_width;
879 proc(center + iteration.start * inner_radii + offset);
880 proc(center + iteration.start * outer_radii + offset);
881 proc(center + iteration.start * inner_radii);
882 proc(center + iteration.start * outer_radii);
886 for (
size_t i = 0;
i < iteration.quadrant_count;
i++) {
887 auto quadrant = iteration.quadrants[
i];
888 for (
size_t j = quadrant.start_index; j < quadrant.end_index; j++) {
889 proc(center + trigs[j] * quadrant.axis * inner_radii);
890 proc(center + trigs[j] * quadrant.axis * outer_radii);
897 proc(center + iteration.end * inner_radii);
898 proc(center + iteration.end * outer_radii);
902 Tessellator::GenerateEndRoundCap(center + iteration.end * base_radii,
903 -iteration.end * half_width,
904 *round_cap_trigs, proc);
907 Vector2 offset =
Vector2{-iteration.end.
y, iteration.end.x} * half_width;
908 proc(center + iteration.end * inner_radii);
909 proc(center + iteration.end * outer_radii);
910 proc(center + iteration.end * inner_radii + offset);
911 proc(center + iteration.end * outer_radii + offset);
916void Tessellator::GenerateRoundCapLine(
918 const EllipticalVertexGenerator::Data&
data,
920 auto p0 =
data.reference_centers[0];
921 auto p1 =
data.reference_centers[1];
922 auto radius =
data.radii.width;
927 auto along = p1 - p0;
928 along *= radius / along.GetLength();
929 auto across =
Point(-along.y, along.x);
931 Tessellator::GenerateStartRoundCap(p0, across, trigs, proc);
932 Tessellator::GenerateEndRoundCap(p1, across, trigs, proc);
935void Tessellator::GenerateFilledEllipse(
937 const EllipticalVertexGenerator::Data&
data,
940 auto radii =
data.radii;
946 for (
auto& trig : trigs) {
947 auto offset = trig * radii;
957 for (
auto& trig : trigs) {
958 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);
964void Tessellator::GenerateFilledRoundRect(
966 const EllipticalVertexGenerator::Data&
data,
972 auto radii =
data.radii;
977 for (
auto& trig : trigs) {
978 auto offset = trig * radii;
979 proc({
left - offset.x, bottom + offset.y});
980 proc({
left - offset.x, top - offset.y});
988 for (
auto& trig : trigs) {
989 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);
990 proc({
right + offset.x, bottom + offset.y});
991 proc({
right + offset.x, top - offset.y});
995void Tessellator::GenerateStartRoundCap(
const Point& p,
999 Point along(perpendicular.y, -perpendicular.x);
1001 for (
auto& trig : trigs) {
1002 auto relative_along = along * trig.cos;
1003 auto relative_across = perpendicular * trig.sin;
1004 proc(p - relative_along + relative_across);
1005 proc(p - relative_along - relative_across);
1009void Tessellator::GenerateEndRoundCap(
const Point& p,
1013 Point along(perpendicular.y, -perpendicular.x);
1018 for (
auto& trig : trigs) {
1019 auto relative_along = along * trig.sin;
1020 auto relative_across = perpendicular * trig.cos;
1021 proc(p + relative_along + relative_across);
1022 proc(p + relative_along - relative_across);
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...
static ArcVertexGenerator MakeStroked(const Arc::Iteration &iteration, Trigs &&trigs, const Rect &oval_bounds, Scalar half_width, Cap cap, std::unique_ptr< Trigs > round_cap_trigs)
size_t GetVertexCount() const override
|VertexGenerator|
PrimitiveType GetTriangleType() const override
|VertexGenerator|
static ArcVertexGenerator MakeFilled(const Arc::Iteration &iteration, Trigs &&trigs, const Rect &oval_bounds, bool use_center, bool supports_triangle_fans)
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)
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...
EllipticalVertexGenerator FilledEllipse(const Matrix &view_transform, const Rect &bounds)
Create a |VertexGenerator| that can produce vertices for a filled ellipse inscribed within the given ...
Tessellator(bool supports_32bit_primitive_indices=true)
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.
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