BalancedColumns.vb
'' 完毕:
Imports System.IO
Imports System.Drawing
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Text
'' 创建具有平衡列的多列文本布局。
'' 此示例的核心是 TextLayout.SplitAndBalance() 方法
'' 它允许在多列之间拆分文本,
'' 并平衡这些柱子,使它们的高度相似,
'' 从而使您能够制作类似杂志和报纸的文本布局。
Public Class BalancedColumns
Function CreatePDF(ByVal stream As Stream) As Integer
Dim doc = New GcPdfDocument()
Dim font = StandardFonts.Times
Dim fontSize = 12
'' 周围 1/2" 边距(72 dpi 是 GcDocs.Pdf 使用的默认分辨率):
Dim margin = 72 / 2
Dim pageWidth = doc.PageSize.Width
Dim pageHeight = doc.PageSize.Height
Dim cW = pageWidth - margin * 2
'' 章节标题的文本格式:
Dim tlCaption = New TextLayout(72)
tlCaption.DefaultFormat.Font = font
tlCaption.DefaultFormat.FontSize = fontSize + 4
tlCaption.DefaultFormat.Underline = True
tlCaption.MaxWidth = pageWidth
tlCaption.MaxHeight = pageHeight
tlCaption.MarginLeft = margin
tlCaption.MarginTop = margin
tlCaption.MarginRight = margin
tlCaption.MarginBottom = margin
tlCaption.TextAlignment = TextAlignment.Center
'' 章节标题的高度(为简单起见,使用常量):
Const captionH = 24.0F
'' 主文档正文的文本布局(默认 GcDocs.Pdf 分辨率为 72dpi):
Dim tl = New TextLayout(72)
tl.DefaultFormat.Font = font
tl.DefaultFormat.FontSize = fontSize
tl.FirstLineIndent = 72 / 2
tl.MaxWidth = pageWidth
tl.MaxHeight = pageHeight
tl.MarginLeft = margin
tl.MarginRight = margin
tl.MarginBottom = margin
tl.MarginTop = margin + captionH
tl.ColumnWidth = cW * 0.3F
tl.TextAlignment = TextAlignment.Justified
'' 控制附加列的 PageSplitArea 数组(第一列由
'' “主”TextLayout,对于每个附加的 TextLayout,必须提供一个 PageSplitArea -
'' 它将创建并返回一个 TextLayout,然后可用于呈现该列):
Dim psas As PageSplitArea() = {
New PageSplitArea(tl) With {.MarginLeft = tl.MarginLeft + (cW * 0.35F)},
New PageSplitArea(tl) With {.ColumnWidth = -cW * 0.3F}
}
'' 用于控制页面之间拆分文本的拆分选项:
Dim tso = New TextSplitOptions(tl) With {
.RestMarginTop = margin,
.MinLinesInFirstParagraph = 2,
.MinLinesInLastParagraph = 2
}
'' 生成多个“章节”,为每个章节提供大纲条目:
Const NChapters = 20
doc.Pages.Add()
For i = 1 To NChapters
'' 打印所有列的章节标题:
Dim chapter = $"Chapter {i}"
tlCaption.Clear()
tlCaption.Append(chapter)
tlCaption.PerformLayout(True)
doc.Pages.Last.Graphics.DrawTextLayout(tlCaption, PointF.Empty)
'' 为章节添加大纲节点:
doc.Outlines.Add(New OutlineNode(chapter, New DestinationFitV(doc.Pages.Last, Nothing)))
''
'' 清除上一章的文本并添加新的章节:
tl.FirstLineIsStartOfParagraph = True
tl.LastLineIsEndOfParagraph = True
tl.Clear()
tl.Append(Util.LoremIpsum(5, 7, 9, 15, 25))
tl.PerformLayout(True)
'' 用于保存最后一章结尾底部坐标的变量:
Dim contentBottom = 0F
'' 打印章节:
Dim tls = New TextLayoutSplitter(tl)
While (True)
Dim tlCol0 = tls.SplitAndBalance(psas, tso)
Dim g = doc.Pages.Last.Graphics
g.DrawTextLayout(tlCol0, PointF.Empty)
g.DrawTextLayout(psas(0).TextLayout, PointF.Empty)
g.DrawTextLayout(psas(1).TextLayout, PointF.Empty)
If tls.SplitResult <> SplitResult.Split Then
'' 章节结束,找出下一章的页面剩余高度:
contentBottom = tl.ContentY + tl.ContentHeight
contentBottom = Math.Max(contentBottom, psas(0).TextLayout.ContentRectangle.Bottom)
contentBottom = Math.Max(contentBottom, psas(1).TextLayout.ContentRectangle.Bottom)
'' 打印完成章节:
Exit While
End If
'' 在新页面上继续打印章节:
psas(0).MarginTop = margin
psas(1).MarginTop = margin
doc.Pages.Add()
End While
'' 下一章 - 查明当前页面是否有足够的空间来开始新的章节:
If contentBottom + captionH < pageHeight * 0.8F Then
'' 在当前页面开始新章节:
contentBottom += pageHeight * 0.05F
tlCaption.MarginTop = contentBottom
tl.MarginTop = contentBottom + captionH
psas(0).MarginTop = tl.MarginTop
psas(1).MarginTop = tl.MarginTop
ElseIf i < NChapters Then
'' 在新的一页上开始新的篇章:
tlCaption.MarginTop = margin
tl.MarginTop = margin + captionH
psas(0).MarginTop = tl.MarginTop
psas(1).MarginTop = tl.MarginTop
doc.Pages.Add()
End If
Next
''
'' 完毕:
doc.Save(stream)
Return doc.Pages.Count
End Function
End Class