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