SvgFontAwesome.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.Linq
Imports System.Collections.Generic
Imports GrapeCity.Documents.Imaging
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Svg
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing

'' This sample shows how to render SVG icons included in the "Free for Web" download of Font Awesome.
'' The sample code also shows how to change the default color of the glyphs.
Public Class SvgFontAwesome
    Private _rnd As Random = Util.NewRandom()

    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 sampleParams Is Nothing Then
            sampleParams = GetSampleParamsList()(0)
        End If

        '' Font and format for captions:
        Const sMargin As Single = 96.0F / 8.0F
        Dim font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeSans.ttf"))
        Dim tf = New TextFormat() With {.Font = font, .FontSize = sMargin * 0.65F}

        '' Set up a layout grid:
        Dim background = Color.White
        Dim foreground = Color.Black
        Const margin As Single = 36.0F
        Const rows As Integer = 10
        Const cols As Integer = 10
        Dim gapx As Single = 96.0F / 8.0F, gapy As Single = gapx
        Dim sWidth As Single = (pixelSize.Width - margin * 2 + gapx) / cols
        Dim sHeight As Single = (pixelSize.Height - margin * 2 + gapy) / rows
        If sWidth > sHeight Then
            gapx += sWidth - sHeight
            sWidth = sHeight
        Else
            gapy += sHeight - sWidth
            sHeight = sWidth
        End If
        Dim ip As New PointF(margin, margin)
        Dim colorize As Boolean = (sampleParams(3) = "colorize")
        Dim maxFiles As Integer = If(targetMime = Util.MimeTypes.TIFF, Integer.MaxValue, rows * cols)

        Dim basePath = Path.Combine("Resources", "FontAwesome", If(colorize, String.Empty, sampleParams(3)))
        Dim fileNames = Directory.GetFiles(basePath, "*.svg", SearchOption.AllDirectories).ToList()
        If colorize Then
            fileNames.Shuffle()
        Else
            fileNames.Sort(StringComparer.Ordinal)
        End If
        Dim files = fileNames.Take(maxFiles)

        Dim images As New List(Of Tuple(Of String, GcSvgDocument))(files.Count())
        For Each fname In files
            images.Add(Tuple.Create(fname, GcSvgDocument.FromFile(fname)))
        Next

        '' Render all images within the grid, adding new pages as needed:
        Dim bmp = New GcBitmap(pixelSize.Width, pixelSize.Height, False, dpi, dpi)
        Dim g = bmp.CreateGraphics(Color.White)
        Dim ms As New MemoryStream()
        Dim tw As GcTiffWriter = Nothing
        If targetMime = Util.MimeTypes.TIFF Then
            tw = New GcTiffWriter(ms)
        End If

        For i As Integer = 0 To images.Count() - 1
            '' Draw border around image:
            Dim rect As New RectangleF(ip, New SizeF(sWidth - gapx, sHeight - gapy))
            g.FillRectangle(rect, background)
            g.DrawRectangle(rect, foreground, 0.5F)
            rect.Inflate(-sMargin, -sMargin)

            '' Draw the SVG:
            Dim svg = images(i).Item2
            Dim s = svg.GetIntrinsicSize(SvgLengthUnits.Points)
            If s.Width > 0 AndAlso s.Height > 0 Then
                '' If image proportions are different from our target rectangle,
                '' we resize the rectangle centering the image in it:
                Dim qSrc = s.Width / s.Height
                Dim qTgt = rect.Width / rect.Height
                If qSrc < qTgt Then
                    rect.Inflate(rect.Width * (qSrc / qTgt - 1) / 2.0F, 0)
                ElseIf qSrc > qTgt Then
                    rect.Inflate(0, rect.Height * (qTgt / qSrc - 1) / 2.0F)
                End If
            End If

            If colorize Then
                svg.RootSvg.Fill = New SvgPaint(Color.FromArgb(_rnd.Next(256), _rnd.Next(256), _rnd.Next(256)))
            End If

            '' Render the SVG:
            g.DrawSvg(svg, rect)

            '' Print the icon file name as caption in the bottom margin:
            g.DrawString(Path.GetFileNameWithoutExtension(images(i).Item1), tf,
                         New RectangleF(rect.X, rect.Bottom, rect.Width, sMargin),
                         TextAlignment.Center, ParagraphAlignment.Near, False)

            ip.X += sWidth
            If (ip.X + sWidth > pixelSize.Width) AndAlso (i < images.Count() - 1) Then
                ip.X = margin
                ip.Y += sHeight
                If ip.Y + sHeight > pixelSize.Height Then
                    If targetMime <> Util.MimeTypes.TIFF Then
                        Throw New Exception("Unexpected: should get here only if target is TIFF.")
                    End If
                    tw.AppendFrame(bmp)
                    bmp.Clear(Color.White)
                    ip.Y = margin
                End If
            End If
        Next

        Select Case targetMime
            Case Util.MimeTypes.TIFF
                tw.Dispose()
            Case Util.MimeTypes.JPEG
                bmp.SaveAsJpeg(ms)
            Case Util.MimeTypes.PNG
                bmp.SaveAsPng(ms)
            Case Util.MimeTypes.BMP
                bmp.SaveAsBmp(ms)
            Case Util.MimeTypes.GIF
                bmp.SaveAsGif(ms)
            Case Util.MimeTypes.WEBP
                bmp.SaveAsWebp(ms)
            Case Else
                Throw New Exception($"Encoding {targetMime} is not supported.")
        End Select

        bmp.Dispose()
        g.Dispose()

        '' Dispose images when done:
        images.ForEach(Sub(t_) t_.Item2.Dispose())

        Return ms
    End Function

    Public Shared Function GetSampleParamsList() As List(Of String())
        '' Strings are name, description, info, rest are arbitrary strings:
        Return New List(Of String()) From {
            New String() {"@b-svg/Font Awesome - brands", "Render Font Awesome SVG glyphs from the ""svgs/brands"" directory",
                          "This sample renders the SVG icons included in the ""svgs/brands/"" directory of the Font Awesome ""Free for Web"" download, sorted by file name.",
                          "brands"},
            New String() {"@b-svg/Font Awesome - regular", "Render Font Awesome SVG glyphs from the ""svgs/brands"" directory",
                          "This sample renders the SVG icons included in the ""svgs/regular/"" directory of the Font Awesome ""Free for Web"" download, sorted by file name.",
                          "regular"},
            New String() {"@b-svg/Font Awesome - solid", "Render Font Awesome SVG glyphs from the ""svgs/solid"" directory",
                          "This sample renders the SVG icons included in the ""svgs/solid/"" directory of the Font Awesome ""Free for Web"" download, sorted by file name.",
                          "solid"},
            New String() {"@b-svg/Font Awesome - colorize", "Render Font Awesome SVG glyphs using random order and colors",
                          "This sample renders the SVG icons included in the ""svgs/"" directory of the Font Awesome ""Free for Web"" download, randomizing the order of the icons and their colors.",
                          "colorize"}
        }
    End Function
End Class