DrawSlantedText.vb
''
'' This code is part of Document Solutions for Imaging demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System.Drawing
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Imaging
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing

'' This demo illustrates the results of using the GcGraphics.DrawSlantedText() method
'' with different combinations of arguments.
'' The DrawSlantedText() method draws text slanted within a specified rectangle
'' similar to how rotated text is drawn in MS Excel cells with borders.
'' See also the DrawRotatedText_0 demo.
Public Class DrawSlantedText
    Private Shared s_names As String() = New String() {
        "Horizontal Stacking 1",
        "Horizontal Stacking 2",
        "Horizontal Stacking 3",
        "Horizontal Stacking 4",
        "Horizontal Stacking 5",
        "Horizontal Stacking 6",
        "Horizontal Stacking 7",
        "Horizontal Stacking 8",
        "Vertical Stacking 1",
        "Vertical Stacking 2",
        "Vertical Stacking 3",
        "Vertical Stacking 4"
    }

    Public Function GenerateImage(
        ByVal pixelSize As Size,
        ByVal dpi As Single,
        ByVal opaque As Boolean,
        Optional ByVal sampleParams As String() = Nothing) As GcBitmap

        If sampleParams Is Nothing Then
            sampleParams = GetSampleParamsList()(0)
        End If

        Dim bmp = New GcBitmap(pixelSize.Width, pixelSize.Height, opaque, dpi, dpi)
        Using g = bmp.CreateGraphics(Color.White)
            '' Set up some values to manage layout:
            Dim margin = g.Resolution
            Dim gap = g.Resolution
            Dim w = pixelSize.Width * 0.3F
            Dim h = w

            Dim q0 = New RectangleF(margin, margin, w, h)
            Dim q1 = New RectangleF(pixelSize.Width - margin - w, margin, w, h)
            Dim q2 = New RectangleF(margin, margin + h + gap, w, h)
            Dim q3 = New RectangleF(pixelSize.Width - margin - w, margin + h + gap, w, h)

            If sampleParams(0) = s_names(0) Then
                '' Various text alignments with SlantedTextAlignment.BelowRotatedInside:
                Draw(g, q0, -70, False, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Leading)
                Draw(g, q1, -70, False, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Trailing)
                Draw(g, q2, -70, False, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Center)
                Draw(g, q3, -70, False, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Distributed)
            ElseIf sampleParams(0) = s_names(1) Then
                '' Various text alignments with SlantedTextAlignment.BelowRotatedOutside:
                Draw(g, q0, -70, False, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Leading)
                Draw(g, q1, -70, False, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Trailing)
                Draw(g, q2, -70, False, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Center)
                Draw(g, q3, -70, False, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Distributed)
            ElseIf sampleParams(0) = s_names(2) Then
                '' Various text alignments with SlantedTextAlignment.AboveRotatedInside:
                Draw(g, q0, -70, False, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Leading)
                Draw(g, q1, -70, False, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Trailing)
                Draw(g, q2, -70, False, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Center)
                Draw(g, q3, -70, False, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Distributed)
            ElseIf sampleParams(0) = s_names(3) Then
                '' Various text alignments with SlantedTextAlignment.AboveRotatedOutside:
                Draw(g, q0, -70, False, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Leading)
                Draw(g, q1, -70, False, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Trailing)
                Draw(g, q2, -70, False, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Center)
                Draw(g, q3, -70, False, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Distributed)
            ElseIf sampleParams(0) = s_names(4) Then
                '' Various text alignments with SlantedTextAlignment.CenterInsideOutside:
                Draw(g, q0, -70, False, SlantedTextAlignment.CenterInsideOutside, TextAlignment.Leading)
                Draw(g, q1, -70, False, SlantedTextAlignment.CenterInsideOutside, TextAlignment.Trailing)
                Draw(g, q2, -70, False, SlantedTextAlignment.CenterInsideOutside, TextAlignment.Center)
                Draw(g, q3, -70, False, SlantedTextAlignment.CenterInsideOutside, TextAlignment.Distributed)
            ElseIf sampleParams(0) = s_names(5) Then
                '' Various text alignments with SlantedTextAlignment.CenterOutsideInside:
                Draw(g, q0, -70, False, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Leading)
                Draw(g, q1, -70, False, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Trailing)
                Draw(g, q2, -70, False, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Center)
                Draw(g, q3, -70, False, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Distributed)
            ElseIf sampleParams(0) = s_names(6) Then
                '' Examples with positive rotation angle using SlantedTextAlignment.BelowRotatedInside:
                Draw(g, q0, 70, False, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Leading)
                Draw(g, q1, 70, False, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Trailing)
                Draw(g, q2, 70, False, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Center)
                Draw(g, q3, 70, False, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Distributed)
            ElseIf sampleParams(0) = s_names(7) Then
                '' Examples with positive rotation angle using SlantedTextAlignment.AboveRotatedInside:
                Draw(g, q0, 70, False, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Leading)
                Draw(g, q1, 70, False, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Trailing)
                Draw(g, q2, 70, False, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Center)
                Draw(g, q3, 70, False, SlantedTextAlignment.AboveRotatedInside, TextAlignment.Distributed)
                '' Vertical stacking:
            ElseIf sampleParams(0) = s_names(8) Then
                '' Vertically stacked text rotated to a negative angle using SlantedTextAlignment.BelowRotatedInside:
                Draw(g, q0, -20, True, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Leading)
                Draw(g, q1, -20, True, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Trailing)
                Draw(g, q2, -20, True, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Center)
                Draw(g, q3, -20, True, SlantedTextAlignment.BelowRotatedInside, TextAlignment.Distributed)
            ElseIf sampleParams(0) = s_names(9) Then
                '' Vertically stacked text rotated to a negative angle using SlantedTextAlignment.BelowRotatedOutside:
                Draw(g, q0, -20, True, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Leading)
                Draw(g, q1, -20, True, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Trailing)
                Draw(g, q2, -20, True, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Center)
                Draw(g, q3, -20, True, SlantedTextAlignment.BelowRotatedOutside, TextAlignment.Distributed)
            ElseIf sampleParams(0) = s_names(10) Then
                '' Vertically stacked text rotated to a positive angle using SlantedTextAlignment.AboveRotatedOutside:
                Draw(g, q0, 20, True, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Leading)
                Draw(g, q1, 20, True, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Trailing)
                Draw(g, q2, 20, True, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Center)
                Draw(g, q3, 20, True, SlantedTextAlignment.AboveRotatedOutside, TextAlignment.Distributed)
            ElseIf sampleParams(0) = s_names(11) Then
                '' Vertically stacked text rotated to a positive angle using SlantedTextAlignment.CenterOutsideInside:
                Draw(g, q0, 20, True, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Leading)
                Draw(g, q1, 20, True, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Trailing)
                Draw(g, q2, 20, True, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Center)
                Draw(g, q3, 20, True, SlantedTextAlignment.CenterOutsideInside, TextAlignment.Distributed)
            End If
        End Using
        Return bmp
    End Function

    Private Shared Sub Draw(g As GcGraphics, rect As RectangleF, angle As Integer, verticalStacking As Boolean,
        slantedAlign As SlantedTextAlignment, textAlign As TextAlignment)

        '' Draw a legend stating the current DrawRotatedText arguments' values:
        Dim tlLegend = g.CreateTextLayout()
        tlLegend.DefaultFormat.FontName = "Calibri"
        tlLegend.DefaultFormat.FontSize = 9
        tlLegend.AppendLine($"Rotation angle: {angle}°")
        tlLegend.AppendLine($"Text alignment: {textAlign}")
        tlLegend.AppendLine($"Slanted text alignment: {slantedAlign}")
        tlLegend.AppendLine($"Is vertical stacking: {verticalStacking}")
        g.DrawTextLayout(tlLegend, rect.Location)

        '' The target rectangle for the DrawRotatedText call:
        Dim d = tlLegend.ContentHeight + g.Resolution
        rect.Y += d
        rect.Height -= d
        rect.Width -= d / 2
        Dim x = rect.X
        Dim y = rect.Y
        Dim w = rect.Width
        Dim h = rect.Height

        '' Draw the target rectangle:
        g.DrawRectangle(rect, New GCDRAW.Pen(Color.PaleGreen, 3))

        If Not verticalStacking Then
            Dim dx As Single = CSng(h / Math.Tan(Math.PI * angle / -180.0))
            Select Case slantedAlign
                Case SlantedTextAlignment.BelowRotatedInside,
                     SlantedTextAlignment.AboveRotatedOutside,
                     SlantedTextAlignment.CenterInsideOutside
                    g.DrawPolygon(New PointF() {
                        New PointF(x + dx, y), New PointF(x + dx + w, y),
                        New PointF(x + w, y + h), New PointF(x, y + h)},
                        New GCDRAW.Pen(Color.Red, 1))
                Case SlantedTextAlignment.BelowRotatedOutside,
                     SlantedTextAlignment.AboveRotatedInside,
                     SlantedTextAlignment.CenterOutsideInside
                    g.DrawPolygon(New PointF() {
                        New PointF(x, y), New PointF(x + w, y),
                        New PointF(x - dx + w, y + h), New PointF(x - dx, y + h)},
                        New GCDRAW.Pen(Color.Red, 1))
            End Select
        Else
            Dim dy As Single = CSng(w * Math.Tan(Math.PI * angle / 180.0))
            Select Case slantedAlign
                Case SlantedTextAlignment.BelowRotatedInside,
                     SlantedTextAlignment.AboveRotatedOutside,
                     SlantedTextAlignment.CenterInsideOutside
                    If angle >= 0 Then
                        g.DrawPolygon(New PointF() {
                            New PointF(x, y), New PointF(x + w, y + dy), New PointF(x + w, y + dy + h), New PointF(x, y + h)},
                            New GCDRAW.Pen(Color.Red, 1))
                    Else
                        g.DrawPolygon(New PointF() {
                            New PointF(x, y - dy), New PointF(x + w, y), New PointF(x + w, y + h), New PointF(x, y - dy + h)},
                            New GCDRAW.Pen(Color.Red, 1))
                    End If
                Case SlantedTextAlignment.BelowRotatedOutside,
                     SlantedTextAlignment.AboveRotatedInside,
                     SlantedTextAlignment.CenterOutsideInside
                    If angle >= 0 Then
                        g.DrawPolygon(New PointF() {
                            New PointF(x, y - dy), New PointF(x + w, y), New PointF(x + w, y + h), New PointF(x, y - dy + h)},
                            New GCDRAW.Pen(Color.Red, 1))
                    Else
                        g.DrawPolygon(New PointF() {
                            New PointF(x, y), New PointF(x + w, y + dy), New PointF(x + w, y + dy + h), New PointF(x, y + h)},
                            New GCDRAW.Pen(Color.Red, 1))
                    End If
            End Select
        End If
        '' Draw slanted text:
        Dim tl = g.CreateTextLayout()
        tl.DefaultFormat.FontName = "Calibri"
        tl.DefaultFormat.FontSize = 12
        tl.TextAlignment = textAlign
        tl.Append("The quick brown fox jumps over the lazy dog. ")
        tl.Append("The quick brown fox jumps over the lazy dog.")
        g.DrawSlantedText(tl, angle, verticalStacking, rect, slantedAlign)
    End Sub

    '' Strings are name, description, info. Rest are arbitrary strings:
    Public Shared Function GetSampleParamsList() As List(Of String())
        Return New List(Of String()) From {
            New String() {s_names(0), "Various text alignments with SlantedTextAlignment.BelowRotatedInside", Nothing},
            New String() {s_names(1), "Various text alignments with SlantedTextAlignment.BelowRotatedOutside", Nothing},
            New String() {s_names(2), "Various text alignments with SlantedTextAlignment.AboveRotatedInside", Nothing},
            New String() {s_names(3), "Various text alignments with SlantedTextAlignment.AboveRotatedOutside", Nothing},
            New String() {s_names(4), "Various text alignments with SlantedTextAlignment.CenterInsideOutside", Nothing},
            New String() {s_names(5), "Various text alignments with SlantedTextAlignment.CenterOutsideInside", Nothing},
            New String() {s_names(6), "Examples with positive rotation angle using SlantedTextAlignment.BelowRotatedInside", Nothing},
            New String() {s_names(7), "Examples with positive rotation angle using SlantedTextAlignment.AboveRotatedInside", Nothing},
            New String() {s_names(8), "Vertically stacked text rotated to a negative angle using SlantedTextAlignment.BelowRotatedInside", Nothing},
            New String() {s_names(9), "Vertically stacked text rotated to a negative angle using SlantedTextAlignment.BelowRotatedOutside", Nothing},
            New String() {s_names(10), "Vertically stacked text rotated to a positive angle using SlantedTextAlignment.AboveRotatedOutside", Nothing},
            New String() {s_names(11), "Vertically stacked text rotated to a positive angle using SlantedTextAlignment.CenterOutsideInside", Nothing}
        }
    End Function
End Class