| Flutter Impeller |

Public Types | Public Member Functions | List of all members
impeller::TessellatorLibtess Class Reference

An extended tessellator that offers arbitrary/concave tessellation via the libtess2 library. More...

`#include <tessellator_libtess.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
| TessellatorLibtess ()
| ~TessellatorLibtess ()
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. More...

## Detailed Description

An extended tessellator that offers arbitrary/concave tessellation via the libtess2 library.

This object is not thread safe, and its methods must not be called from multiple threads.

Definition at line 29 of file tessellator_libtess.h.

## Member Typedef Documentation

## ◆ BuilderCallback

using impeller::TessellatorLibtess::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 48 of file tessellator_libtess.h.

## Member Enumeration Documentation

## ◆ Result

enum impeller::TessellatorLibtess::Result
| strong

Enumerator
kSuccess |
kInputError |
kTessellationError |

Definition at line 35 of file tessellator_libtess.h.

35 {
36 kSuccess,
37 kInputError,
38 kTessellationError,
39 };

## Constructor & Destructor Documentation

## ◆ TessellatorLibtess()

impeller::TessellatorLibtess::TessellatorLibtess | ( |  | ) |

Definition at line 34 of file tessellator_libtess.cc.

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 }

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

## ◆ ~TessellatorLibtess()

impeller::TessellatorLibtess::~TessellatorLibtess | ( |  | ) |
| default

## Member Function Documentation

## ◆ Tessellate()

TessellatorLibtess::Result impeller::TessellatorLibtess::Tessellate | ( | const Path & | path,
|  | Scalar | tolerance,
|  | const BuilderCallback & | callback
| ) |  |

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

Parameters

  [in] | path | The path to tessellate.
  [in] | tolerance | The tolerance value for conversion of the path to a polyline. This value is often derived from the Matrix::GetMaxBasisLength of the CTM applied to the path for rendering.
  [in] | callback | The 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 56 of file tessellator_libtess.cc.

59 {
60 if (!callback) {
61 return TessellatorLibtess::Result::kInputError;
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()) {
71 return TessellatorLibtess::Result::kInputError;
72 }
73
74 auto tessellator = c_tessellator_.get();
75 if (!tessellator) {
76 return TessellatorLibtess::Result::kTessellationError;
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) {
112 return TessellatorLibtess::Result::kTessellationError;
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)) {
135 return TessellatorLibtess::Result::kInputError;
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)) {
156 return TessellatorLibtess::Result::kInputError;
157 }
158 }
159
160 return TessellatorLibtess::Result::kSuccess;
161 }

References impeller::Path::CreatePolyline(), data, impeller::Path::GetFillType(), kInputError, kSuccess, kTessellationError, polyline, and impeller::ToTessWindingRule().

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

The documentation for this class was generated from the following files:

- impeller/tessellator/tessellator_libtess.h
- impeller/tessellator/tessellator_libtess.cc

impeller::kAlloc
static const TESSalloc kAlloc
Definition: tessellator_libtess.cc:24
impeller::TessellatorLibtess::Result::kTessellationError
@ kTessellationError
polyline
const Path::Polyline & polyline
Definition: stroke_path_geometry.cc:296
impeller::TessellatorLibtess::Result::kInputError
@ kInputError
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::DestroyTessellator
void DestroyTessellator(TESStesselator *tessellator)
Definition: tessellator_libtess.cc:163
impeller::ToTessWindingRule
static int ToTessWindingRule(FillType fill_type)
Definition: tessellator_libtess.cc:46
impeller::TessellatorLibtess::Result::kSuccess
@ kSuccess
impeller::CTessellator
std::unique_ptr< TESStesselator, decltype(&DestroyTessellator)> CTessellator
Definition: tessellator_libtess.h:20