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;
        }
    }
}