TextAroundImages.vb
'' 
'' このコードは、DioDocs for PDF のサンプルの一部として提供されています。
'' Copyright (c) GrapeCity inc. All rights reserved.
'' 
Imports System.IO
Imports System.Drawing
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Drawing

'' このサンプルは、矩形領域(この場合は画像)の周りに大きなテキストブロックをフロー
'' させる方法を示します。また、特定の ImageAlign を使用してページに描画された画像の
'' 実際の境界を取得する方法も示します。
Public Class TextAroundImages
    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Dim g = doc.NewPage().Graphics
        Const fontname = "Yu Gothic"
        '' 最初のページの任意の場所に3枚の画像を描画し、
        '' 2~3ページのテキストを印刷して、最初のページの
        '' 画像を囲むようにしたいと考えています。
        '' 
        '' 画像とその矩形を取得します。すべての画像に正方形の
        '' 領域を指定しますが、元の縦横比を維持してその領域内に
        '' 配置されるので、後で画像が描かれた実際の長方形を
        '' 取得します。
        Using imgPuffins As Image = Image.FromFile(Path.Combine("Resources", "Images", "puffins.jpg")),
            imgReds As Image = Image.FromFile(Path.Combine("Resources", "Images", "reds.jpg")),
            imgLavender As Image = Image.FromFile(Path.Combine("Resources", "Images", "lavender.jpg"))
            Dim rectPuffins = New RectangleF(100, 70, 180, 180)
            Dim rectReds = New RectangleF(300, 280, 180, 180)
            Dim rectLavender = New RectangleF(190, 510, 180, 180)
            '' 画像の元のアスペクト比を維持しながら、指定された領域に画像を
            '' 収めて中央に配置する ImageAlign を設定します。
            Dim ia = New ImageAlign(ImageAlignHorz.Center, ImageAlignVert.Center, True, True, True, False, False)
            '' 各画像を描画し、各 DrawImage 呼び出しの出力パラメータとして長方形の配列を
            '' 提供します。これにより、画像によって実際に取得される矩形が得られます
            '' (タイル画像を処理するには配列が必要です)。
            Dim rectsPuffins As RectangleF() = Nothing
            g.DrawImage(imgPuffins, rectPuffins, Nothing, ia, rectsPuffins)
            Dim rectsReds As RectangleF() = Nothing
            g.DrawImage(imgReds, rectReds, Nothing, ia, rectsReds)
            Dim rectsLavender As RectangleF() = Nothing
            g.DrawImage(imgLavender, rectLavender, Nothing, ia, rectsLavender)
            '' テキストを出力するための TextLayout オブジェクトを作成して設定します。
            Dim tl = g.CreateTextLayout()
            tl.DefaultFormat.FontName = fontname
            tl.DefaultFormat.FontSize = 9
            tl.TextAlignment = TextAlignment.Justified
            tl.ParagraphSpacing = 72 / 8
            tl.MaxWidth = doc.PageSize.Width
            tl.MaxHeight = doc.PageSize.Height
            '' 周囲に 1/2 インチの余白。
            tl.MarginAll = 72 / 2
            '' ObjectRect は、TextLayout にフロー領域を指定するために使用される型です。
            '' イメージ矩形に基づいて ObjecRect を作成するローカル関数を設定し、
            '' いくつかのパディングを追加して、結果がよりよく見えるようにしています。
            Dim makeObjectRect As Func(Of RectangleF, ObjectRect) =
            Function(ByVal rect_)
                Return New ObjectRect(rect_.X - 6, rect_.Y - 2, rect_.Width + 12, rect_.Height + 4)
            End Function
            '' TextLayout に ObjectRect の配列を指定します。
            tl.ObjectRects = New List(Of ObjectRect)() From {
                makeObjectRect(rectsPuffins(0)),
                makeObjectRect(rectsReds(0)),
                makeObjectRect(rectsLavender(0))
            }
            '' いくつかのテキストの段落を追加します。
            tl.Append(Util.getString_ja(1, 0, 8))
            '' グリフを計算し、テキストをレイアウトします。
            tl.PerformLayout(True)
            '' ページ間のテキストの分割を制御するオプションを分割します。
            '' デフォルトのコンストラクタを使用して MaxWidth などの値を設定するか、
            '' TextLayout に基づいて TextSplitOptions を作成し、RestObjectRects を
            '' クリアすることができます。
            Dim tso = New TextSplitOptions(tl) With {
                .RestObjectRects = Nothing,
                .MinLinesInFirstParagraph = 2,
                .MinLinesInLastParagraph = 2
            }
            '' ループ内で、テキストを分割して描画します。
            While True
                '' 'rest' は、収まりきらなかったテキストを受け入れます。
                Dim rest As TextLayout = Nothing
                Dim splitResult = tl.Split(tso, rest)
                doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty)
                If splitResult <> SplitResult.Split Then
                    Exit While
                End If
                tl = rest
                '' 最初のページにのみ画像を描画します。
                tl.ObjectRects = Nothing
                doc.Pages.Add()
            End While
            ''
            '' PDF ドキュメントを保存します。
            doc.Save(stream)
            Return doc.Pages.Count
        End Using
    End Function
End Class