示例#1
0
        public static FontModel Load(FontSource source)
        {
            var font = new FontModel();

            var offsetTable = OffsetTable.Load(source);

            if (offsetTable.SfntVersion == 0x10000)
            {
                font.Type = FontType.TrueType;
            }
            else if (offsetTable.SfntVersion == 0x4f54544f)
            {
                font.Type = FontType.OpenType;
            }
            else
            {
                throw new FontException($"Unknown sfntVersion: {offsetTable.SfntVersion:X4}");
            }

            var tableOffsets = new Dictionary <string, uint>(offsetTable.NumTables);

            for (var i = 0; i < offsetTable.NumTables; i++)
            {
                var table = TableRecord.Load(source);
                tableOffsets[table.Tag] = table.Offset;
            }

            LoadFontHeader(source, tableOffsets["head"], out var indexToLocFormat, out var unitsPerEm);
            font.BaseScale  = 1f / unitsPerEm;
            font.UnitsPerEm = unitsPerEm;

            var glyphCount = LoadGlyphCount(source, tableOffsets["maxp"]);

            font._glyphs = new GlyphInfo[glyphCount];

            var numberOfHMetrics = LoadNumberOfHMetrics(source, tableOffsets["hhea"]);

            LoadHorizontalMetrics(font, source, tableOffsets["hmtx"], numberOfHMetrics, glyphCount);

            font._glyphIndexMap = LoadCharacterToGlyphIndexMappingTable(source, tableOffsets["cmap"]);

            if (tableOffsets.ContainsKey("loca"))
            {
                font._localOffsets = LoadIndexToLocation(source, tableOffsets["loca"], glyphCount, indexToLocFormat);
            }

            if (tableOffsets.ContainsKey("glyf"))
            {
                font._glyph = new GlyphTable(tableOffsets["glyf"]);
            }

            if (tableOffsets.ContainsKey("CFF"))
            {
                font._cff = CompactFontFormatTable.Load(tableOffsets["CFF"], source, font);
            }

            return(font);
        }
        public static GlyphContourInfoV2 ToVector2(this GlyphContourInfo g, FontModel model, FontSource source)
        {
            switch (model.Type)
            {
            case FontModel.FontType.TrueType:
                return(FromTtfGlyph(g, model, source));

            case FontModel.FontType.OpenType:
                return(FromOtfGlyph(g, model, source));

            default:
                throw new InvalidEnumArgumentException(model.Type.ToString());
            }
        }
示例#3
0
        private static void LoadHorizontalMetrics(FontModel font, FontSource p, uint tableOffset, int numberOfHMetrics, int numGlyphs)
        {
            ushort advancedWidth   = 0;
            short  leftSideBearing = 0;

            p.Offset = tableOffset;
            for (var i = 0; i < numGlyphs; i++)
            {
                if (i < numberOfHMetrics)
                {
                    advancedWidth   = p.ReadUShort();
                    leftSideBearing = p.ReadShort();
                }
                font._glyphs[i] = new GlyphInfo(advancedWidth, leftSideBearing);
            }
        }
        private static GlyphContourInfoV2 FromOtfGlyph(GlyphContourInfo g, FontModel model, FontSource source)
        {
            var advancedWidth   = g.BaseInfo.AdvancedWidth * model.BaseScale;
            var leftSideBearing = g.BaseInfo.LeftSideBearing * model.BaseScale;

            var contours = new List <List <ContourPoint> >();
            List <ContourPoint> contour = null;

            foreach (var cp in g.Path.Points)
            {
                if (cp.isContour)
                {
                    contour = new List <ContourPoint>();
                    contours.Add(contour);
                }

                if (cp.isCurve)
                {
                    contour.Add(new ContourPoint((short)cp.x, (short)cp.y, false));
                }
                else
                {
                    contour.Add(new ContourPoint((short)cp.x, (short)cp.y, true));
                }
            }

            foreach (var c in contours)
            {
                var first = c[0];
                var last  = c[c.Count - 1];
                if (first.X == last.X && first.Y == last.Y)
                {
                    c.RemoveAt(c.Count - 1);
                }
            }

            return(new GlyphContourInfoV2(advancedWidth, leftSideBearing, ContourToVector(contours, model.BaseScale, false)));
        }
        private static GlyphContourInfoV2 FromTtfGlyph(GlyphContourInfo g, FontModel model, FontSource source)
        {
            var advancedWidth   = g.BaseInfo.AdvancedWidth * model.BaseScale;
            var leftSideBearing = g.BaseInfo.LeftSideBearing * model.BaseScale;

            if (g.Header.NumberOfContours > 0)
            {
                var con = new List <List <ContourPoint> >();

                var points = g.Header.GetGlyphPoints(source);
                if (points == null || points.Length == 0)
                {
                    throw new FontException("Cannot get points");
                }

                var list = new List <ContourPoint>();
                con.Add(list);
                for (var i = 0; i < points.Length; i++)
                {
                    var point        = points[i];
                    var contourPoint = new ContourPoint(point.X, point.Y, point.OnCurve);
                    list.Add(contourPoint);

                    if (point.IsEndPoint && i != points.Length - 1)
                    {
                        list = new List <ContourPoint>();
                        con.Add(list);
                    }
                }

                return(new GlyphContourInfoV2(advancedWidth, leftSideBearing, ContourToVector(con, model.BaseScale, true)));
            }
            else
            {
                // Composite Glyph
                var components = g.Header.GetGlyphComponents(source);

                var con = new List <List <ContourPoint> >();

                foreach (var component in components)
                {
                    var cg = model.GetGlyphFromGid(component.GlyphId, source);
                    if (cg.Header.NumberOfContours > 0)
                    {
                        var points = cg.Header.GetGlyphPoints(source);
                        if (points == null || points.Length == 0)
                        {
                            throw new FontException("Cannot get points");
                        }

                        if (component.MatchedPoints == null)
                        {
                            GlyphTable.GlyphHeader.GlyphComponent.TransformPoints(points, component);
                        }
                        else
                        {
                            // MatchedPoints are not supported.
                            break;
                        }

                        var list = new List <ContourPoint>();
                        con.Add(list);
                        for (var i = 0; i < points.Length; i++)
                        {
                            var point = points[i];

                            var contourPoint = new ContourPoint(point.X, point.Y, point.OnCurve);
                            list.Add(contourPoint);

                            if (point.IsEndPoint && i != points.Length - 1)
                            {
                                list = new List <ContourPoint>();
                                con.Add(list);
                            }
                        }
                    }
                }
                return(new GlyphContourInfoV2(advancedWidth, leftSideBearing, ContourToVector(con, model.BaseScale, true)));
            }
        }