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

'' このサンプルは、タグ付き(構造化)PDF を作成し、TextLayout 内の
'' 個々の段落にタグを付加する方法を示しています。これらの段落を
'' まとめて描画し、ページ間で分割します。
'' この文書を生成するコードは、PaginatedText で使用されている
'' コードに似ていますが、タグが追加されています。
'' タグを表示/閲覧するには、Adobe Acrobat Pro でドキュメントを開き、
'' [表示]-[ナビゲーションパネル]-[タグ]に移動します。
Public Class TagTextLayout
    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()

        '' Part 要素を作成します。これには P(段落)要素が含まれます。
        Dim sePart = New StructElement("Part")
        doc.StructTreeRoot.Children.Add(sePart)

        '' 段落を描画するための TextLayout を作成して設定します。
        Dim tl = New TextLayout(72)
        tl.DefaultFormat.Font = StandardFonts.Times
        tl.DefaultFormat.FontSize = 12
        tl.FirstLineIndent = 72 / 2
        tl.MaxWidth = doc.PageSize.Width
        tl.MaxHeight = doc.PageSize.Height
        tl.MarginAll = tl.Resolution
        '' テキストを追加します(単一のページに収まらないように 20 段落)
        '' TextLayout は段落区切り文字として "\r\n" を解釈することに注意してください)。
        '' 
        '' テキストを取得します(20 段落)。
        Dim text = Util.getString_ja(20)
        '' 個々の段落にタグを付けるには、テキストを段落に分割し、各段落書式の Tag プロパティを
        '' 使用して段落のインデックスを段落に追加する必要があります
        '' (これは PDF タグに関係なく、TextFormat に関連付けることのできる任意のデータです)。
        Dim pars = text.Split(New Char() {vbCr, vbLf}, StringSplitOptions.RemoveEmptyEntries)
        For i = 0 To pars.Length - 1
            Dim tf = New TextFormat(tl.DefaultFormat) With {.Tag = i}
            tl.AppendLine(pars(i), tf)
        Next

        '' テキストをレイアウトします。
        tl.PerformLayout(True)
        '' 分割オプションを使用して、widow/orphan の制御を提供します。
        Dim tso = New TextSplitOptions(tl) With {
            .MinLinesInFirstParagraph = 2,
            .MinLinesInLastParagraph = 2
        }
        '' TextLayoutHandler は ITextLayoutHandler を実装しています。
        '' これにより、テキストが描画されるときにそのタグを付けることができます。
        Dim tlh = New TextLayoutHandler() With {.ParentElement = sePart}

        '' ループ内で、テキストを分割して描画します。
        While True
            '' 'rest' は、収まりきらなかったテキストを受け入れます。
            Dim rest As TextLayout = Nothing
            Dim splitResult = tl.Split(tso, rest)
            Dim page = doc.Pages.Add()
            Dim g = page.Graphics
            '' どのページが表示されているかを TextLayoutHandler に伝えます。
            tlh.Page = page
            '' …そして、それをグラフィックスに関連付けます。
            g.TextLayoutHandler = tlh
            '' 現在のページに収まるテキストを描画し、終了していなければ次のページに進みます。
            g.DrawTextLayout(tl, PointF.Empty)
            If splitResult <> SplitResult.Split Then
                Exit While
            End If
            tl = rest
        End While
        '' ドキュメントをタグ付きとしてマークします。
        doc.MarkInfo.Marked = True
        ''
        '' PDF ドキュメントを保存します。
        doc.Save(stream)
        Return doc.Pages.Count
    End Function

    '' TextLayout によって描画されるときにコンテンツにタグを付けることを可能にするカスタムクラスです。
    Private Class TextLayoutHandler : Implements ITextLayoutHandler
        Private _tagIndex As Integer
        Private _currentParagraphIndex As Integer = -1
        Private _currentparagraphElement As StructElement
        Public Property ParentElement As StructElement
        Public Property Page As Page

        Public Sub TextTagBegin(ByVal graphics As GcPdfGraphics, ByVal textLayout As TextLayout, ByVal tag As Object) Implements ITextLayoutHandler.TextTagBegin
            Dim paragraphIndex As Integer
            If TypeOf tag Is Integer Then
                paragraphIndex = CInt(tag)
            Else
                paragraphIndex = -1
            End If

            Dim paragraphElement As StructElement
            If _currentParagraphIndex = paragraphIndex Then
                paragraphElement = _currentparagraphElement
            Else
                paragraphElement = New StructElement("P")
                ParentElement.Children.Add(paragraphElement)
                _currentparagraphElement = paragraphElement
                _currentParagraphIndex = paragraphIndex
            End If
            ''
            graphics.BeginMarkedContent(New TagMcid("P", _tagIndex))
            Dim mcil = New McrContentItemLink()
            mcil.MCID = _tagIndex
            mcil.Page = Page
            paragraphElement.ContentItems.Add(mcil)
            _tagIndex += 1
        End Sub

        Public Sub TextTagEnd(ByVal graphics As GcPdfGraphics, ByVal textLayout As TextLayout, ByVal tag As Object) Implements ITextLayoutHandler.TextTagEnd
            graphics.EndMarkedContent()
        End Sub

        Public Sub AddTextArea(ByVal bounds As RectangleF) Implements ITextLayoutHandler.AddTextArea
        End Sub
    End Class
End Class