// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
namespace SixLabors.ImageSharp.Drawing {
///
/// Builds the retained array used by flattened segment caches without an intermediate collection copy.
///
///
/// Segment flatteners ultimately need to return a tightly-sized array that can be cached by the segment instance.
/// This builder owns that array while points are appended.
///
internal struct FlattenedPointBuilder
{
private PointF[] points;
private int count;
///
/// Initializes a new instance of the struct.
///
/// The estimated number of points that will be appended.
public FlattenedPointBuilder(int capacity)
{
this.points = new PointF[Math.Max(capacity, 4)];
this.count = 0;
}
///
/// Appends one point to the retained point array.
///
/// The point to append.
public void Add(PointF point)
{
this.EnsureCapacity(this.count + 1);
this.points[this.count++] = point;
}
///
/// Reserves a writable append window for callers that populate multiple points directly.
///
/// The number of points to reserve.
/// A span covering the reserved append window.
public Span GetAppendSpan(int length)
{
this.EnsureCapacity(this.count + length);
return this.points.AsSpan(this.count, length);
}
///
/// Commits points previously written through .
///
/// The number of points written to the reserved append window.
public void Advance(int length) => this.count += length;
///
/// Returns the owned point array.
///
/// The tightly-sized retained point array.
public PointF[] Detach()
{
if (this.count != this.points.Length)
{
Array.Resize(ref this.points, this.count);
}
return this.points;
}
///
/// Ensures the owned array can store the requested total point count.
///
/// The total number of points that must fit.
private void EnsureCapacity(int capacity)
{
if (capacity <= this.points.Length)
{
return;
}
Array.Resize(ref this.points, Math.Max(capacity, this.points.Length * 2));
}
}
}