BalancedColumns.vb
 '' '' This code is part of Document Solutions for PDF demos. '' Copyright (c) MESCIUS inc. All rights reserved. '' Imports System.IO Imports System.Drawing Imports GrapeCity.Documents.Pdf Imports GrapeCity.Documents.Text '' Creates a multi-column text layout with balanced columns. '' The heart of this sample is the TextLayout.SplitAndBalance() method '' which allows splitting a text between multiple columns, '' AND balance those columns so that their heights are similar, '' thus allowing to produce magazine- and newspaper-like text layouts. Public Class BalancedColumns Function CreatePDF(ByVal stream As Stream) As Integer Dim doc = New GcPdfDocument() Dim font = StandardFonts.Times Dim fontSize = 12 '' 1/2" margins all around (72 dpi is the default resolution used by DsPdf): Dim margin = 72 / 2 Dim pageWidth = doc.PageSize.Width Dim pageHeight = doc.PageSize.Height Dim cW = pageWidth - margin * 2 '' Text format for the chapter titles: 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 '' Height of chapter caption (use a const for simplicity): Const captionH = 24.0F '' Text layout for main document body (default DsPdf resolution is 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 '' Array of PageSplitArea's which control additional columns (1st column is controlled by '' the 'main' TextLayout, for each additional one a PageSplitArea must be provided - '' it will create and return a TextLayout that can then be used to render the column): Dim psas As PageSplitArea() = { New PageSplitArea(tl) With {.MarginLeft = tl.MarginLeft + (cW * 0.35F)}, New PageSplitArea(tl) With {.ColumnWidth = -cW * 0.3F} } '' Split options to control splitting text between pages: Dim tso = New TextSplitOptions(tl) With { .RestMarginTop = margin, .MinLinesInFirstParagraph = 2, .MinLinesInLastParagraph = 2 } '' Generate a number of "chapters", provide outline entry for each: Const NChapters = 20 doc.Pages.Add() For i = 1 To NChapters '' Print chapter header across all columns: Dim chapter = $"Chapter {i}" tlCaption.Clear() tlCaption.Append(chapter) tlCaption.PerformLayout(True) doc.Pages.Last.Graphics.DrawTextLayout(tlCaption, PointF.Empty) '' Add outline node for the chapter: doc.Outlines.Add(New OutlineNode(chapter, New DestinationFitV(doc.Pages.Last, Nothing))) '' '' Clear last chapter's text and add new chapter: tl.FirstLineIsStartOfParagraph = True tl.LastLineIsEndOfParagraph = True tl.Clear() tl.Append(Util.LoremIpsum(5, 7, 9, 15, 25)) tl.PerformLayout(True) '' Variable to hold last chapter end's bottom coord: Dim contentBottom = 0F '' Print the chapter: 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 '' End of chapter, find out how much height left on page for next chapter: contentBottom = tl.ContentY + tl.ContentHeight contentBottom = Math.Max(contentBottom, psas(0).TextLayout.ContentRectangle.Bottom) contentBottom = Math.Max(contentBottom, psas(1).TextLayout.ContentRectangle.Bottom) '' Done printing chapter: Exit While End If '' Continue printing chapter on new page: psas(0).MarginTop = margin psas(1).MarginTop = margin doc.Pages.Add() End While '' Next chapter - find out if we have enough space left on current page to start new chapter: If contentBottom + captionH < pageHeight * 0.8F Then '' Start new chapter on current page: 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 '' Start new chapter on new page: tlCaption.MarginTop = margin tl.MarginTop = margin + captionH psas(0).MarginTop = tl.MarginTop psas(1).MarginTop = tl.MarginTop doc.Pages.Add() End If Next '' '' Done: doc.Save(stream) Return doc.Pages.Count End Function End Class