DrawRotatedText.cs
// 
// このコードは、DioDocs for Imaging のサンプルの一部として提供されています。
// © MESCIUS inc. All rights reserved.
// 
using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using GrapeCity.Documents.Drawing;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Imaging;
using GCTEXT = GrapeCity.Documents.Text;
using GCDRAW = GrapeCity.Documents.Drawing;

namespace DsImagingWeb.Demos
{
    // このサンプルでは、GcGraphics.DrawRotatedText() メソッドを
    // さまざまな引数の組み合わせで使用した場合の結果を示します。
    // DrawRotatedText() メソッドは、枠線のない MS Excel のセル内で
    // 回転文字が描画される場合と同様に、指定された矩形内で
    // テキストを回転させて描画します。
    // 関連デモとして DrawSlantedText_0 もご参照ください。
    public class DrawRotatedText
    {
        static string[] s_names = new []
        {
            "Rotate Counter-clockwise",
            "Rotate Clockwise",
            "Vertical Stacking",
            "Varying RotatedTextAlignment",
            "Vertical Stacking Align",
            "Horizontal Stacking Align",
        };

        public GcBitmap GenerateImage(Size pixelSize, float dpi, bool opaque, string[] sampleParams = null)
        {
            sampleParams ??= GetSampleParamsList()[0];

            var bmp = new GcBitmap(pixelSize.Width, pixelSize.Height, opaque, dpi, dpi);
            using var g = bmp.CreateGraphics(Color.White);
            // レイアウトを管理するための値を設定します。
            var margin = g.Resolution;
            var gap = g.Resolution;
            var w = pixelSize.Width * 0.3f;
            var h = w;

            if (sampleParams[0] == s_names[0])
            {
                // さまざまな負の角度でテキストを描画します。
                Draw(g, q0(), angle: -90, false, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
                Draw(g, q1(), angle: -60, false, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
                Draw(g, q2(), angle: -45, false, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
                Draw(g, q3(), angle: -30, false, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
            }
            else if (sampleParams[0] == s_names[1])
            {
                // さまざまな正の角度でテキストを描画します。
                Draw(g, q0(), angle: -90, false, RotatedTextAlignment.TopRight, TextAlignment.Leading);
                Draw(g, q1(), angle: -60, false, RotatedTextAlignment.TopRight, TextAlignment.Leading);
                Draw(g, q2(), angle: -45, false, RotatedTextAlignment.TopRight, TextAlignment.Leading);
                Draw(g, q3(), angle: -30, false, RotatedTextAlignment.TopRight, TextAlignment.Leading);
            }
            else if (sampleParams[0] == s_names[2])
            {
                // さまざまな垂直スタック設定を使用してテキストを描画します。
                Draw(g, q0(), angle: -30, verticalStacking: true, RotatedTextAlignment.TopRight, TextAlignment.Trailing);
                Draw(g, q1(), angle: -30, verticalStacking: false, RotatedTextAlignment.TopRight, TextAlignment.Trailing);
                Draw(g, q2(), angle: -30, verticalStacking: false, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
                Draw(g, q3(), angle: -30, verticalStacking: true, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
            }
            else if (sampleParams[0] == s_names[3])
            {
                // RotatedTextAlignment は、ターゲット矩形(緑)内のテキスト位置(赤)に影響します。
                Draw(g, q0(), angle: -30, verticalStacking: true, RotatedTextAlignment.TopRight, TextAlignment.Trailing);
                Draw(g, q1(), angle: 60, verticalStacking: false, RotatedTextAlignment.BottomRight, TextAlignment.Trailing);
                Draw(g, q2(), angle: 30, verticalStacking: true, RotatedTextAlignment.TopLeft, TextAlignment.Leading);
                Draw(g, q3(), angle: -60, verticalStacking: false, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
            }
            else if (sampleParams[0] == s_names[4])
            {
                // さまざまな TextAlignment 値を使用して、垂直にスタックされたテキストを描画します。
                Draw(g, q0(), angle: 30, verticalStacking: true, RotatedTextAlignment.TopLeft, TextAlignment.Leading);
                Draw(g, q1(), angle: 30, verticalStacking: true, RotatedTextAlignment.TopLeft, TextAlignment.Trailing);
                Draw(g, q2(), angle: 30, verticalStacking: true, RotatedTextAlignment.TopLeft, TextAlignment.Center);
                Draw(g, q3(), angle: 30, verticalStacking: true, RotatedTextAlignment.TopLeft, TextAlignment.Distributed);
            }
            else if (sampleParams[0] == s_names[5])
            {
                // さまざまな TextAlignment 値を使用して、水平にスタックされたテキストを描画します。
                Draw(g, q0(), angle: -70, verticalStacking: false, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
                Draw(g, q1(), angle: -70, verticalStacking: false, RotatedTextAlignment.BottomLeft, TextAlignment.Trailing);
                Draw(g, q2(), angle: -70, verticalStacking: false, RotatedTextAlignment.BottomLeft, TextAlignment.Center);
                Draw(g, q3(), angle: -70, verticalStacking: false, RotatedTextAlignment.BottomLeft, TextAlignment.Distributed);
            }
            return bmp;

            RectangleF q0()
            {
                return new RectangleF(margin, margin, w, h);
            }
            RectangleF q1()
            {
                return new RectangleF(pixelSize.Width - margin - w, margin, w, h);
            }
            RectangleF q2()
            {
                return new RectangleF(margin, margin + h + gap, w, h);
            }
            RectangleF q3()
            {
                return new RectangleF(pixelSize.Width - margin - w, margin + h + gap, w, h);
            }
        }

        static void Draw(GcGraphics g, RectangleF rect, int angle, bool verticalStacking,
            RotatedTextAlignment rotatedAlign, TextAlignment textAlign)
        {
            // 現在の DrawRotatedText 引数の値を説明する凡例を描画します。
            var tlLegend = g.CreateTextLayout();
            tlLegend.DefaultFormat.FontName = "Calibri";
            tlLegend.DefaultFormat.FontSize = 9;
            tlLegend.AppendLine($"Rotation angle: {angle}°");
            tlLegend.AppendLine($"Text alignment: {textAlign}");
            tlLegend.AppendLine($"Rotated text alignment: {rotatedAlign}");
            tlLegend.AppendLine($"Is vertical stacking: {verticalStacking}");
            g.DrawTextLayout(tlLegend, rect.Location);

            // DrawRotatedText 呼び出しのターゲット矩形。
            var d = tlLegend.ContentHeight + 12;
            rect.Y += d;
            rect.Height -= d;

            var tl = g.CreateTextLayout();
            tl.DefaultFormat.FontName = "Calibri";
            tl.DefaultFormat.FontSize = 12;
            tl.Append("The quick brown fox jumps over the lazy dog. ");
            tl.Append("The quick brown fox jumps over the lazy dog.");
            tl.TextAlignment = textAlign;
            // 回転したテキストを描画します。
            g.DrawRotatedText(tl, angle, verticalStacking, rect, rotatedAlign);

            // ターゲット矩形を薄い緑色で縁取りします。
            g.DrawRectangle(rect, new GCDRAW::Pen(Color.PaleGreen, 3));
            // 実際のテキスト矩形を赤色で縁取りします。
            var tlCopy = tl.Clone(true);
            var tlRect = g.MeasureRotatedText(tlCopy, angle, verticalStacking, rect, rotatedAlign);
            g.DrawRectangle(tlRect, new GCDRAW::Pen(Color.Red, 1));
        }

        public static List<string[]> GetSampleParamsList()
        {
            return new List<string[]>()
            {
                // 各文字列は、名前、説明、情報です。残りは任意の文字列です。
                new string[] { s_names[0], "さまざまな負の角度で回転したテキストを描画する", null},
                new string[] { s_names[1], "さまざまな正の角度で回転したテキストを描画する", null},
                new string[] { s_names[2], "さまざまな垂直スタック設定を使用して回転したテキストを描画する", null},
                new string[] { s_names[3], "さまざまな回転テキストの配置設定を使用してテキストを描画する", null},
                new string[] { s_names[4], "さまざまな TextAlignment 値を使用して、垂直にスタックされたテキストを描画する", null},
                new string[] { s_names[5], "さまざまな TextAlignment 値を使用して、水平にスタックされたテキストを描画する", null, },
            };
        }
    }
}