VerticalTextJP.cs
// 完毕:
using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using GrapeCity.Documents.Drawing;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GCTEXT = GrapeCity.Documents.Text;
using GCDRAW = GrapeCity.Documents.Drawing;

namespace DsPdfWeb.Demos.Basics
{
    // 使用具有水平列的布局绘制从右到左的垂直日语文本。
    // 另请参阅ArabicColumnsMultiLangVerticalText。
    public class VerticalTextJP
    {
        const string text = "日本語(にほんご、にっぽんご)は、主として、日本列島で使用されてきた言語である。日本手話を母語とする者などを除いて、ほぼ全ての日本在住者は日本語を第一言語とする。日本国は法令上、公用語を明記していないが、事実上の公用語となっており、学校教育の「国語」で教えられる。使用者は、日本国内を主として約\uFF11億\uFF13千万人。日本語の文法体系や音韻体系を反映する手話として日本語対応手話がある。";

        public int CreatePDF(Stream stream)
        {
            using (var clouds = GCDRAW.Image.FromFile(Path.Combine("Resources", "Images", "clouds.jpg")))
            using (var firth = GCDRAW.Image.FromFile(Path.Combine("Resources", "Images", "firth.jpg")))
            using (var lavender = GCDRAW.Image.FromFile(Path.Combine("Resources", "Images", "lavender.jpg")))
            {
                var yumin = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "yumin.ttf"));
                var ia = new ImageAlign(ImageAlignHorz.Left, ImageAlignVert.Top, true, true, true, false, false);

                var doc = new GcPdfDocument();

                // 将保存并呈现文本的 TextLayout:
                var tl = new TextLayout(72);
                tl.FirstLineIndent = 18;
                tl.ParagraphSpacing = 6;
                tl.FlowDirection = FlowDirection.VerticalRightToLeft;
                tl.TextAlignment = TextAlignment.Justified;
                var tf = new TextFormat() { Font = yumin, FontSize = 12 };
                // 重复测试文本以填充几页:
                for (int i = 0; i < 25; ++i)
                {
                    tl.Append(text, tf);
                    tl.AppendLine();
                }

                // 将文本布局为 4 个水平列:
                // (此示例中的逻辑/代码与ArabicColumns相同):
                const int NCOLS = 4;
                var margin = 36f;
                var gap = 18f;
                var page = doc.NewPage();
                page.Landscape = true;
                var colHeight = (page.Size.Height - margin * 2 - gap * (NCOLS - 1)) / NCOLS;
                tl.MaxWidth = page.Size.Width;
                tl.MaxHeight = page.Size.Height;
                tl.MarginLeft = tl.MarginRight = margin;
                tl.MarginTop = margin;
                tl.MarginBottom = margin + (colHeight + gap) * (NCOLS - 1);
                // 我们可以指定任意矩形,让文本围绕其流动。
                // 在本例中,我们添加 3 个区域来绘制一些图像:
                tl.ObjectRects = new List<ObjectRect>()
                {
                    new ObjectRect(page.Size.Width - margin - 267, margin, 267, 200),
                    new ObjectRect(margin + 100, margin + 60, 133, 100),
                    new ObjectRect(margin, page.Size.Height - margin - 301, 200, 301),
                };
                // 将对象矩形转换为图像区域,调整以提供美观的填充:
                var rClouds = tl.ObjectRects[0].ToRectangleF();
                rClouds.Inflate(-4, -3);
                var rFirth = tl.ObjectRects[1].ToRectangleF();
                rFirth.Inflate(-4, -3);
                var rLavender = tl.ObjectRects[2].ToRectangleF();
                rLavender.Inflate(-4, -3);
                page.Graphics.DrawImage(clouds, rClouds, null, ia);
                page.Graphics.DrawImage(firth, rFirth, null, ia);
                page.Graphics.DrawImage(lavender, rLavender, null, ia);

                // 调用:它计算绘制文本所需的字形,并将其布局:
                tl.PerformLayout(true);

                // 当仍有文本要渲染时循环:
                bool done = false;
                while (!done)
                {
                    for (int col = 0; col < NCOLS; ++col)
                    {
                        int nextcol = (col < NCOLS - 1) ? col + 1 : 0;
                        // TextSplitOptions 告诉 TextLayout.Split() 如何布局剩余的文本。
                        // 在本例中,我们通过更新顶部和底部边距从一列前进到另一列:
                        var tso = new TextSplitOptions(tl)
                        {
                            RestMarginTop = margin + (colHeight + gap) * nextcol,
                            RestMarginBottom = margin + (colHeight + gap) * (NCOLS - 1 - nextcol)
                        };
                        var split = tl.Split(tso, out TextLayout rest);
                        page.Graphics.DrawTextLayout(tl, PointF.Empty);
                        if (split != SplitResult.Split)
                        {
                            done = true;
                            break;
                        }
                        tl = rest;
                    }
                    if (!done)
                    {
                        page = doc.NewPage();
                        page.Landscape = true;
                        // 我们只想在第一页渲染图像,所以清除ObjectRect:
                        if (tl.ObjectRects != null)
                        {
                            tl.ObjectRects = null;
                            // 我们需要重做布局,但不需要重新计算字形:
                            tl.PerformLayout(false);
                        }
                    }
                }
                // 完毕:
                doc.Save(stream);
                return doc.Pages.Count;
            }
        }
    }
}