使用应用程序打包字体

本主题概述如何使用 Windows Presentation Foundation (WPF) 应用程序打包字体。

注意

与大多数类型的软件一样,字体文件是许可的,而不是出售的。 管理字体使用的许可证因供应商而异,但一般情况下,大多数许可证(包括涵盖应用程序和 Windows 随附的字体Microsoft的许可证)不允许将字体嵌入到应用程序内,或者重新分发。 因此,作为开发人员,你有责任确保你在应用程序中嵌入或以其他方式重新分发的任何字体拥有所需的许可证权限。

打包字体简介

可以轻松地将字体打包为 WPF 应用程序中的资源,以显示用户界面文本和其他类型的基于文本的内容。 字体可以独立于应用程序的程序集文件,也可以嵌入在这些文件中。 还可以创建仅限资源的字体库,应用程序可以引用该库。

OpenType 和 TrueType® 字体包含一个类型标志 fsType,用于指示这些字体的嵌入许可权限。 但是,此类型标志仅引用存储在文档中的嵌入字体-它不引用应用程序中嵌入的字体。 可以通过创建 GlyphTypeface 对象并引用其 EmbeddingRights 属性来检索字体的字体嵌入权限。 有关 fsType 标志的详细信息,请参阅 OpenType 规范 的“OS/2 和 Windows 指标”部分。

Microsoft版式 网站包含可帮助查找特定字体供应商或查找用于自定义工作的字体供应商的联系信息。

将字体添加为内容项

可以将字体作为独立于应用程序的程序集文件的项目内容项添加到应用程序。 这意味着内容元素不会嵌入为程序集中的资源。 以下项目文件示例演示如何定义内容项。

<Project DefaultTargets="Build"  
                xmlns="http://schemas.microsoft.com/developer/msbuild/2003">  
  <!-- Other project build settings ... -->  
  
  <ItemGroup>  
    <Content Include="Peric.ttf" />  
    <Content Include="Pericl.ttf" />  
  </ItemGroup>  
</Project>  

为了确保应用程序可以在运行时使用字体,必须在应用程序的部署目录中访问字体。 应用程序项目文件中的 <CopyToOutputDirectory> 元素允许在生成过程中自动将字体复制到应用程序部署目录。 以下项目文件示例演示如何将字体复制到部署目录。

<ItemGroup>  
  <Content Include="Peric.ttf">  
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>  
  </Content>  
  <Content Include="Pericl.ttf">  
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>  
  </Content>  
</ItemGroup>  

下面的代码示例演示如何将应用程序的字体作为内容项引用,所引用的内容项必须与应用程序的程序集文件位于同一目录中。

<TextBlock FontFamily="./#Pericles Light">
  Aegean Sea
</TextBlock>

将字体添加为资源项

可以将字体作为嵌入到应用程序的程序集文件中的项目资源项添加到应用程序。 对资源使用单独的子目录有助于组织应用程序的项目文件。 以下项目文件示例演示如何将字体定义为单独的子目录中的资源项。

<Project DefaultTargets="Build"  
                xmlns="http://schemas.microsoft.com/developer/msbuild/2003">  
  <!-- Other project build settings ... -->  
  
  <ItemGroup>  
    <Resource Include="resources\Peric.ttf" />  
    <Resource Include="resources\Pericl.ttf" />  
  </ItemGroup>  
</Project>  

注意

将字体作为资源添加到应用程序时,请确保设置 <Resource> 元素,而不是应用程序项目文件中的 <EmbeddedResource> 元素。 不支持生成操作的 <EmbeddedResource> 元素。

以下标记示例演示如何引用应用程序的字体资源。

<TextBlock FontFamily="./resources/#Pericles Light">
  Aegean Sea
</TextBlock>

从代码中引用字体资源项

若要从代码引用字体资源项,必须提供由两部分构成的字体资源引用:基本统一资源标识符(URI):和字体位置参考。 这些值用作 FontFamily 方法的参数。 下面的代码示例演示如何在名为 resources的项目子目录中引用应用程序的字体资源。

// The font resource reference includes the base URI reference (application directory level),
// and a relative URI reference.
myTextBlock.FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "./resources/#Pericles Light");
' The font resource reference includes the base URI reference (application directory level),
' and a relative URI reference.
myTextBlock.FontFamily = New FontFamily(New Uri("pack://application:,,,/"), "./resources/#Pericles Light")

基本统一资源标识符(URI)可以包括字体资源所在的应用程序子目录。 在这种情况下,字体位置引用不需要指定目录,但必须包含前导“./”,这表示字体资源位于基本统一资源标识符(URI)指定的同一目录中。 下面的代码示例演示了引用字体资源项的替代方法,它等效于前面的代码示例。

// The base URI reference can include an application subdirectory.
myTextBlock.FontFamily = new FontFamily(new Uri("pack://application:,,,/resources/"), "./#Pericles Light");
' The base URI reference can include an application subdirectory.
myTextBlock.FontFamily = New FontFamily(New Uri("pack://application:,,,/resources/"), "./#Pericles Light")

引用同一应用程序子目录中的字体

可以将应用程序内容和资源文件放在应用程序项目的同一用户定义的子目录中。 以下项目文件示例显示了在同一子目录中定义的内容页和字体资源。

<ItemGroup>  
  <Page Include="pages\HomePage.xaml" />  
</ItemGroup>  
<ItemGroup>  
  <Resource Include="pages\Peric.ttf" />  
  <Resource Include="pages\Pericl.ttf" />  
</ItemGroup>  

由于应用程序内容和字体位于同一个子目录中,因此字体引用相对于应用程序内容。 以下示例演示如何在字体与应用程序位于同一目录中时引用应用程序的字体资源。

<TextBlock FontFamily="./#Pericles Light">
  Aegean Sea
</TextBlock>
// The font resource reference includes the base Uri (application directory level),
// and the file resource location, which is relative to the base Uri.
myTextBlock.FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "/pages/#Pericles Light");
' The font resource reference includes the base Uri (application directory level),
' and the file resource location, which is relative to the base Uri.
myTextBlock.FontFamily = New FontFamily(New Uri("pack://application:,,,/"), "/pages/#Pericles Light")

枚举应用程序中的字体

若要将字体枚举为应用程序中的资源项,请使用 GetFontFamiliesGetTypefaces 方法。 以下示例演示如何使用 GetFontFamilies 方法从应用程序字体位置返回 FontFamily 对象的集合。 在这种情况下,应用程序包含名为“resources”的子目录。

foreach (FontFamily fontFamily in Fonts.GetFontFamilies(new Uri("pack://application:,,,/"), "./resources/"))
{
    // Perform action.
}
For Each fontFamily As FontFamily In Fonts.GetFontFamilies(New Uri("pack://application:,,,/"), "./resources/")
    ' Perform action.
Next fontFamily

以下示例演示如何使用 GetTypefaces 方法从应用程序字体位置返回 Typeface 对象的集合。 在这种情况下,应用程序包含名为“resources”的子目录。

foreach (Typeface typeface in Fonts.GetTypefaces(new Uri("pack://application:,,,/"), "./resources/"))
{
    // Perform action.
}
For Each typeface As Typeface In Fonts.GetTypefaces(New Uri("pack://application:,,,/"), "./resources/")
    ' Perform action.
Next typeface

创建字体资源库

可以创建一个仅包含字体的资源库,此类库项目不包含任何代码。 创建仅资源库是将资源与使用这些库的应用程序代码分离的常见技术。 这还允许将库程序集包含在多个应用程序项目中。 以下项目文件示例展示了一个仅含资源的库项目的关键部分。

<PropertyGroup>  
  <AssemblyName>FontLibrary</AssemblyName>  
  <OutputType>library</OutputType>  
  ...  
</PropertyGroup>  
...
<ItemGroup>  
  <Resource Include="Kooten.ttf" />  
  <Resource Include="Pesca.ttf" />  
</ItemGroup  

引用资源库中的字体

若要从应用程序引用资源库中的字体,必须以库程序集的名称为字体引用前缀。 在这种情况下,字体资源程序集为“FontLibrary”。 若要将程序集名称与程序集内的引用分开,请使用“;”字符。 添加“Component”关键字后跟对字体名称的引用完成对字体库资源的完整引用。 下面的代码示例演示如何引用资源库程序集中的字体。

<Run FontFamily="/FontLibrary;Component/#Kootenay" FontSize="36">
  ABCDEFGHIJKLMNOPQRSTUVWXYZ
</Run>

注意

此 SDK 包含一组可用于 WPF 应用程序的示例 OpenType 字体。 字体在仅限资源的库中定义。 有关详细信息,请参阅 示例 OpenType 字体包

字体使用限制

以下列表描述了在 WPF 应用程序中打包和使用字体的若干限制:

  • 字体嵌入权限位: WPF 应用程序不会检查或强制实施任何字体嵌入权限位。 有关详细信息,请参阅 打包字体介绍 部分。

  • 源自站点的字体: WPF 应用程序不允许对使用 http 或 ftp 统一资源标识符(URI)的字体进行引用。

  • 使用包:表示法 绝对 URI: WPF 应用程序不允许使用“pack:”以编程方式使用“pack:”创建 FontFamily 对象,作为对字体的绝对统一资源标识符(URI)引用的一部分。 例如,"pack://application:,,,/resources/#Pericles Light" 是无效的字体引用。

  • 自动嵌入字体:在设计时,不支持搜索应用程序的字体,并自动将字体嵌入应用程序的资源中。

  • 字体子集: WPF 应用程序不支持为非固定文档创建字体子集。

  • 如果引用不正确,应用程序会回退到使用可用字体。

另请参阅