【问题标题】:Create subset of a TrueType font file using .NET使用 .NET 创建 TrueType 字体文件的子集
【发布时间】:2011-09-24 03:37:56
【问题描述】:

我正在努力实现以下目标:

  1. 创建仅针对特定字符的原始字体文件的子集
  2. 通过 Google 浏览后,我发现了以下可用 API:
    • WPFGlyphTypeface 类的ComputeSubset 方法@
    • CreateFontPackageFontSub.dll
  3. 虽然我能够创建字体文件的子集 a,但我不确定它是否针对我指定的字符,因为当我打开该文件(双击文件)时,我会看到那里的所有字符。我该如何验证呢? 我在c:\windows\fonts 中安装了它,我可以输入该字体中的所有字符,而我期望它只会显示我选择的字符。
  4. 有没有 TrueType 字体 (TTF) 文件的程序员参考资料,可以帮助我们从编程的角度理解 TTF 文件?

【问题讨论】:

    标签: .net file truetype


    【解决方案1】:

    如果你有兴趣学习TTF规范,可以参考微软TrueType规范v1.66。见http://www.microsoft.com/typography/SpecificationsOverview.mspx

    您会感兴趣的字体表是 CMAP 表,它指定了字符代码到字形索引的映射。

    但是,如果您要做的只是验证子集 TTF 字体是否包含正确的字符,我认为参考规范是一种矫枉过正的做法。

    我建议使用工具将字体内容转储为可读格式。有一个名为 TTX 的工具可以输出给定字体的字体表的 XML 表示。见http://www.letterror.com/code/ttx/index.html

    一旦你让 TTX 运行,你可以运行命令“ttx.exe -tcmap MyFont.ttf”,它应该输出一个文件“MyFont.ttx”。在文本编辑器中打开它,它应该会显示它在字体中找到的所有字符代码

    Ujjwal 问题更新:

    1. 我没有使用 .NET 处理字体的经验;抱歉,我无法帮助您解决 .NET 问题

    2. Otaku 提供的 Apple 链接比 Microsoft 规范更具可读性;请注意,Apple 和 Microsoft 的 TTF 格式规范在某些方面略有不同。

    3. 通常我会说字体的大小取决于保留的字符字形的复杂程度以及是否保留提示数据。从我看到的字体来看,这些数据构成了 TTF 字体的大部分。 (实际上嵌入位图占用更多空间,但根据您提到的字体大小,我敢打赌它不包含嵌入位图)

    4. 不确定这是否有用,但如果您无法使用 .NET 更改字体名称,您可能有兴趣查找名为 FontForge http://fontforge.sourceforge.net/ 的工具。我自己并没有真正使用过它,但我相信它应该允许您更改字体名称。

    【讨论】:

    • 是的,fontforge 是一个很棒的工具。它具有修改字体名称和字体系列的功能。事实上,我正在尝试构建一个类似于 fontforge 的简单工具(使用 C#.net),其目标功能非常有限。
    【解决方案2】:

    你提到的两种方法我都用过,第一种方法要容易得多。这是我使用的代码:

    Imports System.Text.Encoding
    Imports System.Collections
    Imports System.Windows.Media
    Public Class FontManager
        Sub New()
            CreateSubSet("my baloney has a first name", New Uri("C:\Windows\Fonts\impact.ttf"))
        End Sub
        Public Sub CreateSubSet(sourceText As String, fontURI As Uri)
            Dim glyphTypeface As GlyphTypeface = New GlyphTypeface(fontURI)
            Dim Index As Generic.ICollection(Of UShort)
            Index = New Generic.List(Of UShort)
            Dim sourceTextBytes As Byte() = Unicode.GetBytes(sourceText)
            Dim sourceTextChars As Char() = Unicode.GetChars(sourceTextBytes)
            Dim sourceTextCharVal As Integer
            Dim glyphIndex As Integer
            For sourceTextCharPos = 0 To UBound(sourceTextChars)
                sourceTextCharVal = AscW(sourceTextChars(sourceTextCharPos))
                glyphIndex = glyphTypeface.CharacterToGlyphMap(sourceTextCharVal)
                Index.Add(glyphIndex)
            Next
            Dim filebytes() As Byte = glyphTypeface.ComputeSubset(Index)
            Using fileStream As New System.IO.FileStream("C:\Users\Me\Documents\impact-subset.ttf", System.IO.FileMode.Create)
                fileStream.Write(filebytes, 0, filebytes.Length)
            End Using
        End Sub
    End Class
    

    当然对于sourceText,您可以根据需要发送唯一字符。

    gilamesh 提到的链接是学习 TTF 字体的好地方。我发现另一个非常宝贵的参考是http://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html

    【讨论】:

    • 感谢@otaku 和@gilamesh。还有几个问题: 1. 如果我选择子集字体(I/p 到 CreateSubSet:“1234”,O/P 文件:subset.ttf),我希望不显示 1、2、3 和 4 以外的字符(在例如 MS 字)。这是一个正确的期望吗? 2. 使用 GlyphTypeface 类的 ComputeSubset 功能是否足够?还是我需要做一些额外的事情,比如删除不必要的查找表?有任何可用的 API 吗? 3. 字体文件的大小减少与我们作为 i/p 传递的字符成正比? 4.我可以修改字体名称和字体系列吗?
    • 只是为了让自己更清楚,如何验证使用此功能创建的字体子集?我想确保字体子集应该只支持我在设置原始字体时选择的字符?
    • @Ujjwal:我可以回答您的问题。 1) 并不是它们不会显示,而是它们不会以您的子集字体显示,因为它们在该字体中不存在,2)够了,我一直用它,3) 不总是成比例的,但绝对小得多,4) 不,不使用这种方法。为此,您必须进行 P/Invoke 呼叫 - 参见 this page 示例。
    • 对于 .otf 字体文件会导致文件复制。我有什么问题吗?
    • 不确定 Hugo,我已经好几年没看过这个了。
    猜你喜欢
    • 2014-12-07
    • 2010-10-06
    • 2019-12-10
    • 2016-12-28
    • 2012-03-18
    • 2016-05-30
    • 1970-01-01
    • 2011-01-04
    • 2011-06-01
    相关资源
    最近更新 更多