15 : point_buffer_(
std::make_unique<
std::vector<
Point>>()),
16 index_buffer_(
std::make_unique<
std::vector<uint16_t>>()),
43 bool supports_primitive_restart,
44 bool supports_triangle_fan) {
45 if (supports_primitive_restart) {
47 const auto [point_count, contour_count] = path.
CountStorage(tolerance);
49 nullptr,
sizeof(
Point) * point_count,
alignof(
Point));
51 nullptr,
sizeof(uint16_t) * (point_count + contour_count),
54 if (supports_triangle_fan) {
58 reinterpret_cast<uint16_t*
>(
67 .index_buffer = std::move(index_buffer),
75 reinterpret_cast<uint16_t*
>(
84 .index_buffer = std::move(index_buffer),
114 .index_buffer = std::move(index_buffer),
126 const auto [arena_length, oversized_length] = writer.
GetVertexCount();
128 if (oversized_length == 0) {
132 arena_length *
sizeof(
Point),
alignof(
Point)),
134 .vertex_count = arena_length,
141 (arena_length + oversized_length) *
sizeof(
Point),
147 arena_length *
sizeof(
Point)
151 oversized_data.data(),
152 oversized_data.size() *
sizeof(
Point)
159 .vertex_count = arena_length + oversized_length,
165 std::vector<Point>& point_buffer,
166 std::vector<uint16_t>& index_buffer,
168 point_buffer.clear();
169 index_buffer.clear();
179 1, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7,
180 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
181 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13,
182 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14,
183 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16,
184 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18,
185 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19,
186 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
187 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
188 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23,
189 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24,
190 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25,
191 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26,
192 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27,
193 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28,
194 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29,
195 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
196 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
197 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
198 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32,
199 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33,
200 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
201 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
202 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35,
203 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36,
204 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
205 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
206 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38,
207 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
208 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
209 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40,
210 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
211 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41,
212 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
213 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
214 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43,
215 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
216 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44,
217 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
218 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
219 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
220 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
221 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47,
222 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
223 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48,
224 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
225 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49,
226 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
227 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50,
228 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
229 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51,
230 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
231 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52,
232 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
233 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53,
234 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
235 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54,
236 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
237 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
238 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
239 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
240 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
241 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
242 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57,
247 if (pixel_radius <= 0.0) {
250 int radius_index = ceil(pixel_radius);
299 return ceil(
kPiOver4 / std::acos(1 - k));
302 void Tessellator::Trigs::init(
size_t divisions) {
303 if (!trigs_.empty()) {
308 trigs_.reserve(divisions + 1);
310 double angle_scale =
kPiOver2 / divisions;
312 trigs_.emplace_back(1.0, 0.0);
313 for (
size_t i = 1; i < divisions; i++) {
314 trigs_.emplace_back(Radians(i * angle_scale));
316 trigs_.emplace_back(0.0, 1.0);
319 Tessellator::Trigs Tessellator::GetTrigsForDivisions(
size_t divisions) {
320 return divisions < Tessellator::kCachedTrigCount
321 ? Trigs(precomputed_trigs_[divisions], divisions)
328 EllipticalVertexGenerator::EllipticalVertexGenerator(
329 EllipticalVertexGenerator::GeneratorProc& generator,
332 size_t vertices_per_trig,
335 trigs_(
std::move(trigs)),
337 vertices_per_trig_(vertices_per_trig) {}
340 const Matrix& view_transform,
346 GetTrigsForDivisions(divisions),
347 PrimitiveType::kTriangleStrip, 4,
349 .reference_centers = {center, center},
350 .radii = {radius, radius},
356 const Matrix& view_transform,
360 if (half_width > 0) {
364 GetTrigsForDivisions(divisions),
365 PrimitiveType::kTriangleStrip, 8,
367 .reference_centers = {center, center},
368 .radii = {radius, radius},
369 .half_width = half_width,
372 return FilledCircle(view_transform, center, radius);
377 const Matrix& view_transform,
381 auto along = p1 - p0;
387 GetTrigsForDivisions(divisions),
388 PrimitiveType::kTriangleStrip, 4,
390 .reference_centers = {p0, p1},
391 .radii = {radius, radius},
395 return FilledCircle(view_transform, p0, radius);
400 const Matrix& view_transform,
401 const Rect& bounds) {
403 return FilledCircle(view_transform, bounds.
GetCenter(),
406 auto max_radius = bounds.
GetSize().MaxDimension();
411 GetTrigsForDivisions(divisions),
412 PrimitiveType::kTriangleStrip, 4,
414 .reference_centers = {center, center},
415 .radii = bounds.
GetSize() * 0.5f,
421 const Matrix& view_transform,
429 auto upper_left = bounds.
GetLeftTop() + radii;
432 GetTrigsForDivisions(divisions),
433 PrimitiveType::kTriangleStrip, 4,
444 return FilledEllipse(view_transform, bounds);
448 void Tessellator::GenerateFilledCircle(
450 const EllipticalVertexGenerator::Data&
data,
452 auto center =
data.reference_centers[0];
453 auto radius =
data.radii.width;
455 FML_DCHECK(center ==
data.reference_centers[1]);
456 FML_DCHECK(radius ==
data.radii.height);
457 FML_DCHECK(
data.half_width < 0);
460 for (
auto& trig : trigs) {
461 auto offset = trig * radius;
471 for (
auto& trig : trigs) {
472 auto offset = trig * radius;
478 void Tessellator::GenerateStrokedCircle(
480 const EllipticalVertexGenerator::Data&
data,
482 auto center =
data.reference_centers[0];
484 FML_DCHECK(center ==
data.reference_centers[1]);
485 FML_DCHECK(
data.radii.IsSquare());
486 FML_DCHECK(
data.half_width > 0 &&
data.half_width <
data.radii.width);
488 auto outer_radius =
data.radii.width +
data.half_width;
489 auto inner_radius =
data.radii.width -
data.half_width;
497 for (
auto& trig : trigs) {
498 auto outer = trig * outer_radius;
499 auto inner = trig * inner_radius;
500 proc({center.x - outer.x, center.y - outer.y});
501 proc({center.x - inner.x, center.y - inner.y});
509 for (
auto& trig : trigs) {
510 auto outer = trig * outer_radius;
511 auto inner = trig * inner_radius;
512 proc({center.x + outer.y, center.y - outer.x});
513 proc({center.x + inner.y, center.y - inner.x});
517 for (
auto& trig : trigs) {
518 auto outer = trig * outer_radius;
519 auto inner = trig * inner_radius;
520 proc({center.x + outer.x, center.y + outer.y});
521 proc({center.x + inner.x, center.y + inner.y});
525 for (
auto& trig : trigs) {
526 auto outer = trig * outer_radius;
527 auto inner = trig * inner_radius;
528 proc({center.x - outer.y, center.y + outer.x});
529 proc({center.x - inner.y, center.y + inner.x});
533 void Tessellator::GenerateRoundCapLine(
535 const EllipticalVertexGenerator::Data&
data,
537 auto p0 =
data.reference_centers[0];
538 auto p1 =
data.reference_centers[1];
539 auto radius =
data.radii.width;
541 FML_DCHECK(radius ==
data.radii.height);
542 FML_DCHECK(
data.half_width < 0);
544 auto along = p1 - p0;
545 along *= radius / along.GetLength();
546 auto across =
Point(-along.y, along.x);
548 for (
auto& trig : trigs) {
549 auto relative_along = along * trig.cos;
550 auto relative_across = across * trig.sin;
551 proc(p0 - relative_along + relative_across);
552 proc(p0 - relative_along - relative_across);
558 for (
auto& trig : trigs) {
559 auto relative_along = along * trig.sin;
560 auto relative_across = across * trig.cos;
561 proc(p1 + relative_along + relative_across);
562 proc(p1 + relative_along - relative_across);
566 void Tessellator::GenerateFilledEllipse(
568 const EllipticalVertexGenerator::Data&
data,
570 auto center =
data.reference_centers[0];
571 auto radii =
data.radii;
573 FML_DCHECK(center ==
data.reference_centers[1]);
574 FML_DCHECK(
data.half_width < 0);
577 for (
auto& trig : trigs) {
578 auto offset = trig * radii;
588 for (
auto& trig : trigs) {
589 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);
595 void Tessellator::GenerateFilledRoundRect(
597 const EllipticalVertexGenerator::Data&
data,
603 auto radii =
data.radii;
605 FML_DCHECK(
data.half_width < 0);
608 for (
auto& trig : trigs) {
609 auto offset = trig * radii;
619 for (
auto& trig : trigs) {
620 auto offset =
Point(trig.sin * radii.width, trig.cos * radii.height);
virtual void Flush(std::optional< Range > range=std::nullopt) const
virtual uint8_t * OnGetContents() const =0
A vertex writer that generates a triangle fan and requires primitive restart.
size_t GetIndexCount() const
A vertex writer that has no hardware requirements.
BufferView Emplace(const BufferType &buffer, size_t alignment=0)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
A vertex writer that generates a line strip topology.
std::pair< size_t, size_t > GetVertexCount() const
const std::vector< Point > & GetOversizedBuffer() const
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Polyline CreatePolyline(Scalar scale, Polyline::PointBufferPtr point_buffer=std::make_unique< std::vector< Point >>(), Polyline::ReclaimPointBufferCallback reclaim=nullptr) const
void WritePolyline(Scalar scale, VertexWriter &writer) const
std::pair< size_t, size_t > CountStorage(Scalar scale) const
Determine required storage for points and number of contours.
A vertex writer that generates a triangle strip and requires primitive restart.
size_t GetIndexCount() const
The |VertexGenerator| implementation common to all shapes that are based on a polygonal representatio...
std::vector< Point > stroke_points_
Used for stroke path generation.
std::vector< Point > & GetStrokePointCache()
Retrieve a pre-allocated arena of kPointArenaSize points.
VertexBuffer GenerateLineStrip(const Path &path, HostBuffer &host_buffer, Scalar tolerance)
Given a path, create a line strip primitive structure.
static constexpr Scalar kCircleTolerance
The pixel tolerance used by the algorighm to determine how many divisions to create for a circle.
static void TessellateConvexInternal(const Path &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
Path::Polyline CreateTempPolyline(const Path &path, Scalar tolerance)
Create a temporary polyline. Only one per-process can exist at a time.
std::unique_ptr< std::vector< Point > > point_buffer_
Used for polyline generation.
std::unique_ptr< std::vector< uint16_t > > index_buffer_
std::function< void(const Point &p)> TessellatedVertexProc
A callback function for a |VertexGenerator| to deliver the vertices it computes as |Point| objects.
VertexBuffer TessellateConvex(const Path &path, HostBuffer &host_buffer, Scalar tolerance, bool supports_primitive_restart=false, bool supports_triangle_fan=false)
Given a convex path, create a triangle fan structure.
static size_t ComputeQuadrantDivisions(Scalar pixel_radius)
@ kNone
Does not use the index buffer.
Tessellator::TessellatedVertexProc TessellatedVertexProc
PrimitiveType
Decides how backend draws pixels based on input vertices.
constexpr float kEhCloseEnough
static constexpr int kPrecomputedDivisionCount
Tessellator::EllipticalVertexGenerator EllipticalVertexGenerator
static int kPrecomputedDivisions[kPrecomputedDivisionCount]
static constexpr size_t kPointArenaSize
The size of the point arena buffer stored on the tessellator.
const Path::Polyline & polyline
const DeviceBuffer * GetBuffer() const
A 4x4 matrix using column-major storage.
constexpr Scalar GetMaxBasisLengthXY() const
std::unique_ptr< std::vector< Point > > PointBufferPtr
constexpr Type GetLength() const
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
constexpr bool IsSquare() const
Returns true if width and height are equal and neither is NaN.
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
constexpr TPoint< T > GetRightBottom() const
constexpr Point GetCenter() const
Get the center point as a |Point|.
constexpr TPoint< T > GetLeftTop() const
constexpr Type MaxDimension() const
std::shared_ptr< const fml::Mapping > data