public static FpgmTable Read(FontStreamReader reader, OffsetTable.Entry entry) { reader.Seek(entry); var instructions = reader.ReadArray <byte>(entry.Length, r => r.ReadUInt8); return(new FpgmTable(instructions)); }
public static CmapFormat Read(FontStreamReader reader, ushort platformId, ushort platformSpecificId) { var length = reader.ReadUInt16(); var language = reader.ReadUInt16(); var glyphIndexArray = reader.ReadArray <byte>(256, r => r.ReadUInt8); return(new CmapFormat0(language, glyphIndexArray)); }
public static LocaTable Read(Font font, FontStreamReader reader, OffsetTable.Entry entry) { reader.Seek(entry); var length = entry.Length; var format = font.HeadTable.IndexToLocFormat; switch (format) { case IndexToLocFormat.Short: return(new LocaTable(reader.ReadArray <uint>(length / sizeof(ushort), r => (() => r.ReadUInt16())))); case IndexToLocFormat.Long: return(new LocaTable(reader.ReadArray <uint>(length / sizeof(uint), r => r.ReadUInt32))); default: throw new FormatException($"Invalid IndexToLocFormat: {format}"); } }
public static CmapFormat Read(FontStreamReader reader, ushort platformId, ushort platformSpecificId) { uint length = reader.ReadUInt16(); var language = reader.ReadUInt16(); length -= 3 * sizeof(ushort); var segCount = (ushort)(reader.ReadUInt16() / 2); // stored as 2 * segCount var searchRange = reader.ReadUInt16(); var entrySelector = reader.ReadUInt16(); var rangeShift = reader.ReadUInt16(); length -= 4 * sizeof(ushort); var endCode = reader.ReadArray <ushort>(segCount, r => r.ReadUInt16); if (endCode[endCode.Length - 1] != 0xffff) { throw new FormatException($"Unexpected last endCode: 0x{endCode[endCode.Length - 1]:X}, expecting 0xffff"); } var reservedPad = reader.ReadUInt16(); // 0 if (reservedPad != 0) { throw new FormatException($"Unexpected value for reservedPad: {reservedPad}, expecting 0"); } length -= (ushort)(segCount * sizeof(ushort) + 1); var startCode = reader.ReadArray <ushort>(segCount, r => r.ReadUInt16); var idDelta = reader.ReadArray <ushort>(segCount, r => r.ReadUInt16); var idRangeOffset = reader.ReadArray <ushort>(segCount, r => r.ReadUInt16); length -= (ushort)(3 * segCount * sizeof(ushort)); var glyphIndexArray = reader.ReadArray <ushort>(length / sizeof(ushort), r => r.ReadUInt16); return(new CmapFormat4(language, startCode, endCode, idDelta, idRangeOffset, glyphIndexArray)); }
private static Glyph ReadCompoundGlyph(FontStreamReader reader, ushort xMin, ushort yMin, ushort xMax, ushort yMax) { var components = new List <CompoundGlyph.Component>(); var flags = GlyphComponentFlags.MoreComponents; while (flags.HasFlag(GlyphComponentFlags.MoreComponents)) { flags = (GlyphComponentFlags)reader.ReadUInt16(); var glyphIndex = reader.ReadInt16(); if (flags.HasFlag(GlyphComponentFlags.WeHaveInstructions) && flags.HasFlag(GlyphComponentFlags.MoreComponents)) { throw new NotImplementedException(); } var arg1 = flags.HasFlag(GlyphComponentFlags.Arg12AreWords) ? reader.ReadInt16() : reader.ReadUInt8(); var arg2 = flags.HasFlag(GlyphComponentFlags.Arg12AreWords) ? reader.ReadInt16() : reader.ReadUInt8(); var matrix = new decimal[] { 1, 0, 0, 1, 0, 0 }; short?destPointIndex = null; short?srcPointIndex = null; if (flags.HasFlag(GlyphComponentFlags.ArgsAreXYValues)) { matrix[4] = arg1; matrix[5] = arg2; } else { destPointIndex = arg1; srcPointIndex = arg1; } if (flags.HasFlag(GlyphComponentFlags.WeHaveAScale)) { matrix[0] = matrix[3] = reader.ReadF2Dot14(); } else if (flags.HasFlag(GlyphComponentFlags.WeHaveAnXYScale)) { matrix[0] = reader.ReadF2Dot14(); matrix[3] = reader.ReadF2Dot14(); } else if (flags.HasFlag(GlyphComponentFlags.WeHave2By2)) { matrix[0] = reader.ReadF2Dot14(); matrix[1] = reader.ReadF2Dot14(); matrix[2] = reader.ReadF2Dot14(); matrix[3] = reader.ReadF2Dot14(); } components.Add(new CompoundGlyph.Component(glyphIndex, matrix, destPointIndex, srcPointIndex)); } var instructions = new byte[0]; if (flags.HasFlag(GlyphComponentFlags.WeHaveInstructions)) { var instructionLength = reader.ReadUInt16(); instructions = reader.ReadArray <byte>(instructionLength, r => r.ReadUInt8); } return(new CompoundGlyph(components, instructions)); }
private static Glyph ReadSimpleGlyph(FontStreamReader reader, short numberOfContours, ushort xMin, ushort yMin, ushort xMax, ushort yMax) { var endPoints = reader.ReadArray <ushort>((ushort)numberOfContours, r => r.ReadUInt16); var instructionLength = reader.ReadUInt16(); var instructions = reader.ReadArray <byte>(instructionLength, r => r.ReadUInt8); if (numberOfContours == 0) { return(new SimpleGlyph(xMin, yMin, xMax, yMax, endPoints, instructions, new Point[0])); } var numberOfPoints = endPoints.Max() + 1; var flags = new SimpleGlyphFlags[numberOfPoints]; var points = new Point[numberOfPoints]; for (var i = 0; i < numberOfPoints; i++) { var flag = (SimpleGlyphFlags)reader.ReadUInt8(); flags[i] = flag; points[i] = new Point { OnCurve = flag.HasFlag(SimpleGlyphFlags.OnCurve) }; if (flag.HasFlag(SimpleGlyphFlags.Repeat)) { var count = reader.ReadUInt8(); while (count-- > 0) { flags[++i] = flag; points[i] = new Point { OnCurve = flag.HasFlag(SimpleGlyphFlags.OnCurve) }; } } } // read X short value = 0; for (var i = 0; i < numberOfPoints; i++) { var flag = flags[i]; if (flag.HasFlag(SimpleGlyphFlags.XShort)) { if (flag.HasFlag(SimpleGlyphFlags.XSame)) { value += reader.ReadUInt8(); } else { value -= reader.ReadUInt8(); } } else if (!flag.HasFlag(SimpleGlyphFlags.XSame)) { value += reader.ReadInt16(); } points[i].X = value; } // read Y value = 0; for (var i = 0; i < numberOfPoints; i++) { var flag = flags[i]; if (flag.HasFlag(SimpleGlyphFlags.YShort)) { if (flag.HasFlag(SimpleGlyphFlags.YSame)) { value += reader.ReadUInt8(); } else { value -= reader.ReadUInt8(); } } else if (!flag.HasFlag(SimpleGlyphFlags.YSame)) { value += reader.ReadInt16(); } points[i].Y = value; } return(new SimpleGlyph(xMin, yMin, xMax, yMax, endPoints, instructions, points)); }