public IGlyphDescription Merge(IGlyphDescription glyph) { var newPoints = MergePoints(glyph); var newEndpoints = MergeContourEndPoints(glyph); return(new Glyph(false, Instructions, newEndpoints, newPoints, Bounds)); }
public static GlyphDataTable Load(TrueTypeDataBytes data, TrueTypeHeaderTable table, TableRegister.Builder tableRegister) { data.Seek(table.Offset); var indexToLocationTable = tableRegister.IndexToLocationTable; var offsets = indexToLocationTable.GlyphOffsets; var entryCount = offsets.Length; var glyphCount = entryCount - 1; var glyphs = new IGlyphDescription[glyphCount]; var emptyGlyph = Glyph.Empty(tableRegister.HeaderTable.Bounds); var compositeLocations = new Dictionary <int, TemporaryCompositeLocation>(); for (var i = 0; i < glyphCount; i++) { if (offsets[i] == offsets[i + 1]) { // empty glyph glyphs[i] = emptyGlyph; continue; } data.Seek(offsets[i] + table.Offset); var contourCount = data.ReadSignedShort(); var minX = data.ReadSignedShort(); var minY = data.ReadSignedShort(); var maxX = data.ReadSignedShort(); var maxY = data.ReadSignedShort(); var bounds = new PdfRectangle(minX, minY, maxX, maxY); // If the number of contours is greater than or equal zero it's a simple glyph. if (contourCount >= 0) { glyphs[i] = ReadSimpleGlyph(data, contourCount, bounds); } else { compositeLocations.Add(i, new TemporaryCompositeLocation(data.Position, bounds, contourCount)); } } // Build composite glyphs by combining simple and other composite glyphs. foreach (var compositeLocation in compositeLocations) { glyphs[compositeLocation.Key] = ReadCompositeGlyph(data, compositeLocation.Value, compositeLocations, glyphs, emptyGlyph); } return(new GlyphDataTable(table, glyphs)); }
private IReadOnlyList <IGlyphDescription> ReadGlyphs() { var data = tableBytes; var offsets = glyphOffsets; var entryCount = offsets.Count; var glyphCount = entryCount - 1; var result = new IGlyphDescription[glyphCount]; var emptyGlyph = Glyph.Empty(maxGlyphBounds); var compositeLocations = new Dictionary <int, TemporaryCompositeLocation>(); for (var i = 0; i < glyphCount; i++) { if (offsets[i + 1] <= offsets[i]) { // empty glyph result[i] = emptyGlyph; continue; } data.Seek(offsets[i]); var contourCount = data.ReadSignedShort(); var minX = data.ReadSignedShort(); var minY = data.ReadSignedShort(); var maxX = data.ReadSignedShort(); var maxY = data.ReadSignedShort(); var bounds = new PdfRectangle(minX, minY, maxX, maxY); // If the number of contours is greater than or equal zero it's a simple glyph. if (contourCount >= 0) { result[i] = ReadSimpleGlyph(data, contourCount, bounds); } else { compositeLocations.Add(i, new TemporaryCompositeLocation(data.Position, bounds, contourCount)); } } // Build composite glyphs by combining simple and other composite glyphs. foreach (var compositeLocation in compositeLocations) { result[compositeLocation.Key] = ReadCompositeGlyph(data, compositeLocation.Value, compositeLocations, result, emptyGlyph); } return(result); }
private GlyphPoint[] MergePoints(IGlyphDescription glyph) { var newPoints = new GlyphPoint[Points.Length + glyph.Points.Length]; for (int i = 0; i < Points.Length; i++) { newPoints[i] = Points[i]; } for (int i = 0; i < glyph.Points.Length; i++) { newPoints[i + Points.Length] = glyph.Points[i]; } return(newPoints); }
public static GlyphDataTable Load(TrueTypeDataBytes data, TrueTypeHeaderTable table, TableRegister tableRegister) { data.Seek(table.Offset); var headerTable = tableRegister.HeaderTable; var indexToLocationTable = tableRegister.IndexToLocationTable; var offsets = indexToLocationTable.GlyphOffsets; var entryCount = offsets.Length; var glyphCount = entryCount - 1; var glyphs = new IGlyphDescription[glyphCount]; for (var i = 0; i < glyphCount; i++) { if (offsets[i] == offsets[i + 1]) { // empty glyph continue; } data.Seek(offsets[i] + table.Offset); var contourCount = data.ReadSignedShort(); var minX = data.ReadSignedShort(); var minY = data.ReadSignedShort(); var maxX = data.ReadSignedShort(); var maxY = data.ReadSignedShort(); var bounds = new PdfRectangle(minX, minY, maxX, maxY); // If the number of contours is greater than or equal zero it's a simple glyph. if (contourCount >= 0) { glyphs[i] = ReadSimpleGlyph(data, contourCount, bounds); } else { } } return(new GlyphDataTable(table, glyphs)); }
private int[] MergeContourEndPoints(IGlyphDescription glyph) { var destinationLastEndPoint = EndPointsOfContours[EndPointsOfContours.Length - 1] + 1; var endPoints = new int[EndPointsOfContours.Length + glyph.EndPointsOfContours.Length]; for (var i = 0; i < EndPointsOfContours.Length; i++) { endPoints[i] = EndPointsOfContours[i]; } for (var i = 0; i < glyph.EndPointsOfContours.Length; i++) { endPoints[i + EndPointsOfContours.Length] = glyph.EndPointsOfContours[i] + destinationLastEndPoint; } return(endPoints); }
/** * Set the points of a glyph from the GlyphDescription. */ private Point[] Describe(IGlyphDescription gd) { int endPtIndex = 0; int endPtOfContourIndex = -1; Point[] points = new Point[gd.PointCount]; for (int i = 0; i < gd.PointCount; i++) { if (endPtOfContourIndex == -1) { endPtOfContourIndex = gd.GetEndPtOfContours(endPtIndex); } bool endPt = endPtOfContourIndex == i; if (endPt) { endPtIndex++; endPtOfContourIndex = -1; } points[i] = new Point(gd.GetXCoordinate(i), gd.GetYCoordinate(i), (gd.GetFlags(i) & GlyfDescript.ON_CURVE) != 0, endPt); } return(points); }
private static IGlyphDescription ReadCompositeGlyph(TrueTypeDataBytes data, TemporaryCompositeLocation compositeLocation, Dictionary <int, TemporaryCompositeLocation> compositeLocations, IGlyphDescription[] glyphs, IGlyphDescription emptyGlyph) { bool HasFlag(CompositeGlyphFlags value, CompositeGlyphFlags target) { return((value & target) == target); } data.Seek(compositeLocation.Position); var components = new List <CompositeComponent>(); // First recursively find all components and ensure they are available. CompositeGlyphFlags flags; do { flags = (CompositeGlyphFlags)data.ReadUnsignedShort(); var glyphIndex = data.ReadUnsignedShort(); var childGlyph = glyphs[glyphIndex]; if (childGlyph == null) { if (!compositeLocations.TryGetValue(glyphIndex, out var missingComposite)) { throw new InvalidOperationException($"The composite glyph required a contour at index {glyphIndex} but there was no simple or composite glyph at this location."); } var position = data.Position; childGlyph = ReadCompositeGlyph(data, missingComposite, compositeLocations, glyphs, emptyGlyph); data.Seek(position); glyphs[glyphIndex] = childGlyph; } short arg1, arg2; if (HasFlag(flags, CompositeGlyphFlags.Args1And2AreWords)) { arg1 = data.ReadSignedShort(); arg2 = data.ReadSignedShort(); } else { arg1 = data.ReadByte(); arg2 = data.ReadByte(); } decimal xscale = 1; decimal scale01 = 0; decimal scale10 = 0; decimal yscale = 1; if (HasFlag(flags, CompositeGlyphFlags.WeHaveAScale)) { xscale = ReadTwoFourteenFormat(data); yscale = xscale; } else if (HasFlag(flags, CompositeGlyphFlags.WeHaveAnXAndYScale)) { xscale = ReadTwoFourteenFormat(data); yscale = ReadTwoFourteenFormat(data); } else if (HasFlag(flags, CompositeGlyphFlags.WeHaveATwoByTwo)) { xscale = ReadTwoFourteenFormat(data); scale01 = ReadTwoFourteenFormat(data); scale10 = ReadTwoFourteenFormat(data); yscale = ReadTwoFourteenFormat(data); } if (HasFlag(flags, CompositeGlyphFlags.ArgsAreXAndYValues)) { components.Add(new CompositeComponent(glyphIndex, new PdfMatrix3By2(xscale, scale01, scale10, yscale, arg1, arg2))); } else { // TODO: Not implemented, it is unclear how to do this. } } while (HasFlag(flags, CompositeGlyphFlags.MoreComponents)); // Now build the final glyph from the components. IGlyphDescription builderGlyph = null; foreach (var component in components) { var glyph = glyphs[component.Index]; var transformed = glyph.Transform(component.Transformation); if (builderGlyph == null) { builderGlyph = transformed; } else { builderGlyph = builderGlyph.Merge(transformed); } } builderGlyph = builderGlyph ?? emptyGlyph; return(new Glyph(false, builderGlyph.Instructions, builderGlyph.EndPointsOfContours, builderGlyph.Points, compositeLocation.Bounds)); }
public GlyphRenderer(IGlyphDescription glyphDescription) { this.glyphDescription = glyphDescription; }