SvgGraphicsArch.vb
''
'' This code is part of Document Solutions for Imaging demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System
Imports System.IO
Imports System.Drawing
Imports System.Collections.Generic
Imports System.Linq
Imports System.Numerics
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Imaging
Imports GrapeCity.Documents.Svg
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing

'' This example shows how to render an arch on GcSvgGraphics
'' using graphics paths. The arch is positioned in the center
'' of the resultant image using graphics transformation matrix.
Public Class SvgGraphicsArch
    Public ReadOnly Property DefaultMime As String
        Get
            Return Util.MimeTypes.SVG
        End Get
    End Property

    Public Function GenerateImageStream(
            ByVal targetMime As String,
            ByVal pixelSize As Size,
            ByVal dpi As Single,
            ByVal opaque As Boolean,
            Optional ByVal sampleParams As String() = Nothing) As Stream

        If targetMime <> Util.MimeTypes.SVG Then
            Throw New Exception("This sample only supports SVG output format.")
        End If

        Dim background As Color = Color.PaleGoldenrod,
            line As Color = Color.FromArgb(11, 83, 69),
            arc As Color = Color.FromArgb(22, 160, 133),
            fill As Color = Color.FromArgb(255, 171, 145),
            marks As Color = Color.DarkGray,
            text As Color = Color.Black,
            textBack As Color = Color.Cornsilk

        Dim Inch = dpi
        Dim ms = New MemoryStream()
        Using g As New GcSvgGraphics(pixelSize.Width, pixelSize.Height)
            If opaque Then
                g.FillRectangle(New RectangleF(0, 0, g.Width, g.Height), background)
            End If

            '' Arc bounding rectangle:
            Dim rc = New RectangleF(0, 0, Inch * 4, Inch * 4.8F)

            '' Use transform to center all drawing:
            Dim t = g.Transform
            g.Transform = Matrix3x2.CreateTranslation(g.Width / 2 - rc.Width / 2, g.Height / 2 - rc.Height / 2)

            '' Draw the arc:
            DrawArch(g, rc, rc.Height * 0.3F, rc.Width * 0.08F, line, arc, fill)

            '' Add a label:
            Dim tf = New TextFormat() With {
                .Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeSerif.ttf")),
                .FontSize = Inch / 6,
                .ForeColor = text
            }
            g.DrawString("ARCH", tf, rc, TextAlignment.Center, ParagraphAlignment.Center, False)

            '' Measurement lines:
            Dim w = Inch / 8
            Dim pen = New GCDRAW.Pen(marks)

            Dim txt = $"{(rc.Width / Inch):F}"""
            Dim s = g.MeasureString(txt, tf)
            Dim d = s.Height * 1.5F
            g.DrawLine(rc.Left, rc.Top - d, rc.Right, rc.Top - d, pen)
            g.DrawLine(rc.Left, rc.Top - d, rc.Left + w, rc.Top - d - w, pen)
            g.DrawLine(rc.Left, rc.Top - d, rc.Left + w, rc.Top - d + w, pen)
            g.DrawLine(rc.Right, rc.Top - d, rc.Right - w, rc.Top - d - w, pen)
            g.DrawLine(rc.Right, rc.Top - d, rc.Right - w, rc.Top - d + w, pen)

            Dim rcTxt = New RectangleF(rc.Left + rc.Width / 2 - s.Width / 2, rc.Top - d - s.Height / 2, s.Width, s.Height)
            rcTxt.Inflate(2, 2)
            g.FillRectangle(rcTxt, textBack)
            g.DrawString(txt, tf, rcTxt, TextAlignment.Center, ParagraphAlignment.Center, False)

            txt = $"{(rc.Height / Inch):F}"""
            s = g.MeasureString(txt, tf)
            d = s.Width
            g.DrawLine(rc.Left - d, rc.Top, rc.Left - d, rc.Bottom, pen)
            g.DrawLine(rc.Left - d, rc.Top, rc.Left - d - w, rc.Top + w, pen)
            g.DrawLine(rc.Left - d, rc.Top, rc.Left - d + w, rc.Top + w, pen)
            g.DrawLine(rc.Left - d, rc.Bottom, rc.Left - d - w, rc.Bottom - w, pen)
            g.DrawLine(rc.Left - d, rc.Bottom, rc.Left - d + w, rc.Bottom - w, pen)
            rcTxt = New RectangleF(rc.Left - d - s.Width / 2, rc.Top + rc.Height / 2 - s.Height / 2, s.Width, s.Height)
            rcTxt.Inflate(2, 2)
            g.FillRectangle(rcTxt, textBack)
            g.DrawString(txt, tf, rcTxt, TextAlignment.Center, ParagraphAlignment.Center, False)

            '' Restore transform:
            g.Transform = t

            '' Done:
            Dim svg = g.ToSvgDocument()
            svg.Save(ms)
            ms.Seek(0, SeekOrigin.Begin)
            Return ms
        End Using
    End Function

    Private Sub DrawArch(g As GcGraphics, rc As RectangleF, harc As Single, wd As Single, line As Color, arch As Color, fill As Color)
        Dim path = g.CreatePath()
        '' Insides filler (start from bottom left, to clockwise):
        path.BeginFigure(rc.Left + wd, rc.Bottom - wd)
        path.AddLine(rc.Left + wd, rc.Top + harc)
        path.AddArc(New ArcSegment() With {
            .ArcSize = ArcSize.Small,
            .Point = New PointF(rc.Right - wd, rc.Top + harc),
            .RotationAngle = 0,
            .Size = New SizeF(rc.Width / 2.0F - wd, harc - wd),
            .SweepDirection = SweepDirection.Clockwise
        })
        path.AddLine(rc.Right - wd, rc.Bottom - wd)
        path.EndFigure(FigureEnd.Closed)
        g.FillPath(path, fill)
        path.Dispose()

        '' Arc outlines (start from bottom left, to clockwise):
        path = g.CreatePath()
        path.BeginFigure(rc.Left, rc.Bottom)
        path.AddLine(rc.Left, rc.Top + harc)
        path.AddLine(rc.Left + wd, rc.Top + harc)
        path.AddLine(rc.Left + wd, rc.Bottom - wd)
        path.EndFigure(FigureEnd.Closed)
        path.BeginFigure(rc.Left, rc.Top + harc)
        path.AddArc(New ArcSegment() With {
            .ArcSize = ArcSize.Small,
            .Point = New PointF(rc.Right, rc.Top + harc),
            .RotationAngle = 0,
            .Size = New SizeF(rc.Width / 2.0F, harc),
            .SweepDirection = SweepDirection.Clockwise
        })
        path.AddLine(rc.Right - wd, rc.Top + harc)
        path.AddArc(New ArcSegment() With {
            .ArcSize = ArcSize.Small,
            .Point = New PointF(rc.Left + wd, rc.Top + harc),
            .RotationAngle = 0,
            .Size = New SizeF(rc.Width / 2.0F - wd, harc - wd),
            .SweepDirection = SweepDirection.CounterClockwise
        })
        path.EndFigure(FigureEnd.Closed)
        path.BeginFigure(rc.Right, rc.Top + harc)
        path.AddLine(rc.Right, rc.Bottom)
        path.AddLine(rc.Right - wd, rc.Bottom - wd)
        path.AddLine(rc.Right - wd, rc.Top + harc)
        path.EndFigure(FigureEnd.Closed)
        path.BeginFigure(rc.Right, rc.Bottom)
        path.AddLine(rc.Left, rc.Bottom)
        path.AddLine(rc.Left + wd, rc.Bottom - wd)
        path.AddLine(rc.Right - wd, rc.Bottom - wd)
        path.EndFigure(FigureEnd.Closed)

        g.FillPath(path, arch)
        g.DrawPath(path, New GCDRAW.Pen(line, 2))

        path.Dispose()
    End Sub
End Class