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 
8 #include "third_party/libtess2/Include/tesselator.h"
9 
10 namespace impeller {
11 
12 static void* HeapAlloc(void* userData, unsigned int size) {
13  return malloc(size);
14 }
15 
16 static void* HeapRealloc(void* userData, void* ptr, unsigned int size) {
17  return realloc(ptr, size);
18 }
19 
20 static void HeapFree(void* userData, void* ptr) {
21  free(ptr);
22 }
23 
24 // Note: these units are "number of entities" for bucket size and not in KB.
25 static const TESSalloc kAlloc = {
26  HeapAlloc, HeapRealloc, HeapFree, 0, /* =userData */
27  16, /* =meshEdgeBucketSize */
28  16, /* =meshVertexBucketSize */
29  16, /* =meshFaceBucketSize */
30  16, /* =dictNodeBucketSize */
31  16, /* =regionBucketSize */
32  0 /* =extraVertices */
33 };
34 
36  : c_tessellator_(nullptr, &DestroyTessellator) {
37  TESSalloc alloc = kAlloc;
38  {
39  // libTess2 copies the TESSalloc despite the non-const argument.
40  CTessellator tessellator(::tessNewTess(&alloc), &DestroyTessellator);
41  c_tessellator_ = std::move(tessellator);
42  }
43 }
44 
46 
47 static int ToTessWindingRule(FillType fill_type) {
48  switch (fill_type) {
49  case FillType::kOdd:
50  return TESS_WINDING_ODD;
51  case FillType::kNonZero:
52  return TESS_WINDING_NONZERO;
53  }
54  return TESS_WINDING_ODD;
55 }
56 
57 namespace {
58 
59 class Polyline : public impeller::PathTessellator::VertexWriter {
60  public:
61  struct Contour {
62  const size_t start;
63  const size_t end;
64 
65  size_t size() const { return end - start; }
66  };
67 
68  void Write(Point point) override { points.emplace_back(point); }
69 
70  void EndContour() override {
71  size_t contour_end = points.size();
72  contours.push_back({contour_start_, contour_end});
73  contour_start_ = contour_end;
74  }
75 
76  std::vector<Point> points;
77  std::vector<Contour> contours;
78 
79  private:
80  size_t contour_start_ = 0u;
81 };
82 
83 } // namespace
84 
86  const PathSource& source,
87  Scalar tolerance,
88  const BuilderCallback& callback) {
89  if (!callback) {
91  }
92 
93  Polyline polyline;
94  PathTessellator::PathToFilledVertices(source, polyline, tolerance);
95 
96  auto fill_type = source.GetFillType();
97 
98  if (polyline.points.empty()) {
100  }
101 
102  auto tessellator = c_tessellator_.get();
103  if (!tessellator) {
105  }
106 
107  constexpr int kVertexSize = 2;
108  constexpr int kPolygonSize = 3;
109 
110  //----------------------------------------------------------------------------
111  /// Feed contour information to the tessellator.
112  ///
113  static_assert(sizeof(Point) == 2 * sizeof(float));
114  for (auto contour : polyline.contours) {
115  ::tessAddContour(tessellator, // the C tessellator
116  kVertexSize, //
117  polyline.points.data() + contour.start, //
118  sizeof(Point), //
119  contour.size() //
120  );
121  }
122 
123  //----------------------------------------------------------------------------
124  /// Let's tessellate.
125  ///
126  auto result = ::tessTesselate(tessellator, // tessellator
127  ToTessWindingRule(fill_type), // winding
128  TESS_POLYGONS, // element type
129  kPolygonSize, // polygon size
130  kVertexSize, // vertex size
131  nullptr // normal (null is automatic)
132  );
133 
134  if (result != 1) {
136  }
137 
138  int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
139 
140  // We default to using a 16bit index buffer, but in cases where we generate
141  // more tessellated data than this can contain we need to fall back to
142  // dropping the index buffer entirely. Instead code could instead switch to
143  // a uint32 index buffer, but this is done for simplicity with the other
144  // fast path above.
145  if (element_item_count < USHRT_MAX) {
146  int vertex_item_count = tessGetVertexCount(tessellator);
147  auto vertices = tessGetVertices(tessellator);
148  auto elements = tessGetElements(tessellator);
149 
150  // libtess uses an int index internally due to usage of -1 as a sentinel
151  // value.
152  std::vector<uint16_t> indices(element_item_count);
153  for (int i = 0; i < element_item_count; i++) {
154  indices[i] = static_cast<uint16_t>(elements[i]);
155  }
156  if (!callback(vertices, vertex_item_count, indices.data(),
157  element_item_count)) {
159  }
160  } else {
161  std::vector<Point> points;
162  std::vector<float> data;
163 
164  int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize;
165  auto vertices = tessGetVertices(tessellator);
166  points.reserve(vertex_item_count);
167  for (int i = 0; i < vertex_item_count; i += 2) {
168  points.emplace_back(vertices[i], vertices[i + 1]);
169  }
170 
171  int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
172  auto elements = tessGetElements(tessellator);
173  data.reserve(element_item_count);
174  for (int i = 0; i < element_item_count; i++) {
175  data.emplace_back(points[elements[i]].x);
176  data.emplace_back(points[elements[i]].y);
177  }
178  if (!callback(data.data(), element_item_count, nullptr, 0u)) {
180  }
181  }
182 
184 }
185 
186 void DestroyTessellator(TESStesselator* tessellator) {
187  if (tessellator != nullptr) {
188  ::tessDeleteTess(tessellator);
189  }
190 }
191 
192 } // namespace impeller
virtual FillType GetFillType() const =0
An interface for generating a multi contour polyline as a triangle strip.
static void PathToFilledVertices(const PathSource &source, VertexWriter &writer, Scalar scale)
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 PathSource &source, 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:19
void DestroyTessellator(TESStesselator *tessellator)
static void * HeapAlloc(void *userData, unsigned int size)
TPoint< Scalar > Point
Definition: point.h:327
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 size_t start
const size_t end
std::vector< Point > points
std::vector< Contour > contours
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:68