Exemple #1
0
        public IGlyphDescription Merge(IGlyphDescription glyph)
        {
            var newPoints    = MergePoints(glyph);
            var newEndpoints = MergeContourEndPoints(glyph);

            return(new Glyph(false, Instructions, newEndpoints, newPoints, Bounds));
        }
Exemple #2
0
        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));
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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));
        }
Exemple #6
0
        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);
        }
Exemple #8
0
        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;
 }