AiLoremOutlines.cs
// 
// このコードは、DioDocs for PDF のサンプルの一部として提供されています。
// © MESCIUS inc. All rights reserved.
// 
using Azure;
using Azure.AI.OpenAI;
using DsPdfWeb.Demos.Common;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Pdf.AI;
using GrapeCity.Documents.Text;
using OpenAI.Chat;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading.Tasks;

namespace DsPdfWeb.Demos
{
    // このサンプルはランダムな内容を含むPDFを生成し、
    // PDF AIアシスタント (DsPdfAI) を使用して文書内容を解析し、
    // 推定された見出しに基づいてアウトラインツリー(ブックマーク)を生成し、
    // それをPDFに追加します。
    //
    // 複数ページのPDF文書を生成するために TextLayout を使用する例については、
    // PaginatedText を参照してください。
    //
    // このサンプルをローカルで実行するには、
    // Util.OpenAIToken、Util.AzureOpenAIToken、および Util.AzureEndPoint プロパティを使用して
    // OpenAIの認証情報とAzureのエンドポイントを設定してください。

    public class AiLoremOutlines
    {
        public int CreatePDF(Stream stream)
        {
            var doc = GeneratePDF();
            try
            {
                // AIアシスタントを使用して文書内容を解析し、アウトラインを生成します。
                var a = new AzureOpenAIDocumentAssistant(Util.AzureEndPoint, Util.AzureOpenAIToken);
                var task = a.BuildOutlines(doc);
                task.Wait();
                // ビューワがPDFを開いたときにアウトライン(ブックマーク)を表示するようにページモードを設定します。
                doc.PageMode = PageMode.UseOutlines;
            }
            catch (Exception ex)
            {
                // エンドポイント、APIキーの割り当てを確認してください。
                Util.CreatePdfError(doc, ex.Message);
            }
            doc.Save(stream);
            return doc.Pages.Count;
        }

        // ランダムな階層構造のコンテンツを含むPDFを生成して返します。
        GcPdfDocument GeneratePDF()
        {
            var doc = new GcPdfDocument();
            var rnd = Util.NewRandom();
            var tl = new TextLayout(72)
            {
                MaxWidth = doc.PageSize.Width,
                MaxHeight = doc.PageSize.Height,
                MarginAll = 72,
                FirstLineIndent = 36,
            };
            tl.DefaultFormat.Font = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            var fmtChapter = new TextFormat(tl.DefaultFormat) { FontSize = 18, FontBold = true };
            var fmtSection = new TextFormat(tl.DefaultFormat) { FontSize = 16, FontBold = true };
            var fmtSubSection = new TextFormat(tl.DefaultFormat) { FontSize = 14, FontBold = true };
            var fmtNormal = new TextFormat(tl.DefaultFormat) { FontSize = 12 };
            for (int i = 0; i < rnd.Next(2, 5); i++)
            {
                tl.Append($"Chapter {i + 1}: {Util.LoremIpsum(1, 1, 1, 1, 4).TrimEnd()}", fmtChapter);
                tl.AppendParagraphBreak(fmtChapter);
                for (int j = 0; j < rnd.Next(2, 4); j++)
                {
                    tl.Append($"Section {i + 1}.{j + 1}: {Util.LoremIpsum(1, 1, 1, 1, 4).TrimEnd()}", fmtSection);
                    tl.AppendParagraphBreak(fmtSection);
                    for (int k = 0; k < rnd.Next(2, 3); k++)
                    {
                        tl.Append($"Sub-section {i + 1}.{j + 1}.{k + 1}: {Util.LoremIpsum(1, 1, 1, 1, 4).TrimEnd()}", fmtSubSection);
                        tl.AppendParagraphBreak(fmtSubSection);
                        tl.AppendLine(Util.LoremIpsum(1), fmtNormal);
                    }
                }
            }
            // TextLayout を分割して描画します(PaginatedText サンプル参照)。
            var tso = new TextSplitOptions(tl)
            {
                MinLinesInFirstParagraph = 2,
                MinLinesInLastParagraph = 2,
            };
            tl.PerformLayout(true);
            var tls = new TextLayoutSplitter(tl);
            for (var tlPage = tls.Split(tso); tlPage != null; tlPage = tls.Split(tso))
                doc.NewPage().Graphics.DrawTextLayout(tlPage, PointF.Empty);
            return doc;
        }
    }
}