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>

Classes

class  EllipticalVertexGenerator
 The |VertexGenerator| implementation common to all shapes that are based on a polygonal representation of an ellipse. More...
 
class  VertexGenerator
 An object which produces a list of vertices as |Point|s that tessellate a previously provided shape and delivers the vertices through a |TessellatedVertexProc| callback. More...
 

Public Types

enum  Result {
  Result::kSuccess,
  Result::kInputError,
  Result::kTessellationError
}
 
using TessellatedVertexProc = std::function< void(const Point &p)>
 A callback function for a |VertexGenerator| to deliver the vertices it computes as |Point| objects. More...
 

Public Member Functions

 Tessellator ()
 
virtual ~Tessellator ()
 
VertexBuffer TessellateConvex (const Path &path, HostBuffer &host_buffer, Scalar tolerance)
 Given a convex path, create a triangle fan structure. More...
 
Path::Polyline CreateTempPolyline (const Path &path, Scalar tolerance)
 Create a temporary polyline. Only one per-process can exist at a time. More...
 
EllipticalVertexGenerator FilledCircle (const Matrix &view_transform, const Point &center, Scalar radius)
 Create a |VertexGenerator| that can produce vertices for a filled circle of the given radius around the given center with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. More...
 
EllipticalVertexGenerator StrokedCircle (const Matrix &view_transform, const Point &center, Scalar radius, Scalar half_width)
 Create a |VertexGenerator| that can produce vertices for a stroked circle of the given radius and half_width around the given shared center with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. The outer edge of the stroked circle is generated at (radius + half_width) and the inner edge is generated at (radius - half_width). More...
 
EllipticalVertexGenerator RoundCapLine (const Matrix &view_transform, const Point &p0, const Point &p1, Scalar radius)
 Create a |VertexGenerator| that can produce vertices for a line with round end caps of the given radius with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. More...
 
EllipticalVertexGenerator FilledEllipse (const Matrix &view_transform, const Rect &bounds)
 Create a |VertexGenerator| that can produce vertices for a filled ellipse inscribed within the given bounds with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. More...
 
EllipticalVertexGenerator FilledRoundRect (const Matrix &view_transform, const Rect &bounds, const Size &radii)
 Create a |VertexGenerator| that can produce vertices for a filled round rect within the given bounds and corner radii with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. More...
 

Static Public Member Functions

static void TessellateConvexInternal (const Path &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
 

Static Public Attributes

static constexpr Scalar kCircleTolerance = 0.1f
 The pixel tolerance used by the algorighm to determine how many divisions to create for a circle. More...
 

Protected Attributes

std::unique_ptr< std::vector< Point > > point_buffer_
 Used for polyline generation. More...
 
std::unique_ptr< std::vector< uint16_t > > index_buffer_
 

Detailed Description

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

Also contains functionality for optimized generation of circles and ellipses.

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

Definition at line 31 of file tessellator.h.

Member Typedef Documentation

◆ TessellatedVertexProc

using impeller::Tessellator::TessellatedVertexProc = std::function<void(const Point& p)>

A callback function for a |VertexGenerator| to deliver the vertices it computes as |Point| objects.

Definition at line 78 of file tessellator.h.

Member Enumeration Documentation

◆ Result

Enumerator
kSuccess 
kInputError 
kTessellationError 

Definition at line 70 of file tessellator.h.

70  {
71  kSuccess,
72  kInputError,
73  kTessellationError,
74  };

Constructor & Destructor Documentation

◆ Tessellator()

impeller::Tessellator::Tessellator ( )

Definition at line 9 of file tessellator.cc.

10  : point_buffer_(std::make_unique<std::vector<Point>>()),
11  index_buffer_(std::make_unique<std::vector<uint16_t>>()) {
12  point_buffer_->reserve(2048);
13  index_buffer_->reserve(2048);
14 }

References index_buffer_, and point_buffer_.

◆ ~Tessellator()

impeller::Tessellator::~Tessellator ( )
virtualdefault

Member Function Documentation

◆ CreateTempPolyline()

Path::Polyline impeller::Tessellator::CreateTempPolyline ( const Path path,
Scalar  tolerance 
)

Create a temporary polyline. Only one per-process can exist at a time.

The tessellator itself is not a thread safe class and should only be used from the raster thread.

Definition at line 18 of file tessellator.cc.

19  {
20  FML_DCHECK(point_buffer_);
21  point_buffer_->clear();
22  auto polyline =
23  path.CreatePolyline(tolerance, std::move(point_buffer_),
24  [this](Path::Polyline::PointBufferPtr point_buffer) {
25  point_buffer_ = std::move(point_buffer);
26  });
27  return polyline;
28 }

References impeller::Path::CreatePolyline(), point_buffer_, and polyline.

◆ FilledCircle()

EllipticalVertexGenerator impeller::Tessellator::FilledCircle ( const Matrix view_transform,
const Point center,
Scalar  radius 
)

Create a |VertexGenerator| that can produce vertices for a filled circle of the given radius around the given center with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform.

Note that the view transform is only used to choose the number of sample points to use per quarter circle and the returned points are not transformed by it, instead they are relative to the coordinate space of the center point.

Definition at line 237 of file tessellator.cc.

240  {
241  auto divisions =
242  ComputeQuadrantDivisions(view_transform.GetMaxBasisLength() * radius);
243  return EllipticalVertexGenerator(Tessellator::GenerateFilledCircle,
244  GetTrigsForDivisions(divisions),
246  {
247  .reference_centers = {center, center},
248  .radii = {radius, radius},
249  .half_width = -1.0f,
250  });
251 }

References impeller::ComputeQuadrantDivisions(), and impeller::Matrix::GetMaxBasisLength().

◆ FilledEllipse()

EllipticalVertexGenerator impeller::Tessellator::FilledEllipse ( const Matrix view_transform,
const Rect bounds 
)

Create a |VertexGenerator| that can produce vertices for a filled ellipse inscribed within the given bounds with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform.

Note that the view transform is only used to choose the number of sample points to use per quarter circle and the returned points are not transformed by it, instead they are relative to the coordinate space of the bounds.

Definition at line 297 of file tessellator.cc.

299  {
300  if (bounds.IsSquare()) {
301  return FilledCircle(view_transform, bounds.GetCenter(),
302  bounds.GetWidth() * 0.5f);
303  }
304  auto max_radius = bounds.GetSize().MaxDimension();
305  auto divisions =
306  ComputeQuadrantDivisions(view_transform.GetMaxBasisLength() * max_radius);
307  auto center = bounds.GetCenter();
308  return EllipticalVertexGenerator(Tessellator::GenerateFilledEllipse,
309  GetTrigsForDivisions(divisions),
311  {
312  .reference_centers = {center, center},
313  .radii = bounds.GetSize() * 0.5f,
314  .half_width = -1.0f,
315  });
316 }

References impeller::ComputeQuadrantDivisions(), impeller::TRect< T >::GetCenter(), impeller::Matrix::GetMaxBasisLength(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetWidth(), and impeller::TRect< T >::IsSquare().

◆ FilledRoundRect()

EllipticalVertexGenerator impeller::Tessellator::FilledRoundRect ( const Matrix view_transform,
const Rect bounds,
const Size radii 
)

Create a |VertexGenerator| that can produce vertices for a filled round rect within the given bounds and corner radii with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform.

Note that the view transform is only used to choose the number of sample points to use per quarter circle and the returned points are not transformed by it, instead they are relative to the coordinate space of the bounds.

Definition at line 318 of file tessellator.cc.

321  {
322  if (radii.width * 2 < bounds.GetWidth() ||
323  radii.height * 2 < bounds.GetHeight()) {
324  auto max_radius = radii.MaxDimension();
325  auto divisions = ComputeQuadrantDivisions(
326  view_transform.GetMaxBasisLength() * max_radius);
327  auto upper_left = bounds.GetLeftTop() + radii;
328  auto lower_right = bounds.GetRightBottom() - radii;
329  return EllipticalVertexGenerator(Tessellator::GenerateFilledRoundRect,
330  GetTrigsForDivisions(divisions),
332  {
333  .reference_centers =
334  {
335  upper_left,
336  lower_right,
337  },
338  .radii = radii,
339  .half_width = -1.0f,
340  });
341  } else {
342  return FilledEllipse(view_transform, bounds);
343  }
344 }

References impeller::ComputeQuadrantDivisions(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeftTop(), impeller::Matrix::GetMaxBasisLength(), impeller::TRect< T >::GetRightBottom(), impeller::TRect< T >::GetWidth(), impeller::TSize< T >::height, impeller::TSize< T >::MaxDimension(), and impeller::TSize< T >::width.

◆ RoundCapLine()

EllipticalVertexGenerator impeller::Tessellator::RoundCapLine ( const Matrix view_transform,
const Point p0,
const Point p1,
Scalar  radius 
)

Create a |VertexGenerator| that can produce vertices for a line with round end caps of the given radius with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform.

Note that the view transform is only used to choose the number of sample points to use per quarter circle and the returned points are not transformed by it, instead they are relative to the coordinate space of the two points.

Definition at line 274 of file tessellator.cc.

278  {
279  auto along = p1 - p0;
280  auto length = along.GetLength();
281  if (length > kEhCloseEnough) {
282  auto divisions =
283  ComputeQuadrantDivisions(view_transform.GetMaxBasisLength() * radius);
284  return EllipticalVertexGenerator(Tessellator::GenerateRoundCapLine,
285  GetTrigsForDivisions(divisions),
287  {
288  .reference_centers = {p0, p1},
289  .radii = {radius, radius},
290  .half_width = -1.0f,
291  });
292  } else {
293  return FilledCircle(view_transform, p0, radius);
294  }
295 }

References impeller::ComputeQuadrantDivisions(), impeller::TPoint< T >::GetLength(), impeller::Matrix::GetMaxBasisLength(), and impeller::kEhCloseEnough.

◆ StrokedCircle()

EllipticalVertexGenerator impeller::Tessellator::StrokedCircle ( const Matrix view_transform,
const Point center,
Scalar  radius,
Scalar  half_width 
)

Create a |VertexGenerator| that can produce vertices for a stroked circle of the given radius and half_width around the given shared center with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. The outer edge of the stroked circle is generated at (radius + half_width) and the inner edge is generated at (radius - half_width).

Note that the view transform is only used to choose the number of sample points to use per quarter circle and the returned points are not transformed by it, instead they are relative to the coordinate space of the center point.

Definition at line 253 of file tessellator.cc.

257  {
258  if (half_width > 0) {
259  auto divisions = ComputeQuadrantDivisions(
260  view_transform.GetMaxBasisLength() * radius + half_width);
261  return EllipticalVertexGenerator(Tessellator::GenerateStrokedCircle,
262  GetTrigsForDivisions(divisions),
264  {
265  .reference_centers = {center, center},
266  .radii = {radius, radius},
267  .half_width = half_width,
268  });
269  } else {
270  return FilledCircle(view_transform, center, radius);
271  }
272 }

References impeller::ComputeQuadrantDivisions(), and impeller::Matrix::GetMaxBasisLength().

◆ TessellateConvex()

VertexBuffer impeller::Tessellator::TessellateConvex ( const Path path,
HostBuffer host_buffer,
Scalar  tolerance 
)

Given a convex path, create a triangle fan structure.

Parameters
[in]pathThe path to tessellate.
[in]toleranceThe 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.
Returns
A point vector containing the vertices in triangle strip format.
Parameters
[in]host_bufferThe host buffer for allocation of vertices/index data.
Returns
A vertex buffer containing all data from the provided curve.

Definition at line 30 of file tessellator.cc.

32  {
33  FML_DCHECK(point_buffer_);
34  FML_DCHECK(index_buffer_);
36 
37  if (point_buffer_->empty()) {
38  return VertexBuffer{
39  .vertex_buffer = {},
40  .index_buffer = {},
41  .vertex_count = 0u,
42  .index_type = IndexType::k16bit,
43  };
44  }
45 
46  BufferView vertex_buffer = host_buffer.Emplace(
47  point_buffer_->data(), sizeof(Point) * point_buffer_->size(),
48  alignof(Point));
49 
50  BufferView index_buffer = host_buffer.Emplace(
51  index_buffer_->data(), sizeof(uint16_t) * index_buffer_->size(),
52  alignof(uint16_t));
53 
54  return VertexBuffer{
55  .vertex_buffer = std::move(vertex_buffer),
56  .index_buffer = std::move(index_buffer),
57  .vertex_count = index_buffer_->size(),
58  .index_type = IndexType::k16bit,
59  };
60 }

References impeller::HostBuffer::Emplace(), index_buffer_, impeller::k16bit, point_buffer_, TessellateConvexInternal(), and impeller::VertexBuffer::vertex_buffer.

◆ TessellateConvexInternal()

void impeller::Tessellator::TessellateConvexInternal ( const Path path,
std::vector< Point > &  point_buffer,
std::vector< uint16_t > &  index_buffer,
Scalar  tolerance 
)
static

Visible for testing.

This method only exists for the ease of benchmarking without using the real allocator needed by the [host_buffer].

Definition at line 62 of file tessellator.cc.

65  {
66  point_buffer.clear();
67  index_buffer.clear();
68 
69  VertexWriter writer(point_buffer, index_buffer);
70 
71  path.WritePolyline(tolerance, writer);
72 }

References impeller::Path::WritePolyline().

Referenced by impeller::BM_Convex(), TessellateConvex(), and impeller::testing::TEST().

Member Data Documentation

◆ index_buffer_

std::unique_ptr<std::vector<uint16_t> > impeller::Tessellator::index_buffer_
protected

Definition at line 288 of file tessellator.h.

Referenced by TessellateConvex(), and Tessellator().

◆ kCircleTolerance

constexpr Scalar impeller::Tessellator::kCircleTolerance = 0.1f
staticconstexpr

The pixel tolerance used by the algorighm to determine how many divisions to create for a circle.

No point on the polygon of vertices should deviate from the true circle by more than this tolerance.

Definition at line 214 of file tessellator.h.

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

◆ point_buffer_

std::unique_ptr<std::vector<Point> > impeller::Tessellator::point_buffer_
protected

Used for polyline generation.

Definition at line 287 of file tessellator.h.

Referenced by CreateTempPolyline(), TessellateConvex(), and Tessellator().


The documentation for this class was generated from the following files:
impeller::EllipticalVertexGenerator
Tessellator::EllipticalVertexGenerator EllipticalVertexGenerator
Definition: tessellator.cc:224
polyline
const Path::Polyline & polyline
Definition: stroke_path_geometry.cc:303
impeller::IndexType::k16bit
@ k16bit
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:56
impeller::Tessellator::FilledCircle
EllipticalVertexGenerator FilledCircle(const Matrix &view_transform, const Point &center, Scalar radius)
Create a |VertexGenerator| that can produce vertices for a filled circle of the given radius around t...
Definition: tessellator.cc:237
impeller::ComputeQuadrantDivisions
static size_t ComputeQuadrantDivisions(Scalar pixel_radius)
Definition: tessellator.cc:144
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::Point
TPoint< Scalar > Point
Definition: point.h:322
impeller::Tessellator::point_buffer_
std::unique_ptr< std::vector< Point > > point_buffer_
Used for polyline generation.
Definition: tessellator.h:287
impeller::Tessellator::FilledEllipse
EllipticalVertexGenerator FilledEllipse(const Matrix &view_transform, const Rect &bounds)
Create a |VertexGenerator| that can produce vertices for a filled ellipse inscribed within the given ...
Definition: tessellator.cc:297
impeller::Tessellator::TessellateConvexInternal
static void TessellateConvexInternal(const Path &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
Definition: tessellator.cc:62
impeller::Tessellator::index_buffer_
std::unique_ptr< std::vector< uint16_t > > index_buffer_
Definition: tessellator.h:288
impeller::Path::Polyline::PointBufferPtr
std::unique_ptr< std::vector< Point > > PointBufferPtr
Definition: path.h:98