BalancedColumns.vb
  1. ''
  2. '' This code is part of Document Solutions for PDF demos.
  3. '' Copyright (c) MESCIUS inc. All rights reserved.
  4. ''
  5. Imports System.IO
  6. Imports System.Drawing
  7. Imports GrapeCity.Documents.Pdf
  8. Imports GrapeCity.Documents.Text
  9.  
  10. '' Creates a multi-column text layout with balanced columns.
  11. '' The heart of this sample is the TextLayout.SplitAndBalance() method
  12. '' which allows splitting a text between multiple columns,
  13. '' AND balance those columns so that their heights are similar,
  14. '' thus allowing to produce magazine- and newspaper-like text layouts.
  15. Public Class BalancedColumns
  16. Function CreatePDF(ByVal stream As Stream) As Integer
  17. Dim doc = New GcPdfDocument()
  18. Dim font = StandardFonts.Times
  19. Dim fontSize = 12
  20. '' 1/2" margins all around (72 dpi is the default resolution used by DsPdf):
  21. Dim margin = 72 / 2
  22. Dim pageWidth = doc.PageSize.Width
  23. Dim pageHeight = doc.PageSize.Height
  24. Dim cW = pageWidth - margin * 2
  25. '' Text format for the chapter titles:
  26. Dim tlCaption = New TextLayout(72)
  27. tlCaption.DefaultFormat.Font = font
  28. tlCaption.DefaultFormat.FontSize = fontSize + 4
  29. tlCaption.DefaultFormat.Underline = True
  30. tlCaption.MaxWidth = pageWidth
  31. tlCaption.MaxHeight = pageHeight
  32. tlCaption.MarginLeft = margin
  33. tlCaption.MarginTop = margin
  34. tlCaption.MarginRight = margin
  35. tlCaption.MarginBottom = margin
  36. tlCaption.TextAlignment = TextAlignment.Center
  37. '' Height of chapter caption (use a const for simplicity):
  38. Const captionH = 24.0F
  39. '' Text layout for main document body (default DsPdf resolution is 72dpi):
  40. Dim tl = New TextLayout(72)
  41. tl.DefaultFormat.Font = font
  42. tl.DefaultFormat.FontSize = fontSize
  43. tl.FirstLineIndent = 72 / 2
  44. tl.MaxWidth = pageWidth
  45. tl.MaxHeight = pageHeight
  46. tl.MarginLeft = margin
  47. tl.MarginRight = margin
  48. tl.MarginBottom = margin
  49. tl.MarginTop = margin + captionH
  50. tl.ColumnWidth = cW * 0.3F
  51. tl.TextAlignment = TextAlignment.Justified
  52. '' Array of PageSplitArea's which control additional columns (1st column is controlled by
  53. '' the 'main' TextLayout, for each additional one a PageSplitArea must be provided -
  54. '' it will create and return a TextLayout that can then be used to render the column):
  55. Dim psas As PageSplitArea() = {
  56. New PageSplitArea(tl) With {.MarginLeft = tl.MarginLeft + (cW * 0.35F)},
  57. New PageSplitArea(tl) With {.ColumnWidth = -cW * 0.3F}
  58. }
  59. '' Split options to control splitting text between pages:
  60. Dim tso = New TextSplitOptions(tl) With {
  61. .RestMarginTop = margin,
  62. .MinLinesInFirstParagraph = 2,
  63. .MinLinesInLastParagraph = 2
  64. }
  65. '' Generate a number of "chapters", provide outline entry for each:
  66. Const NChapters = 20
  67. doc.Pages.Add()
  68. For i = 1 To NChapters
  69. '' Print chapter header across all columns:
  70. Dim chapter = $"Chapter {i}"
  71. tlCaption.Clear()
  72. tlCaption.Append(chapter)
  73. tlCaption.PerformLayout(True)
  74. doc.Pages.Last.Graphics.DrawTextLayout(tlCaption, PointF.Empty)
  75. '' Add outline node for the chapter:
  76. doc.Outlines.Add(New OutlineNode(chapter, New DestinationFitV(doc.Pages.Last, Nothing)))
  77. ''
  78. '' Clear last chapter's text and add new chapter:
  79. tl.FirstLineIsStartOfParagraph = True
  80. tl.LastLineIsEndOfParagraph = True
  81. tl.Clear()
  82. tl.Append(Util.LoremIpsum(5, 7, 9, 15, 25))
  83. tl.PerformLayout(True)
  84. '' Variable to hold last chapter end's bottom coord:
  85. Dim contentBottom = 0F
  86. '' Print the chapter:
  87. Dim tls = New TextLayoutSplitter(tl)
  88. While (True)
  89. Dim tlCol0 = tls.SplitAndBalance(psas, tso)
  90. Dim g = doc.Pages.Last.Graphics
  91. g.DrawTextLayout(tlCol0, PointF.Empty)
  92. g.DrawTextLayout(psas(0).TextLayout, PointF.Empty)
  93. g.DrawTextLayout(psas(1).TextLayout, PointF.Empty)
  94. If tls.SplitResult <> SplitResult.Split Then
  95. '' End of chapter, find out how much height left on page for next chapter:
  96. contentBottom = tl.ContentY + tl.ContentHeight
  97. contentBottom = Math.Max(contentBottom, psas(0).TextLayout.ContentRectangle.Bottom)
  98. contentBottom = Math.Max(contentBottom, psas(1).TextLayout.ContentRectangle.Bottom)
  99. '' Done printing chapter:
  100. Exit While
  101. End If
  102. '' Continue printing chapter on new page:
  103. psas(0).MarginTop = margin
  104. psas(1).MarginTop = margin
  105. doc.Pages.Add()
  106. End While
  107. '' Next chapter - find out if we have enough space left on current page to start new chapter:
  108. If contentBottom + captionH < pageHeight * 0.8F Then
  109. '' Start new chapter on current page:
  110. contentBottom += pageHeight * 0.05F
  111. tlCaption.MarginTop = contentBottom
  112. tl.MarginTop = contentBottom + captionH
  113. psas(0).MarginTop = tl.MarginTop
  114. psas(1).MarginTop = tl.MarginTop
  115. ElseIf i < NChapters Then
  116. '' Start new chapter on new page:
  117. tlCaption.MarginTop = margin
  118. tl.MarginTop = margin + captionH
  119. psas(0).MarginTop = tl.MarginTop
  120. psas(1).MarginTop = tl.MarginTop
  121. doc.Pages.Add()
  122. End If
  123. Next
  124. ''
  125. '' Done:
  126. doc.Save(stream)
  127. Return doc.Pages.Count
  128. End Function
  129. End Class
  130.