Flutter Impeller
impeller::Tessellator Class Reference

A utility that generates triangles of the specified fill type given a polyline. This happens on the CPU. More...

#include <tessellator.h>

Public Types

enum  Result {
  Result::kSuccess,
  Result::kInputError,
  Result::kTessellationError
}
 
using BuilderCallback = std::function< bool(const float *vertices, size_t vertices_count, const uint16_t *indices, size_t indices_count)>
 A callback that returns the results of the tessellation. More...
 

Public Member Functions

 Tessellator ()
 
 ~Tessellator ()
 
Tessellator::Result Tessellate (FillType fill_type, const Path::Polyline &polyline, const BuilderCallback &callback) const
 Generates filled triangles from the polyline. A callback is invoked once for the entire tessellation. More...
 

Detailed Description

A utility that generates triangles of the specified fill type given a polyline. This happens on the CPU.

Definition at line 35 of file tessellator.h.

Member Typedef Documentation

◆ BuilderCallback

using impeller::Tessellator::BuilderCallback = std::function<bool(const float* vertices, size_t vertices_count, const uint16_t* indices, size_t indices_count)>

A callback that returns the results of the tessellation.

   The index buffer may not be populated, in which case [indices] will
   be nullptr and indices_count will be 0. 

Definition at line 54 of file tessellator.h.

Member Enumeration Documentation

◆ Result

Enumerator
kSuccess 
kInputError 
kTessellationError 

Definition at line 37 of file tessellator.h.

37  {
38  kSuccess,
39  kInputError,
40  kTessellationError,
41  };

Constructor & Destructor Documentation

◆ Tessellator()

impeller::Tessellator::Tessellator ( )

Definition at line 34 of file tessellator.cc.

34  : c_tessellator_(nullptr, &DestroyTessellator) {
35  TESSalloc alloc = kAlloc;
36  {
37  // libTess2 copies the TESSalloc despite the non-const argument.
38  CTessellator tessellator(::tessNewTess(&alloc), &DestroyTessellator);
39  c_tessellator_ = std::move(tessellator);
40  }
41 }

References impeller::DestroyTessellator(), and impeller::kAlloc.

◆ ~Tessellator()

impeller::Tessellator::~Tessellator ( )
default

Member Function Documentation

◆ Tessellate()

Tessellator::Result impeller::Tessellator::Tessellate ( FillType  fill_type,
const Path::Polyline polyline,
const BuilderCallback callback 
) const

Generates filled triangles from the polyline. A callback is invoked once for the entire tessellation.

Parameters
[in]fill_typeThe fill rule to use when filling.
[in]polylineThe polyline
[in]callbackThe callback, return false to indicate failure.
Returns
The result status of the tessellation.

Feed contour information to the tessellator.

Let's tessellate.

Definition at line 61 of file tessellator.cc.

64  {
65  if (!callback) {
66  return Result::kInputError;
67  }
68 
69  if (polyline.points.empty()) {
70  return Result::kInputError;
71  }
72 
73  auto tessellator = c_tessellator_.get();
74  if (!tessellator) {
76  }
77 
78  constexpr int kVertexSize = 2;
79  constexpr int kPolygonSize = 3;
80 
81  //----------------------------------------------------------------------------
82  /// Feed contour information to the tessellator.
83  ///
84  static_assert(sizeof(Point) == 2 * sizeof(float));
85  for (size_t contour_i = 0; contour_i < polyline.contours.size();
86  contour_i++) {
87  size_t start_point_index, end_point_index;
88  std::tie(start_point_index, end_point_index) =
89  polyline.GetContourPointBounds(contour_i);
90 
91  ::tessAddContour(tessellator, // the C tessellator
92  kVertexSize, //
93  polyline.points.data() + start_point_index, //
94  sizeof(Point), //
95  end_point_index - start_point_index //
96  );
97  }
98 
99  //----------------------------------------------------------------------------
100  /// Let's tessellate.
101  ///
102  auto result = ::tessTesselate(tessellator, // tessellator
103  ToTessWindingRule(fill_type), // winding
104  TESS_POLYGONS, // element type
105  kPolygonSize, // polygon size
106  kVertexSize, // vertex size
107  nullptr // normal (null is automatic)
108  );
109 
110  if (result != 1) {
112  }
113 
114  int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
115 
116  // We default to using a 16bit index buffer, but in cases where we generate
117  // more tessellated data than this can contain we need to fall back to
118  // dropping the index buffer entirely. Instead code could instead switch to
119  // a uint32 index buffer, but this is done for simplicity with the other
120  // fast path above.
121  if (element_item_count < USHRT_MAX) {
122  int vertex_item_count = tessGetVertexCount(tessellator);
123  auto vertices = tessGetVertices(tessellator);
124  auto elements = tessGetElements(tessellator);
125 
126  // libtess uses an int index internally due to usage of -1 as a sentinel
127  // value.
128  std::vector<uint16_t> indices(element_item_count);
129  for (int i = 0; i < element_item_count; i++) {
130  indices[i] = static_cast<uint16_t>(elements[i]);
131  }
132  if (!callback(vertices, vertex_item_count, indices.data(),
133  element_item_count)) {
134  return Result::kInputError;
135  }
136  } else {
137  std::vector<Point> points;
138  std::vector<float> data;
139 
140  int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize;
141  auto vertices = tessGetVertices(tessellator);
142  points.reserve(vertex_item_count);
143  for (int i = 0; i < vertex_item_count; i += 2) {
144  points.emplace_back(vertices[i], vertices[i + 1]);
145  }
146 
147  int element_item_count = tessGetElementCount(tessellator) * kPolygonSize;
148  auto elements = tessGetElements(tessellator);
149  data.reserve(element_item_count);
150  for (int i = 0; i < element_item_count; i++) {
151  data.emplace_back(points[elements[i]].x);
152  data.emplace_back(points[elements[i]].y);
153  }
154  if (!callback(data.data(), element_item_count, nullptr, 0u)) {
155  return Result::kInputError;
156  }
157  }
158 
159  return Result::kSuccess;
160 }

References impeller::Path::Polyline::contours, impeller::Path::Polyline::GetContourPointBounds(), kInputError, kSuccess, kTessellationError, impeller::Path::Polyline::points, and impeller::ToTessWindingRule().

Referenced by impeller::BM_Polyline(), impeller::Tessellate(), impeller::testing::TEST(), and impeller::testing::TEST_P().


The documentation for this class was generated from the following files:
impeller::kAlloc
static const TESSalloc kAlloc
Definition: tessellator.cc:24
impeller::Tessellator::Result::kInputError
@ kInputError
impeller::Point
TPoint< Scalar > Point
Definition: point.h:306
impeller::Tessellator::Result::kTessellationError
@ kTessellationError
impeller::DestroyTessellator
void DestroyTessellator(TESStesselator *tessellator)
Definition: tessellator.cc:162
impeller::Tessellator::Result::kSuccess
@ kSuccess
impeller::ToTessWindingRule
static int ToTessWindingRule(FillType fill_type)
Definition: tessellator.cc:45
impeller::CTessellator
std::unique_ptr< TESStesselator, decltype(&DestroyTessellator)> CTessellator
Definition: tessellator.h:22