private static void ReadGlyph(FontGlyph g, LocaTable locaTable, ByteReader glyfTableReader, float scale) { int glyphIndex = g.MapIndex; int[] glyphOffsets = locaTable.GlyphOffsets; if (glyphIndex > glyphOffsets.Length) { return; } int glyphOffset = glyphOffsets[glyphIndex]; int nextOffset = glyphOffsets[glyphIndex + 1]; // No data for glyph. if (glyphOffset == nextOffset || glyphOffset >= glyfTableReader.Data.Length) { return; } glyfTableReader.Position = glyphOffset; int numberOfContours = glyfTableReader.ReadShortBE(); float minX = glyfTableReader.ReadShortBE(); float minY = glyfTableReader.ReadShortBE(); float maxX = glyfTableReader.ReadShortBE(); float maxY = glyfTableReader.ReadShortBE(); g.Min = new Vector2(minX, minY) * scale; g.Max = new Vector2(maxX, maxY) * scale; // Simple glyph if (numberOfContours > 0) { // Indices for the last point of each contour var endPointIndices = new ushort[numberOfContours]; for (var i = 0; i < endPointIndices.Length; i++) { endPointIndices[i] = glyfTableReader.ReadUShortBE(); } ushort instructionLength = glyfTableReader.ReadUShortBE(); glyfTableReader.ReadBytes(instructionLength); int numberOfCoordinates = endPointIndices[^ 1] + 1;
public static void ParseGlyf(ByteReader reader, LocaTable locaTableParsed, FontGlyph[] glyphs, float scale) { // First pass: read commands of all glyphs for (var i = 0; i < glyphs.Length; i++) { FontGlyph glyph = glyphs[i]; ReadGlyph(glyph, locaTableParsed, reader, scale); } // Second pass: combine composite glyphs. for (var i = 0; i < glyphs.Length; i++) { FontGlyph glyph = glyphs[i]; if (!glyph.Composite) { continue; } CombineCompositeGlyph(glyph, glyphs); } }