SvgGraphicsPicInArch.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.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. It also shows how a path can be used
'' to clip the drawing, and how to draw raster images
'' on GcSvgGraphics.
'' The arch drawing code is similar to that used in SvgGraphicsArch.
Public Class SvgGraphicsPicInArch
    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

        '' Note that the foreground image is a PNG with some transparency:
        Dim imageFn As String = Path.Combine("Resources", "ImagesBis", "minerva-masked.png")
        Dim backFn As String = Path.Combine("Resources", "Images", "colosseum.jpg")

        Dim background As Color = Color.FromArgb(230, 153, 77)
        Dim line As Color = Color.FromArgb(102, 34, 0)
        Dim arch As Color = Color.FromArgb(147, 78, 31)
        Dim archBack As Color = Color.FromArgb(0, 191, 255)
        Dim fill As Color = Color.FromArgb(255, 171, 145)
        Dim marks As Color = Color.FromArgb(170, 62, 9)
        Dim text As Color = Color.Black
        Dim 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 * 5, Inch * 6.4F)

            '' 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)

            '' Load and flip the foreground and background images.
            Using bmp0 As New GcBitmap(imageFn),
                bmp As GcBitmap = bmp0.FlipRotate(FlipRotateAction.FlipHorizontal),
                backBmpT As New GcBitmap(backFn),
                backBmp As GcBitmap = backBmpT.FlipRotate(FlipRotateAction.FlipHorizontal)

                '' Draw the arch and images inside:
                Dim innerPath = DrawArch(g, rc, rc.Height * 0.35F, rc.Width * 0.08F, line, arch, fill)
                Using clip = g.PushClip(innerPath)
                    '' Fill background with a color to tint the background, draw background semi-transparently,
                    '' draw foreground opaque (but it has transparent pixels):
                    g.FillRectangle(rc, archBack)
                    Dim ia = New ImageAlign(ImageAlignHorz.Center, ImageAlignVert.Center, True, True, True, False, False)
                    g.DrawImage(backBmp, rc, rc, ia, 0.7F)
                    g.DrawImage(bmp, rc, rc, ia, 1.0F)
                End Using

                '' 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)
            End Using
        End Using
        Return ms
    End Function

    Private Function DrawArch(g As GcGraphics, rc As RectangleF, harc As Single, wd As Single, line As Color, arch As Color, fill As Color) As IPath
        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)
        Dim innerPath = path '' keep for clipping

        '' 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()
        Return innerPath
    End Function
End Class