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  ArcVertexGenerator
 The |VertexGenerator| implementation common to all shapes that are based on a polygonal representation of an ellipse. More...
 
class  EllipticalVertexGenerator
 The |VertexGenerator| implementation common to all shapes that are based on a polygonal representation of an ellipse. More...
 
class  Trigs
 
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 class  Result {
  kSuccess ,
  kInputError ,
  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 PathSource &path, HostBuffer &data_host_buffer, HostBuffer &indexes_host_buffer, Scalar tolerance, bool supports_primitive_restart=false, bool supports_triangle_fan=false)
 Given a convex path, create a triangle fan structure. 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...
 
ArcVertexGenerator FilledArc (const Matrix &view_transform, const Arc &arc, bool supports_triangle_fans)
 Create a |VertexGenerator| that can produce vertices for a stroked arc inscribed within the given oval_bounds with the given stroke half_width with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. The outer edge of the stroked arc is generated at (radius + half_width) and the inner edge is generated at (radius - half_width). More...
 
ArcVertexGenerator StrokedArc (const Matrix &view_transform, const Arc &arc, Cap cap, Scalar half_width)
 Create a |VertexGenerator| that can produce vertices for a stroked arc inscribed within the given oval_bounds with the given stroke half_width with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. The outer edge of the stroked arc 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...
 
std::vector< Point > & GetStrokePointCache ()
 Retrieve a pre-allocated arena of kPointArenaSize points. More...
 
Trigs GetTrigsForDeviceRadius (Scalar pixel_radius)
 

Static Public Member Functions

static void TessellateConvexInternal (const PathSource &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_
 
std::vector< Pointstroke_points_
 Used for stroke path generation. More...
 

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 37 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 97 of file tessellator.h.

Member Enumeration Documentation

◆ Result

Enumerator
kSuccess 
kInputError 
kTessellationError 

Definition at line 89 of file tessellator.h.

89  {
90  kSuccess,
91  kInputError,
92  kTessellationError,
93  };

Constructor & Destructor Documentation

◆ Tessellator()

impeller::Tessellator::Tessellator ( )

Definition at line 296 of file tessellator.cc.

297  : point_buffer_(std::make_unique<std::vector<Point>>()),
298  index_buffer_(std::make_unique<std::vector<uint16_t>>()),
300  point_buffer_->reserve(2048);
301  index_buffer_->reserve(2048);
302 }
std::vector< Point > stroke_points_
Used for stroke path generation.
Definition: tessellator.h:383
std::unique_ptr< std::vector< Point > > point_buffer_
Used for polyline generation.
Definition: tessellator.h:380
std::unique_ptr< std::vector< uint16_t > > index_buffer_
Definition: tessellator.h:381
static constexpr size_t kPointArenaSize
The size of the point arena buffer stored on the tessellator.
Definition: tessellator.h:25

References index_buffer_, and point_buffer_.

◆ ~Tessellator()

impeller::Tessellator::~Tessellator ( )
virtualdefault

Member Function Documentation

◆ FilledArc()

ArcVertexGenerator impeller::Tessellator::FilledArc ( const Matrix view_transform,
const Arc arc,
bool  supports_triangle_fans 
)

Create a |VertexGenerator| that can produce vertices for a stroked arc inscribed within the given oval_bounds with the given stroke half_width with enough polygon sub-divisions to provide reasonable fidelity when viewed under the given view transform. The outer edge of the stroked arc 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 oval bounds.

Definition at line 557 of file tessellator.cc.

559  {
560  size_t divisions = ComputeQuadrantDivisions(
561  view_transform.GetMaxBasisLengthXY() * arc.GetOvalSize().MaxDimension());
562 
563  return ArcVertexGenerator(
564  arc.ComputeIterations(divisions), GetTrigsForDivisions(divisions),
565  arc.GetOvalBounds(), arc.IncludeCenter(), supports_triangle_fans);
566 };
Tessellator::ArcVertexGenerator ArcVertexGenerator
Definition: tessellator.cc:440

References impeller::Arc::ComputeIterations(), impeller::Matrix::GetMaxBasisLengthXY(), impeller::Arc::GetOvalBounds(), impeller::Arc::GetOvalSize(), impeller::Arc::IncludeCenter(), and impeller::TSize< T >::MaxDimension().

◆ 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 453 of file tessellator.cc.

456  {
457  size_t divisions =
458  ComputeQuadrantDivisions(view_transform.GetMaxBasisLengthXY() * radius);
459  return EllipticalVertexGenerator(Tessellator::GenerateFilledCircle,
460  GetTrigsForDivisions(divisions),
462  {
463  .reference_centers = {center, center},
464  .radii = {radius, radius},
465  .half_width = -1.0f,
466  });
467 }
Tessellator::EllipticalVertexGenerator EllipticalVertexGenerator
Definition: tessellator.cc:439

References impeller::Matrix::GetMaxBasisLengthXY().

Referenced by FilledEllipse(), and RoundCapLine().

◆ 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 607 of file tessellator.cc.

609  {
610  if (bounds.IsSquare()) {
611  return FilledCircle(view_transform, bounds.GetCenter(),
612  bounds.GetWidth() * 0.5f);
613  }
614  auto max_radius = bounds.GetSize().MaxDimension();
615  auto divisions = ComputeQuadrantDivisions(
616  view_transform.GetMaxBasisLengthXY() * max_radius);
617  auto center = bounds.GetCenter();
618  return EllipticalVertexGenerator(Tessellator::GenerateFilledEllipse,
619  GetTrigsForDivisions(divisions),
621  {
622  .reference_centers = {center, center},
623  .radii = bounds.GetSize() * 0.5f,
624  .half_width = -1.0f,
625  });
626 }
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:453

References FilledCircle(), impeller::TRect< T >::GetCenter(), impeller::Matrix::GetMaxBasisLengthXY(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::IsSquare(), and impeller::kTriangleStrip.

Referenced by FilledRoundRect().

◆ 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 628 of file tessellator.cc.

631  {
632  if (radii.width * 2 < bounds.GetWidth() ||
633  radii.height * 2 < bounds.GetHeight()) {
634  auto max_radius = radii.MaxDimension();
635  auto divisions = ComputeQuadrantDivisions(
636  view_transform.GetMaxBasisLengthXY() * max_radius);
637  auto upper_left = bounds.GetLeftTop() + radii;
638  auto lower_right = bounds.GetRightBottom() - radii;
639  return EllipticalVertexGenerator(Tessellator::GenerateFilledRoundRect,
640  GetTrigsForDivisions(divisions),
642  {
643  .reference_centers =
644  {
645  upper_left,
646  lower_right,
647  },
648  .radii = radii,
649  .half_width = -1.0f,
650  });
651  } else {
652  return FilledEllipse(view_transform, bounds);
653  }
654 }
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:607

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

◆ GetStrokePointCache()

std::vector< Point > & impeller::Tessellator::GetStrokePointCache ( )

Retrieve a pre-allocated arena of kPointArenaSize points.

Definition at line 306 of file tessellator.cc.

306  {
307  return stroke_points_;
308 }

References stroke_points_.

◆ GetTrigsForDeviceRadius()

Tessellator::Trigs impeller::Tessellator::GetTrigsForDeviceRadius ( Scalar  pixel_radius)

Return a vector of Trig (cos, sin pairs) structs for a 90 degree circle quadrant of the specified pixel radius

Definition at line 310 of file tessellator.cc.

310  {
311  return GetTrigsForDivisions(ComputeQuadrantDivisions(pixel_radius));
312 }

Referenced by impeller::ArcStrokeGeometry::Dispatch(), impeller::StrokeRectGeometry::GetPositionBuffer(), impeller::StrokePathSegmentReceiver::RecordArc(), and impeller::testing::TEST().

◆ 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 584 of file tessellator.cc.

588  {
589  auto along = p1 - p0;
590  auto length = along.GetLength();
591  if (length > kEhCloseEnough) {
592  auto divisions =
593  ComputeQuadrantDivisions(view_transform.GetMaxBasisLengthXY() * radius);
594  return EllipticalVertexGenerator(Tessellator::GenerateRoundCapLine,
595  GetTrigsForDivisions(divisions),
597  {
598  .reference_centers = {p0, p1},
599  .radii = {radius, radius},
600  .half_width = -1.0f,
601  });
602  } else {
603  return FilledCircle(view_transform, p0, radius);
604  }
605 }
constexpr float kEhCloseEnough
Definition: constants.h:57

References FilledCircle(), impeller::TPoint< T >::GetLength(), impeller::Matrix::GetMaxBasisLengthXY(), impeller::kEhCloseEnough, and impeller::kTriangleStrip.

◆ StrokedArc()

ArcVertexGenerator impeller::Tessellator::StrokedArc ( const Matrix view_transform,
const Arc arc,
Cap  cap,
Scalar  half_width 
)

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

Note that the arc may not include the center and its bounds must be a perfect circle (width == height)

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 oval bounds.

Definition at line 568 of file tessellator.cc.

571  {
572  FML_DCHECK(half_width > 0);
573  FML_DCHECK(arc.IsPerfectCircle());
574  FML_DCHECK(!arc.IncludeCenter());
575  size_t divisions =
576  ComputeQuadrantDivisions(view_transform.GetMaxBasisLengthXY() *
577  (arc.GetOvalSize().MaxDimension() + half_width));
578 
579  return ArcVertexGenerator(arc.ComputeIterations(divisions),
580  GetTrigsForDivisions(divisions),
581  arc.GetOvalBounds(), half_width, cap);
582 }

References impeller::Arc::ComputeIterations(), impeller::Matrix::GetMaxBasisLengthXY(), impeller::Arc::GetOvalBounds(), impeller::Arc::GetOvalSize(), impeller::Arc::IncludeCenter(), impeller::Arc::IsPerfectCircle(), and impeller::TSize< T >::MaxDimension().

◆ 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 469 of file tessellator.cc.

473  {
474  if (half_width > 0) {
475  auto divisions = ComputeQuadrantDivisions(
476  view_transform.GetMaxBasisLengthXY() * radius + half_width);
477  return EllipticalVertexGenerator(Tessellator::GenerateStrokedCircle,
478  GetTrigsForDivisions(divisions),
480  {
481  .reference_centers = {center, center},
482  .radii = {radius, radius},
483  .half_width = half_width,
484  });
485  } else {
486  return FilledCircle(view_transform, center, radius);
487  }
488 }

References impeller::Matrix::GetMaxBasisLengthXY().

◆ TessellateConvex()

VertexBuffer impeller::Tessellator::TessellateConvex ( const PathSource path,
HostBuffer data_host_buffer,
HostBuffer indexes_host_buffer,
Scalar  tolerance,
bool  supports_primitive_restart = false,
bool  supports_triangle_fan = false 
)

Given a convex path, create a triangle fan structure.

Parameters
[in]pathThe path to tessellate.
[in]host_bufferThe host buffer for allocation of vertices/index data.
[in]toleranceThe tolerance value for conversion of the path to a polyline. This value is often derived from the Matrix::GetMaxBasisLengthXY of the CTM applied to the path for rendering.
Returns
A vertex buffer containing all data from the provided curve.

Definition at line 314 of file tessellator.cc.

319  {
320  if (supports_primitive_restart) {
321  // Primitive Restart.
322  const auto [point_count, contour_count] =
323  PathTessellator::CountFillStorage(path, tolerance);
324  BufferView point_buffer = data_host_buffer.Emplace(
325  nullptr, sizeof(Point) * point_count, alignof(Point));
326  BufferView index_buffer = indexes_host_buffer.Emplace(
327  nullptr, sizeof(uint16_t) * (point_count + contour_count),
328  alignof(uint16_t));
329 
330  if (supports_triangle_fan) {
331  FanPathVertexWriter writer(
332  reinterpret_cast<Point*>(point_buffer.GetBuffer()->OnGetContents() +
333  point_buffer.GetRange().offset),
334  reinterpret_cast<uint16_t*>(
335  index_buffer.GetBuffer()->OnGetContents() +
336  index_buffer.GetRange().offset));
337  PathTessellator::PathToFilledVertices(path, writer, tolerance);
338  FML_DCHECK(writer.GetPointCount() <= point_count);
339  FML_DCHECK(writer.GetIndexCount() <= (point_count + contour_count));
340  point_buffer.GetBuffer()->Flush(point_buffer.GetRange());
341  index_buffer.GetBuffer()->Flush(index_buffer.GetRange());
342 
343  return VertexBuffer{
344  .vertex_buffer = std::move(point_buffer),
345  .index_buffer = std::move(index_buffer),
346  .vertex_count = writer.GetIndexCount(),
347  .index_type = IndexType::k16bit,
348  };
349  } else {
350  StripPathVertexWriter writer(
351  reinterpret_cast<Point*>(point_buffer.GetBuffer()->OnGetContents() +
352  point_buffer.GetRange().offset),
353  reinterpret_cast<uint16_t*>(
354  index_buffer.GetBuffer()->OnGetContents() +
355  index_buffer.GetRange().offset));
356  PathTessellator::PathToFilledVertices(path, writer, tolerance);
357  FML_DCHECK(writer.GetPointCount() <= point_count);
358  FML_DCHECK(writer.GetIndexCount() <= (point_count + contour_count));
359  point_buffer.GetBuffer()->Flush(point_buffer.GetRange());
360  index_buffer.GetBuffer()->Flush(index_buffer.GetRange());
361 
362  return VertexBuffer{
363  .vertex_buffer = std::move(point_buffer),
364  .index_buffer = std::move(index_buffer),
365  .vertex_count = writer.GetIndexCount(),
366  .index_type = IndexType::k16bit,
367  };
368  }
369  }
370 
371  FML_DCHECK(point_buffer_);
372  FML_DCHECK(index_buffer_);
374 
375  if (point_buffer_->empty()) {
376  return VertexBuffer{
377  .vertex_buffer = {},
378  .index_buffer = {},
379  .vertex_count = 0u,
380  .index_type = IndexType::k16bit,
381  };
382  }
383 
384  BufferView vertex_buffer = data_host_buffer.Emplace(
385  point_buffer_->data(), sizeof(Point) * point_buffer_->size(),
386  alignof(Point));
387 
388  BufferView index_buffer = indexes_host_buffer.Emplace(
389  index_buffer_->data(), sizeof(uint16_t) * index_buffer_->size(),
390  alignof(uint16_t));
391 
392  return VertexBuffer{
393  .vertex_buffer = std::move(vertex_buffer),
394  .index_buffer = std::move(index_buffer),
395  .vertex_count = index_buffer_->size(),
396  .index_type = IndexType::k16bit,
397  };
398 }
static void PathToFilledVertices(const PathSource &source, VertexWriter &writer, Scalar scale)
static std::pair< size_t, size_t > CountFillStorage(const PathSource &source, Scalar scale)
static void TessellateConvexInternal(const PathSource &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
Definition: tessellator.cc:400
TPoint< Scalar > Point
Definition: point.h:327

References impeller::PathTessellator::CountFillStorage(), impeller::HostBuffer::Emplace(), impeller::DeviceBuffer::Flush(), impeller::BufferView::GetBuffer(), impeller::BufferView::GetRange(), index_buffer_, impeller::k16bit, impeller::Range::offset, impeller::DeviceBuffer::OnGetContents(), impeller::PathTessellator::PathToFilledVertices(), point_buffer_, TessellateConvexInternal(), and impeller::VertexBuffer::vertex_buffer.

◆ TessellateConvexInternal()

void impeller::Tessellator::TessellateConvexInternal ( const PathSource 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 400 of file tessellator.cc.

403  {
404  point_buffer.clear();
405  index_buffer.clear();
406 
407  GLESPathVertexWriter writer(point_buffer, index_buffer);
408 
409  PathTessellator::PathToFilledVertices(path, writer, tolerance);
410 }

References impeller::PathTessellator::PathToFilledVertices().

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 381 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 264 of file tessellator.h.

Referenced by impeller::testing::TEST().

◆ point_buffer_

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

Used for polyline generation.

Definition at line 380 of file tessellator.h.

Referenced by TessellateConvex(), and Tessellator().

◆ stroke_points_

std::vector<Point> impeller::Tessellator::stroke_points_
protected

Used for stroke path generation.

Definition at line 383 of file tessellator.h.

Referenced by GetStrokePointCache().


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