LangLayers.cs
// 
// このコードは、DioDocs for PDF のサンプルの一部として提供されています。
// Copyright (c) GrapeCity inc. All rights reserved.
// 
using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Pdf.Layers;
using GrapeCity.Documents.Pdf.Annotations;
using GrapeCity.Documents.Pdf.Graphics;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Drawing;

namespace GcPdfWeb.Samples
{
    // このサンプルでは、GcPdf の資料を使用して PDF を作成しています。
    // PDF レイヤー(オプションコンテンツ)は、複数の言語で記述された資料を
    // 同じ1ページの PDF にて提供するために使用されています。 対応するビューワ(Adobe Readerなど)を
    // 使用することで、異なる言語の表示/非表示を切り替えることができます。
    public class LangLayers
    {
        // レイヤ名は言語に対応するように設定します。
        const string c_lyrEN = "英語";
        const string c_lyrJP = "日本語";

        public void CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();

            // 英語及び日本語のレイヤーを追加し、
            // 日本語のレイヤーをデフォルトで非表示にします。
            doc.OptionalContent.AddLayer(c_lyrEN);
            doc.OptionalContent.AddLayer(c_lyrJP);
            doc.OptionalContent.SetLayerDefaultState(c_lyrJP, false);

            var page = doc.Pages.Add();
            page.Landscape = true;
            var g = page.Graphics;

            // 背景画像
            var picBack = Image.FromFile(Path.Combine("Resources", "ImagesBis", "2020-website-gcdocs-headers_tall.png"));
            var rc = page.Bounds;
            rc.Height *= 0.5f;
            g.DrawImage(picBack, rc, null, ImageAlign.StretchImage);

            // スクリーンショットを含む画像
            var picScreens = Image.FromFile(Path.Combine("Resources", "ImagesBis", "docs-main-02.png"));
            var picScreensSize = new SizeF(picScreens.Width / 2, picScreens.Height / 2);
            var rcScreen = new RectangleF(
                page.Bounds.Width - picScreensSize.Width - 8,
                8,
                picScreensSize.Width,
                picScreensSize.Height);
            g.DrawImage(picScreens, rcScreen, null, ImageAlign.StretchImage);

            // テキストフォーマット
            var fReg = Font.FromFile(Path.Combine("Resources", "Fonts", "OpenSans-Regular.ttf"));
            var fBold = Font.FromFile(Path.Combine("Resources", "Fonts", "OpenSans-Bold.ttf"));
            var tfNorm = new TextFormat() { Font = fReg, FontSize = 9, ForeColor = Color.White };
            var tfCap = new TextFormat(tfNorm) { FontSize = tfNorm.FontSize * 1.6f };
            var tfBlack = new TextFormat(tfNorm) { ForeColor = Color.FromArgb(32, 32, 32) };
            var tfHdr = new TextFormat(tfBlack) { Font = fBold };

            // 英語のテキストを描画します。
            var ip = new PointF(36, 24);
            var ip1 = ip;
            ip = DrawText1(c_lyrEN, doc, g, ip1, tfNorm, tfCap);
            ip.Y += 170;
            var ip2 = ip;
            DrawText2(c_lyrEN, doc, g, ip2, tfHdr, tfBlack);

            // 日本語のテキストを描画します。
            var fRegJp = Font.FromFile(Path.Combine("Resources", "Fonts", "YuGothR.ttc"));
            var fBoldJp = Font.FromFile(Path.Combine("Resources", "Fonts", "YuGothB.ttc"));
            DrawText1(c_lyrJP, doc, g, ip1, new TextFormat(tfNorm) { Font = fRegJp }, new TextFormat(tfCap) { Font = fRegJp });
            DrawText2(c_lyrJP, doc, g, ip2, new TextFormat(tfHdr) { Font = fBoldJp }, new TextFormat(tfBlack) { Font = fRegJp });

            // PDF を保存します。
            doc.Save(stream);
        }

        class Texts
        {
            public string Caption { get; set; }
            public string SubCap { get; set; }
            public string Bullet1 { get; set; }
            public string Bullet2 { get; set; }
            public string Bullet3 { get; set; }
            public string Bullet4 { get; set; }
            public string Bullet5 { get; set; }
            public string Pt1Hdr { get; set; }
            public string Pt1Txt { get; set; }
            public string Pt2Hdr { get; set; }
            public string Pt2Txt { get; set; }
            public string Pt3Hdr { get; set; }
            public string Pt3Txt { get; set; }
            public string Pt4Hdr { get; set; }
            public string Pt4Txt { get; set; }
            public string Pt5Hdr { get; set; }
            public string Pt5Txt { get; set; }
            public string Pt6Hdr { get; set; }
            public string Pt6Txt { get; set; }
        }

        static Dictionary<string, Texts> _texts = new Dictionary<string, Texts>()
        {
            { "英語", new Texts() {
                Caption = "Feature-Rich PDF API Library for .NET 5",
                SubCap = "Take total control of PDFs - generate documents with speed, memory efficiency, and no dependencies.",
                Bullet1 = "Generate, load, edit, and save PDF documents in code",
                Bullet2 = "Support multiple languages with full text, paragraph formatting, and fonts",
                Bullet3 = "Redact content from PDFs with the new redaction tool",
                Bullet4 = "Support hundreds of PDF features",
                Bullet5 = "All features are fully supported on Windows, macOS, and Linux",
                Pt1Hdr = "Fast and Efficient",
                Pt1Txt = "Save memory and time with the lightweight API architecture to generate and work with PDF documents in .NET 5 effortlessly.",
                Pt2Hdr = "Comprehensive API for Adobe PDF",
                Pt2Txt = "Generate, edit, and store feature-rich PDF documents without compromising design or features. This API conforms to Adobe PDF specification 2.0",
                Pt3Hdr = "Complete Text Support",
                Pt3Txt = "Documents for PDF includes text and paragraph formatting, special characters, multiple languages, RTL support, and vertical and rotated text for all supported platforms.",
                Pt4Hdr = "Feature-rich API",
                Pt4Txt = "Generate PDF forms with everything from signatures to security features. You can add, delete, copy and move pages, change page sizes, orientation, generate linearized PDFs, add annotations, redact content from PDF documents, and compress PDF files.",
                Pt5Hdr = "Full .NET Support for Windows, Linux, and Mac",
                Pt5Txt = "Develop for any .NET platform and major operating systems with a single code base. Use in your apps for .NET Core, .NET Framework, Mono, Xamarin.iOS, and Xamarin.Android.",
                Pt6Hdr = "Deploy Apps with PDFs to the Cloud",
                Pt6Txt = "Cloud-based deployment means you can be everywhere. With NuGet and Documents for PDF, you can deploy to Azure, AWS, and AWS Lambda.",
            }},
            { "日本語", new Texts() {
                Caption = "PDFを作成・編集するAPIライブラリ",
                SubCap = "DioDocs for PDFはC#およびVB.NETのコードからAPIを利用してPDFファイルを作成・編集できます。クロスプラットフォームで動作する.NETアプリケーション開発において、PDFファイルの操作を実装できるAPIライブラリです。",
                Bullet1 = "PDF文書の生成、読み込み、編集、保存をコードで実現",
                Bullet2 = "日本語のフォント、段組み、縦書きにも対応",
                Bullet3 = "PDFコンテンツの墨消しが可能",
                Bullet4 = "様々なPDF機能をサポート",
                Bullet5 = "すべての機能はWindows、macOS、Linuxに完全対応",
                Pt1Hdr = "PDF用の包括的なAPI",
                Pt1Txt = "PDFバージョン「1.7」に準拠したAPIを提供します。レイアウトや機能を損なうことなく、豊富な機能を備えたPDF文書を作成、編集、読み込み、保存できます。",
                Pt2Hdr = "100を超えるPDF操作機能",
                Pt2Txt = "ページの追加や削除、ページサイズ、向きの変更だけでなく、ファイルの圧縮、Webに最適化したPDFの生成など高度な機能もAPI操作で実現します。また、署名からセキュリティ機能まで様々な機能を含んだPDFフォームを作成可能です。",
                Pt3Hdr = "完全なテキスト描画",
                Pt3Txt = "PDF文書にテキストの描画情報が保持されます。テキストと段落の書式、特殊文字、複数の言語、縦書き、テキスト角度などが保持されるので、完全な形でテキスト描画を再現できます。",
                Pt4Hdr = "高速、軽量アーキテクチャ",
                Pt4Txt = "軽量APIアーキテクチャでメモリと時間を節約できます。また、Adobe Acrobatなどのソフトウェアやツールに依存せずPDF文書を作成・編集可能です。",
                Pt5Hdr = ".NET Standard 2.0以上に準拠",
                Pt5Txt = ".NET Core、.NET Framework、Xamarinで動作する.NETアプリケーションを開発できます。Windows、macOS、Linuxなどクロスプラットフォーム環境で動作可能です。",
                Pt6Hdr = "クラウドアプリケーション展開",
                Pt6Txt = "Azure、AWS、GCPなどのパブリッククラウドに配置する.NETアプリケーションの開発で利用可能です。仮想マシン、コンテナ、サーバーレスなどの方法で配置できます。",
            }}
        };


        static PointF DrawText1(string lang, GcPdfDocument doc, GcPdfGraphics g, PointF ip, TextFormat tf, TextFormat tfCap)
        {
            var txts = _texts[lang];
            g.BeginLayer(lang);

            var tl = g.CreateTextLayout();
            tl.MaxWidth = 72 * 5;

            tl.AppendLine(txts.Caption, tfCap);
            tl.AppendLine(tf);
            tl.AppendLine(txts.SubCap, tf);
            tl.AppendLine(tf);
            g.DrawTextLayout(tl, ip);

            // 箇条書きのリスト
            ip.Y += tl.ContentHeight;
            tl.Clear();
            const string bullet = "\x2022\x2003";
            tl.FirstLineIndent = -g.MeasureString(bullet, tf).Width;
            tl.ParagraphSpacing += 5;

            tl.Append(bullet, tf);
            tl.AppendLine(txts.Bullet1, tf);
            tl.Append(bullet, tf);
            tl.AppendLine(txts.Bullet2, tf);
            tl.Append(bullet, tf);
            tl.AppendLine(txts.Bullet3, tf);
            tl.Append(bullet, tf);
            tl.AppendLine(txts.Bullet4, tf);
            tl.Append(bullet, tf);
            tl.AppendLine(txts.Bullet5, tf);
            g.DrawTextLayout(tl, ip);

            g.EndLayer();

            ip.Y += tl.ContentHeight;
            return ip;
        }

        static void DrawText2(string lang, GcPdfDocument doc, GcPdfGraphics g, PointF ip, TextFormat tfHdr, TextFormat tfBlack)
        {
            var tl = g.CreateTextLayout();
            tl.FirstLineIndent = 0;
            tl.MaxWidth = (doc.Pages[0].Bounds.Width - ip.X * 2 - 36) / 3;
            var ip1 = ip;
            var txts = _texts[lang];

            drawItem(ip, txts.Pt1Hdr, txts.Pt1Txt);
            ip.X += tl.MaxWidth.Value + 18;
            ip1.Y = Math.Max(ip1.Y, ip.Y + tl.ContentHeight);
            drawItem(ip, txts.Pt2Hdr, txts.Pt2Txt);
            ip.X += tl.MaxWidth.Value + 18;
            ip1.Y = Math.Max(ip1.Y, ip.Y + tl.ContentHeight);
            drawItem(ip, txts.Pt3Hdr, txts.Pt3Txt);

            ip1.Y = Math.Max(ip1.Y, ip.Y + tl.ContentHeight);
            ip1.Y += 18;
            ip = ip1;
            drawItem(ip, txts.Pt4Hdr, txts.Pt4Txt);
            ip.X += tl.MaxWidth.Value + 18;
            drawItem(ip, txts.Pt5Hdr, txts.Pt5Txt);
            ip.X += tl.MaxWidth.Value + 18;
            drawItem(ip, txts.Pt6Hdr, txts.Pt6Txt);

            void drawItem(PointF p, string header, string text)
            {
                tl.Clear();
                tl.AppendLine(header, tfHdr);
                tl.AppendLine(text, tfBlack);
                g.BeginLayer(lang);
                g.DrawTextLayout(tl, new PointF(p.X, p.Y + 8));
                g.EndLayer();
            }
        }
    }
}