CMapResources.vb
'' 
'' このコードは、DioDocs for PDF のサンプルの一部として提供されています。
'' 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

'' このサンプルは ExtractText サンプルと同じですが、GcPdf に
'' 組み込まれていない、あまり一般的ではない Cmap を使用するPDF を読み込みます。
'' なお、そのような CMap の多くは、オプションの GrapeCity.Documents.Pdf.Resources 
'' パッケージによって提供されています。このパッケージは GcPdf によって自動的
'' には参照されませんが、(このサンプルのように)プロジェクトに追加することで、
'' GcPdfDocument の静的コンストラクタにて自動的に取得され、追加の Cmap が利用
'' 可能になります。
'' 
'' このサンプルで使用されている ExternalCMapTest.pdf には、さほど一般的ではない
'' CMapの1つを使用してエンコードされたテキストが含まれています。
'' GrapeCity.Documents.Pdf.Resources を参照すると、GetText() メソッドを使用して
'' その PDF からテキストを取得できます。
'' このサンプルをダウンロードして、GrapeCity.Documents.Pdf.Resources への参照を
'' 削除すると、サンプルはビルドされて実行されますが、テキストを抽出することは
'' できません。
'' 
'' 必要に応じて、静的な GcPdfDocument.CMapProvider プロパティを使用して、任意の
'' CMap を GcPdf で利用することができます。
''     
Public Class CMapResources
    Function CreatePDF(ByVal stream As Stream) As Integer
        Const pdfName = "ExternalCMapTest.pdf"

        '' 起動時に GcPdfDocument クラスのコンストラクタによって 
        '' GrapeCity.Documents.Pdf.Resources.dll が検出される場合、以下の行は必要ありません
        '' (これはアプリケーションの展開方法によって異なります)。
        GcPdfDocument.CMapProvider = CMapProvider.Instance

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

        Dim rc = Util.AddNote(
            "このサンプルは、PDF を一時的な GcPdfDocument に読み込み、" +
            "Page.GetText() メソッドを使用して読み込まれたドキュメントの各ページからすべてのテキストを取得し、" +
            "それらすべてのテキストを TextLayout に追加して現在のドキュメントにレンダリングします。 " +
            "このサンプルでPDFによって使用されるCMapは、以下のオプションパッケージによって提供されます。 " +
            "https://www.nuget.org/packages/GrapeCity.DioDocs.Pdf.Resources.ja/ " +
            "特定のPDFのテキストのほとんどは、GcPdf自体に組み込まれていないあまり一般的でないCMapを使用して" +
            "いるため、このパッケージを参照しないとそれらが見つかりません。" +
            vbLf + vbLf +
            "プロジェクトで GrapeCity.Documents.Pdf.Resources を使用するには、アセンブリへの参照を追加し、" +
            "GrapeCity.Documents.Pdf.Resources.dll がランタイムディレクトリに存在することを確認するか、" +
            "プロジェクトの初期化コードに以下の行を追加します。" +
            vbLf + vbTab + "GcPdfDocument.CMapProvider = CMapProvider.Instance;",
            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)

        '' キャプションのテキスト書式。
        Dim tf = New TextFormat() With
            {
                .Font = arialbd,
                .FontSize = 14,
                .ForeColor = Color.Blue
            }
        '' テキストを描画するためのテキストレイアウト。
        Dim tl = Page.Graphics.CreateTextLayout()
        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

        '' widow/orphan 制御のテキスト分割オプション。
        Dim tso = New TextSplitOptions(tl) With
            {
                .MinLinesInFirstParagraph = 2,
                .MinLinesInLastParagraph = 2,
                .RestMarginTop = rc.Left
            }

        '' 任意の PDF を開き、一時的なドキュメントに読み込んで、マップを使用してテキストを検索します。
        Using fs = New FileStream(Path.Combine("Resources", "PDFs", pdfName), FileMode.Open, FileAccess.Read)
            Dim doc1 = New GcPdfDocument()
            doc1.Load(fs)

            '' 読み込まれたドキュメントのページのテキストを取得します。
            Dim texts = New List(Of String)()
            doc1.Pages.ToList().ForEach(Sub(p_) texts.Add(p_.GetText()))

            '' テキストレイアウトにテキストとキャプションを追加します。
            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' は、収まりきらなかったテキストを受け入れます。
                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
        '' PDF ドキュメントを保存します。
        doc.Save(stream)
        Return doc.Pages.Count
    End Function
End Class