Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
tessellator_libtess.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include "third_party/libtess2/Include/tesselator.h"
8
9namespace impeller {
10
11static void* HeapAlloc(void* userData, unsigned int size) {
12 return malloc(size);
13}
14
15static void* HeapRealloc(void* userData, void* ptr, unsigned int size) {
16 return realloc(ptr, size);
17}
18
19static void HeapFree(void* userData, void* ptr) {
20 free(ptr);
21}
22
23// Note: these units are "number of entities" for bucket size and not in KB.
24static const TESSalloc kAlloc = {
25 HeapAlloc, HeapRealloc, HeapFree, 0, /* =userData */
26 16, /* =meshEdgeBucketSize */
27 16, /* =meshVertexBucketSize */
28 16, /* =meshFaceBucketSize */
29 16, /* =dictNodeBucketSize */
30 16, /* =regionBucketSize */
31 0 /* =extraVertices */
32};
33
35 : Tessellator(), c_tessellator_(nullptr, &DestroyTessellator) {
36 TESSalloc alloc = kAlloc;
37 {
38 // libTess2 copies the TESSalloc despite the non-const argument.
39 CTessellator tessellator(::tessNewTess(&alloc), &DestroyTessellator);
40 c_tessellator_ = std::move(tessellator);
41 }
42}
43
45
46static int ToTessWindingRule(FillType fill_type) {
47 switch (fill_type) {
48 case FillType::kOdd:
49 return TESS_WINDING_ODD;
51 return TESS_WINDING_NONZERO;
52 }
53 return TESS_WINDING_ODD;
54}
55
57 const Path& path,
58 Scalar tolerance,
60 if (!callback) {
62 }
63
64 point_buffer_->clear();
65 auto polyline =
66 path.CreatePolyline(tolerance, std::move(point_buffer_),
67 [this](Path::Polyline::PointBufferPtr point_buffer) {
68 point_buffer_ = std::move(point_buffer);
69 });
70
71 auto fill_type = path.GetFillType();
72
73 if (polyline.points->empty()) {
75 }
76
77 auto tessellator = c_tessellator_.get();
78 if (!tessellator) {
80 }
81
82 constexpr int kVertexSize = 2;
83 constexpr int kPolygonSize = 3;
84
85 //----------------------------------------------------------------------------
86 /// Feed contour information to the tessellator.
87 ///
88 static_assert(sizeof(Point) == 2 * sizeof(float));
89 for (size_t contour_i = 0; contour_i < polyline.contours.size();
90 contour_i++) {
91 size_t start_point_index, end_point_index;
92 std::tie(start_point_index, end_point_index) =
93 polyline.GetContourPointBounds(contour_i);
94
95 ::tessAddContour(tessellator, // the C tessellator
96 kVertexSize, //
97 polyline.points->data() + start_point_index, //
98 sizeof(Point), //
99 end_point_index - start_point_index //
100 );
101 }
102
103 //----------------------------------------------------------------------------
104 /// Let's tessellate.
105 ///
106 auto result = ::tessTesselate(tessellator, // tessellator
107 ToTessWindingRule(fill_type), // winding
108 TESS_POLYGONS, // element type
109 kPolygonSize, // polygon size
110 kVertexSize, // vertex size
111 nullptr // normal (null is automatic)
112 );
113
114 if (result != 1) {
116 }
117
118 int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
119
120 // We default to using a 16bit index buffer, but in cases where we generate
121 // more tessellated data than this can contain we need to fall back to
122 // dropping the index buffer entirely. Instead code could instead switch to
123 // a uint32 index buffer, but this is done for simplicity with the other
124 // fast path above.
125 if (element_item_count < USHRT_MAX) {
126 int vertex_item_count = tessGetVertexCount(tessellator);
127 auto vertices = tessGetVertices(tessellator);
128 auto elements = tessGetElements(tessellator);
129
130 // libtess uses an int index internally due to usage of -1 as a sentinel
131 // value.
132 std::vector<uint16_t> indices(element_item_count);
133 for (int i = 0; i < element_item_count; i++) {
134 indices[i] = static_cast<uint16_t>(elements[i]);
135 }
136 if (!callback(vertices, vertex_item_count, indices.data(),
137 element_item_count)) {
138 return Result::kInputError;
139 }
140 } else {
141 std::vector<Point> points;
142 std::vector<float> data;
143
144 int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize;
145 auto vertices = tessGetVertices(tessellator);
146 points.reserve(vertex_item_count);
147 for (int i = 0; i < vertex_item_count; i += 2) {
148 points.emplace_back(vertices[i], vertices[i + 1]);
149 }
150
151 int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
152 auto elements = tessGetElements(tessellator);
153 data.reserve(element_item_count);
154 for (int i = 0; i < element_item_count; i++) {
155 data.emplace_back(points[elements[i]].x);
156 data.emplace_back(points[elements[i]].y);
157 }
158 if (!callback(data.data(), element_item_count, nullptr, 0u)) {
159 return Result::kInputError;
160 }
161 }
162
163 return Result::kSuccess;
164}
165
166void DestroyTessellator(TESStesselator* tessellator) {
167 if (tessellator != nullptr) {
168 ::tessDeleteTess(tessellator);
169 }
170}
171
172} // namespace impeller
static const int points[]
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition path.h:51
std::function< bool(const float *vertices, size_t vertices_count, const uint16_t *indices, size_t indices_count)> BuilderCallback
A callback that returns the results of the tessellation.
Tessellator::Result Tessellate(const Path &path, Scalar tolerance, const BuilderCallback &callback)
Generates filled triangles from the path. A callback is invoked once for the entire tessellation.
A utility that generates triangles of the specified fill type given a polyline. This happens on the C...
Definition tessellator.h:29
std::unique_ptr< std::vector< Point > > point_buffer_
Used for polyline generation.
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
double y
double x
float Scalar
Definition scalar.h:18
void DestroyTessellator(TESStesselator *tessellator)
FillType
Definition path.h:29
TPoint< Scalar > Point
Definition point.h:316
static void * HeapRealloc(void *userData, void *ptr, unsigned int size)
static void * HeapAlloc(void *userData, unsigned int size)
std::unique_ptr< TESStesselator, decltype(&DestroyTessellator)> CTessellator
static int ToTessWindingRule(FillType fill_type)
static void HeapFree(void *userData, void *ptr)
static const TESSalloc kAlloc
const Path::Polyline & polyline
std::unique_ptr< std::vector< Point > > PointBufferPtr
Definition path.h:97