PDFsharp 1.50を使ってPDFのコメントを透明テキストとして貼り付け直す

 ここ最近PDFsharp 1.50をPowerShellから使って日本語フォントの設定透明文字にするようにしていましたが、目的はPDFのコメントを透明テキストとして本文に貼り付けることでした。
 使い方は、

PS C:\Users\user> .\this.ps1 -PDFDIR "E:\PDF"

という具合で、そのフォルダ以下のPDFファイルすべてが編集対象になります。スクリプトの内容は以下。

Param([string] $PDFDIR = "D:\PDF")

# PDF操作ライブラリ
Add-Type -LiteralPath "C:\bat\PdfSharp.dll"
# 定数設定
Set-Variable -Name xFont -Value (New-Object -TypeName PdfSharp.Drawing.XFont -ArgumentList "游明朝", 10, "Regular") -Option Constant
Set-Variable -Name xBrush -Value (New-Object -TypeName PdfSharp.Drawing.XSolidBrush([PdfSharp.Drawing.XColor]::FromArgb(1, 255, 0, 0))) -Option Constant
Set-Variable -Name xFormat -Value ([PdfSharp.Drawing.XStringFormats]::TopLeft) -Option Constant

foreach ($editPdf in (Get-ChildItem -LiteralPath $PDFDIR -File -Recurse -Filter "*.pdf" | ForEach-Object { $_.FullName })) {
    Get-Date -UFormat "%T`tPDF編集開始: ${edit_pdf}"
    if ($true -eq (Test-Path -LiteralPath $editPdf -PathType Leaf)) {

        $cTime = Get-ItemPropertyValue -LiteralPath $editPdf -Name CreationTime
        $wTime = Get-ItemPropertyValue -LiteralPath $editPdf -Name LastWriteTime

        try {
            $pdfDoc = [PdfSharp.Pdf.IO.PdfReader]::Open($editPdf, [PdfSharp.Pdf.IO.PdfDocumentOpenMode]::Modify)
            # 透明文字対応のPDFバージョンへ
            if ($pdfDoc.Version -lt 14) {
                $pdfDoc.Version = 14
            }

            for ($i = 0; $i -lt $pdfDoc.PageCount; $i++) {
                $page = $pdfDoc.Pages[$i]
                $xText = [PdfSharp.Drawing.Layout.XTextFormatter]::new( `
                    [Pdfsharp.Drawing.XGraphics]::FromPdfPage($page) `
                )
 
                # Removeすると配列も変わるので逆順で処理
                for ($j = ($page.Annotations.Count - 1); $j -ge 0; $j--) {
                    $annot = $page.Annotations[$j]
                    if ($null -ne $annot.Contents) {
                        # 座標が異なるのでページ高さから計算 -15は微調整
                        $calcY = [Math]::Abs($page.Height.Value - $annot.Rectangle.Y1 - 15)
                        $xText.DrawString( `
                            $annot.Contents, `
                            $xFont, `
                            $xBrush, `
                            ([PdfSharp.Drawing.XRect]::new( `
                                $annot.Rectangle.X1, `
                                $calcY, `
                                [Math]::Abs($page.Width.Value - $annot.Rectangle.X1 - 100), `
                                $calcY) `
                            ), `
                            $xFormat `
                        )
                        $page.Annotations.Remove($annot)
                    }
                }
            }
            $pdfDoc.Save($editPdf)
        }
        catch {
            Get-Date -UFormat "%T`tPDF編集エラー: ${edit_pdf}: ${_}"
        }
        finally {
            $pdfDoc.Close()
        }

        Set-ItemProperty -LiteralPath $editPdf -Name CreationTime -Value $cTime
        Set-ItemProperty -LiteralPath $editPdf -Name LastWriteTime -Value $wTime

    }
}
Get-Date -UFormat "%T`tPDF変換完了"

 というのもうちで使っている全文検索システムでPDFのコメントって検索の対象にならないんですよね。そして普通のAcrobatで開いてもコメントの検索はチェックを入れる必要があったり。ということで検索システムに引っかかりやすいように、コメントを透明テキストで本文中へ移動するスクリプトを作成したのでした。
 注意点として、もとのPDFファイルを上書きしてしまうので、それがマズイ場合は$pdfDoc.Save($editPdf)で別ファイル名にしてください。
 コメントのあった座標に透明テキストを入れるようにしていますが、計算はかなり適当です。ページ外にはみ出た文字はないものとして扱われる点も注意ですね。
 あと日本語の長文コメントは枠を超えて記入されるようです。XTextFormatterのDrawStringで英文のみだとちゃんと枠内で改行されるのですが、日本語では単語の境界となる空白がないので改行が入らないのかもと推測しています。
 検索システムでファイルの更新日を変えたくなかったので、編集前にGet-ItemPropertyValueでCreationTimeとLastWriteTimeを得て最終的にSet-ItemPropertyでもとに戻しています。処理が不要な方はこの4行はいりません。