FontFallbacks.cs
// 完毕:
using System;
using System.IO;
using System.Drawing;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GCTEXT = GrapeCity.Documents.Text;
using GCDRAW = GrapeCity.Documents.Drawing;
namespace DsPdfWeb.Demos.Basics
{
// 后备字体是用于绘制不存在的字形的字体
// 以应用程序指定的字体。
// GcDocs.Pdf 提供后备字体系列的默认列表
// 自动初始化,并包含大字体
// 通常适合用作许多人的后备
// 某些常见字体没有字形的语言。
// 这些自动添加的后备字体系列可用
// 通过 FontCollection.SystemFonts 静态集合上的方法。
// 您可以自定义默认(且依赖于系统)行为
// 通过提供您自己的后备字体,并添加它们
// 由全局 FontCollection.SystemFonts 管理的后备,
// 通过将它们添加到您自己的 FontCollection 实例中,
// 或您正在使用的特定字体。
// 通过这种方式可以微调后备字体行为
// 并且完全独立于系统。
//
// 此示例演示了基本的后备行为 -
// 清除系统回退并再次重新添加它们。
// 此外,它还打印后备字体列表
// 在当前系统上找到。
public class FontFallbacks
{
public int CreatePDF(Stream stream)
{
// 设置 GcPdfDocument:
var doc = new GcPdfDocument();
var g = doc.NewPage().Graphics;
// 设置一些辅助变量来渲染文本行:
const float margin = 36;
// 插入点(GcDocs.Pdf 的默认分辨率为 72dpi,周围使用 1/2" 边距):
var ip = new PointF(margin, margin);
// 使用一种标准字体初始化文本格式。标准字体最少
// 并且包含很少的非拉丁字符的字形。
var tf = new TextFormat() { Font = StandardFonts.Courier, FontSize = 14 };
// 获取后备字体系列列表:
string[] fallbacks = FontCollection.SystemFonts.GetFallbackFontFamilies();
// 清除全局后备列表:
FontCollection.SystemFonts.ClearFallbackFontFamilies();
FontCollection.SystemFonts.ClearFallbackFonts();
// 现在没有全局后备字体,因此日语文本使用
// 标准字体将产生“空白框”而不是真正的日语字符:
g.DrawString("A Japanese text that won't render: あなたは日本語を話せますか?", tf, ip);
ip.Y += 36;
// 将后备字体系列的原始列表重新添加到全局 SystemFonts:
FontCollection.SystemFonts.AppendFallbackFontFamilies(fallbacks);
// 在某些系统上,默认系统后备可能不提供日语字形,
// 所以我们添加自己的后备以防万一:
var arialuni = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "arialuni.ttf"));
FontCollection.SystemFonts.AppendFallbackFonts(arialuni);
// 现在后备字体再次可用,将呈现相同的日语文本
// 正确地,因为将找到适当的后备:
g.DrawString("Same text with fallbacks available: あなたは日本語を話せますか?", tf, ip);
ip.Y += 36;
// 最后,我们列出所有后备并使用每个后备打印测试行:
Action<string> drawTestLine = (fnt_) =>
{
var tf1 = new TextFormat() { FontName = fnt_ };
var tstr = $"{fnt_}: The quick brown fox jumps over the lazy dog.";
var s = g.MeasureString(tstr, tf1, doc.PageSize.Width - margin * 2);
g.DrawString(tstr, tf1, new RectangleF(ip, s));
ip.Y += s.Height * 1.5f;
if (ip.Y > doc.Pages.Last.Size.Height - margin * 2)
{
g = doc.NewPage().Graphics;
ip.Y = 36;
}
};
foreach (var fnt in fallbacks)
drawTestLine(fnt);
// 完毕:
doc.Save(stream);
return doc.Pages.Count;
}
}
}