如何在.NET中创建子集字体?

Tod*_*ain 8 .net fonts system.drawing gdi+ truetype

我有一个Silverlight应用程序,我需要嵌入一些不常见的字体.这对我来说很简单,只需复制TTF/OTF并用我的应用程序编译.但是,在许多情况下,实际上只使用了5-10个字符.在其他情况下,一些字体文件非常大(例如Arial Unicode MS Regular是22.1 MB).我的应用程序的快速下载时间非常重要,因此优化使用的字体至关重要.

所以,我在想的是我在Expression Blend等应用程序中看到过,其中a <Glyph/> 用于创建只读字体,你也可以选择只嵌入某些字符.在其他情况下,我看到人们使用仅包含某些字符的字体作为完整字体的子集(而不是<Glyph/>在Silverlight中使用a ,而只是使用子集.TTF作为<FontFamily/>.)这就是什么我在追求,除了我没有使用表达式.

我不是在寻找偷偷摸摸的解决方法,比如导出到XPS文件并抓取.odtff文件.

是否有一种编程方式(.NET/GDI +)来创建只包含某些字符的字体子集并将其编译为.TTF/.OTF?此外,这也需要适用于.TTC文件.

jos*_*736 5

原生API CreateFontPackage可能正是您要寻找的.您可以传递TTF和要保留的字符列表.如果你通过TTFCFP_SUBSETusSubsetFormat,你会再回来,只有那些字符工作TTF.

这是一个线程,看似是一个工作示例的代码(不幸的是在C中).


Eug*_*rda 5

在WPF中,字体有静态和动态链接.这一切都可以在Blend中定义.使用字体的静态链接,只需编译所需的字符并将其嵌入到程序集中.通过动态链接,嵌入了所有字体集.因此,尝试为所选字体设置静态链接,并尝试它是否有效.

UPD

尝试将以下代码添加到您的.csproj文件中.这里我们包括Tahoma字体.AutoFill属性设置为true表示我们将嵌入仅用于控件的汇编中使用的字符.该集字符的<Charachters/>标签填充点包括这些字符转换成汇编.所有其他标签设置为false,因为我们不需要它们.

<ItemGroup>
    <BlendEmbeddedFont Include="Fonts\tahoma.ttf">
      <IsSystemFont>True</IsSystemFont>
      <All>False</All>
      <AutoFill>True</AutoFill>
      <Characters>dasf</Characters>
      <Uppercase>False</Uppercase>
      <Lowercase>False</Lowercase>
      <Numbers>False</Numbers>
      <Punctuation>False</Punctuation>
    </BlendEmbeddedFont>
    <BlendEmbeddedFont Include="Fonts\tahomabd.ttf">
      <IsSystemFont>True</IsSystemFont>
      <All>False</All>
      <AutoFill>True</AutoFill>
      <Characters>dasf</Characters>
      <Uppercase>False</Uppercase>
      <Lowercase>False</Lowercase>
      <Numbers>False</Numbers>
      <Punctuation>False</Punctuation>
    </BlendEmbeddedFont>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

  <Import Project="$(MSBuildExtensionsPath)\Microsoft\Expression\Blend\3.0\WPF\Microsoft.Expression.Blend.WPF.targets" />
Run Code Online (Sandbox Code Playgroud)


Tod*_*ain 4

更改对此的接受答案,因为它是纯 .NET,没有外部引用。使用.NET 4.0:

Imports System.Windows.Media
Imports System.Text.Encoding
Imports System.Collections

Public Sub CreateSubSet(sourceText As String, fontURI As Uri)
    Dim gt As FontEmbeddingManager = New FontEmbeddingManager

    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\new-subset.ttf", System.IO.FileMode.Create)
        fileStream.Write(filebytes, 0, filebytes.Length)
    End Using
End Sub
Run Code Online (Sandbox Code Playgroud)