BackgroundBitmap.cs
//
// This code is part of Document Solutions for Imaging demos.
// Copyright (c) MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
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
{
    // This sample demonstrates the use of BitmapRenderer.BackgroundBitmap
    // when drawing on a bitmap.
    //
    // When drawing semi-transparent graphic objects, usually the resulting color
    // of a pixel is a combination of the target bitmap pixel's color and the color
    // of the graphic object's pixel. But if the BackgroundBitmap is set on the
    // BitmapRenderer, pixels of that bitmap will be used instead of the target
    // bitmap's pixels when determining the resulting color. Background bitmaps
    // are used to support Isolated and Knockout transparency groups (as defined
    // in the PDF specification 1.7 sections 7.3.4 and 7.3.5) when rendering PDFs
    // to images.
    public class BackgroundBitmap
    {
        public GcBitmap GenerateImage(Size pixelSize, float dpi, bool _, string[] _1 = null)
        {
            var hx = pixelSize.Width / 2;
            var hy = pixelSize.Height / 2;

            // The spectrum image used for the backdrop:
            using var bmp0 = new GcBitmap(Path.Combine("Resources", "ImagesBis", "spectrum-pastel-500x500.png"));
            using var bmp1 = bmp0.Resize(hx, hy, InterpolationMode.Cubic);

            using var bmpBackdrop = new GcBitmap(hx, hy, false, dpi, dpi);
            using var bmpInitial = new GcBitmap(hx, hy, false, dpi, dpi);
            using var gB = bmpBackdrop.CreateGraphics();
            using var gI = bmpInitial.CreateGraphics();

            gB.Renderer.Aliased = true;
            gB.Renderer.BlendMode = BlendMode.Multiply;
            gI.Renderer.Aliased = true;
            gI.Renderer.BlendMode = BlendMode.Multiply;

            // The target bitmap will contain 4 demo quadrants:
            var bmp = new GcBitmap(pixelSize.Width, pixelSize.Height, false, dpi, dpi);

            // Isolated, Knockout:
            bmpBackdrop.BitBlt(bmp1, 0, 0);
            bmpInitial.Clear(Color.Transparent);
            gB.Renderer.BackgroundBitmap = bmpInitial;
            FillCircles(gB, hx, hy);
            bmp.BitBlt(bmpBackdrop, 0, 0);

            // Isolated, Non-knockout:
            FillCircles(gI, hx, hy);
            bmpBackdrop.BitBlt(bmp1, 0, 0);
            bmpBackdrop.AlphaBlend(bmpInitial, 0, 0);
            bmp.BitBlt(bmpBackdrop, hx, 0);

            // Non-isolated, Knockout:
            bmpBackdrop.BitBlt(bmp1, 0, 0);
            bmpInitial.BitBlt(bmp1, 0, 0);
            FillCircles(gB, hx, hy);
            bmp.BitBlt(bmpBackdrop, 0, hy);

            // Non-isolated, Non-knockout:
            bmpBackdrop.BitBlt(bmp1, 0, 0);
            gB.Renderer.BackgroundBitmap = null;
            FillCircles(gB, hx, hy);
            bmp.BitBlt(bmpBackdrop, hx, hy);

            // Adornments:
            using var g = bmp.CreateGraphics();
            g.DrawLine(0, hy, bmp.PixelWidth, hy, new GCDRAW.Pen(Color.Black));
            g.DrawLine(hx, 0, hx, bmp.PixelHeight, new GCDRAW.Pen(Color.Black));
            var tf = new TextFormat()
            {
                Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "courbd.ttf")),
                FontSize = 16,
            };
            var d = 40;
            g.DrawString("Isolated, Knockout", tf, new RectangleF(0, hy - d, hx, d),
                TextAlignment.Center, ParagraphAlignment.Center, false);
            g.DrawString("Isolated, Non-knockout", tf, new RectangleF(hx, hy - d, hx, d),
                TextAlignment.Center, ParagraphAlignment.Center, false);
            g.DrawString("Non-isolated, Knockout", tf, new RectangleF(0, hy * 2 - d, hx, d),
                TextAlignment.Center, ParagraphAlignment.Center, false);
            g.DrawString("Non-isolated, Non-knockout", tf, new RectangleF(hx, hy * 2 - d, hx, d),
                TextAlignment.Center, ParagraphAlignment.Center, false);

            // Done:
            return bmp;
        }

        void FillCircles(GcBitmapGraphics g, float hx, float hy)
        {
            var dx = hx / 10;
            var dy = hy / 10;
            var qx = hx / 2;
            var qy = hy / 2;

            g.FillEllipse(new RectangleF(dx, dy, qx, qy), Color.LightGray);
            g.FillEllipse(new RectangleF(qx - dx, dy, qx, qy), Color.LightGray);
            g.FillEllipse(new RectangleF(dx, qy - dy, qx, qy), Color.LightGray);
            g.FillEllipse(new RectangleF(qx - dx, qy - dy, qx, qy), Color.LightGray);
        }
    }
}