DrawSlantedText.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;
using GCTEXT = GrapeCity.Documents.Text;
using GCDRAW = GrapeCity.Documents.Drawing;

namespace DsPdfWeb.Demos.Basics
{
    // このデモでは、GcGraphics.DrawSlantedText() メソッドを使用した結果を示します。
    // 引数をさまざまに組み合わせて使用​​します。
    // DrawSlantedText() メソッドは、指定された四角形内に斜めのテキストを描画します。
    // これは、回転されたテキストが境界線付きの MS Excel セルに描画される方法と似ています。
    // DrawRotatedText も参照してください。
    public class DrawSlantedText
    {
        public int CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            var page = doc.Pages.Add();
            var g = page.Graphics;
            // レイアウトを管理するためにいくつかの値を設定
            var gap = g.Resolution;
            var w = page.Size.Width / 3;
            var h = w;

            // SlantedTextAlignment.BelowRotatedInside を使用したさまざまなテキストの配置
            Draw(g, q0(), angle: -70, false, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Leading);
            Draw(g, q1(), angle: -70, false, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Trailing);
            Draw(g, q2(), angle: -70, false, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Center);
            Draw(g, q3(), angle: -70, false, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Distributed);
            // SlantedTextAlignment.BelowRotatedOutside によるさまざまなテキストの配置
            page = doc.Pages.Add();
            g = page.Graphics;
            Draw(g, q0(), angle: -70, false, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Leading);
            Draw(g, q1(), angle: -70, false, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Trailing);
            Draw(g, q2(), angle: -70, false, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Center);
            Draw(g, q3(), angle: -70, false, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Distributed);
            // SlantedTextAlignment.AboveRotatedInside によるさまざまなテキストの配置
            page = doc.Pages.Add();
            g = page.Graphics;
            Draw(g, q0(), angle: -70, false, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Leading);
            Draw(g, q1(), angle: -70, false, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Trailing);
            Draw(g, q2(), angle: -70, false, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Center);
            Draw(g, q3(), angle: -70, false, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Distributed);
            // SlantedTextAlignment.AboveRotatedOutside によるさまざまなテキストの配置
            page = doc.Pages.Add();
            g = page.Graphics;
            Draw(g, q0(), angle: -70, false, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Leading);
            Draw(g, q1(), angle: -70, false, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Trailing);
            Draw(g, q2(), angle: -70, false, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Center);
            Draw(g, q3(), angle: -70, false, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Distributed);
            // SlantedTextAlignment.CenterInsideOutside を使用したさまざまなテキストの配置
            page = doc.Pages.Add();
            g = page.Graphics;
            Draw(g, q0(), angle: -70, false, SlantedTextAlignment.CenterInsideOutside, TextAlignment.Leading);
            Draw(g, q1(), angle: -70, false, SlantedTextAlignment.CenterInsideOutside, TextAlignment.Trailing);
            Draw(g, q2(), angle: -70, false, SlantedTextAlignment.CenterInsideOutside, TextAlignment.Center);
            Draw(g, q3(), angle: -70, false, SlantedTextAlignment.CenterInsideOutside, TextAlignment.Distributed);
            // SlantedTextAlignment.CenterOutsideInside によるさまざまなテキストの配置
            page = doc.Pages.Add();
            g = page.Graphics;
            Draw(g, q0(), angle: -70, false, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Leading);
            Draw(g, q1(), angle: -70, false, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Trailing);
            Draw(g, q2(), angle: -70, false, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Center);
            Draw(g, q3(), angle: -70, false, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Distributed);
            // SlantedTextAlignment.BelowRotatedInside を使用した正の回転角度の例
            page = doc.Pages.Add();
            g = page.Graphics;
            Draw(g, q0(), angle: 70, false, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Leading);
            Draw(g, q1(), angle: 70, false, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Trailing);
            Draw(g, q2(), angle: 70, false, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Center);
            Draw(g, q3(), angle: 70, false, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Distributed);
            // SlantedTextAlignment.AboveRotatedInside を使用した正の回転角度の例
            page = doc.Pages.Add();
            g = page.Graphics;
            Draw(g, q0(), angle: 70, false, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Leading);
            Draw(g, q1(), angle: 70, false, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Trailing);
            Draw(g, q2(), angle: 70, false, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Center);
            Draw(g, q3(), angle: 70, false, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Distributed);

            // 以下は、垂直方向に積み上げられたテキストの例

            // SlantedTextAlignment.BelowRotatedInside を使用して負の角度に回転された垂直に積み上げられたテキスト
            page = doc.Pages.Add();
            g = page.Graphics;
            Draw(g, q0(), angle: -20, true, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Leading);
            Draw(g, q1(), angle: -20, true, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Trailing);
            Draw(g, q2(), angle: -20, true, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Center);
            Draw(g, q3(), angle: -20, true, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Distributed);
            // SlantedTextAlignment.BelowRotatedOutside を使用して負の角度に回転された垂直に積み上げられたテキスト
            page = doc.Pages.Add();
            g = page.Graphics;
            Draw(g, q0(), angle: -20, true, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Leading);
            Draw(g, q1(), angle: -20, true, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Trailing);
            Draw(g, q2(), angle: -20, true, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Center);
            Draw(g, q3(), angle: -20, true, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Distributed);
            // SlantedTextAlignment.AboveRotatedOutside を使用して正の角度に回転された垂直方向に積み重ねられたテキスト
            page = doc.Pages.Add();
            g = page.Graphics;
            Draw(g, q0(), angle: 20, true, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Leading);
            Draw(g, q1(), angle: 20, true, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Trailing);
            Draw(g, q2(), angle: 20, true, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Center);
            Draw(g, q3(), angle: 20, true, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Distributed);
            // SlantedTextAlignment.CenterOutsideInside を使用して正の角度に回転された垂直に積み上げられたテキスト
            page = doc.Pages.Add();
            g = page.Graphics;
            Draw(g, q0(), angle: 20, true, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Leading);
            Draw(g, q1(), angle: 20, true, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Trailing);
            Draw(g, q2(), angle: 20, true, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Center);
            Draw(g, q3(), angle: 20, true, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Distributed);

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

            RectangleF q0()
            {
                return new RectangleF(gap, gap, w, h);
            }
            RectangleF q1()
            {
                return new RectangleF(gap + w + gap, gap, w, h);
            }
            RectangleF q2()
            {
                return new RectangleF(gap, gap + h + gap, w, h);
            }
            RectangleF q3()
            {
                return new RectangleF(gap + w + gap, gap + h + gap, w, h);
            }
        }

        static void Draw(GcGraphics g, RectangleF rect, int angle, bool verticalStacking,
            SlantedTextAlignment slantedAlign, TextAlignment textAlign)
        {
            // 現在の DrawRotatedText 引数の値を示す凡例を描画
            var tlLegend = g.CreateTextLayout();
            tlLegend.DefaultFormat.FontName = "Yu gothic";
            tlLegend.DefaultFormat.FontSize = 9;
            tlLegend.AppendLine($"Rotation angle: {angle}°");
            tlLegend.AppendLine($"Text alignment: {textAlign}");
            tlLegend.AppendLine($"Slanted text alignment: {slantedAlign}");
            tlLegend.AppendLine($"Is vertical stacking: {verticalStacking}");
            g.DrawTextLayout(tlLegend, rect.Location);

            // DrawRotatedText 呼び出しのターゲット四角形
            var d = tlLegend.ContentHeight + g.Resolution;
            rect.Y += d;
            rect.Height -= d;
            rect.Width -= d / 2;
            var x = rect.X;
            var y = rect.Y;
            var w = rect.Width;
            var h = rect.Height;

            // ターゲットの四角形を描画
            g.DrawRectangle(rect, new GCDRAW::Pen(Color.PaleGreen, 3));

            if (!verticalStacking)
            {
                float dx = (float)(h / Math.Tan(Math.PI * angle / -180.0));
                switch (slantedAlign)
                {
                    case SlantedTextAlignment.BelowRotatedInside:
                    case SlantedTextAlignment.AboveRotatedOutside:
                    case SlantedTextAlignment.CenterInsideOutside:
                        g.DrawPolygon(new[] {
                            new PointF(x + dx, y), new PointF(x + dx + w, y),
                            new PointF(x + w, y + h), new PointF(x, y + h)},
                            new GCDRAW::Pen(Color.Red, 1));
                        break;
                    case SlantedTextAlignment.BelowRotatedOutside:
                    case SlantedTextAlignment.AboveRotatedInside:
                    case SlantedTextAlignment.CenterOutsideInside:
                        g.DrawPolygon(new[] {
                            new PointF(x, y), new PointF(x + w, y),
                            new PointF(x - dx + w, y + h), new PointF(x - dx, y + h)},
                            new GCDRAW::Pen(Color.Red, 1));
                        break;
                }
            }
            else
            {
                float dy = (float)(w * Math.Tan(Math.PI * angle / 180.0));
                switch (slantedAlign)
                {
                    case SlantedTextAlignment.BelowRotatedInside:
                    case SlantedTextAlignment.AboveRotatedOutside:
                    case SlantedTextAlignment.CenterInsideOutside:
                        if (angle >= 0)
                            g.DrawPolygon(new[] {
                                new PointF(x, y), new PointF(x + w, y + dy), new PointF(x + w, y + dy + h), new PointF(x, y + h)},
                                new GCDRAW::Pen(Color.Red, 1));
                        else
                            g.DrawPolygon(new[] {
                                new PointF(x, y - dy), new PointF(x + w, y), new PointF(x + w, y + h), new PointF(x, y - dy + h)},
                                new GCDRAW::Pen(Color.Red, 1));
                        break;
                    case SlantedTextAlignment.BelowRotatedOutside:
                    case SlantedTextAlignment.AboveRotatedInside:
                    case SlantedTextAlignment.CenterOutsideInside:
                        if (angle >= 0)
                            g.DrawPolygon(new[] {
                                new PointF(x, y - dy), new PointF(x + w, y), new PointF(x + w, y + h), new PointF(x, y - dy + h)},
                                new GCDRAW::Pen(Color.Red, 1));
                        else
                            g.DrawPolygon(new[] {
                                new PointF(x, y), new PointF(x + w, y + dy), new PointF(x + w, y + dy + h), new PointF(x, y + h)},
                                new GCDRAW::Pen(Color.Red, 1));
                        break;
                }
            }
            // 斜めのテキストを描画
            var tl = g.CreateTextLayout();
            tl.DefaultFormat.SidewaysInVerticalText = true;
            tl.DefaultFormat.FontName = "Yu gothic";
            tl.DefaultFormat.FontSize = 12;
            tl.TextAlignment = textAlign;
            tl.Append("DioDocs(ディオドック)は、Excelや PDFなどの文書を、コードからAPIを利用 することで操作できます。\n");
            g.DrawSlantedText(tl, angle, verticalStacking, rect, slantedAlign);
        }        
    }
}