ImageLinks.vb
'' 
'' このコードは、DioDocs for PDF のサンプルの一部として提供されています。
'' © MESCIUS inc. All rights reserved.
'' 
Imports System.IO
Imports System.Drawing
Imports System.Numerics
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Pdf.Annotations
Imports GrapeCity.Documents.Pdf.Actions
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing

'' このサンプルは、ディレクトリ内にあるすべての画像を読み込み、
'' 各画像を PDF の各ページにできるだけ大きなサイズでレンダリングします。
'' 最後に、大きな画像にリンクされた画像サムネイルの目次を文書に挿入します。
'' SlidePages も参照してください。
Public Class ImageLinks
    Private Class ImageInfo
        Public Property Name As String
        Public Property Image As IImage
        Public Property PageIdx As Integer
    End Class

    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Dim fnt = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf"))
        '' 周囲に1/4 インチの余白を設定します。
        Const margin = 36.0F

        '' Resources/Images フォルダからすべての画像を読み込みます。
        Dim imageInfos As New List(Of ImageInfo)
        For Each fname In Directory.GetFiles(Path.Combine("Resources", "Images"), "*", SearchOption.AllDirectories)
            imageInfos.Add(New ImageInfo() With {.Name = Path.GetFileName(fname), .Image = Util.ImageFromFile(fname)})
        Next
        imageInfos.Shuffle()
        '' 画像を水平方向の中央および垂直方向の上部に配置するよう設定します。
        Dim ia = New ImageAlign(ImageAlignHorz.Center, ImageAlignVert.Top, True, True, True, False, False)
        '' ページ全体に表示するためのフルサイズの画像矩形。
        Dim rBig = New RectangleF(margin, margin, doc.PageSize.Width - margin * 2, doc.PageSize.Height - margin * 2)
        '' 各ページに1つずつフルサイズの画像を描画します。
        For i = 0 To imageInfos.Count - 1
            Dim g = doc.NewPage().Graphics
            Dim ii = imageInfos(i)
            g.DrawImage(ii.Image, rBig, Nothing, ia)
            ii.PageIdx = i
        Next
        '' サムネイル付きのページをドキュメントの先頭に 4x5 グリッドとして挿入します(SlidePages を参照してください)
        Const rows = 5
        Const cols = 4
        Dim gapx = 72.0F / 4, gapy = gapx
        Dim sWidth = (doc.PageSize.Width - margin * 2 + gapx) / cols
        Dim sHeight = (doc.PageSize.Height - margin * 2 + gapy) / rows
        If (sWidth > sHeight) Then
            gapx += sWidth - sHeight
            sWidth = sHeight
        Else
            gapy += sHeight - sWidth
            sHeight = sWidth
        End If
        Const sMargin = 72.0F / 6
        '' サムネイルを垂直方向の中央に配置します。
        ia.AlignVert = ImageAlignVert.Center
        '' 画像キャプションのテキスト書式。
        Dim tf = New TextFormat() With {.Font = fnt, .FontSize = sMargin * 0.65F}
        '' 挿入位置。
        Dim ip = New PointF(margin, margin)
        Dim page = doc.Pages.Insert(0)
        For i = 0 To imageInfos.Count() - 1
            Dim ii = imageInfos(i)
            Dim rect = New RectangleF(ip, New SizeF(sWidth - gapx, sHeight - gapy))
            '' フルサイズの画像があるページへのリンクを追加します。
            '' (目次に含まれるページの数がわかると、ページインデックスが更新されます)
            page.Annotations.Add(New LinkAnnotation(rect, New DestinationFit(ii.PageIdx)))
            '' サムネイルを描画します。
            Dim g = page.Graphics
            g.FillRectangle(rect, Color.LightGray)
            g.DrawRectangle(rect, Color.Black, 0.5F)
            rect.Inflate(-sMargin, -sMargin)
            Dim imageRect As RectangleF() = Nothing
            g.DrawImage(ii.Image, rect, Nothing, ia, imageRect)
            g.DrawRectangle(imageRect(0), Color.DarkGray, 1)
            '' スライドの下部余白に画像ファイル名をキャプションとして出力します。
            g.DrawString(ii.Name, tf,
                New RectangleF(rect.X, rect.Bottom, rect.Width, sMargin),
                TextAlignment.Center, ParagraphAlignment.Near, False)
            ip.X += sWidth
            If (ip.X + sWidth > doc.PageSize.Width) Then
                ip.X = margin
                ip.Y += sHeight
                If (ip.Y + sHeight > doc.PageSize.Height) Then
                    page = doc.Pages.Insert(doc.Pages.IndexOf(page) + 1)
                    ip.Y = margin
                End If
            End If
        Next
        '' すべての目次ページを調べ、ドキュメントの先頭に挿入された目次ページを考慮して、
        '' リンク先のページインデックスを更新します。
        Dim tocPages = doc.Pages.IndexOf(page) + 1
        For i = 0 To tocPages - 1
            For Each ann In doc.Pages(i).Annotations
                If TypeOf ann Is LinkAnnotation AndAlso TypeOf CType(ann, LinkAnnotation).Dest Is DestinationFit Then
                    Dim link = DirectCast(ann, LinkAnnotation)
                    Dim dest = DirectCast(CType(ann, LinkAnnotation).Dest, DestinationFit)
                    link.Dest = New DestinationFit(dest.PageIndex.Value + tocPages)
                End If
            Next
        Next
        ''
        '' PDF ドキュメントを保存します。
        doc.Save(stream)
        imageInfos.ForEach(Sub(ii_) ii_.Image.Dispose())
        Return doc.Pages.Count
    End Function
End Class