7 #include "third_party/libtess2/Include/tesselator.h"
11 static void*
HeapAlloc(
void* userData,
unsigned int size) {
15 static void*
HeapRealloc(
void* userData,
void* ptr,
unsigned int size) {
16 return realloc(ptr, size);
19 static void HeapFree(
void* userData,
void* ptr) {
35 : point_buffer_(
std::make_unique<
std::vector<
Point>>()),
37 point_buffer_->reserve(2048);
42 c_tessellator_ = std::move(tessellator);
51 return TESS_WINDING_ODD;
53 return TESS_WINDING_NONZERO;
55 return TESS_WINDING_ODD;
65 point_buffer_->clear();
69 point_buffer_ = std::move(point_buffer);
78 auto tessellator = c_tessellator_.get();
83 constexpr
int kVertexSize = 2;
84 constexpr
int kPolygonSize = 3;
89 static_assert(
sizeof(
Point) == 2 *
sizeof(
float));
90 for (
size_t contour_i = 0; contour_i <
polyline.contours.size();
92 size_t start_point_index, end_point_index;
93 std::tie(start_point_index, end_point_index) =
94 polyline.GetContourPointBounds(contour_i);
96 ::tessAddContour(tessellator,
98 polyline.points->data() + start_point_index,
100 end_point_index - start_point_index
107 auto result = ::tessTesselate(tessellator,
119 int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
126 if (element_item_count < USHRT_MAX) {
127 int vertex_item_count = tessGetVertexCount(tessellator);
128 auto vertices = tessGetVertices(tessellator);
129 auto elements = tessGetElements(tessellator);
133 std::vector<uint16_t> indices(element_item_count);
134 for (
int i = 0; i < element_item_count; i++) {
135 indices[i] =
static_cast<uint16_t
>(elements[i]);
137 if (!callback(vertices, vertex_item_count, indices.data(),
138 element_item_count)) {
142 std::vector<Point> points;
143 std::vector<float> data;
145 int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize;
146 auto vertices = tessGetVertices(tessellator);
147 points.reserve(vertex_item_count);
148 for (
int i = 0; i < vertex_item_count; i += 2) {
149 points.emplace_back(vertices[i], vertices[i + 1]);
152 int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
153 auto elements = tessGetElements(tessellator);
154 data.reserve(element_item_count);
155 for (
int i = 0; i < element_item_count; i++) {
156 data.emplace_back(points[elements[i]].x);
157 data.emplace_back(points[elements[i]].y);
159 if (!callback(data.data(), element_item_count,
nullptr, 0u)) {
169 FML_DCHECK(point_buffer_);
170 point_buffer_->clear();
174 point_buffer_ = std::move(point_buffer);
181 FML_DCHECK(point_buffer_);
183 std::vector<Point> output;
184 point_buffer_->clear();
188 point_buffer_ = std::move(point_buffer);
194 output.reserve(
polyline.points->size() +
195 (4 * (
polyline.contours.size() - 1)));
196 bool previous_contour_odd_points =
false;
197 for (
auto j = 0u; j <
polyline.contours.size(); j++) {
198 auto [start, end] =
polyline.GetContourPointBounds(j);
199 auto first_point =
polyline.GetPoint(start);
204 if (
polyline.GetPoint(end - 1) == first_point) {
210 output.emplace_back(output.back());
211 output.emplace_back(first_point);
212 output.emplace_back(first_point);
217 if (previous_contour_odd_points) {
218 output.emplace_back(first_point);
221 output.emplace_back(first_point);
224 size_t a = start + 1;
227 output.emplace_back(
polyline.GetPoint(a));
228 output.emplace_back(
polyline.GetPoint(
b));
233 previous_contour_odd_points =
false;
234 output.emplace_back(
polyline.GetPoint(a));
236 previous_contour_odd_points =
true;
243 if (tessellator !=
nullptr) {
244 ::tessDeleteTess(tessellator);
251 1, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7,
252 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
253 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13,
254 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14,
255 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16,
256 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18,
257 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19,
258 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
259 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
260 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23,
261 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24,
262 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25,
263 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26,
264 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27,
265 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28,
266 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29,
267 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
268 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
269 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
270 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32,
271 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33,
272 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
273 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
274 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35,
275 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36,
276 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
277 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
278 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38,
279 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
280 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
281 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40,
282 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
283 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41,
284 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
285 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
286 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43,
287 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
288 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44,
289 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
290 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
291 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
292 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
293 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47,
294 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
295 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48,
296 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
297 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49,
298 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
299 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50,
300 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
301 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51,
302 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
303 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52,
304 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
305 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53,
306 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
307 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54,
308 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
309 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
310 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
311 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
312 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
313 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
314 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57,
319 if (pixel_radius <= 0.0) {
322 int radius_index = ceil(pixel_radius);
371 return ceil(
kPiOver4 / std::acos(1 - k));
374 void Tessellator::Trigs::init(
size_t divisions) {
375 if (!trigs_.empty()) {
380 trigs_.reserve(divisions + 1);
382 double angle_scale =
kPiOver2 / divisions;
384 trigs_.emplace_back(1.0, 0.0);
385 for (
size_t i = 1; i < divisions; i++) {
386 trigs_.emplace_back(Radians(i * angle_scale));
388 trigs_.emplace_back(0.0, 1.0);
391 Tessellator::Trigs Tessellator::GetTrigsForDivisions(
size_t divisions) {
392 return divisions < Tessellator::kCachedTrigCount
393 ? Trigs(precomputed_trigs_[divisions], divisions)
400 EllipticalVertexGenerator::EllipticalVertexGenerator(
401 EllipticalVertexGenerator::GeneratorProc& generator,
404 size_t vertices_per_trig,
407 trigs_(
std::move(trigs)),
409 vertices_per_trig_(vertices_per_trig) {}
412 const Matrix& view_transform,
418 GetTrigsForDivisions(divisions),
419 PrimitiveType::kTriangleStrip, 4,
421 .reference_centers = {center, center},
422 .radii = {radius, radius},
428 const Matrix& view_transform,
432 if (half_width > 0) {
436 GetTrigsForDivisions(divisions),
437 PrimitiveType::kTriangleStrip, 8,
439 .reference_centers = {center, center},
440 .radii = {radius, radius},
441 .half_width = half_width,
444 return FilledCircle(view_transform, center, radius);
449 const Matrix& view_transform,
453 auto along = p1 - p0;
459 GetTrigsForDivisions(divisions),
460 PrimitiveType::kTriangleStrip, 4,
462 .reference_centers = {p0, p1},
463 .radii = {radius, radius},
467 return FilledCircle(view_transform, p0, radius);
472 const Matrix& view_transform,
473 const Rect& bounds) {
475 return FilledCircle(view_transform, bounds.
GetCenter(),
478 auto max_radius = bounds.
GetSize().MaxDimension();
483 GetTrigsForDivisions(divisions),
484 PrimitiveType::kTriangleStrip, 4,
486 .reference_centers = {center, center},
487 .radii = bounds.
GetSize() * 0.5f,
493 const Matrix& view_transform,
501 auto upper_left = bounds.
GetLeftTop() + radii;
504 GetTrigsForDivisions(divisions),
505 PrimitiveType::kTriangleStrip, 4,
516 return FilledEllipse(view_transform, bounds);
520 void Tessellator::GenerateFilledCircle(
522 const EllipticalVertexGenerator::Data& data,
524 auto center = data.reference_centers[0];
525 auto radius = data.radii.width;
527 FML_DCHECK(center == data.reference_centers[1]);
528 FML_DCHECK(radius == data.radii.height);
529 FML_DCHECK(data.half_width < 0);
532 for (
auto& trig : trigs) {
533 auto offset = trig * radius;
543 for (
auto& trig : trigs) {
544 auto offset = trig * radius;
550 void Tessellator::GenerateStrokedCircle(
552 const EllipticalVertexGenerator::Data& data,
554 auto center = data.reference_centers[0];
556 FML_DCHECK(center == data.reference_centers[1]);
557 FML_DCHECK(data.radii.IsSquare());
558 FML_DCHECK(data.half_width > 0 && data.half_width < data.radii.width);
560 auto outer_radius = data.radii.width + data.half_width;
561 auto inner_radius = data.radii.width - data.half_width;
569 for (
auto& trig : trigs) {
570 auto outer = trig * outer_radius;
571 auto inner = trig * inner_radius;
572 proc({center.x - outer.x, center.y - outer.y});
573 proc({center.x - inner.x, center.y - inner.y});
581 for (
auto& trig : trigs) {
582 auto outer = trig * outer_radius;
583 auto inner = trig * inner_radius;
584 proc({center.x + outer.y, center.y - outer.x});
585 proc({center.x + inner.y, center.y - inner.x});
589 for (
auto& trig : trigs) {
590 auto outer = trig * outer_radius;
591 auto inner = trig * inner_radius;
592 proc({center.x + outer.x, center.y + outer.y});
593 proc({center.x + inner.x, center.y + inner.y});
597 for (
auto& trig : trigs) {
598 auto outer = trig * outer_radius;
599 auto inner = trig * inner_radius;
600 proc({center.x - outer.y, center.y + outer.x});
601 proc({center.x - inner.y, center.y + inner.x});
605 void Tessellator::GenerateRoundCapLine(
607 const EllipticalVertexGenerator::Data& data,
609 auto p0 = data.reference_centers[0];
610 auto p1 = data.reference_centers[1];
611 auto radius = data.radii.width;
613 FML_DCHECK(radius == data.radii.height);
614 FML_DCHECK(data.half_width < 0);
616 auto along = p1 - p0;
617 along *= radius / along.GetLength();
618 auto across =
Point(-along.y, along.x);
620 for (
auto& trig : trigs) {
621 auto relative_along = along * trig.cos;
622 auto relative_across = across * trig.sin;
623 proc(p0 - relative_along + relative_across);
624 proc(p0 - relative_along - relative_across);
630 for (
auto& trig : trigs) {
631 auto relative_along = along * trig.sin;
632 auto relative_across = across * trig.cos;
633 proc(p1 + relative_along + relative_across);
634 proc(p1 + relative_along - relative_across);
638 void Tessellator::GenerateFilledEllipse(
640 const EllipticalVertexGenerator::Data& data,
642 auto center = data.reference_centers[0];
643 auto radii = data.radii;
645 FML_DCHECK(center == data.reference_centers[1]);
646 FML_DCHECK(data.half_width < 0);
649 for (
auto& trig : trigs) {
650 auto offset = trig * radii;
660 for (
auto& trig : trigs) {
661 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);
667 void Tessellator::GenerateFilledRoundRect(
669 const EllipticalVertexGenerator::Data& data,
671 Scalar left = data.reference_centers[0].x;
672 Scalar top = data.reference_centers[0].y;
673 Scalar right = data.reference_centers[1].x;
674 Scalar bottom = data.reference_centers[1].y;
675 auto radii = data.radii;
677 FML_DCHECK(data.half_width < 0);
680 for (
auto& trig : trigs) {
681 auto offset = trig * radii;
691 for (
auto& trig : trigs) {
692 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);