SvgGraphicsText.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 GrapeCity.Documents.Imaging
Imports GrapeCity.Documents.Svg
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Drawing
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing

'' This sample demonstrates drawing text on an SVG using GcSvgGraphics.
'' It shows how to render text as true SVG <text> elements (rather than paths),
'' so that the text remains searchable, selectable, and copyable.
'' The demo draws rounded rectangles in two ways: using the dedicated
'' DrawRoundRect/FillRoundRect methods, and by constructing a custom
'' graphics path. Labels are added inside the shapes using DrawString,
'' and the result is saved as an SVG document.
'' See also RoundRectangle and SvgGraphicsRoundRectangle samples.
Public Class SvgGraphicsText
    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 Inch = dpi
        Dim ms = New MemoryStream()
        Using g As New GcSvgGraphics(pixelSize.Width, pixelSize.Height)

            '' IMPORTANT: this property is true by default on GcSvgGraphics, which usually yields better text fidelity,
            '' but text cannot be searched/selected/copied in this case, and the SVG file size is larger.
            '' Setting this property to false results in text rendered using SVG 'text' elements, so that
            '' text can be searched/selected/copied. Compare to the SvgGraphicsRoundRectangle example
            '' which is identical to this example but draws text as paths:
            g.DrawTextAsPath = False

            If opaque Then
                g.FillRectangle(New RectangleF(0, 0, g.Width, g.Height), Color.White)
            End If

            Dim rc = 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." & vbCrLf & vbCrLf &
                "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:
            Dim rx As Single = 36, ry As Single = 24

            '' Using dedicated methods to draw and fill round rectangles:
            Dim 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:
            Dim tf = New TextFormat() With {
                .Font = GCTEXT.Font.FromFile(System.IO.Path.Combine("Resources", "Fonts", "FreeSerif.ttf")),
                .FontSize = Inch / 6
            }
            g.DrawString("The easy way.", tf, rEasy, TextAlignment.Center, ParagraphAlignment.Center, False)

            '' Using graphics path to achieve the same result:
            Dim rHard = rEasy
            rHard.Offset(0, rEasy.Height + Inch / 2)
            Dim 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:
            Dim svg = g.ToSvgDocument()
            svg.Save(ms)
            ms.Seek(0, SeekOrigin.Begin)
            Return ms
        End Using
    End Function

    '' This method shows how to create a graphics path that may be used
    '' to fill or draw arbitrary shapes on a GcGraphics.
    Private Function MakeRoundRect(g As GcGraphics, rc As RectangleF, rx As Single, ry As Single) As IPath
        Dim path = g.CreatePath()
        Dim 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() With {.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() With {.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() With {.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() With {.Point = New PointF(rc.Left + rx, rc.Top), .SweepDirection = SweepDirection.Clockwise, .Size = sz})
        path.EndFigure(FigureEnd.Closed)
        Return path
    End Function
End Class