''
'' This code is part of Document Solutions for PDF demos.
'' Copyright (c) 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
'' This sample shows how To create tagged (structured) PDF And attach
'' tags to individual paragraphs in a TextLayout that is used to render
'' them together, splitting between pages.
'' The code generating the document is similar to that used in PaginatedText,
'' but adds tags.
'' To see/explore the tags, open the document in Adobe Acrobat Pro and go to
'' View | Navigation Panels | Tags.
Public Class TagTextLayout
Function CreatePDF(ByVal stream As Stream) As Integer
Dim doc = New GcPdfDocument()
'' Create a Part element, it will contain P (paragraph) elements:
Dim sePart = New StructElement("Part")
doc.StructTreeRoot.Children.Add(sePart)
'' Create and set up a TextLayout to render paragraphs:
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
''
'' Append the text (20 paragraphs so they would not fit on a single page)
'' (note that TextLayout interprets vbCrLf as paragraph delimiter):
''
'' Get the text (20 paragraphs):
Dim text = Util.LoremIpsum(20)
'' In order to tag the individual paragraphs, we need to split the text into paragraphs,
'' and use each paragraph format's Tag property (which is not related to PDF tags,
'' it is just an arbitrary data that can be associated with a TextFormat) to add the
'' paragraph's index to the paragraph:
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
'' Layout the text:
tl.PerformLayout(True)
'' Use split options to provide widow/orphan control:
Dim tso = New TextSplitOptions(tl) With {
.MinLinesInFirstParagraph = 2,
.MinLinesInLastParagraph = 2
}
'' TextLayoutHandler implements ITextLayoutHandler, which
'' allows tagging the text as it is rendered:
Dim tlh = New TextLayoutHandler() With {.ParentElement = sePart}
'' In a loop, split and render the text:
While True
'' 'rest' will accept the text that did not fit:
Dim rest As TextLayout = Nothing
Dim splitResult = tl.Split(tso, rest)
Dim page = doc.Pages.Add()
Dim g = page.Graphics
'' Tell the TextLayoutHandler which page we're on:
tlh.Page = page
'' ..and associate it with the graphics:
g.TextLayoutHandler = tlh
'' Draw the text that fits on the current page, and advance to next page unless we're done:
g.DrawTextLayout(tl, PointF.Empty)
If splitResult <> SplitResult.Split Then
Exit While
End If
tl = rest
End While
'' Mark document as tagged:
doc.MarkInfo.Marked = True
''
'' Done:
doc.Save(stream)
Return doc.Pages.Count
End Function
'' Custom class that allows tagging content as it is rendered by 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