// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Buffers;
namespace SixLabors.ImageSharp.Drawing.Processing.Backends {
internal static partial class DefaultRasterizer
{
///
/// Contract implemented by retained line-block payloads.
///
/// The concrete retained line-block type.
internal interface ILineBlock
where TSelf : class, ILineBlock
{
///
/// Gets the number of lines stored in a full block.
///
public static abstract int LineCount { get; }
///
/// Gets the next block in the retained chain.
///
public TSelf? Next { get; }
///
/// Rasterizes the leading lines from this block.
///
/// The number of leading lines to rasterize from this block.
/// The mutable scan-conversion context to write into.
public void Rasterize(int count, ref Context context);
}
///
/// Retained tile-space bounds for one linearized geometry payload.
///
internal readonly struct TileBounds
{
///
/// Initializes a new instance of the struct.
///
/// The tile-space left coordinate.
/// The tile-space top coordinate.
/// The tile-space column count.
/// The tile-space row count.
public TileBounds(int x, int y, int columnCount, int rowCount)
{
this.X = x;
this.Y = y;
this.ColumnCount = columnCount;
this.RowCount = rowCount;
}
///
/// Gets the tile-space left coordinate.
///
public int X { get; }
///
/// Gets the tile-space top coordinate.
///
public int Y { get; }
///
/// Gets the tile-space column count.
///
public int ColumnCount { get; }
///
/// Gets the tile-space row count.
///
public int RowCount { get; }
}
///
/// Holds the finalized retained raster payload for one line-block encoding.
///
/// The concrete retained line-block type.
internal sealed class LinearizedRasterData
where TLineBlock : class, ILineBlock
{
///
/// Initializes a new instance of the class.
///
/// The source linear geometry.
/// The retained tile-space bounds.
/// The retained line-block chain for each row band.
/// The valid line count in each row's front block.
/// The retained start-cover seeds for each row band.
public LinearizedRasterData(
LinearGeometry geometry,
TileBounds bounds,
TLineBlock?[] lines,
int[] firstBlockLineCounts,
IMemoryOwner?[] startCoverTable)
{
this.Geometry = geometry;
this.Bounds = bounds;
this.Lines = lines;
this.FirstBlockLineCounts = firstBlockLineCounts;
this.StartCoverTable = startCoverTable;
}
///
/// Gets the source linear geometry.
///
public LinearGeometry Geometry { get; }
///
/// Gets the retained tile-space bounds.
///
public TileBounds Bounds { get; }
///
/// Gets the retained line-block chain for each row band.
///
public TLineBlock?[] Lines { get; }
///
/// Gets the valid front-block line count for each row band.
///
public int[] FirstBlockLineCounts { get; }
///
/// Gets the retained start-cover seeds for each row band.
///
public IMemoryOwner?[] StartCoverTable { get; }
///
/// Iterates the retained line blocks for one row band.
///
/// The row band index to iterate.
/// The mutable scan-conversion context.
public void Iterate(int rowIndex, ref Context context)
{
int count = this.FirstBlockLineCounts[rowIndex];
TLineBlock? lineBlock = this.Lines[rowIndex];
while (lineBlock is not null)
{
lineBlock.Rasterize(count, ref context);
lineBlock = lineBlock.Next;
count = TLineBlock.LineCount;
}
}
}
}
}