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

namespace GcPdfWeb.Samples
{
    // このサンプルでは、GcPdfGraphics にて描画する際の、様々なブレンドモードの
    // エフェクトを示しています。なお、GcGraphics(GcPdfGraphics を含む)の
    // インスタンスに設定されている現在のブレンドモードは、
    // 画像だけでなくすべての描画操作に影響することに注意してください。
    // このサンプルでは、2ページ目下部にあるブレンドモード名のレンダリングにて
    // その影響を確認することができます。
    public class AllBlendModes
    {
        public void CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            var page = doc.NewPage();
            var g = page.Graphics;

            var iorchid = Image.FromFile(Path.Combine("Resources", "ImagesBis", "orchid.jpg"));
            var ispectr = Image.FromFile(Path.Combine("Resources", "ImagesBis", "spectrum-pastel-500x500.png"));

            const int margin = 36;
            const int NCOLS = 4;
            var w = (int)((page.Size.Width - margin * 2) / NCOLS);
            var h = (int)((iorchid.Height * w) / iorchid.Width);

            // 見出しのテキストレイアウト
            var tl = g.CreateTextLayout();
            tl.DefaultFormat.Font = Font.FromFile(Path.Combine("Resources", "Fonts", "cour.ttf"));
            tl.DefaultFormat.FontSize = 12;
            tl.ParagraphAlignment = ParagraphAlignment.Center;
            tl.TextAlignment = TextAlignment.Center;
            tl.MaxWidth = w;
            tl.MaxHeight = h;
            tl.MarginTop = h - g.MeasureString("QWERTY", tl.DefaultFormat).Height * 1.4f;

            int row = 0, col, dy;
            // 格子状にすべてのブレンドモードをレンダリングします。
            var modes = Enum.GetValues(typeof(BlendMode));
            for (int i = 0; i < 2; ++i)
            {
                row = col = 0;
                Image iback, ifore;
                if (i == 0)
                {
                    iback = ispectr;
                    ifore = iorchid;
                    var trc1 = Common.Util.AddNote(
                        "以下の画像は、GcPdf がサポートする様々なブレンドモードを使用して、" +
                        "2つの画像(スペクトルと蘭)を合成して描画したものです。" +
                        "まずスペクトルの画像が通常どおりに描画され、次にサポートされているブレンドモードにて" +
                        "描画された蘭の画像が重ねられます。また、各画像の下部にブレンドモード名が表示されます。" +
                        "\n" +
                        "2ページ目のものは、同じ画像で構成されていますが、逆の順序で描画されています。" +
                        "蘭は通常どおりに描画され、スペクトルは様々なモードを使用して合成されています。" +
                        "\n" +
                        "なお、現在のブレンドモードは、画像だけでなく GcGraphics のすべての描画に影響することに" +
                        "注意してください。2ページ目下部のブレンドモード名の描画にてそれを確認できます。",
                        page);
                    dy = (int)trc1.Bottom;
                }
                else // i == 1
                {
                    iback = iorchid;
                    ifore = ispectr;
                    page = doc.Pages.Add();
                    g = page.Graphics;
                    dy = 0;
                }
                foreach (var mode in modes)
                {
                    var blendMode = (BlendMode)mode;
                    if (!g.IsBlendModeSupported(blendMode))
                        continue;

                    int x = margin + w * col;
                    int y = margin + h * row + dy;
                    var r = new RectangleF(x, y, w, h);

                    g.BlendMode = BlendMode.Normal;
                    g.DrawImage(iback, r, null, ImageAlign.StretchImage);
                    g.BlendMode = blendMode;
                    g.DrawImage(ifore, r, null, ImageAlign.StretchImage);
                    g.BlendMode = BlendMode.Normal;

                    // 見出し
                    tl.Clear();
                    tl.Append(blendMode.ToString());
                    tl.PerformLayout(true);
                    var rc = tl.ContentRectangle;
                    rc.Offset(x, y);
                    rc.Inflate(4, 2);
                    g.FillRectangle(rc, Color.White);
                    g.DrawTextLayout(tl, new PointF(x, y));
                    nextRowCol();
                }
            }
            // テキストの合成
            page = doc.Pages[1];
            g = page.Graphics;
            var trc = Common.Util.AddNote(
                "以下の画像は、サポートされているブレンドモード名を、対応するブレンドモードを使用して" +
                "矩形にレンダリングしたものです。" +
                "各矩形は,まず BlendMode.Normal を使用してスペクトルの画像が描画され、" +
                "次に現在のブレンドモードを使用して黒と白のテキストが描画され、" +
                "最後に背景が黒くなるよう BlendMode.Difference を使用して同じスペクトルの画像が描画されています。" +
                "なお、「B:」の付く名前は黒で、「W:」の付く名前は白で描画されています。" +
                "ほとんどの組み合わせはカラフルな結果になりますが、一部の組み合わせでは結果が見えません。",
                page,
                new RectangleF(margin, margin + h * row + 12, page.Bounds.Width - margin * 2, 0));

            var yoff = (int)trc.Bottom + 12;
            tl.DefaultFormat.FontBold = true;
            tl.DefaultFormat.FontSize = 16;
            h = (int)(g.MeasureString("QWERTY", tl.DefaultFormat).Height * 1.4f) * 2;
            tl.MaxWidth = w;
            tl.MaxHeight = h;
            tl.MarginTop = (h - h / 1.4f) / 2;

            tl.DefaultFormat.ForeColor = Color.Black;
            var tfWhite = new TextFormat(tl.DefaultFormat) { ForeColor = Color.White };

            row = col = 0;
            foreach (var mode in modes)
            {
                var blendMode = (BlendMode)mode;
                if (!g.IsBlendModeSupported(blendMode))
                    continue;

                int x = margin + w * col;
                int y = yoff + h * row;
                var r = new RectangleF(x, y, w, h);

                // スペクトルの画像を通常どおりに描画します。
                g.BlendMode = BlendMode.Normal;
                g.DrawImage(ispectr, r, null, ImageAlign.StretchImage);
                // 現在のブレンドモードを使用して、ブレンドモード名を描画します。
                tl.Clear();
                tl.AppendLine($"B: {blendMode}");
                tl.Append($"W: {blendMode}", tfWhite);
                tl.PerformLayout(true);
                var rc = tl.ContentRectangle;
                rc.Offset(x, y);
                rc.Inflate(4, 2);
                // 現在のブレンドモード
                g.BlendMode = blendMode;
                g.DrawTextLayout(tl, new PointF(x, y));
                // BlendMode.Difference を使用してスペクトルの画像を再度描画すると、
                // 黒の背景に(ほぼ)カラフルなテキストが表示されます。
                g.BlendMode = BlendMode.Difference;
                g.DrawImage(ispectr, r, null, ImageAlign.StretchImage);
                // 現在の領域を示す矩形を描画します。
                g.BlendMode = BlendMode.Normal;
                g.DrawRectangle(r, Color.Gray);
                nextRowCol();
            }
            // PDF ドキュメントを保存します。
            doc.Save(stream);
            
            void nextRowCol()
            {
                if (++col == NCOLS)
                {
                    col = 0;
                    ++row;
                }
            }
        }
    }
}