DropCap.vb
''
'' This code is part of GrapeCity Documents for PDF samples.
'' Copyright (c) GrapeCity, Inc. All rights reserved.
''
Imports System.IO
Imports System.Drawing
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Text

'' Demonstrates how to create a drop cap in GcPdf.
Public Class DropCap
    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Dim g = doc.NewPage().Graphics
        '' Get some text and split it into first letter (drop cap) and the rest:
        Dim text = Util.LoremIpsum(1)
        Dim head = text.Substring(0, 1)
        Dim tail = text.Substring(1)
        '' Use the Times font:
        Dim fnt = Font.FromFile(Path.Combine("Resources", "Fonts", "times.ttf"))
        '' Text layout for the drop cap:
        Dim tlHead = g.CreateTextLayout()
        tlHead.DefaultFormat.Font = fnt
        tlHead.DefaultFormat.FontSize = 40
        tlHead.Append(head)
        tlHead.PerformLayout(True)
        '' Text layout for the rest of the text:
        Dim tlTail = g.CreateTextLayout()
        tlTail.DefaultFormat.Font = fnt
        tlTail.DefaultFormat.FontSize = 12
        '' Use whole page with 1" margins all around:
        tlTail.MaxWidth = doc.Pages.Last.Size.Width - 72 * 2
        tlTail.MaxHeight = doc.Pages.Last.Size.Height - 72 * 2
        tlTail.Append(tail)
        '' Before we layout the main body of the text, we calculate the size and position
        '' of the drop cap rectangle, and add it to the main text layout's ObjectRects -
        '' the list of rectangles that the main text will flow around.
        ''
        '' Note: While we could simply position the drop cap rectangle at the top/left of the 
        '' main text, it looks better if the tops of the drop cap and the main text's glyphs
        '' are aligned. For this, we need to calculate the offets of letter tops within
        '' the text bounding boxes, and adjust the position of the drop cap accordingly
        '' (raise it a little).
        '' (For this adjustment we need the sCapHeight field which is present if the font's
        '' os/2 table version 2 and higher, so we must test for that and skip this step if
        '' the CapHeight is not available).
        Dim dy = 0F
        If fnt.CapHeight <> -1 Then
            '' We move the drop cap position up by the amount equal to the difference between the
            '' top spacing within the Em square of the drop cap's font size and the font size of the rest of the text:
            Dim k = tlHead.DefaultFormat.FontSize * tlHead.Resolution * tlHead.FontScaleFactor / (fnt.UnitsPerEm * 72)
            dy = (fnt.HorizontalAscender - fnt.CapHeight) * k
            k /= tlHead.DefaultFormat.FontSize
            k *= tlTail.DefaultFormat.FontSize
            dy -= (fnt.HorizontalAscender - fnt.SmallXHeight) * k
        End If
        '' Specify the rectangle for the main text to flow around:
        tlTail.ObjectRects = New List(Of ObjectRect) From {New ObjectRect(0, -dy, tlHead.ContentWidth * 1.2F, tlHead.ContentHeight)}
        '' Layout the main text now:
        tlTail.PerformLayout(True)
        '' Draw everything:
        g.DrawTextLayout(tlHead, New PointF(72, 72 - dy))
        g.DrawTextLayout(tlTail, New PointF(72, 72))
        ''
        '' Done:
        doc.Save(stream)
        Return doc.Pages.Count
    End Function
End Class