PageLabels.cs
// 
// このコードは、DioDocs for PDF のサンプルの一部として提供されています。
// © MESCIUS inc. All rights reserved.
// 
using System;
using System.IO;
using System.Drawing;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Drawing;

namespace DsPdfWeb.Demos.Basics
{
    // このサンプルでは、ドキュメントにページラベルを追加する方法を示します。
    // ページラベルを使用すると、ドキュメントを論理的に関連するページ範囲のシーケンスに
    // 分割できます(例:序文、本文、ポストフェイス)。
    // 「チャプター」で構成されるこのサンプルでは、各章に個別のページラベル範囲を追加します。
    // このサンプルのコードは、Outlines サンプルに似ています。
    public class PageLabels
    {
        public int CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            // メインテキストのテキストレイアウト(デフォルトの DsPdf 解像度は 72 dpi です)。
            var tl = new TextLayout(72);
            tl.DefaultFormat.Font = Common.Util.getFont();
            tl.DefaultFormat.FontSize = 12;
            tl.FirstLineIndent = 72 / 2;
            tl.MaxWidth = doc.PageSize.Width;
            tl.MaxHeight = doc.PageSize.Height;
            tl.MarginAll = tl.Resolution;
            // 章のヘッダーのテキストレイアウトです。
            var tlCaption = new TextLayout(72);
            tlCaption.DefaultFormat.Font = Common.Util.getFont();
            tlCaption.DefaultFormat.FontBold = true;
            tlCaption.DefaultFormat.FontSize = tl.DefaultFormat.FontSize + 4;
            tlCaption.DefaultFormat.Underline = true;
            tlCaption.MaxWidth = tl.MaxWidth;
            tlCaption.MarginAll = tlCaption.Resolution;
            // ページ間のテキストの分割を制御する分割オプションです。
            var to = new TextSplitOptions(tl)
            {
                RestMarginTop = tl.Resolution,
                MinLinesInFirstParagraph = 2,
                MinLinesInLastParagraph = 2
            };
            // いくつかの章を生成し、それぞれにアウトラインエントリーを提供します。
            const int NChapters = 20;
            for (int i = 0; i < NChapters; ++i)
            {
                // 章タイトル - 章のヘッダーとして印刷し、アウトラインノードとして追加します。
                string chapter = $"第 {i + 1} 章";

                // ページラベルを追加するのに必要なのは、範囲内の最初のページの
                // インデックスに関連付けられたページラベル範囲、範囲プレフィックス
                // および番号付けスタイルを追加することだけです。
                doc.PageLabelingRanges.Add(doc.Pages.Count, new PageLabelingRange($"{chapter}, p. ", NumberingStyle.DecimalArabic, 1));

                doc.Pages.Add();
                tlCaption.Clear();
                tlCaption.Append(chapter);
                tlCaption.PerformLayout(true);
                // 章のアウトラインノードを追加します。
                doc.Outlines.Add(new OutlineNode(chapter, new DestinationFitH(doc.Pages.Last, tlCaption.MarginTop)));
                // キャプションを出力します。
                doc.Pages.Last.Graphics.DrawTextLayout(tlCaption, PointF.Empty);
                // 章のテキストです。
                tl.Clear();
                tl.FirstLineIsStartOfParagraph = true;
                tl.LastLineIsEndOfParagraph = true;
                tl.Append(Common.Util.getString_ja(1, 0, 5));
                // メインテキストレイアウト内の章ヘッダーを考慮します。
                tl.MarginTop = tlCaption.ContentRectangle.Bottom + 12;
                tl.PerformLayout(true);
                // 章を出力します。
                while (true)
                {
                    // 'rest' は、収まりきらなかったテキストを受け入れます。
                    var splitResult = tl.Split(to, out TextLayout rest);
                    doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
                    if (splitResult != SplitResult.Split)
                        break;
                    tl = rest;
                    var p = doc.Pages.Add();
                }
            }
            // PDF ドキュメントを保存します。
            doc.Save(stream);
            return doc.Pages.Count;
        }
    }
}