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_POSITIVE;
57 return TESS_WINDING_NEGATIVE;
59 return TESS_WINDING_ABS_GEQ_TWO;
61 return TESS_WINDING_ODD;
71 point_buffer_->clear();
75 point_buffer_ = std::move(point_buffer);
80 if (polyline.points->empty()) {
84 auto tessellator = c_tessellator_.get();
89 constexpr
int kVertexSize = 2;
90 constexpr
int kPolygonSize = 3;
95 static_assert(
sizeof(
Point) == 2 *
sizeof(
float));
96 for (
size_t contour_i = 0; contour_i < polyline.contours.size();
98 size_t start_point_index, end_point_index;
99 std::tie(start_point_index, end_point_index) =
100 polyline.GetContourPointBounds(contour_i);
102 ::tessAddContour(tessellator,
104 polyline.points->data() + start_point_index,
106 end_point_index - start_point_index
113 auto result = ::tessTesselate(tessellator,
125 int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
132 if (element_item_count < USHRT_MAX) {
133 int vertex_item_count = tessGetVertexCount(tessellator);
134 auto vertices = tessGetVertices(tessellator);
135 auto elements = tessGetElements(tessellator);
139 std::vector<uint16_t> indices(element_item_count);
140 for (
int i = 0; i < element_item_count; i++) {
141 indices[i] =
static_cast<uint16_t
>(elements[i]);
143 if (!callback(vertices, vertex_item_count, indices.data(),
144 element_item_count)) {
148 std::vector<Point> points;
149 std::vector<float> data;
151 int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize;
152 auto vertices = tessGetVertices(tessellator);
153 points.reserve(vertex_item_count);
154 for (
int i = 0; i < vertex_item_count; i += 2) {
155 points.emplace_back(vertices[i], vertices[i + 1]);
158 int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
159 auto elements = tessGetElements(tessellator);
160 data.reserve(element_item_count);
161 for (
int i = 0; i < element_item_count; i++) {
162 data.emplace_back(points[elements[i]].x);
163 data.emplace_back(points[elements[i]].y);
165 if (!callback(data.data(), element_item_count,
nullptr, 0u)) {
175 std::vector<Point> output;
177 point_buffer_->clear();
181 point_buffer_ = std::move(point_buffer);
184 output.reserve(polyline.points->size() +
185 (4 * (polyline.contours.size() - 1)));
186 for (
auto j = 0u; j < polyline.contours.size(); j++) {
188 auto first_point = polyline.GetPoint(start);
193 if (polyline.GetPoint(end - 1) == first_point) {
199 output.emplace_back(output.back());
200 output.emplace_back(first_point);
201 output.emplace_back(first_point);
203 output.emplace_back(first_point);
206 size_t a = start + 1;
209 output.emplace_back(polyline.GetPoint(a));
210 output.emplace_back(polyline.GetPoint(b));
215 output.emplace_back(polyline.GetPoint(a));
222 if (tessellator !=
nullptr) {
223 ::tessDeleteTess(tessellator);
230 1, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7,
231 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
232 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13,
233 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14,
234 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16,
235 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18,
236 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19,
237 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
238 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
239 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23,
240 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24,
241 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25,
242 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26,
243 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27,
244 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28,
245 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29,
246 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
247 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
248 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
249 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32,
250 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33,
251 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
252 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
253 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35,
254 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36,
255 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
256 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
257 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38,
258 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
259 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
260 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40,
261 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
262 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41,
263 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
264 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
265 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43,
266 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
267 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44,
268 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
269 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
270 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
271 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
272 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47,
273 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
274 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48,
275 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
276 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49,
277 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
278 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50,
279 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
280 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51,
281 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
282 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52,
283 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
284 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53,
285 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
286 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54,
287 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
288 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
289 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
290 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
291 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
292 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
293 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57,
298 if (pixel_radius <= 0.0) {
301 int radius_index = ceil(pixel_radius);
350 return ceil(
kPiOver4 / std::acos(1 - k));
353 void Tessellator::Trigs::init(
size_t divisions) {
354 if (!trigs_.empty()) {
359 trigs_.reserve(divisions + 1);
361 double angle_scale =
kPiOver2 / divisions;
363 trigs_.emplace_back(1.0, 0.0);
364 for (
size_t i = 1; i < divisions; i++) {
365 trigs_.emplace_back(Radians(i * angle_scale));
367 trigs_.emplace_back(0.0, 1.0);
370 Tessellator::Trigs Tessellator::GetTrigsForDivisions(
size_t divisions) {
371 return divisions < Tessellator::kCachedTrigCount
372 ? Trigs(precomputed_trigs_[divisions], divisions)
379 EllipticalVertexGenerator::EllipticalVertexGenerator(
380 EllipticalVertexGenerator::GeneratorProc& generator,
383 size_t vertices_per_trig,
386 trigs_(
std::move(trigs)),
388 vertices_per_trig_(vertices_per_trig) {}
391 const Matrix& view_transform,
397 GetTrigsForDivisions(divisions),
398 PrimitiveType::kTriangleStrip, 4,
400 .reference_centers = {center, center},
401 .radii = {radius, radius},
407 const Matrix& view_transform,
411 if (half_width > 0) {
415 GetTrigsForDivisions(divisions),
416 PrimitiveType::kTriangleStrip, 8,
418 .reference_centers = {center, center},
419 .radii = {radius, radius},
420 .half_width = half_width,
423 return FilledCircle(view_transform, center, radius);
428 const Matrix& view_transform,
432 auto along = p1 - p0;
438 GetTrigsForDivisions(divisions),
439 PrimitiveType::kTriangleStrip, 4,
441 .reference_centers = {p0, p1},
442 .radii = {radius, radius},
446 return FilledCircle(view_transform, p0, radius);
451 const Matrix& view_transform,
452 const Rect& bounds) {
454 return FilledCircle(view_transform, bounds.
GetCenter(),
462 GetTrigsForDivisions(divisions),
463 PrimitiveType::kTriangleStrip, 4,
465 .reference_centers = {center, center},
466 .radii = bounds.
GetSize() * 0.5f,
472 const Matrix& view_transform,
480 auto upper_left = bounds.
GetLeftTop() + radii;
483 GetTrigsForDivisions(divisions),
484 PrimitiveType::kTriangleStrip, 4,
495 return FilledEllipse(view_transform, bounds);
499 void Tessellator::GenerateFilledCircle(
501 const EllipticalVertexGenerator::Data& data,
503 auto center = data.reference_centers[0];
504 auto radius = data.radii.width;
506 FML_DCHECK(center == data.reference_centers[1]);
507 FML_DCHECK(radius == data.radii.height);
508 FML_DCHECK(data.half_width < 0);
511 for (
auto& trig : trigs) {
512 auto offset = trig * radius;
513 proc({center.x - offset.x, center.y + offset.y});
514 proc({center.x - offset.x, center.y - offset.y});
522 for (
auto& trig : trigs) {
523 auto offset = trig * radius;
524 proc({center.x + offset.y, center.y + offset.x});
525 proc({center.x + offset.y, center.y - offset.x});
529 void Tessellator::GenerateStrokedCircle(
531 const EllipticalVertexGenerator::Data& data,
533 auto center = data.reference_centers[0];
535 FML_DCHECK(center == data.reference_centers[1]);
536 FML_DCHECK(data.radii.IsSquare());
537 FML_DCHECK(data.half_width > 0 && data.half_width < data.radii.width);
539 auto outer_radius = data.radii.width + data.half_width;
540 auto inner_radius = data.radii.width - data.half_width;
548 for (
auto& trig : trigs) {
549 auto outer = trig * outer_radius;
550 auto inner = trig * inner_radius;
551 proc({center.x - outer.x, center.y - outer.y});
552 proc({center.x - inner.x, center.y - inner.y});
560 for (
auto& trig : trigs) {
561 auto outer = trig * outer_radius;
562 auto inner = trig * inner_radius;
563 proc({center.x + outer.y, center.y - outer.x});
564 proc({center.x + inner.y, center.y - inner.x});
568 for (
auto& trig : trigs) {
569 auto outer = trig * outer_radius;
570 auto inner = trig * inner_radius;
571 proc({center.x + outer.x, center.y + outer.y});
572 proc({center.x + inner.x, center.y + inner.y});
576 for (
auto& trig : trigs) {
577 auto outer = trig * outer_radius;
578 auto inner = trig * inner_radius;
579 proc({center.x - outer.y, center.y + outer.x});
580 proc({center.x - inner.y, center.y + inner.x});
584 void Tessellator::GenerateRoundCapLine(
586 const EllipticalVertexGenerator::Data& data,
588 auto p0 = data.reference_centers[0];
589 auto p1 = data.reference_centers[1];
590 auto radius = data.radii.width;
592 FML_DCHECK(radius == data.radii.height);
593 FML_DCHECK(data.half_width < 0);
595 auto along = p1 - p0;
596 along *= radius / along.GetLength();
597 auto across =
Point(-along.y, along.x);
599 for (
auto& trig : trigs) {
600 auto relative_along = along * trig.cos;
601 auto relative_across = across * trig.sin;
602 proc(p0 - relative_along + relative_across);
603 proc(p0 - relative_along - relative_across);
609 for (
auto& trig : trigs) {
610 auto relative_along = along * trig.sin;
611 auto relative_across = across * trig.cos;
612 proc(p1 + relative_along + relative_across);
613 proc(p1 + relative_along - relative_across);
617 void Tessellator::GenerateFilledEllipse(
619 const EllipticalVertexGenerator::Data& data,
621 auto center = data.reference_centers[0];
622 auto radii = data.radii;
624 FML_DCHECK(center == data.reference_centers[1]);
625 FML_DCHECK(data.half_width < 0);
628 for (
auto& trig : trigs) {
629 auto offset = trig * radii;
630 proc({center.x - offset.x, center.y + offset.y});
631 proc({center.x - offset.x, center.y - offset.y});
639 for (
auto& trig : trigs) {
640 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);
641 proc({center.x + offset.x, center.y + offset.y});
642 proc({center.x + offset.x, center.y - offset.y});
646 void Tessellator::GenerateFilledRoundRect(
648 const EllipticalVertexGenerator::Data& data,
650 Scalar left = data.reference_centers[0].x;
651 Scalar top = data.reference_centers[0].y;
652 Scalar right = data.reference_centers[1].x;
653 Scalar bottom = data.reference_centers[1].y;
654 auto radii = data.radii;
656 FML_DCHECK(data.half_width < 0);
659 for (
auto& trig : trigs) {
660 auto offset = trig * radii;
661 proc({left - offset.x, bottom + offset.y});
662 proc({left - offset.x, top - offset.y});
670 for (
auto& trig : trigs) {
671 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);
672 proc({right + offset.x, bottom + offset.y});
673 proc({right + offset.x, top - offset.y});