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);
203 if (
polyline.GetPoint(end - 1) == first_point) {
209 output.emplace_back(output.back());
210 output.emplace_back(first_point);
211 output.emplace_back(first_point);
216 if (previous_contour_odd_points) {
217 output.emplace_back(first_point);
220 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;
244 if (tessellator !=
nullptr) {
245 ::tessDeleteTess(tessellator);
252 1, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7,
253 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
254 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13,
255 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14,
256 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16,
257 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18,
258 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19,
259 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
260 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
261 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23,
262 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24,
263 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25,
264 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26,
265 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27,
266 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28,
267 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29,
268 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
269 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
270 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
271 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32,
272 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33,
273 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
274 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
275 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35,
276 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36,
277 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
278 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
279 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38,
280 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
281 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
282 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40,
283 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
284 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41,
285 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
286 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
287 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43,
288 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
289 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44,
290 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
291 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
292 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
293 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
294 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47,
295 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
296 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48,
297 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
298 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49,
299 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
300 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50,
301 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
302 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51,
303 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
304 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52,
305 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
306 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53,
307 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
308 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54,
309 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
310 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
311 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
312 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
313 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
314 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
315 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57,
320 if (pixel_radius <= 0.0) {
323 int radius_index = ceil(pixel_radius);
372 return ceil(
kPiOver4 / std::acos(1 - k));
375 void Tessellator::Trigs::init(
size_t divisions) {
376 if (!trigs_.empty()) {
381 trigs_.reserve(divisions + 1);
383 double angle_scale =
kPiOver2 / divisions;
385 trigs_.emplace_back(1.0, 0.0);
386 for (
size_t i = 1; i < divisions; i++) {
387 trigs_.emplace_back(Radians(i * angle_scale));
389 trigs_.emplace_back(0.0, 1.0);
392 Tessellator::Trigs Tessellator::GetTrigsForDivisions(
size_t divisions) {
393 return divisions < Tessellator::kCachedTrigCount
394 ? Trigs(precomputed_trigs_[divisions], divisions)
401 EllipticalVertexGenerator::EllipticalVertexGenerator(
402 EllipticalVertexGenerator::GeneratorProc& generator,
405 size_t vertices_per_trig,
408 trigs_(
std::move(trigs)),
410 vertices_per_trig_(vertices_per_trig) {}
413 const Matrix& view_transform,
419 GetTrigsForDivisions(divisions),
420 PrimitiveType::kTriangleStrip, 4,
422 .reference_centers = {center, center},
423 .radii = {radius, radius},
429 const Matrix& view_transform,
433 if (half_width > 0) {
437 GetTrigsForDivisions(divisions),
438 PrimitiveType::kTriangleStrip, 8,
440 .reference_centers = {center, center},
441 .radii = {radius, radius},
442 .half_width = half_width,
445 return FilledCircle(view_transform, center, radius);
450 const Matrix& view_transform,
454 auto along = p1 - p0;
460 GetTrigsForDivisions(divisions),
461 PrimitiveType::kTriangleStrip, 4,
463 .reference_centers = {p0, p1},
464 .radii = {radius, radius},
468 return FilledCircle(view_transform, p0, radius);
473 const Matrix& view_transform,
474 const Rect& bounds) {
476 return FilledCircle(view_transform, bounds.
GetCenter(),
479 auto max_radius = bounds.
GetSize().MaxDimension();
484 GetTrigsForDivisions(divisions),
485 PrimitiveType::kTriangleStrip, 4,
487 .reference_centers = {center, center},
488 .radii = bounds.
GetSize() * 0.5f,
494 const Matrix& view_transform,
502 auto upper_left = bounds.
GetLeftTop() + radii;
505 GetTrigsForDivisions(divisions),
506 PrimitiveType::kTriangleStrip, 4,
517 return FilledEllipse(view_transform, bounds);
521 void Tessellator::GenerateFilledCircle(
523 const EllipticalVertexGenerator::Data& data,
525 auto center = data.reference_centers[0];
526 auto radius = data.radii.width;
528 FML_DCHECK(center == data.reference_centers[1]);
529 FML_DCHECK(radius == data.radii.height);
530 FML_DCHECK(data.half_width < 0);
533 for (
auto& trig : trigs) {
534 auto offset = trig * radius;
544 for (
auto& trig : trigs) {
545 auto offset = trig * radius;
551 void Tessellator::GenerateStrokedCircle(
553 const EllipticalVertexGenerator::Data& data,
555 auto center = data.reference_centers[0];
557 FML_DCHECK(center == data.reference_centers[1]);
558 FML_DCHECK(data.radii.IsSquare());
559 FML_DCHECK(data.half_width > 0 && data.half_width < data.radii.width);
561 auto outer_radius = data.radii.width + data.half_width;
562 auto inner_radius = data.radii.width - data.half_width;
570 for (
auto& trig : trigs) {
571 auto outer = trig * outer_radius;
572 auto inner = trig * inner_radius;
573 proc({center.x - outer.x, center.y - outer.y});
574 proc({center.x - inner.x, center.y - inner.y});
582 for (
auto& trig : trigs) {
583 auto outer = trig * outer_radius;
584 auto inner = trig * inner_radius;
585 proc({center.x + outer.y, center.y - outer.x});
586 proc({center.x + inner.y, center.y - inner.x});
590 for (
auto& trig : trigs) {
591 auto outer = trig * outer_radius;
592 auto inner = trig * inner_radius;
593 proc({center.x + outer.x, center.y + outer.y});
594 proc({center.x + inner.x, center.y + inner.y});
598 for (
auto& trig : trigs) {
599 auto outer = trig * outer_radius;
600 auto inner = trig * inner_radius;
601 proc({center.x - outer.y, center.y + outer.x});
602 proc({center.x - inner.y, center.y + inner.x});
606 void Tessellator::GenerateRoundCapLine(
608 const EllipticalVertexGenerator::Data& data,
610 auto p0 = data.reference_centers[0];
611 auto p1 = data.reference_centers[1];
612 auto radius = data.radii.width;
614 FML_DCHECK(radius == data.radii.height);
615 FML_DCHECK(data.half_width < 0);
617 auto along = p1 - p0;
618 along *= radius / along.GetLength();
619 auto across =
Point(-along.y, along.x);
621 for (
auto& trig : trigs) {
622 auto relative_along = along * trig.cos;
623 auto relative_across = across * trig.sin;
624 proc(p0 - relative_along + relative_across);
625 proc(p0 - relative_along - relative_across);
631 for (
auto& trig : trigs) {
632 auto relative_along = along * trig.sin;
633 auto relative_across = across * trig.cos;
634 proc(p1 + relative_along + relative_across);
635 proc(p1 + relative_along - relative_across);
639 void Tessellator::GenerateFilledEllipse(
641 const EllipticalVertexGenerator::Data& data,
643 auto center = data.reference_centers[0];
644 auto radii = data.radii;
646 FML_DCHECK(center == data.reference_centers[1]);
647 FML_DCHECK(data.half_width < 0);
650 for (
auto& trig : trigs) {
651 auto offset = trig * radii;
661 for (
auto& trig : trigs) {
662 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);
668 void Tessellator::GenerateFilledRoundRect(
670 const EllipticalVertexGenerator::Data& data,
672 Scalar left = data.reference_centers[0].x;
673 Scalar top = data.reference_centers[0].y;
674 Scalar right = data.reference_centers[1].x;
675 Scalar bottom = data.reference_centers[1].y;
676 auto radii = data.radii;
678 FML_DCHECK(data.half_width < 0);
681 for (
auto& trig : trigs) {
682 auto offset = trig * radii;
692 for (
auto& trig : trigs) {
693 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);