TateChuYoko.cs
// 
// このコードは、DioDocs for PDF のサンプルの一部として提供されています。
// © MESCIUS inc. All rights reserved.
// 
using System;
using System.IO;
using System.Drawing;
using System.Text.RegularExpressions;
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
{
    // このサンプルは、縦書きのブロック内に直立の短い英数字を描画する方法を示します。
    // これは、中国語、日本語、韓国語における縦書きテキストの描画で使用されます。
    // CSS では、これは日本語の名前で「縦中横(Tate Chu Yoko)」と呼ばれています。
    // この処理を実現するには、GcGraphicsのTextFormat.UprightInVerticalText プロパティ
    // を設定し、TextLayout と TextFormat などのプロパティを使用して、動作を調整します。
    public class TateChuYoko
    {
        public int CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            var page = doc.NewPage();
            var g = page.Graphics;

            var rc = Common.Util.AddNote(
                "縦書きテキストに横書きの数字や英文字がある場合、文字の描画方向を変更して混在させます。" +
                "CSS では、これは日本語の名前で「縦中横(Tate Chu Yoko)」と呼ばれており、" +
                "中国語、日本語、韓国語の縦書きテキストで使われます。" +
                "縦中横をサポートするための機能として、TextFormat.UprightInVerticalText や" +
                "TextLayout 、TextFormat の関連プロパティなどを提供しています。",
                page);

            var fntJp = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "YuGothM.ttc"));
            var fntLat = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "MyriadPro-Cond.otf"));
            var hiliteFore = Color.DarkSlateBlue;
            var hiliteBack = Color.FromArgb(unchecked((int)0xffffff99));

            var tl = g.CreateTextLayout();

            // テキストフローと他のレイアウトプロパティを設定します。
            tl.FlowDirection = FlowDirection.VerticalRightToLeft;
            tl.MaxWidth = page.Size.Width;
            tl.MaxHeight = page.Size.Height;
            tl.MarginAll = 72;
            tl.MarginTop = rc.Bottom + 36;
            tl.ParagraphSpacing = 12;
            tl.LineSpacingScaleFactor = 1.4f;

            // g.FillRectangle(
            // new RectangleF(tl.MarginLeft, tl.MarginTop, tl.MaxWidth.Value - tl.MarginLeft - tl.MarginRight, tl.MaxHeight.Value - tl.MarginTop - tl.MarginBottom),
            // Color.AliceBlue);

            // 直立のテキストのテキスト書式(短いラテン文字または数字)
            // (GlyphWidths は対応するフォント機能を ON にしますが、フォントに
            // 存在する機能のみに影響を与えます)
            var fUpright = new TextFormat()
            {
                Font = fntLat,
                FontSize = 14,
                UprightInVerticalText = true,
                GlyphWidths = GlyphWidths.QuarterWidths,
                TextRunAsCluster = true,
            };
            // 縦書きのテキスト(日本語)および横書きのテキスト(ラテン文字)のテキスト書式
            var fVertical = new TextFormat(fUpright)
            {
                Font = fntJp,
                UprightInVerticalText = false,
                GlyphWidths = GlyphWidths.Default,
                TextRunAsCluster = false,
            };

            // 横書きのテキストランが垂直方向の間隔に影響を与えないように設定します。
            fVertical.UseVerticalLineGapForSideways = true;
            // このコメント付きの部分は、実質的に上記の
            // UseVerticalLineGapForSideways プロパティと同じことを行います。
            /*
            var scale = fVertical.FontSize * tl.FontScaleFactor / fntJp.UnitsPerEm;
            if (!fVertical.FontSizeInGraphicUnits)
                scale *= tl.Resolution / 72f;
            fVertical.LineGap = fntJp.VerticalLineGap * scale;
            */

            // 強調表示されたヘッダ用の2つの追加のテキスト書式
            var fUpHdr = new TextFormat(fUpright)
            {
                ForeColor = hiliteFore,
                BackColor = hiliteBack
            };
            var fVertHdr = new TextFormat(fVertical)
            {
                ForeColor = hiliteFore,
                BackColor = hiliteBack
            };

            tl.Append("PDF", fUpright);
            tl.Append("ファイルをコードから", fVertical);
            tl.Append("API", fUpright);
            tl.Append("を利用することで操作できます。クロスプラットフォーム環境で動作するアプリケーションの開発を支援する", fVertical);
            tl.Append("API", fUpright);
            tl.Append("ライブラリです。", fVertical);

            // 残りのテキスト用の小さいフォントサイズ
            fUpright.FontSize -= 2;
            fVertical.FontSize -= 2;

            // 1:
            tl.AppendParagraphBreak();
            tl.Append("PDF", fUpHdr);
            tl.Append("用の包括的な", fVertHdr);
            tl.Append("API", fUpHdr);

            tl.AppendSoftBreak();
            tl.Append("PDF", fUpright);
            tl.Append("バージョン「", fVertical);
            tl.Append("1.7", fUpright);
            tl.Append("」に準拠した", fVertical);
            tl.Append("API", fUpright);
            tl.Append("を提供し、レイアウトや機能を損なうことなく、豊富な機能を備えた", fVertical);
            tl.Append("PDF", fUpright);
            tl.Append("文書を生成、編集、保存できます。", fVertical);

            // 2:
            tl.AppendParagraphBreak();
            tl.Append("完全なテキスト描画", fVertHdr);

            tl.AppendSoftBreak();
            tl.Append("PDF", fUpright);
            tl.Append("文書にテキストの描画情報が保持されます。テキストと段落の書式、特殊文字、複数の言語、縦書き、テキスト角度などが保持さるので、完全な形でテキスト描画を再現できます。", fVertical);

            // 3:
            tl.AppendParagraphBreak();
            tl.Append(".NET Standard 2.0 準拠", fVertHdr);

            tl.AppendSoftBreak();
            tl.Append(".NET Core、.NET Framework、Xamarinで動作するアプリケーションを開発できます。Windows、macOS、Linuxなどクロスプラットフォーム環境で動作可能です。", fVertical);

            // 4:
            tl.AppendParagraphBreak();
            tl.Append("100", fUpHdr);
            tl.Append("を超える", fVertHdr);
            tl.Append("PDF", fUpHdr);
            tl.Append("操作機能", fVertHdr);

            tl.AppendSoftBreak();
            tl.Append("ページの追加や削除、ページサイズ、向きの変更だけでなく、ファイルの圧縮、", fVertical);
            tl.Append("Web", fUpright);
            tl.Append("に最適化した", fVertical);
            tl.Append("PDF", fUpright);
            tl.Append("の生成など高度な機能も", fVertical);
            tl.Append("API", fUpright);
            tl.Append("操作で実現します。また、署名からセキュリティ機能まで様々な機能を含んだ", fVertical);
            tl.Append("PDF", fUpright);
            tl.Append("フォームを生成可能です。", fVertical);

            // 5:
            tl.AppendParagraphBreak();
            tl.Append("高速、軽量アーキテクチャ", fVertHdr);

            tl.AppendSoftBreak();
            tl.Append("軽量", fVertical);
            tl.Append("API", fUpright);
            tl.Append("アーキテクチャでメモリと時間を節約できます。", fVertical);
            tl.AppendSoftBreak();
            tl.Append("また、他の生成用ツールに依存せずドキュメントを生成可能です。", fVertical);

            // 6:
            tl.AppendParagraphBreak();
            tl.Append("クラウドアプリケーション展開", fVertHdr);
            tl.Append("", fUpHdr);

            tl.AppendSoftBreak();
            tl.Append("Azure、AWSなどのサービスに配置するクラウドアプリケーションの開発で利用可能です。仮想マシン、コンテナ、サーバーレスなどの方法で配置できます。", fVertical);

            // 7
            tl.AppendParagraphBreak();
            tl.Append("和暦の日付表示", fVertHdr);
            tl.AppendSoftBreak();
            //和暦でDataTimeを文字列に変換する
            var dt = DateTime.Today;
            System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("ja-JP", false);
            ci.DateTimeFormat.Calendar = new System.Globalization.JapaneseCalendar();
            tl.Append(dt.ToString("gg", ci), fVertical);
            int year = ci.DateTimeFormat.Calendar.GetYear(dt);
            if(year == 1)
                tl.Append("元", fVertical);
            else
                tl.Append(year.ToString("##"), fUpright);
            tl.Append("年", fVertical);
            tl.Append(dt.Month.ToString(), fUpright);
            tl.Append("月", fVertical);
            tl.Append(dt.Day.ToString(), fUpright);
            tl.Append("日", fVertical);
            tl.Append("(", fVertical);
            tl.Append(dt.ToString("ddd",ci), fVertical);
            tl.Append(")", fVertical);

            tl.PerformLayout(true);
            g.DrawTextLayout(tl, PointF.Empty);

            // PDF ドキュメントを保存します。
            doc.Save(stream);
            return doc.Pages.Count;
        }
    }
}