// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
using System.Buffers;
namespace SixLabors.ImageSharp.Drawing.Processing.Backends {
internal static partial class DefaultRasterizer
{
///
/// Flush-scoped retained row-local raster payload for one prepared fill geometry.
///
internal sealed class RasterizableGeometry : IDisposable
{
private readonly RasterizableBandInfo[] bandInfos;
private readonly LineArrayX16Y16Block?[]? linesX16;
private readonly LineArrayX32Y16Block?[]? linesX32;
private readonly int[] firstBlockLineCounts;
private readonly IMemoryOwner?[] startCoverTable;
///
/// Initializes a new instance of the class.
///
/// The first absolute row-band index touched by the geometry.
/// The number of retained local row bands owned by the geometry.
/// The geometry-local visible band width in pixels.
/// The bit-vector width in machine words required by the geometry.
/// The scanner cover/area stride required by the geometry.
/// The retained row-band height in pixels.
/// Indicates whether the geometry uses the narrow X16Y16 line encoding.
/// The retained metadata for each local row band.
/// The retained narrow line chains for each local row band.
/// The retained wide line chains for each local row band.
/// The valid line count in each front retained block.
/// The retained start-cover table for each local row band.
public RasterizableGeometry(
int firstRowBandIndex,
int rowBandCount,
int width,
int wordsPerRow,
int coverStride,
int bandHeight,
bool isX16,
RasterizableBandInfo[] bandInfos,
LineArrayX16Y16Block?[]? linesX16,
LineArrayX32Y16Block?[]? linesX32,
int[] firstBlockLineCounts,
IMemoryOwner?[] startCoverTable)
{
this.FirstRowBandIndex = firstRowBandIndex;
this.RowBandCount = rowBandCount;
this.Width = width;
this.WordsPerRow = wordsPerRow;
this.CoverStride = coverStride;
this.BandHeight = bandHeight;
this.IsX16 = isX16;
this.bandInfos = bandInfos;
this.linesX16 = linesX16;
this.linesX32 = linesX32;
this.firstBlockLineCounts = firstBlockLineCounts;
this.startCoverTable = startCoverTable;
}
///
/// Gets the first absolute row-band index touched by this geometry.
///
public int FirstRowBandIndex { get; }
///
/// Gets the number of retained local row bands owned by this geometry.
///
public int RowBandCount { get; }
///
/// Gets the geometry-local visible band width in pixels.
///
public int Width { get; }
///
/// Gets the bit-vector width in machine words required by this geometry.
///
public int WordsPerRow { get; }
///
/// Gets the scanner cover/area stride required by this geometry.
///
public int CoverStride { get; }
///
/// Gets the retained row-band height in pixels.
///
public int BandHeight { get; }
///
/// Gets a value indicating whether this geometry uses Blaze's narrow X16Y16 line arrays.
///
public bool IsX16 { get; }
///
/// Returns when the given local row band has retained coverage payload.
///
/// The local row band index.
/// when the row band has retained coverage; otherwise .
public bool HasCoverage(int localRowIndex) => this.bandInfos[localRowIndex].HasCoverage;
///
/// Gets the retained narrow line block chain for one local row.
///
/// The local row band index.
/// The retained narrow line chain for the row.
public LineArrayX16Y16Block? GetLinesX16ForRow(int localRowIndex) => this.linesX16![localRowIndex];
///
/// Gets the retained wide line block chain for one local row.
///
/// The local row band index.
/// The retained wide line chain for the row.
public LineArrayX32Y16Block? GetLinesX32ForRow(int localRowIndex) => this.linesX32![localRowIndex];
///
/// Gets the number of valid lines in the first retained block for a local row.
///
/// The local row band index.
/// The valid line count in the front retained block.
public int GetFirstBlockLineCountForRow(int localRowIndex) => this.firstBlockLineCounts[localRowIndex];
///
/// Gets the retained start-cover table entry for a local row, if one exists.
///
/// The local row band index.
/// The retained start-cover span for the row.
public ReadOnlySpan GetCoversForRow(int localRowIndex)
{
IMemoryOwner? covers = this.startCoverTable[localRowIndex];
return covers is null ? ReadOnlySpan.Empty : covers.Memory.Span[..this.BandHeight];
}
///
/// Gets the retained start-cover row payload without further interpretation, matching Blaze naming.
///
/// The local row band index.
/// The retained start-cover span for the row.
public ReadOnlySpan GetActualCoversForRow(int localRowIndex) => this.GetCoversForRow(localRowIndex);
///
/// Gets retained metadata for one local row band.
///
/// The local row band index.
/// The retained band metadata.
public RasterizableBandInfo GetBandInfo(int localRowIndex) => this.bandInfos[localRowIndex];
///
/// Releases the retained line blocks and start-cover storage.
///
public void Dispose()
{
if (this.linesX16 is not null)
{
Array.Clear(this.linesX16);
}
if (this.linesX32 is not null)
{
Array.Clear(this.linesX32);
}
for (int i = 0; i < this.startCoverTable.Length; i++)
{
this.startCoverTable[i]?.Dispose();
}
}
}
}
}