TagTextLayout.vb
- ''
- '' 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
-