BalancedColumns.vb
''
'' このコードは、DioDocs for PDF のサンプルの一部として提供されています。
'' © MESCIUS inc. All rights reserved.
''
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 fontname = "Yu Gothic"
Dim fontSize = 10
'' 1/2" の余白(72 dpi は DsPdf で使用されるデフォルトの解像度です)。
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.FontName = fontname
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 を使用。
Const captionH = 24.0F
'' メインドキュメントの本文のテキストレイアウト(デフォルトの DsPdf 解像度は 72 dpi です)。
Dim tl = New TextLayout(72)
tl.DefaultFormat.FontName = fontname
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 の配列。
'' (第1列は 'main' 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 = $"第 {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.Count - 1, Nothing)))
''
'' 最終章のテキストをクリアし、新しい章を追加します。
tl.FirstLineIsStartOfParagraph = True
tl.LastLineIsEndOfParagraph = True
tl.Clear()
tl.Append(Util.getString_ja(1, 1, 5, 2, 30, True))
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
''
'' PDF ドキュメントを保存します。
doc.Save(stream)
Return doc.Pages.Count
End Function
End Class