//Apache2, 2016-present, WinterDev using System.IO; namespace Typography.OpenFont.Tables { //from https://docs.microsoft.com/en-us/typography/opentype/spec/gdef //Ligature Caret List Table //The Ligature Caret List table (LigCaretList) defines caret positions for all the ligatures in a font. //The table consists of an offset to a Coverage table that lists all the ligature glyphs (Coverage), //a count of the defined ligatures (LigGlyphCount), //and an array of offsets to LigGlyph tables (LigGlyph). //The array lists the LigGlyph tables, //one for each ligature in the Coverage table, in the same order as the Coverage Index. //Example 4 at the end of this chapter shows a LigCaretList table. //LigCaretList table //Type Name Description //Offset16 Coverage Offset to Coverage table - from beginning of LigCaretList table //uint16 LigGlyphCount Number of ligature glyphs //Offset16 LigGlyph[LigGlyphCount] Array of offsets to LigGlyph tables-from beginning of LigCaretList table-in Coverage Index order /// /// Ligature Caret List Table, defines caret positions for all the ligatures in a font /// class LigCaretList { LigGlyph[] _ligGlyphs; CoverageTable _coverageTable; public static LigCaretList CreateFrom(BinaryReader reader, long beginAt) { reader.BaseStream.Seek(beginAt, SeekOrigin.Begin); //---- LigCaretList ligcaretList = new LigCaretList(); ushort coverageOffset = reader.ReadUInt16(); ushort ligGlyphCount = reader.ReadUInt16(); ushort[] ligGlyphOffsets = Utils.ReadUInt16Array(reader, ligGlyphCount); LigGlyph[] ligGlyphs = new LigGlyph[ligGlyphCount]; for (int i = 0; i < ligGlyphCount; ++i) { ligGlyphs[i] = LigGlyph.CreateFrom(reader, beginAt + ligGlyphOffsets[i]); } ligcaretList._ligGlyphs = ligGlyphs; ligcaretList._coverageTable = CoverageTable.CreateFrom(reader, beginAt + coverageOffset); return ligcaretList; } } //A Ligature Glyph table (LigGlyph) contains the caret coordinates for a single ligature glyph. //The number of coordinate values, each defined in a separate CaretValue table, //equals the number of components in the ligature minus one (1).*** //The LigGlyph table consists of a count of the number of CaretValue tables defined for the ligature (CaretCount) and //an array of offsets to CaretValue tables (CaretValue). //Example 4 at the end of the chapter shows a LigGlyph table. //LigGlyph table //Type Name Description //uint16 CaretCount Number of CaretValues for this ligature (components - 1) //Offset16 CaretValue[CaretCount] Array of offsets to CaretValue tables-from beginning of LigGlyph table-in increasing coordinate order Caret Values Table /// /// A Ligature Glyph table (LigGlyph) contains the caret coordinates for a single ligature glyph. /// class LigGlyph { ushort[] _caretValueOffsets; public static LigGlyph CreateFrom(BinaryReader reader, long beginAt) { reader.BaseStream.Seek(beginAt, SeekOrigin.Begin); //---------- LigGlyph ligGlyph = new LigGlyph(); ushort caretCount = reader.ReadUInt16(); ligGlyph._caretValueOffsets = Utils.ReadUInt16Array(reader, caretCount); return ligGlyph; } } //A Caret Values table (CaretValues), which defines caret positions for a ligature, //can be any of three possible formats. //One format uses design units to define the caret position. //The other two formats use a contour point or (in non-variable fonts) a Device table to fine-tune a caret's position at specific font sizes //and device resolutions. //In a variable font, the third format uses a VariationIndex table (a variant of a Device table) //to reference variation data for adjustment of the caret position for the current variation instance, as needed. //Caret coordinates are either X or Y values, depending upon the text direction. /// /// A Caret Values table (CaretValues) /// class CaretValues { } //------------------------- //CaretValue Format 1 //------------------------- //The first format (CaretValueFormat1) consists of a format identifier (CaretValueFormat), //followed by a single coordinate for the caret position (Coordinate). The Coordinate is in design units. //This format has the benefits of small size and simplicity, but the Coordinate value cannot be hinted for fine adjustments at different device resolutions. //Example 4 at the end of this chapter shows a CaretValueFormat1 table. //------------------------- //CaretValueFormat1 table: Design units only //------------------------- //Type Name Description //uint16 CaretValueFormat Format identifier-format = 1 //int16 Coordinate X or Y value, in design units //------------------------- //NOTE: int16 // // //CaretValue Format 2 // //The second format (CaretValueFormat2) specifies the caret coordinate in terms of a contour point index on a specific glyph. //During font hinting, the contour point on the glyph outline may move. //The point's final position after hinting provides the final value for rendering a given font size. //The table contains a format identifier (CaretValueFormat) and a contour point index (CaretValuePoint). //Example 5 at the end of this chapter demonstrates a CaretValueFormat2 table. //------------------------- //CaretValueFormat2 table: Contour point //Type Name Description //uint16 CaretValueFormat Format identifier-format = 2 //uint16 CaretValuePoint Contour point index on glyph //------------------------- // //CaretValue Format 3 //The third format (CaretValueFormat3) also specifies the value in design units, but, //in non-variable fonts, it uses a Device table rather than a contour point to adjust the value. //This format offers the advantage of fine-tuning the Coordinate value for any device resolution. //(For more information about Device tables, see the chapter, Common Table Formats.) //In variable fonts, CaretValueFormat3 must be used to reference variation data to adjust caret positions for different variation instances, //if needed. In this case, CaretValueFormat3 specifies an offset to a VariationIndex table, which is a variant of the Device table used for variations. // Note: While separate VariationIndex table references are required for each value that requires variation, //two or more values that require the same variation-data values can have offsets that point to the same VariationIndex table, //and two or more VariationIndex tables can reference the same variation data entries. // Note: If no VariationIndex table is used for a particular caret position value, then that value is used for all variation instances. //The format consists of a format identifier (CaretValueFormat), an X or Y value (Coordinate), and an offset to a Device or VariationIndex table. //Example 6 at the end of this chapter shows a CaretValueFormat3 table. //------------------------- //CaretValueFormat3 table: Design units plus Device or VariationIndex table //Type Name Description //uint16 CaretValueFormat Format identifier-format = 3 //int16 Coordinate X or Y value, in design units //Offset16 DeviceTable Offset to Device table (non-variable font) / Variation Index table (variable font) for X or Y value-from beginning of CaretValue table //------------------------------------------------------------------------------- //NOTE: Offset16 //------------------------------------------------------------------------------- // //Mark Attachment Class Definition Table //A Mark Attachment Class Definition Table defines the class to which a mark glyph may belong. //This table uses the same format as the Class Definition table (for details, see the chapter, Common Table Formats ). //Example 7 in this document shows a MarkAttachClassDef table. //Mark Glyph Sets Table //Mark glyph sets are used in GSUB and GPOS lookups to filter which marks in a string are considered or ignored. //Mark glyph sets are defined in a MarkGlyphSets table, which contains offsets to individual sets each represented by a standard Coverage table: //--------------------------------------------------------- //MarkGlyphSetsTable //--------------------------------------------------------- //Type Name Description //uint16 MarkSetTableFormat Format identifier == 1 //uint16 MarkSetCount Number of mark sets defined //Offset32 Coverage [MarkSetCount] Array of offsets to mark set coverage tables. //--------------------------------------------------------- //Mark glyph sets are used for the same purpose as mark attachment classes, which is as filters for GSUB and GPOS lookups. //Mark glyph sets differ from mark attachment classes, however, //in that mark glyph sets may intersect as needed by the font developer. //As for mark attachment classes, only one mark glyph set can be referenced in any given lookup. //Note that the array of offsets for the Coverage tables uses ULONG, not Offset. *** class MarkGlyphSetsTable { ushort _format; uint[] _coverageOffset; public static MarkGlyphSetsTable CreateFrom(BinaryReader reader, long beginAt) { reader.BaseStream.Seek(beginAt, SeekOrigin.Begin); // MarkGlyphSetsTable markGlyphSetsTable = new MarkGlyphSetsTable(); markGlyphSetsTable._format = reader.ReadUInt16(); ushort markSetCount = reader.ReadUInt16(); uint[] coverageOffset = markGlyphSetsTable._coverageOffset = new uint[markSetCount]; for (int i = 0; i < markSetCount; ++i) { //Note that the array of offsets for the Coverage tables uses ULONG coverageOffset[i] = reader.ReadUInt32();// } return markGlyphSetsTable; } } }