ReadTagsToOutlines.vb
''
'' This code is part of Document Solutions for PDF .NET demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System.IO
Imports System.Drawing
Imports System.Linq
Imports System.Collections.Generic
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Pdf.TextMap
Imports GrapeCity.Documents.Pdf.Structure
Imports GrapeCity.Documents.Pdf.Recognition.Structure

'' Find tables and read their data using structure tags.
Public Class ReadTagsToOutlines
    Public Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Using s = File.OpenRead(Path.Combine("Resources", "PDFs", "C1Olap-QuickStart.pdf"))
            doc.Load(s)

            '' Get the LogicalStructure and top parent element:
            Dim ls As LogicalStructure = doc.GetLogicalStructure()
            Dim root As Element = ls.Elements(0)

            '' Iterate over elements and select all heading elements (H1, H2, H3 etc.):
            Dim outlines As OutlineNodeCollection = doc.Outlines
            Dim outlinesLevel = 1
            For Each e As Element In root.Children
                Dim eType = e.StructElement.Type
                If String.IsNullOrEmpty(eType) OrElse Not eType.StartsWith("H") Then
                    Continue For
                End If
                ' Note: topmost level is 1:
                Dim headingLevel As Integer = 0
                If Not Integer.TryParse(eType.Substring(1), headingLevel) OrElse headingLevel < 1 Then
                    Continue For
                End If
                ' Get the element text:
                Dim text = e.GetText()
                ' Find the target page:
                Dim pg = FindPage(e.StructElement)
                If pg IsNot Nothing Then
                    Dim o = New OutlineNode(text, New DestinationFit(pg))
                    If headingLevel > outlinesLevel Then
                        outlinesLevel += 1
                        outlines = outlines.Last().Children
                    ElseIf headingLevel < outlinesLevel Then
                        outlinesLevel -= 1
                        Dim par = DirectCast(outlines.Owner, OutlineNode).Parent
                        outlines = If(par Is Nothing, doc.Outlines, par.Children)
                    End If
                    outlines.Add(o)
                End If
            Next
            doc.Save(stream)
            '' Done:
            Return doc.Pages.Count
        End Using
    End Function

    Private Function FindPage(se As StructElement) As Page
        If se.DefaultPage IsNot Nothing Then
            Return se.DefaultPage
        End If
        If se.HasChildren Then
            For Each child In se.Children
                Dim p = FindPage(child)
                If p IsNot Nothing Then
                    Return p
                End If
            Next
        End If
        Return Nothing
    End Function
End Class