DropCap.cs
// 完毕:
using System;
using System.Collections.Generic;
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 中创建首字下沉。
    public class DropCap
    {
        public int CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            var g = doc.NewPage().Graphics;
            // 获取一些文本并将其拆分为第一个字母(首字下沉)和其余字母:
            var text = Common.Util.LoremIpsum(1);
            var head = text.Substring(0, 1);
            var tail = text.Substring(1);
            // 使用 Times 字体:
            var font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "times.ttf"));
            // 首字下沉的文本布局:
            var tlHead = g.CreateTextLayout();
            tlHead.DefaultFormat.Font = font;
            tlHead.DefaultFormat.FontSize = 40;
            tlHead.Append(head);
            tlHead.PerformLayout(true);
            // 其余文本的文本布局:
            var tlTail = g.CreateTextLayout();
            tlTail.DefaultFormat.Font = font;
            tlTail.DefaultFormat.FontSize = 12;
            // 使用四周留有 1 英寸边距的整页:
            tlTail.MaxWidth = doc.Pages.Last.Size.Width - 72 * 2;
            tlTail.MaxHeight = doc.Pages.Last.Size.Height - 72 * 2;
            tlTail.Append(tail);
            // 在我们布局文本主体之前,我们计算一下大小和位置
            // 的首字下沉矩形,并将其添加到主文本布局的 ObjectRects -
            // 主要文本将围绕的矩形列表。
            // 
            // 注意:虽然我们可以简单地将首字下沉矩形放置在顶部/左侧
            // 主要文本,如果首字下沉的顶部和主要文本的字形看起来更好
            // 对齐。为此,我们需要计算字母顶部的偏移量
            // 文本边界框,并相应地调整首字下沉的位置
            // (稍微提高一点)。
            // (对于此调整,我们需要 sCapHeight 字段,如果字体的
            // os/2 表版本 2 及更高版本,因此我们必须对此进行测试,并在以下情况下跳过此步骤
            // CapHeight 不可用)。
            float dy = 0;
            if (font.CapHeight != -1)
            {
                // 我们将首字下沉位置向上移动,移动量等于
                // 首字下沉字体大小和文本其余部分的字体大小的 Em 方块内的顶部间距:
                float k = tlHead.DefaultFormat.FontSize * tlHead.Resolution * tlHead.FontScaleFactor / (font.UnitsPerEm * 72);
                dy = (font.HorizontalAscender - font.CapHeight) * k;
                k /= tlHead.DefaultFormat.FontSize;
                k *= tlTail.DefaultFormat.FontSize;
                dy -= (font.HorizontalAscender - font.SmallXHeight) * k;
            }
            // 指定主要文本围绕的矩形:
            tlTail.ObjectRects = new List<ObjectRect>() { new ObjectRect(0, -dy, tlHead.ContentWidth * 1.2f, tlHead.ContentHeight) };
            // 现在布局正文:
            tlTail.PerformLayout(true);
            // 画出一切:
            g.DrawTextLayout(tlHead, new PointF(72, 72 - dy));
            g.DrawTextLayout(tlTail, new PointF(72, 72));
            // 完毕:
            doc.Save(stream);
            return doc.Pages.Count;
        }
    }
}