CMapResources.vb
''
'' This code is part of GrapeCity Documents for PDF samples.
'' Copyright (c) GrapeCity, Inc. All rights reserved.
''
Imports System
Imports System.IO
Imports System.Linq
Imports System.Collections.Generic
Imports System.Drawing
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Text

'' This sample is identical to the ExtractText sample,
'' but it loads a PDF that uses less common CMaps that are not built
'' into GcPdf. But, many such CMaps are provided by the optional
'' GrapeCity.Documents.Pdf.Resources package. It is not automatically
'' referenced by GcPdf, but if a reference to it is added to a project
'' (like in this sample), it will be picked up automatically
'' by the GcPdfDocument static ctor, and the additional CMaps 
'' will become available.
''
'' The ExternalCMapTest.pdf used by this sample contains text
'' that is encoded using one of those less common CMaps.
'' Referencing GrapeCity.Documents.Pdf.Resources allows to retrieve
'' the text from that PDF using the GetText() method. 
'' If you download this sample and REMOVE the reference 
'' to GrapeCity.Documents.Pdf.Resources, the sample will build and run,
'' but it will not be able to extract the text.
'' 
'' If needed, arbitrary CMaps can be made available to GcPdf
'' using the static GcPdfDocument.CMapProvider property.
'' 
Public Class CMapResources
    Function CreatePDF(ByVal stream As Stream) As Integer
        Const pdfName = "ExternalCMapTest.pdf"

        '' This line may Not be needed if the GcPdfDocument class ctor finds
        '' the GrapeCity.Documents.Pdf.Resources.dll at startup
        '' (this depends on the way the app Is deployed):
        GcPdfDocument.CMapProvider = CMapProvider.Instance

        Dim doc = New GcPdfDocument()
        Dim Page = doc.NewPage()

        Dim rc = Util.AddNote(
            "This sample loads a PDF into a temporary GcPdfDocument, " +
            "retrieves all text from each page of the loaded document using the Page.GetText() method, " +
            "adds all those texts to a TextLayout and renders it into the current document. " +
            "CMaps used by the PDF in this sample are provided by the optional " +
            "https://www.nuget.org/packages/GrapeCity.Documents.Pdf.Resources/ package. " +
            "Without a reference to that package most of the text in this particular PDF will not be found " +
            "as it uses the less common CMaps that are not built into GcPdf itself." +
            vbLf + vbLf +
            "To use GrapeCity.Documents.Pdf.Resources in a project, add a reference to it, " +
            "and either make sure that GrapeCity.Documents.Pdf.Resources.dll is present in the runtime directory, " +
            "or add the line:" +
            vbLf + vbTab + "GcPdfDocument.CMapProvider = CMapProvider.Instance;" +
            vbLf + "to the project's initialization code.",
            Page)

        Dim arialbd = Font.FromFile(Path.Combine("Resources", "Fonts", "arialbd.ttf"))
        Dim segoe = Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf"))
        Dim arialuni = Font.FromFile(Path.Combine("Resources", "Fonts", "arialuni.ttf"))
        segoe.AddLinkedFont(arialuni)

        '' Text format for captions:
        Dim tf = New TextFormat() With
            {
                .Font = arialbd,
                .FontSize = 14,
                .ForeColor = Color.Blue
            }
        '' Text layout to render the text:
        Dim tl = New TextLayout()
        tl.DefaultFormat.Font = segoe
        tl.DefaultFormat.FontSize = 12
        tl.MaxWidth = doc.PageSize.Width
        tl.MaxHeight = doc.PageSize.Height
        tl.MarginAll = rc.Left
        tl.MarginTop = rc.Bottom + 36

        '' Text split options for widow/orphan control:
        Dim tso = New TextSplitOptions(tl) With
            {
                .MinLinesInFirstParagraph = 2,
                .MinLinesInLastParagraph = 2,
                .RestMarginTop = rc.Left
            }

        '' Open an arbitrary PDF, load it into a temp document and get all page texts:
        Using fs = New FileStream(Path.Combine("Resources", "PDFs", pdfName), FileMode.Open, FileAccess.Read)
            Dim doc1 = New GcPdfDocument()
            doc1.Load(fs)

            '' Get the texts of the loaded document's pages:
            Dim texts = New List(Of String)()
            doc1.Pages.ToList().ForEach(Sub(p_) texts.Add(p_.GetText()))

            '' Add texts and captions to the text layout:
            For i = 0 To texts.Count - 1
                tl.AppendLine($"Text from page {i + 1} of {pdfName}:", tf)
                tl.AppendLine(texts(i))
            Next
            tl.PerformLayout(True)
            While True
                '' 'rest' will accept the text that did not fit:
                Dim rest As TextLayout = Nothing
                Dim splitResult = tl.Split(tso, rest)
                doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty)
                If splitResult <> SplitResult.Split Then
                    Exit While
                End If
                tl = rest
                doc.Pages.Add()
            End While
        End Using
        '' Done
        doc.Save(stream)
        Return doc.Pages.Count
    End Function
End Class