// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System.Collections.Generic; using System.Linq; namespace SixLabors.Fonts { /// /// Represents a shaped and line-broken block of text. /// internal sealed class TextBox { private readonly TextDirection textDirection; private float? scaledMaxAdvance; private float? minY; private int glyphLayoutCount; private bool hasGlyphLayoutCounts; /// /// Initializes a new instance of the class. /// /// The shaped, line-broken lines that make up this text box. /// The block-level text direction. public TextBox(IReadOnlyList textLines, TextDirection textDirection) { this.TextLines = textLines; this.textDirection = textDirection; } /// /// Gets the shaped and line-broken lines that make up the text. /// public IReadOnlyList TextLines { get; } /// /// Returns the widest scaled line advance across all lines. The result is memoized. /// /// The widest scaled line advance. public float ScaledMaxAdvance() => this.scaledMaxAdvance ??= this.TextLines.Max(x => x.ScaledLineAdvance); /// /// Returns the smallest (most negative) scaled Y position encountered across all lines. /// Used to detect ink that extends above the typographic ascender (stacked marks in Tibetan etc.). /// The result is memoized. /// /// The smallest scaled Y position in the text box. public float ScaledMinY() => this.minY ??= this.TextLines.Min(x => x.ScaledMinY); /// /// Counts all glyph entries emitted from this text box. The result is memoized. /// /// The number of glyph entries that layout will emit. public int CountGlyphLayouts() => this.hasGlyphLayoutCounts ? this.glyphLayoutCount : this.CountGlyphLayoutsCore(); /// /// Computes the glyph-layout count in one pass. /// /// The number of glyph entries that layout will emit. private int CountGlyphLayoutsCore() { int count = 0; for (int i = 0; i < this.TextLines.Count; i++) { count += this.TextLines[i].CountGlyphLayouts(); } this.glyphLayoutCount = count; this.hasGlyphLayoutCounts = true; return count; } /// /// Returns the block-level text direction used for alignment calculations. /// /// The block-level text direction. public TextDirection TextDirection() => this.textDirection; } }