Flutter Impeller
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 
9 namespace impeller {
10 
11 static void* HeapAlloc(void* userData, unsigned int size) {
12  return malloc(size);
13 }
14 
15 static void* HeapRealloc(void* userData, void* ptr, unsigned int size) {
16  return realloc(ptr, size);
17 }
18 
19 static 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.
24 static 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  : 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 
46 static int ToTessWindingRule(FillType fill_type) {
47  switch (fill_type) {
48  case FillType::kOdd:
49  return TESS_WINDING_ODD;
50  case FillType::kNonZero:
51  return TESS_WINDING_NONZERO;
52  }
53  return TESS_WINDING_ODD;
54 }
55 
57  const Path& path,
58  Scalar tolerance,
59  const BuilderCallback& callback) {
60  if (!callback) {
62  }
63 
64  std::unique_ptr<std::vector<Point>> point_buffer =
65  std::make_unique<std::vector<Point>>();
66  auto polyline = path.CreatePolyline(tolerance, std::move(point_buffer));
67 
68  auto fill_type = path.GetFillType();
69 
70  if (polyline.points->empty()) {
72  }
73 
74  auto tessellator = c_tessellator_.get();
75  if (!tessellator) {
77  }
78 
79  constexpr int kVertexSize = 2;
80  constexpr int kPolygonSize = 3;
81 
82  //----------------------------------------------------------------------------
83  /// Feed contour information to the tessellator.
84  ///
85  static_assert(sizeof(Point) == 2 * sizeof(float));
86  for (size_t contour_i = 0; contour_i < polyline.contours.size();
87  contour_i++) {
88  size_t start_point_index, end_point_index;
89  std::tie(start_point_index, end_point_index) =
90  polyline.GetContourPointBounds(contour_i);
91 
92  ::tessAddContour(tessellator, // the C tessellator
93  kVertexSize, //
94  polyline.points->data() + start_point_index, //
95  sizeof(Point), //
96  end_point_index - start_point_index //
97  );
98  }
99 
100  //----------------------------------------------------------------------------
101  /// Let's tessellate.
102  ///
103  auto result = ::tessTesselate(tessellator, // tessellator
104  ToTessWindingRule(fill_type), // winding
105  TESS_POLYGONS, // element type
106  kPolygonSize, // polygon size
107  kVertexSize, // vertex size
108  nullptr // normal (null is automatic)
109  );
110 
111  if (result != 1) {
113  }
114 
115  int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
116 
117  // We default to using a 16bit index buffer, but in cases where we generate
118  // more tessellated data than this can contain we need to fall back to
119  // dropping the index buffer entirely. Instead code could instead switch to
120  // a uint32 index buffer, but this is done for simplicity with the other
121  // fast path above.
122  if (element_item_count < USHRT_MAX) {
123  int vertex_item_count = tessGetVertexCount(tessellator);
124  auto vertices = tessGetVertices(tessellator);
125  auto elements = tessGetElements(tessellator);
126 
127  // libtess uses an int index internally due to usage of -1 as a sentinel
128  // value.
129  std::vector<uint16_t> indices(element_item_count);
130  for (int i = 0; i < element_item_count; i++) {
131  indices[i] = static_cast<uint16_t>(elements[i]);
132  }
133  if (!callback(vertices, vertex_item_count, indices.data(),
134  element_item_count)) {
136  }
137  } else {
138  std::vector<Point> points;
139  std::vector<float> data;
140 
141  int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize;
142  auto vertices = tessGetVertices(tessellator);
143  points.reserve(vertex_item_count);
144  for (int i = 0; i < vertex_item_count; i += 2) {
145  points.emplace_back(vertices[i], vertices[i + 1]);
146  }
147 
148  int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
149  auto elements = tessGetElements(tessellator);
150  data.reserve(element_item_count);
151  for (int i = 0; i < element_item_count; i++) {
152  data.emplace_back(points[elements[i]].x);
153  data.emplace_back(points[elements[i]].y);
154  }
155  if (!callback(data.data(), element_item_count, nullptr, 0u)) {
157  }
158  }
159 
161 }
162 
163 void DestroyTessellator(TESStesselator* tessellator) {
164  if (tessellator != nullptr) {
165  ::tessDeleteTess(tessellator);
166  }
167 }
168 
169 } // namespace impeller
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:54
FillType GetFillType() const
Definition: path.cc:110
Polyline CreatePolyline(Scalar scale, Polyline::PointBufferPtr point_buffer=std::make_unique< std::vector< Point >>(), Polyline::ReclaimPointBufferCallback reclaim=nullptr) const
Definition: path.cc:355
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.
TessellatorLibtess::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.
int32_t x
static void * HeapRealloc(void *userData, void *ptr, unsigned int size)
float Scalar
Definition: scalar.h:18
void DestroyTessellator(TESStesselator *tessellator)
static void * HeapAlloc(void *userData, unsigned int size)
FillType
Definition: path.h:32
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::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:67