protected void ReadXCoordinates(BinaryReaderFont reader, int count) { SimpleGlyphFlags bit1 = SimpleGlyphFlags.X_SHORT_VECTOR; SimpleGlyphFlags bit4 = SimpleGlyphFlags.X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR; xCoordinates = new short[count]; int prevX = 0; for (int i = 0; i < count; i++) { SimpleGlyphFlags flag = flags[i]; int x = 0; if ((flag & bit1) > 0) { x = reader.ReadByte(); if ((flag & bit4) == 0) { x = -x; } } else { if ((flag & bit4) == 0) { x = reader.ReadInt16(); } } xCoordinates[i] = (short)(x + prevX); prevX = xCoordinates[i]; } }
protected void ReadYCoordinates(BinaryReaderFont reader, int count) { SimpleGlyphFlags bit2 = SimpleGlyphFlags.Y_SHORT_VECTOR; SimpleGlyphFlags bit5 = SimpleGlyphFlags.Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR; yCoordinates = new short[count]; int prevY = 0; for (int i = 0; i < count; i++) { SimpleGlyphFlags flag = flags[i]; int y = 0; if ((flag & bit2) > 0) { y = reader.ReadByte(); if ((flag & bit5) == 0) { y = -y; } } else { if ((flag & bit5) == 0) { y = reader.ReadInt16(); } } yCoordinates[i] = (short)(y + prevY); prevY = yCoordinates[i]; } }
private static void ReadSimpleGlyph(TrueTypeDataBytes data, int numberOfContours) { bool HasFlag(SimpleGlyphFlags flags, SimpleGlyphFlags value) { return((flags & value) != 0); } if (numberOfContours == 0) { return; } var endPointsOfContours = new ushort[numberOfContours]; for (var i = 0; i < numberOfContours; i++) { endPointsOfContours[i] = data.ReadUnsignedShort(); } var instructionLength = data.ReadUnsignedShort(); var instructions = new byte[instructionLength]; for (var i = 0; i < instructionLength; i++) { instructions[i] = data.ReadByte(); } var lastPointIndex = endPointsOfContours[numberOfContours - 1]; var pointCount = lastPointIndex + 1; var perPointFlags = new SimpleGlyphFlags[pointCount]; for (var i = 0; i < pointCount; i++) { var flags = (SimpleGlyphFlags)data.ReadByte(); perPointFlags[i] = flags; if (!HasFlag(flags, SimpleGlyphFlags.Repeat)) { continue; } var numberOfRepeats = data.ReadByte(); for (var r = 0; r < numberOfRepeats; r++) { i++; perPointFlags[i] = flags; } } // ReSharper disable UnusedVariable var xCoordinates = ReadCoordinates(perPointFlags, data, SimpleGlyphFlags.XSingleByte, SimpleGlyphFlags.ThisXIsTheSame); var yCoordinates = ReadCoordinates(perPointFlags, data, SimpleGlyphFlags.YSingleByte, SimpleGlyphFlags.ThisYIsTheSame); // ReSharper restore UnusedVariable }
private static SimpleGlyphFlags[] ReadFlags(TrueTypeDataBytes data, int pointCount) { var result = new SimpleGlyphFlags[pointCount]; for (var i = 0; i < pointCount; i++) { result[i] = (SimpleGlyphFlags)data.ReadByte(); } return(result); }
private static short[] ReadCoordinates(SimpleGlyphFlags[] flags, TrueTypeDataBytes data, SimpleGlyphFlags isSingleByte, SimpleGlyphFlags isTheSameAsPrevious) { bool HasFlag(SimpleGlyphFlags set, SimpleGlyphFlags f) { return((set & f) != 0); } var coordinates = new short[flags.Length]; var value = 0; for (var i = 0; i < flags.Length; i++) { var flag = flags[i]; if (HasFlag(flag, isSingleByte)) { var b = data.ReadByte(); // If SingleByte is set, the IsTheSame flag describes the sign of the value, // with a value of 1 equalling positive and a zero value negative. if (HasFlag(flag, isTheSameAsPrevious)) { value += b; } else { value -= b; } } else { short delta; // If this flag is set, then the current coordinate is the same as the previous coordinate. if (HasFlag(flag, isTheSameAsPrevious)) { delta = 0; } else { // If the IsTheSame flag is not set, the current coordinate is a signed 16-bit delta vector. delta = data.ReadSignedShort(); } value += delta; } coordinates[i] = (short)value; } return(coordinates); }
protected void ReadFlags(BinaryReaderFont reader, int count) { flags = new SimpleGlyphFlags[count]; for (int i = 0; i < count; i++) { SimpleGlyphFlags flag = (SimpleGlyphFlags)reader.ReadByte(); flags[i] = flag; if (flag.HasFlag(SimpleGlyphFlags.REPEAT_FLAG)) { int repeat = reader.ReadByte(); for (int n = 0; n <= repeat; n++) { flags[i + n] = flag; } i += repeat; } } }
private static SimpleGlyphFlags[] ReadFlags(TrueTypeDataBytes data, int pointCount) { var result = new SimpleGlyphFlags[pointCount]; for (var i = 0; i < pointCount; i++) { result[i] = (SimpleGlyphFlags)data.ReadByte(); if (result[i].HasFlag(SimpleGlyphFlags.Repeat)) { var numberOfRepeats = data.ReadByte(); for (int j = 0; j < numberOfRepeats; j++) { result[i + j + 1] = result[i]; } i += numberOfRepeats; } } return(result); }
private static short[] ReadCoordinates(TrueTypeDataBytes data, int pointCount, SimpleGlyphFlags[] flags, SimpleGlyphFlags isByte, SimpleGlyphFlags signOrSame) { var xs = new short[pointCount]; var x = 0; for (var i = 0; i < pointCount; i++) { int dx; if (flags[i].HasFlag(isByte)) { var b = data.ReadByte(); dx = flags[i].HasFlag(signOrSame) ? b : -b; } else { if (flags[i].HasFlag(signOrSame)) { dx = 0; } else { dx = data.ReadSignedShort(); } } x += dx; xs[i] = (short)x; } return(xs); }
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 }); }
private void ElaborateCoords(List <SimpleGlyphFlags> flags, List <GlyphPoint> points, Action <int, double> map, SimpleGlyphFlags byteFlag, SimpleGlyphFlags deltaFlag) { var value = 0.0d; for (int i = 0; i < points.Count; i++) { var flag = flags[i]; if (flag.HasFlag(byteFlag)) { if (flag.HasFlag(deltaFlag)) { value += _file.GetUint8(); } else { value -= _file.GetUint8(); } } else if (!flag.HasFlag(deltaFlag)) { value += _file.GetInt16(); } else { // value not changed // this is why X and Y are separate } map(i, value); } }
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)); }
private static short[] ReadCoordinates(TrueTypeDataBytes data, int pointCount, SimpleGlyphFlags[] flags, SimpleGlyphFlags isByte, SimpleGlyphFlags signOrSame) { bool HasFlag(SimpleGlyphFlags value, SimpleGlyphFlags target) { return((value & target) == target); } var xs = new short[pointCount]; var x = 0; for (var i = 0; i < pointCount; i++) { var flag = flags[i]; int dx; if (HasFlag(flag, isByte)) { var b = data.ReadByte(); dx = HasFlag(flag, signOrSame) ? b : -b; } else { if (HasFlag(flag, signOrSame)) { dx = 0; } else { dx = data.ReadSignedShort(); } } x += dx; xs[i] = (short)x; } return(xs); }
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 }; }