概述

许多文档格式都与字体紧密绑定。例如,当用户向 DOCX 文档中添加文本时,这段文本总是具有某种已定义的字体。有些文档格式通常会将字体数据嵌入到文档文件本身中,比如 PDF。但其他格式,如 Office 系列格式,通常依赖于操作系统中已安装的字体。

字体格式也有很多。例如,绝大多数已安装的字体以 TTF(TrueType)OTF(OpenType) 格式呈现。Office Open XML 文档还支持 EOT(Embedded OpenType) 格式。而在 Web 上,最常用的格式是 WOFFWOFF2

目录

获取所有使用的字体

在字体相关的场景中,最有用的功能是列出并返回它们。GroupDocs.Viewer 提供了一个专用方法 GetAllFonts() —— 当文档被加载到 Viewer 类的实例中时,调用此方法即可获取文档中使用的所有字体列表。返回的列表中,每个字体都以实现了 IFontInfo 接口的对象形式呈现。该接口包含每种可能字体的通用属性:族名、样式、格式以及二进制内容。

特定格式族(如 WordProcessing、Spreadsheet、Presentation 和 PDF)都有各自对 IFontInfo 的实现;这些实现提供了针对相应格式族的更多专有数据。例如,WordProcessingFontInfoPresentationFontInfoPdfFontInfo 类型包含 IsEmbedded 布尔属性——用于指示该字体是嵌入在已加载文档主体中,还是已安装在操作系统中。SpreadsheetFontInfo 类型则包含大量电子表格专用的字体信息:颜色、是否加下划线或删除线等。WordProcessingFontInfo 可能还包含备用族名,诸如此类。

下面给出一个简短示例:

using GroupDocs.Viewer;
// ...

const string filename = "sample.docx";
string inputPath = "\full\path\" + filename;

using (Viewer viewer = new Viewer(inputPath))
{
    Fonts.IFontInfo[] allFonts = viewer.GetAllFonts();
    Console.WriteLine("{0} fonts found in the '{1}' document", allFonts.Length, filename);
    foreach (Fonts.IFontInfo font in allFonts)
    {
        Console.WriteLine("Font '{0}' of '{1}' style has {2} bytes and is of '{3}' format",
            font.FamilyName,
            font.Style,
            font.Content.Length,
            font.Format);
    }
}

请注意,字体提取仅支持 WordProcessing、Spreadsheet、Presentation 和 PDF 这几类格式;对于其他文档格式,GetAllFonts() 方法将返回空数组。

处理缺失的字体

一种常见情形是:文档最初在作者机器上创建并使用了某种字体 “AAA”,随后在 客户机器上使用 GroupDocs.Viewer 进行处理,而该机器缺少字体 “AAA”。此时 GroupDocs.Viewer 会尝试 替代该字体,使用一套复杂的字体替代规则:它会分析文档的元数据、缺失字体的备用名称、文档设置、操作系统设置、系统已安装的所有字体等。最终,如果操作系统“非常干净”,即根本没有任何已安装字体,GroupDocs.Viewer 将使用嵌入在 GroupDocs.Viewer 程序集中(DLL)的字体作为最后的补救。例如,对于 WordProcessing 系列格式,GroupDocs.Viewer 内部存储了免费字体 “Fanwood”。

当前,GroupDocs.Viewer 在文档 渲染期间(调用 Viewer.View() 方法时)静默执行 字体替代 操作——不会产生任何消息或事件来告知哪些字体缺失、被替代为哪种字体、以及具体针对哪个文档。实现此类通知功能相当困难,因为很难确定应以何种形式、何种内容提供通知,以及客户端应如何利用这些信息。

不过,GroupDocs.Viewer 为用户提供了两种解决方案:手动 指定 缺失字体,或手动 替代 缺失字体。

指定缺失的字体

如果用户一开始就知道某个文档使用了字体 “AAA”,并且知道目标机器上没有安装该字体,同时手头拥有该字体 “AAA”的二进制内容,则可以在调用 Viewer.View() 方法之前 指定 该字体。

要指定一个或多个未在目标操作系统中安装的自定义字体,用户需要 添加自定义字体来源字体来源 实际上是一个文件夹,里面存放一个或多个字体文件。对应的类是 FolderFontSource。随后通过 FontSettings 类的 SetFontSources() 方法将 字体来源 添加到 GroupDocs.Viewer。

下面的代码片段演示了这一过程。假设 “sample.docx” 文档使用了罕见字体 “AAA.ttf”,该字体未安装在目标操作系统中。用户将 “AAA.ttf” 放入 "C:\custom_fonts" 文件夹,然后创建指向该文件夹的 FolderFontSource 实例。随后将该实例传递给 FontSettings 静态类,最后将 “sample.docx” 渲染为 HTML。结果,在生成的 HTML 文档中会使用 “AAA” 字体。

using GroupDocs.Viewer;
using GroupDocs.Viewer.Options;
using GroupDocs.Viewer.Fonts;
// ...

// 指定字体来源。
FolderFontSource fontSource = 
    new FolderFontSource(@"C:\custom_fonts", SearchOption.TopFolderOnly);
FontSettings.SetFontSources(fontSource);

using (Viewer viewer = new Viewer("sample.docx"))
{
    // 创建 HTML 文件。
    HtmlViewOptions viewOptions = HtmlViewOptions.ForEmbeddedResources();
    viewer.View(viewOptions);
}

替换缺失的字体

如果用户一开始就知道某个文档使用了字体 “AAA”,并且知道目标机器上没有该字体,但手头 没有 该字体的二进制内容,则可以指定另一种字体 “BBB”,让它在渲染时 代替 缺失的 “AAA”。与前一种情况不同,这需要通过 视图选项 来实现,然后将这些选项传递给 Viewer.View() 方法。

此选项称为 DefaultFontName,它是抽象类 BaseViewOptions 中声明的字符串属性,因此对所有渲染选项均通用:HtmlViewerOptionsPdfViewOptionsPngViewOptions、以及 JpgViewOptions

当指定此选项后,GroupDocs.Viewer 在渲染时会使用该字体来替代所有不可用的字体。例如,文档包含非英文字符的字体时,指定默认字体名称可确保 GroupDocs.Viewer 用具有相同字符集的字体来替换任何缺失的字体。当然,DefaultFontName 所指的字体必须已安装在执行渲染的操作系统上。

以下代码片段演示了如何设置默认字体名称:

using GroupDocs.Viewer;
using GroupDocs.Viewer.Options;
// ...

using (Viewer viewer = new Viewer("sample.pptx"))
{
    // 创建用于渲染 HTML 文档(带嵌入资源)的选项。
    HtmlViewOptions viewOptions = HtmlViewOptions.ForEmbeddedResources();
   
    // 在选项中指定默认字体名称。
    viewOptions.DefaultFontName = "Courier New";
    
    // 将输入 PPTX 渲染为输出 HTML。
    viewer.View(viewOptions);
}          

在 HTML 中排除字体

将文档渲染为 HTML 格式时,GroupDocs.Viewer 默认会把所有使用的字体导出到 HTML 文档中。这保证了即使观看设备上缺少相应字体,也能正确显示。字体可以作为外部资源(HtmlViewOptions.ForExternalResources)存储,亦或通过 data URI scheme 结合 base64 编码直接嵌入到 HTML 标记中(HtmlViewOptions.ForEmbeddedResources)。几乎所有自身支持字体的文档格式都支持导出字体到 HTML:Microsoft Office(除 Excel 外)、OpenDocument、电子邮件、PDF、电子书等。

然而,有时该功能并非所需。实际上,嵌入字体会显著增大生成的 HTML 文档体积。如果目标机器或设备已经预装了所有使用的字体,浏览器完全可以直接使用系统字体。

为满足此类需求,GroupDocs.Viewer 提供了 排除字体 的能力,可通过两种方式实现:排除所有字体仅排除特定字体

这两种方式均通过 HtmlViewOptions 类的不同属性来控制:

  • ExcludeFonts 是一个布尔标记,启用后(true)会禁止将任何使用的字体导出到生成的 HTML 文档中,默认值为 false(未禁用)。
  • FontsToExclude 是一个字符串列表,每个元素表示一个需要从生成的 HTML 文档中排除的字体名称。默认情况下列表为空——不排除任何字体。请注意,仅当 ExcludeFontsfalse 时此属性才会生效。

下面的两个代码片段分别演示了这两种可能性:第一个使用 ExcludeFonts,第二个使用 FontsToExclude

using GroupDocs.Viewer;
using GroupDocs.Viewer.Options;
// ...

using (Viewer viewer = new Viewer("sample.docx"))
{
    // 创建 HTML 文件。
    var viewOptions = HtmlViewOptions.ForEmbeddedResources();    
    viewOptions.ExcludeFonts = true;
    viewer.View(viewOptions);
}
using GroupDocs.Viewer;
using GroupDocs.Viewer.Options;
// ...

using (Viewer viewer = new Viewer("presentation.pptx"))
{
    // 创建 HTML 文件。
    var viewOptions = HtmlViewOptions.ForEmbeddedResources();    
    viewOptions.FontsToExclude.Add("Times New Roman"); // 排除 Times New Roman 字体。
    viewOptions.FontsToExclude.Add("Arial"); // 排除 Arial 字体。
    viewer.View(viewOptions);
}

结论

GroupDocs.Viewer 的核心定位是将各种格式的文档渲染为常见的“可查看”格式——HTML、PDF、JPEG 和 PNG。近期我们在字体处理方面新增了多项实用功能,帮助用户查看和检查使用的字体、调节字体导出行为以及自定义字体替代策略。

另请参阅

获取免费试用版

您可以从 releases.groupdocs.com 下载 GroupDocs.Viewer for .NET 的免费试用版。也可以通过此处获取临时许可证,以无限制地试用全部功能和特性。