SvgRandomArt.cs
//
// This code is part of Document Solutions for PDF demos.
// Copyright (c) MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Svg;
using GCTEXT = GrapeCity.Documents.Text;
using GCDRAW = GrapeCity.Documents.Drawing;
using DsPdfWeb.Demos.Common;

namespace DsPdfWeb.Demos
{
    // This sample generates some random abstract art using the SVG path API
    // provided by GcSvgDocument.
    public class SvgRandomArt
    {
        private Random _rnd = Util.NewRandom();

        public int CreatePDF(Stream stream)
        {
            using var svgDoc = new GcSvgDocument();
            var svg = svgDoc.RootSvg;
            svg.ViewBox = new SvgViewBox(0, 0, 100, 100);

            // Random art:
            for (int i = 0; i < _rnd.Next(6, 12); i++)
                AddFigure(svg, _rnd);

            // Border:
            svg.Children.Add(new SvgRectElement()
            {
                Width = new SvgLength(100),
                Height = new SvgLength(100),
                Stroke = new SvgPaint(Color.FromArgb(_rnd.Next(256), _rnd.Next(256), _rnd.Next(256))),
                Fill = SvgPaint.None
            });
            // Clip:
            svg.Clip = new SvgClip(new SvgLength(0), new SvgLength(0), new SvgLength(100), new SvgLength(100));

            // Render the SVG image to a PDF:
            var doc = new GcPdfDocument();
            var page = doc.NewPage();
            var g = page.Graphics;
            var s = svgDoc.GetIntrinsicSize(SvgLengthUnits.Points);

            var margin = 72;
            var rect = new RectangleF(margin, margin, page.Size.Width - margin * 2, page.Size.Width - margin * 2);
            g.DrawSvg(svgDoc, rect);

            // Done:
            doc.Save(stream);
            return doc.Pages.Count;
        }

        int Next100()
        {
            return _rnd.Next(100);
        }

        void AddFigure(SvgSvgElement svg, Random rnd)
        {
            var pb = new SvgPathBuilder();
            var startX = Next100();
            var startY = Next100();
            pb.AddMoveTo(false, startX, startY);
            for (int i = 0; i < rnd.Next(20, 80); ++i)
                AddCurve(pb, rnd);
            pb.AddCurveTo(false, Next100(), Next100(), Next100(), Next100(), startX, startY);

            svg.Children.Add(new SvgPathElement()
            {
                FillRule = SvgFillRule.EvenOdd,
                Fill = new SvgPaint(Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256))),
                Stroke = new SvgPaint(Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256))),
                StrokeWidth = new SvgLength(rnd.Next(20) / 10f, SvgLengthUnits.Percentage),
                PathData = pb.ToPathData(),
                FillOpacity = Next100() / 100f,
                StrokeOpacity = Next100() / 100f,
            });
        }

        void AddCurve(SvgPathBuilder pb, Random _rnd)
        {
            switch (_rnd.Next(5))
            {
                case 0:
                    pb.AddCurveTo(false, Next100(), Next100(), Next100(), Next100(), Next100(), Next100());
                    break;
                case 1:
                    pb.AddSmoothCurveTo(false, Next100(), Next100(), Next100(), Next100());
                    break;
                case 2:
                    pb.AddQuadraticBezierCurveTo(false, Next100(), Next100(), Next100(), Next100());
                    break;
                case 3:
                    pb.AddSmoothQuadraticBezierCurveTo(false, Next100(), Next100());
                    break;
                case 4:
                    pb.AddEllipticalArc(false, Next100(), Next100(), _rnd.Next(360),
                        _rnd.Next(2) == 0 ? GCDRAW.ArcSize.Small : GCDRAW.ArcSize.Large,
                        _rnd.Next(2) == 0 ? GCDRAW.SweepDirection.Clockwise : GCDRAW.SweepDirection.CounterClockwise,
                        Next100(), Next100());
                    break;
            }
        }
    }
}