SvgGraphicsRoundRectangle.cs
//
// This code is part of GrapeCity Documents for Imaging samples.
// Copyright (c) GrapeCity, Inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using GrapeCity.Documents.Imaging;
using GrapeCity.Documents.Svg;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Drawing;

namespace GcImagingWeb.Samples
{
    // This example shows how to draw on GcSvgGraphics.
    // It draws round rectangles using both dedicated DrawRoundRect/FillRoundRect
    // methods and graphics paths.
    // Note that the code in this sample is identical to the drawing code
    // in the RoundRectangle sample, but creates a vector SVG image
    // rather than a raster GcBitmap.
    public class SvgGraphicsRoundRectangle
    {
        public string DefaultMime { get => Common.Util.MimeTypes.SVG; }

        public Stream GenerateImageStream(string targetMime, Size pixelSize, float dpi, bool opaque, string[] sampleParams = null)
        {
            if (targetMime != Common.Util.MimeTypes.SVG)
                throw new Exception("This sample only supports SVG output format.");

            var Inch = dpi;
            var ms = new MemoryStream();
            using var g = new GcSvgGraphics(pixelSize.Width, pixelSize.Height);
            if (opaque)
                g.FillRectangle(new RectangleF(0, 0, g.Width, g.Height), Color.White);

            var rc = Common.Util.AddNote(
                "GcGraphics has dedicated methods to easily draw and fill rectangles with rounded corners. " +
                "This sample also shows how the same result may be achieved using graphics paths. " +
                "While they are not really needed for drawing round rectangles, graphics paths allow " +
                "to draw and fill arbitrary figures with complex geometries.\r\n\r\n" +
                "Note that this version of the \"Round Rectangles\" sample draws on a GcSvgGraphics, " +
                "and produces a vector SVG image rather than a raster image (JPEG, PNG etc.).",
                g);

            // Rounded rectangle's radii:
            float rx = 36, ry = 24;

            // Using dedicated methods to draw and fill round rectangles:
            var rEasy = new RectangleF(rc.Left, rc.Bottom + Inch / 2, Inch * 2, Inch);
            g.FillRoundRect(rEasy, rx, ry, Color.PaleGreen);
            g.DrawRoundRect(rEasy, rx, ry, Color.Blue, 4);
            // Add a label:
            var tf = new TextFormat()
            {
                Font = Font.FromFile(Path.Combine("Resources", "Fonts", "times.ttf")),
                FontSize = Inch / 6
            };
            g.DrawString("The easy way.", tf, rEasy, TextAlignment.Center, ParagraphAlignment.Center, false);

            // Using graphics path to achieve the same result:
            var rHard = rEasy;
            rHard.Offset(0, rEasy.Height + Inch / 2);
            var path = MakeRoundRect(g, rHard, rx, ry);
            g.FillPath(path, Color.PaleVioletRed);
            g.DrawPath(path, Color.Purple, 4);
            // Add a label:
            g.DrawString("The hard way.", tf, rHard, TextAlignment.Center, ParagraphAlignment.Center, false);

            // Done:
            var svg = g.ToSvgDocument();
            svg.Save(ms);
            ms.Seek(0, SeekOrigin.Begin);
            return ms;
        }

        // This method shows how to create a graphics path that may be used
        // to fill or draw arbitrary shapes on a GcGraphics.
        private IPath MakeRoundRect(GcGraphics g, RectangleF rc, float rx, float ry)
        {
            var path = g.CreatePath();
            var sz = new SizeF(rx, ry);
            // start from horizontal top left
            path.BeginFigure(new PointF(rc.Left + rx, rc.Top));
            path.AddLine(new PointF(rc.Right - rx, rc.Top));
            path.AddArc(new ArcSegment() { Point = new PointF(rc.Right, rc.Top + ry), SweepDirection = SweepDirection.Clockwise, Size = sz });
            path.AddLine(new PointF(rc.Right, rc.Bottom - ry));
            path.AddArc(new ArcSegment() { Point = new PointF(rc.Right - rx, rc.Bottom), SweepDirection = SweepDirection.Clockwise, Size = sz });
            path.AddLine(new PointF(rc.Left + rx, rc.Bottom));
            path.AddArc(new ArcSegment() { Point = new PointF(rc.Left, rc.Bottom - ry), SweepDirection = SweepDirection.Clockwise, Size = sz });
            path.AddLine(new PointF(rc.Left, rc.Top + ry));
            path.AddArc(new ArcSegment() { Point = new PointF(rc.Left + rx, rc.Top), SweepDirection = SweepDirection.Clockwise, Size = sz });
            path.EndFigure(FigureEnd.Closed);
            return path;
        }
    }
}