// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System.IO; namespace SixLabors.Fonts.Tables.AdvancedTypographic { /// /// The MarkGlyphSets table allows the definition of sets of mark glyphs that can be used /// in lookup flag mark filtering. This provides more flexibility than the MarkAttachmentType. /// /// internal sealed class MarkGlyphSetsTable { /// /// Gets or sets the format identifier. /// public ushort Format { get; internal set; } /// /// Gets or sets the array of offsets to Coverage tables, from the beginning of the MarkGlyphSets table. /// public uint[]? CoverageOffset { get; internal set; } /// /// Gets the loaded Coverage tables for each mark glyph set. /// public CoverageTable[]? Coverages { get; private set; } /// /// Loads the from the binary reader at the specified offset. /// /// The big endian binary reader. /// Offset from the beginning of the GDEF table to the MarkGlyphSets table. /// The . public static MarkGlyphSetsTable Load(BigEndianBinaryReader reader, long offset) { reader.Seek(offset, SeekOrigin.Begin); MarkGlyphSetsTable markGlyphSetsTable = new() { Format = reader.ReadUInt16() }; ushort markSetCount = reader.ReadUInt16(); uint[] coverageOffsets = reader.ReadUInt32Array(markSetCount); markGlyphSetsTable.CoverageOffset = coverageOffsets; // Load the referenced Coverage tables now so we can use them during shaping. // Coverage offsets are relative to the start of the MarkGlyphSets table. CoverageTable[] coverages = new CoverageTable[markSetCount]; for (int i = 0; i < markSetCount; i++) { long covOffset = offset + coverageOffsets[i]; coverages[i] = CoverageTable.Load(reader, covOffset); } markGlyphSetsTable.Coverages = coverages; return markGlyphSetsTable; } /// /// Determines whether the specified glyph is contained in the given mark glyph set. /// /// The index of the mark glyph set. /// The glyph identifier to look up. /// if the glyph is in the set; otherwise, . public bool Contains(ushort markGlyphSetIndex, ushort glyphId) { CoverageTable[]? coverages = this.Coverages; if (coverages is null) { return false; } int i = markGlyphSetIndex; if ((uint)i >= (uint)coverages.Length) { return false; } return coverages[i].CoverageIndexOf(glyphId) >= 0; } } }