在C#中查找字形宽度(私有字体)

时间:2018-01-11 13:09:08

标签: c# asp.net pdf fonts

为了在PDF中嵌入字体,需要确定一组字形宽度(包含在元数据中)。为了在文本流动时对文本消耗的页面区域进行计算,需要知道相同的信息。

我正在考虑在Web服务器上使用C#来生成PDF文档。字体不是(也不是)安装的;它们可以从TTF文件/流加载。我需要知道"页面中有多少"将被用于正确处理文本溢出,并且如果要嵌入字体,还需要提供字形宽度。

System.Drawing.Text.PrivateFontCollection可以获得"单元格的上升/下降和行间距,这对垂直计算很有用,但我还需要进行水平计算。

有没有办法从C#访问私有(即未安装)字体的字形宽度而不诉诸于此: How to get glyph widths by parsing a TTF font file?

1 个答案:

答案 0 :(得分:2)

System.Windows.Media(PresentationCore.dll)中的GlyphTypeface类提供了对em的分数的提前宽度的访问。 PDF字体描述符要求宽度为整数千分之一的整数。

using System;
using System.Windows.Media; // requires PresentationCore.dll

namespace ConsoleAppFontMetrics
{
    internal class Metrics
    {
        internal static void PrintWidths(string path)
        {
            var ffs = Fonts.GetFontFamilies(path);
            foreach (var ff in ffs)
            {
                foreach (var t in ff.GetTypefaces())
                {
                    Console.WriteLine(t.Style);
                    if (t.TryGetGlyphTypeface(out GlyphTypeface gt))
                    {
                        foreach (var ctg in gt.CharacterToGlyphMap)
                        {
                            var width = (int)Math.Round(gt.AdvanceWidths[ctg.Value] * 1000);

                            Console.WriteLine($"{(char)ctg.Key} ({ctg.Key}) Width = {width}");
                        }
                    }
                }
            }
        }
    }
}

为我的TrueType字体运行上面的代码给了我:

Normal
a (97) Width = 1160
b (98) Width = 1663
c (99) Width = 2065

输出与先前导出的PDF(来自其他程序)内嵌的字体中的元数据匹配。

8 0 obj
<<
/Type/Font
/Subtype/TrueType
/Name/F2
/BaseFont/XXXXXX
/FontDescriptor 7 0 R
/FirstChar 97
/LastChar 99
/Widths[1160 1663 2065]
>>
endobj