static CompositeGlyph ReadCompositeGlyph(DataReader reader) { // we need to keep reading glyphs for as long as // our flags tell us that there are more to read var subglyphs = new List <Subglyph>(); CompositeGlyphFlags flags; do { flags = (CompositeGlyphFlags)reader.ReadUInt16BE(); var subglyph = new Subglyph { Flags = flags }; subglyph.Index = reader.ReadUInt16BE(); // read in args; they vary in size based on flags if ((flags & CompositeGlyphFlags.ArgsAreWords) != 0) { subglyph.Arg1 = reader.ReadInt16BE(); subglyph.Arg2 = reader.ReadInt16BE(); } else { subglyph.Arg1 = reader.ReadSByte(); subglyph.Arg2 = reader.ReadSByte(); } // figure out the transform; we can either have no scale, a uniform // scale, two independent scales, or a full 2x2 transform matrix // transform components are in 2.14 fixed point format var transform = Matrix3x2.Identity; if ((flags & CompositeGlyphFlags.HaveScale) != 0) { var scale = reader.ReadInt16BE() / F2Dot14ToFloat; transform.M11 = scale; transform.M22 = scale; } else if ((flags & CompositeGlyphFlags.HaveXYScale) != 0) { transform.M11 = reader.ReadInt16BE() / F2Dot14ToFloat; transform.M22 = reader.ReadInt16BE() / F2Dot14ToFloat; } else if ((flags & CompositeGlyphFlags.HaveTransform) != 0) { transform.M11 = reader.ReadInt16BE() / F2Dot14ToFloat; transform.M12 = reader.ReadInt16BE() / F2Dot14ToFloat; transform.M21 = reader.ReadInt16BE() / F2Dot14ToFloat; transform.M22 = reader.ReadInt16BE() / F2Dot14ToFloat; } subglyph.Transform = transform; subglyphs.Add(subglyph); } while ((flags & CompositeGlyphFlags.MoreComponents) != 0); var result = new CompositeGlyph { Subglyphs = subglyphs.ToArray() }; // if we have instructions, read them now if ((flags & CompositeGlyphFlags.HaveInstructions) != 0) { var instructionLength = reader.ReadUInt16BE(); result.Instructions = reader.ReadBytes(instructionLength); } return(result); }
static SimpleGlyph ReadSimpleGlyph(DataReader reader, int contourCount) { // read contour endpoints var contours = new int[contourCount]; var lastEndpoint = reader.ReadUInt16BE(); contours[0] = lastEndpoint; for (int i = 1; i < contours.Length; i++) { var endpoint = reader.ReadUInt16BE(); contours[i] = endpoint; if (contours[i] <= lastEndpoint) { throw new InvalidFontException("Glyph contour endpoints are unordered."); } lastEndpoint = endpoint; } // the last contour's endpoint is the number of points in the glyph var pointCount = lastEndpoint + 1; var points = new Point[pointCount]; // read instruction data var instructionLength = reader.ReadUInt16BE(); var instructions = reader.ReadBytes(instructionLength); // read flags var flags = new SimpleGlyphFlags[pointCount]; int flagIndex = 0; while (flagIndex < flags.Length) { var f = (SimpleGlyphFlags)reader.ReadByte(); flags[flagIndex++] = f; // if Repeat is set, this flag data is repeated n more times if ((f & SimpleGlyphFlags.Repeat) != 0) { var count = reader.ReadByte(); for (int i = 0; i < count; i++) { flags[flagIndex++] = f; } } } // Read points, first doing all X coordinates and then all Y coordinates. // The point packing is insane; coords are either 1 byte or 2; they're // deltas from previous point, and flags let you repeat identical points. var x = 0; for (int i = 0; i < points.Length; i++) { var f = flags[i]; var delta = 0; if ((f & SimpleGlyphFlags.ShortX) != 0) { delta = reader.ReadByte(); if ((f & SimpleGlyphFlags.SameX) == 0) { delta = -delta; } } else if ((f & SimpleGlyphFlags.SameX) == 0) { delta = reader.ReadInt16BE(); } x += delta; points[i].X = (FUnit)x; } var y = 0; for (int i = 0; i < points.Length; i++) { var f = flags[i]; var delta = 0; if ((f & SimpleGlyphFlags.ShortY) != 0) { delta = reader.ReadByte(); if ((f & SimpleGlyphFlags.SameY) == 0) { delta = -delta; } } else if ((f & SimpleGlyphFlags.SameY) == 0) { delta = reader.ReadInt16BE(); } y += delta; points[i].Y = (FUnit)y; points[i].Type = (f & SimpleGlyphFlags.OnCurve) != 0 ? PointType.OnCurve : PointType.Quadratic; } return(new SimpleGlyph { Points = points, ContourEndpoints = contours, Instructions = instructions }); }
static string ExtractString(DataReader reader, uint baseOffset, StringData data) { reader.Seek(baseOffset + data.Offset); var bytes = reader.ReadBytes(data.Length); return Encoding.BigEndianUnicode.GetString(bytes); }
static CompositeGlyph ReadCompositeGlyph(DataReader reader) { // we need to keep reading glyphs for as long as // our flags tell us that there are more to read var subglyphs = new List<Subglyph>(); CompositeGlyphFlags flags; do { flags = (CompositeGlyphFlags)reader.ReadUInt16BE(); var subglyph = new Subglyph { Flags = flags }; subglyph.Index = reader.ReadUInt16BE(); // read in args; they vary in size based on flags if ((flags & CompositeGlyphFlags.ArgsAreWords) != 0) { subglyph.Arg1 = reader.ReadInt16BE(); subglyph.Arg2 = reader.ReadInt16BE(); } else { subglyph.Arg1 = reader.ReadSByte(); subglyph.Arg2 = reader.ReadSByte(); } // figure out the transform; we can either have no scale, a uniform // scale, two independent scales, or a full 2x2 transform matrix // transform components are in 2.14 fixed point format var transform = Matrix3x2.Identity; if ((flags & CompositeGlyphFlags.HaveScale) != 0) { var scale = reader.ReadInt16BE() / F2Dot14ToFloat; transform.M11 = scale; transform.M22 = scale; } else if ((flags & CompositeGlyphFlags.HaveXYScale) != 0) { transform.M11 = reader.ReadInt16BE() / F2Dot14ToFloat; transform.M22 = reader.ReadInt16BE() / F2Dot14ToFloat; } else if ((flags & CompositeGlyphFlags.HaveTransform) != 0) { transform.M11 = reader.ReadInt16BE() / F2Dot14ToFloat; transform.M12 = reader.ReadInt16BE() / F2Dot14ToFloat; transform.M21 = reader.ReadInt16BE() / F2Dot14ToFloat; transform.M22 = reader.ReadInt16BE() / F2Dot14ToFloat; } subglyph.Transform = transform; subglyphs.Add(subglyph); } while ((flags & CompositeGlyphFlags.MoreComponents) != 0); var result = new CompositeGlyph { Subglyphs = subglyphs.ToArray() }; // if we have instructions, read them now if ((flags & CompositeGlyphFlags.HaveInstructions) != 0) { var instructionLength = reader.ReadUInt16BE(); result.Instructions = reader.ReadBytes(instructionLength); } return result; }
static SimpleGlyph ReadSimpleGlyph(DataReader reader, int contourCount) { // read contour endpoints var contours = new int[contourCount]; var lastEndpoint = reader.ReadUInt16BE(); contours[0] = lastEndpoint; for (int i = 1; i < contours.Length; i++) { var endpoint = reader.ReadUInt16BE(); contours[i] = endpoint; if (contours[i] <= lastEndpoint) throw new InvalidFontException("Glyph contour endpoints are unordered."); lastEndpoint = endpoint; } // the last contour's endpoint is the number of points in the glyph var pointCount = lastEndpoint + 1; var points = new Point[pointCount]; // read instruction data var instructionLength = reader.ReadUInt16BE(); var instructions = reader.ReadBytes(instructionLength); // read flags var flags = new SimpleGlyphFlags[pointCount]; int flagIndex = 0; while (flagIndex < flags.Length) { var f = (SimpleGlyphFlags)reader.ReadByte(); flags[flagIndex++] = f; // if Repeat is set, this flag data is repeated n more times if ((f & SimpleGlyphFlags.Repeat) != 0) { var count = reader.ReadByte(); for (int i = 0; i < count; i++) flags[flagIndex++] = f; } } // Read points, first doing all X coordinates and then all Y coordinates. // The point packing is insane; coords are either 1 byte or 2; they're // deltas from previous point, and flags let you repeat identical points. var x = 0; for (int i = 0; i < points.Length; i++) { var f = flags[i]; var delta = 0; if ((f & SimpleGlyphFlags.ShortX) != 0) { delta = reader.ReadByte(); if ((f & SimpleGlyphFlags.SameX) == 0) delta = -delta; } else if ((f & SimpleGlyphFlags.SameX) == 0) delta = reader.ReadInt16BE(); x += delta; points[i].X = (FUnit)x; } var y = 0; for (int i = 0; i < points.Length; i++) { var f = flags[i]; var delta = 0; if ((f & SimpleGlyphFlags.ShortY) != 0) { delta = reader.ReadByte(); if ((f & SimpleGlyphFlags.SameY) == 0) delta = -delta; } else if ((f & SimpleGlyphFlags.SameY) == 0) delta = reader.ReadInt16BE(); y += delta; points[i].Y = (FUnit)y; points[i].Type = (f & SimpleGlyphFlags.OnCurve) != 0 ? PointType.OnCurve : PointType.Quadratic; } return new SimpleGlyph { Points = points, ContourEndpoints = contours, Instructions = instructions }; }
public static byte[] ReadProgram(DataReader reader, TableRecord[] tables, FourCC tag) { var index = FindTable(tables, tag); if (index == -1) return null; reader.Seek(tables[index].Offset); return reader.ReadBytes((int)tables[index].Length); }