FontCollection.cs
// 完毕:
using System;
using System.IO;
using System.Drawing;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;

namespace DsPdfWeb.Demos
{
    // 此示例展示了如何创建、初始化和使用 FontCollection 类,
    // 这是管理字体并在渲染文本时使用它们的推荐方法
    // PDF 文档解决方案。
    // 
    // 要记住的要点以及建议遵循的步骤,
    // 将 FontCollection 与 GcDocs.Pdf 一起使用时:
    // 
    // 1. 创建 FontCollection 类的实例。
    //    FontCollection 不是静态类,您需要它的实例才能使用。
    //    另外,它是 Font 对象的常规 .NET 集合,因此一切正常
    //    可以在其上使用集合操作方法(添加、插入、删除等)。
    // 
    // 2. 使用以下任一方法用字体填充字体集合:
    //    - RegisterDirectory():注册指定目录中找到的所有字体;
    //    - RegisterFont():注册在指定文件中找到的字体;
    //    - 添加(字体):添加您创建的字体实例。
    //    请注意,使用字体集合注册目录或字体是一种快速的方法
    //    和轻量级操作。字体集合实际上并没有加载所有字体数据
    //    当目录或单个字体注册到它时。相反,它只加载
    //    最少的信息,以便快速有效地查找和提供字体
    //    需要的时候。
    // 
    // 3. 将字体集合的实例分配给 TextLayout.FontCollection(并分配给
    //    GcGraphics.FontCollection(如果使用 GcGraphics.MeasureString/DrawString),以便
    //    可以找到正确的字体。
    // 
    // 4. 在文本渲染代码中,通过指定字体名称(TextFormat.FontName、
    //    名称必须完全匹配,但大小写并不重要),字体粗体和斜体
    //    标志(TextFormat.FontBold/FontItalic)。如果请求的合适的粗体/斜体版本
    //    在集合中找到字体,将使用它;否则将应用字体模拟。
    // 
    // 5. FontCollection方法和属性是线程安全的,所以一旦你的字体集合
    //    已填充,您可以缓存并在会话和/或模块之间共享它
    //    您的申请。修改和访问时需要谨慎
    //    不过,字体集合同时来自不同的线程,因为它可能会改变
    //    在集合上的某些条件的检查和对该检查的操作之间。
    //    对于这种情况,提供了 FontCollection.SyncRoot 属性,并且应该使用该属性。
    // 
    //    此示例中的代码说明了上述大部分内容。
    public class FontCollectionTest
    {
        public int CreatePDF(Stream stream)
        {
            // 创建一个 FontCollection 实例:
            var fc = new FontCollection();
            // 使用指定目录中的字体填充它:
            fc.RegisterDirectory(Path.Combine("Resources", "Fonts"));

            // 使用字体集合生成示例文档以提供字体:
            var doc = new GcPdfDocument();
            var page = doc.Pages.Add();
            var g = page.Graphics;

            // 为了使 TextLayout/TextFormat 能够使用字体集合,它必须是
            // 与其关联如下:
            var tl = new TextLayout(g.Resolution) { FontCollection = fc };

            // 使用我们集合中的不同字体渲染一些字符串:
            var tf = new TextFormat() { FontName = "times new roman", FontSize = 16 };
            tl.Append("Using FontCollection to manage fonts and render text\n\n", tf);
            tf.FontSize = 12;
            tl.Append("Text rendered using Times New Roman regular font. \n", tf);
            // 设置字体样式(粗体或斜体)将告诉字体集合
            // 搜索合适的字体(如果没有找到,将使用仿真):
            tf.FontItalic = true;
            tl.Append("Text rendered using Times New Roman italic font. \n", tf);
            // 文本格式在附加文本时应用于文本运行,
            // 所以我们可以重复使用相同的格式,修改其属性
            // 呈现不同格式的文本:
            tf.FontBold = true;
            tl.Append("Text rendered using Times New Roman bold italic font. \n", tf);
            tf.FontItalic = false;
            tl.Append("Text rendered using Times New Roman bold font. \n", tf);
            tf.FontName = "segoe ui";
            tl.Append("Text rendered using Segoe UI bold font. \n", tf);
            tf.FontBold = false;
            tl.Append("Text rendered using Segoe UI regular font. \n", tf);

            // 将页面设置应用到页面布局并渲染页面:
            tl.MaxWidth = page.Size.Width;
            tl.MaxHeight = page.Size.Height;
            tl.MarginAll = 72;
            tl.PerformLayout(true);
            g.DrawTextLayout(tl, PointF.Empty);

            // 如果使用 GcGraphics.DrawString/MeasureString,这将允许 TextLayout
            // 由 GcGraphics 内部创建,用于在字体集合中查找指定字体:
            g.FontCollection = fc;

            // 使用GcGraphics.DrawString显示也使用了字体集合
            // 一旦设置了 FontCollection,图形就会显示:
            g.DrawString("Text rendered using Segoe UI bold, drawn by GcGraphics.DrawString() method.",
                new TextFormat() { FontName = "segoe ui", FontBold = true, FontSize = 10 },
                new PointF(72, tl.ContentRectangle.Bottom + 12));

            // 完毕:
            doc.Save(stream);
            return doc.Pages.Count;
        }
    }
}