SoftEdges.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 how to create a Soft Edges effect using DsImaging.
    // The Soft Edges effect deflates all non-transparent areas of an image by a specified amount,
    // then applies a Gaussian blur to make the border smooth. It is one of the effects
    // that are found in MS Word for example.
    // 
    // To achieve this effect in DsImaging, the GrayscaleBitmap.ApplyGlow() method is used
    // on the transparency mask built from the color image on which we want the soft edges to appear,
    // along with a few other simple steps as illustrated by this code.
    //
    // The same GrayscaleBitmap.ApplyGlow() method is also used to achieve the Glow effect
    // as illustrated by the Glow and GlowAlt examples.
    public class SoftEdges
    {
        private GCTEXT.Font _font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "calibri.ttf"));

        public GcBitmap GenerateImage(Size pixelSize, float dpi, bool opaque, string[] sampleParams = null)
        {
            // Draw text and logo on a transparent bitmap:
            var bmp = new GcBitmap(pixelSize.Width, pixelSize.Height, false);
            bmp.Clear(Color.Transparent);
            drawTextAndLogo();

            // Convert the image to a transparency mask:
            using var gs = bmp.ToGrayscaleBitmap(ColorChannel.Alpha);

            // Apply the Soft Edges effect to it; while for Glow the inflation radius is positive,
            // for Soft Edges it should be negative, -6 here (9 is the blur radius):
            gs.ApplyGlow(-6, 9);

            // Use the resulting GrayscaleBitmap as a transparency mask when drawing the text and logo once again:
            bmp.Clear(Color.Gray);
            bmp.EnsureRendererCreated().TransparencyMaskBitmap = gs;

            // Finally, draw the text and logo once more over the prepared background:
            drawTextAndLogo();

            // Done
            return bmp;

            void drawTextAndLogo()
            {
                DrawText(bmp.EnsureRendererCreated(), pixelSize, dpi);
                DrawLogo(bmp.EnsureRendererCreated(), new PointF(pixelSize.Width / 2, (int)(pixelSize.Height * 0.8)), pixelSize.Width / 2);
            }
        }

        void DrawText(BitmapRenderer renderer, Size pixelSize, float dpi)
        {
            var f1 = new TextFormat
            {
                Font = _font,
                FontSize = pixelSize.Height / 6,
                ForeColor = Color.DarkOrchid,
                FontBold = true
            };
            var f2 = new TextFormat(f1)
            {
                ForeColor = Color.White,
                StrokePen = new GCDRAW.Pen(Color.DarkOrchid, 3)
            };
            var tl = new TextLayout(dpi)
            {
                MaxWidth = pixelSize.Width,
                MaxHeight = pixelSize.Height,
                ParagraphAlignment = ParagraphAlignment.Near,
                TextAlignment = TextAlignment.Center,
                MarginTop = dpi * 2,
                LineSpacingScaleFactor = 0.7f,
            };
            tl.Append("Document", f1);
            tl.Append("Solutions", f2);

            // Draw the text:
            renderer.SlowAntialiasing = true;
            renderer.DrawTextLayout(tl, 0, 0);
        }

        void DrawLogo(BitmapRenderer renderer, PointF center, float width)
        {
            var pb = new PathBuilder();
            pb.BeginFigure(100, 350);
            pb.AddLine(210, 310);
            var arc = new ArcSegment
            {
                Size = new SizeF(183, 173),
                SweepDirection = SweepDirection.Clockwise,
                Point = new PointF(550, 205),
            };
            pb.AddArc(arc);
            pb.AddLine(650, 170);
            pb.AddLine(680, 250);
            pb.AddLine(575, 285);
            arc.Point = new PointF(240, 390);
            pb.AddArc(arc);
            pb.AddLine(130, 430);
            pb.EndFigure(true);
            pb.Figures.Add(new EllipticFigure(new RectangleF(295, 197, 200, 190)));
            var gpFill = pb.ToPath();
            var gpStroke = gpFill.Widen(new GCDRAW.Pen(Color.Black, 20));

            // Our 'base' size is 800 x 600 pixels:
            float scale = width / 800;
            renderer.Transform = Matrix3x2.CreateScale(scale) *
                Matrix3x2.CreateTranslation(center.X - 400 * scale, center.Y - 300 * scale);
            renderer.FillPath(gpFill, Color.CornflowerBlue);
            renderer.FillPath(gpStroke, Color.DarkOrchid);
            renderer.Transform = Matrix3x2.Identity;
        }
    }
}