Ejemplo n.º 1
0
        internal static Glyph GetGlypUnscaled(Renderer renderer, PointF[] points, int[] contours, float linearHorizontalAdvance, SimpleGlyph simpleGlyph)
        {
            var g = new Glyph
            {
                renderer         = renderer,
                points           = points,
                contours         = contours,
                ContourEndpoints = simpleGlyph.ContourEndpoints
            };

            if (g.points.Length == 0)
            {
                return(g);
            }

            // TODO (mr): Check if this is working correctly accross all our implementations
            g.HorizontalMetrics = new GlyphMetrics(new Vector2(0, 0), points[^ 1].P.X - points[^ 2].P.X, linearHorizontalAdvance);
Ejemplo n.º 2
0
        public static void ReadGlyph(
            DataReader reader, int glyphIndex, int recursionDepth,
            BaseGlyph[] glyphTable, uint glyfOffset, uint glyfLength, uint *loca
            )
        {
            // check if this glyph has already been loaded; this can happen
            // if we're recursively loading subglyphs as part of a composite
            if (glyphTable[glyphIndex] != null)
            {
                return;
            }

            // prevent bad font data from causing infinite recursion
            if (recursionDepth > MaxRecursion)
            {
                throw new InvalidFontException("Bad font data; infinite composite recursion.");
            }

            // check if this glyph doesn't have any actual data
            GlyphHeader header;
            var         offset = loca[glyphIndex];

            if ((glyphIndex < glyphTable.Length - 1 && offset == loca[glyphIndex + 1]) || offset >= glyfLength)
            {
                // this is an empty glyph, so synthesize a header
                header = default(GlyphHeader);
            }
            else
            {
                // seek to the right spot and load the header
                reader.Seek(glyfOffset + loca[glyphIndex]);
                header = new GlyphHeader
                {
                    ContourCount = reader.ReadInt16BE(),
                    MinX         = reader.ReadInt16BE(),
                    MinY         = reader.ReadInt16BE(),
                    MaxX         = reader.ReadInt16BE(),
                    MaxY         = reader.ReadInt16BE()
                };

                if (header.ContourCount < -1 || header.ContourCount > MaxContours)
                {
                    throw new InvalidFontException("Invalid number of contours for glyph.");
                }
            }

            if (header.ContourCount > 0)
            {
                // positive contours means a simple glyph
                glyphTable[glyphIndex] = ReadSimpleGlyph(reader, header.ContourCount);
            }
            else if (header.ContourCount == -1)
            {
                // -1 means composite glyph
                var composite = ReadCompositeGlyph(reader);
                var subglyphs = composite.Subglyphs;

                // read each subglyph recrusively
                for (var i = 0; i < subglyphs.Length; i++)
                {
                    ReadGlyph(reader, subglyphs[i].Index, recursionDepth + 1, glyphTable, glyfOffset, glyfLength, loca);
                }

                glyphTable[glyphIndex] = composite;
            }
            else
            {
                // no data, so synthesize an empty glyph
                glyphTable[glyphIndex] = new SimpleGlyph
                {
                    Points           = new Point[0],
                    ContourEndpoints = new int[0]
                };
            }

            // save bounding box
            var glyph = glyphTable[glyphIndex];

            glyph.MinX = header.MinX;
            glyph.MinY = header.MinY;
            glyph.MaxX = header.MaxX;
            glyph.MaxY = header.MaxY;
        }