// 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)); } } }