技術記事

HotPDFを使用したDelphiでのPDF注釈: タイプと四角形

注釈はページコンテンツではありません。 TextOut を呼び出したり、四角形を描画したりすると、そのマークはページのコンテンツストリームの一部になり、レンダラーがペイントするバイトに焼き付けられます。注釈は、独自の四角形、独自の外観、および独自のライフサイクルを持ち、 /Annots 配列を介してページにぶら下がる別個の辞書です。リーダーは、基になるページのグリフに1つも触れることなく、注釈を開いたり、移動したり、非表示にしたり、削除したりできます。この分離が注釈が存在する最大の理由であり、また、人々が最初に驚く2つのこと、つまり注釈がどこに配置されるのか、特定のビューアがそれを取得した後にどのように見えるのかの理由でもあります

HotPDFは、ページオブジェクト上の AddXxxAnnotation 呼び出しのファミリを通じてISO 32000注釈サブタイプを公開します。これらはすべて同じ形を共有しています。つまり、PDFユーザースペースのページに注釈を固定する四角形、ペイロード(テキスト、スタンプ名、ポイントのペア)、および色です。四角形を正しく設定すれば、ほとんどの作業は完了です。残りは、どのサブタイプが独自の外観を持ち、どのサブタイプがビューアの描画に依存するかを知ることです

ページ全体に配置されたテキストノートアイコン、フリーテキストボックス、正方形と線のマークアップ、および承認スタンプを示す、HotPDFによって生成されたPDFページ
テキストノート、フリーテキスト、幾何学的なマークアップ、スタンプなど、複数の注釈サブタイプを一度に保持する1つのページ

四角形は注釈であり、テキストではありません

すべての注釈の呼び出しは TRect を受け取りますが、その四角形は TextOut に渡す座標とは意味が異なります。テキストノートの場合、それはクリック可能なホットスポットであり、ノートアイコンが配置され、クリックするとコメントがポップアップする小さな領域です。四角形またはフリーテキストボックスの場合、それはマークアップの可視範囲です。スタンプの場合、それはスタンプアートがスケーリングされるボックスです。数値はPDFのユーザースペースポイントであり、HotPDFの他の部分が使用するのと同じ規則である、Yが上に向かって増加するページの左下隅から測定されます

テキストノートは最も軽量なサブタイプです。本文テキスト、アイコンの四角形、デフォルトで開くかどうかのフラグ、アイコン名、および色を指定します

Pdf.CurrentPage.AddTextAnnotation(
  'Reviewer: confirm the totals on this line before sign-off.',
  Rect(120, 700, 140, 720),   // icon hotspot, ~20pt square
  False,                      // closed until the reader clicks it
  taComment,                  // bubble icon
  clBlue);

テキストノートは、誰かがそれをクリックするまでは単なるアイコンであるため、ここの四角形は意図的に小さく、1辺が約20ポイントになっています。四角形を大きくしても、大きなノートは得られません。片隅にアイコンがピン留めされた、特大のクリックターゲットが得られるだけです。 Open フラグは、ドキュメントの読み込み時にポップアップを表示するかどうかを制御します。一握りのノートを True に設定すると、それらは互いに重なり合い、コンテンツの上にも重なるため、読者にすぐに見てもらいたい1つのノートのためにそのフラグを予約しておいてください

アイコン名は THPDFTextAnnotationType から取得され、 taCommenttaKeytaNotetaHelptaParagraphtaNewParagraphtaInsert などの標準のノートアイコンにマップされます。アイコンは、タイプが変更する唯一のものです。動作は変わりません。また、すべてのビューアが7つすべてを描画するわけではないことを知っておく価値があります。古いリーダーと新しいリーダーで安全なのは、 taCommenttaNote 、および taHelp です

フリーテキストはページに書き込まれますが、注釈のままです

フリーテキスト注釈は、キャプションのように四角形の中にテキストがクリックなしで表示されるため、コンテンツのように見えます。しかし、それは依然として注釈であり、それに伴うすべての分離性を備えています。これは、後で誰かが削除できるべきレビュースタンプやドラフトラベルにまさに必要なものです。このシグネチャは、アイコンとオープンフラグを位置合わせ(ジャスティフィケーション)値に交換します

Pdf.CurrentPage.AddFreeTextAnnotation(
  'DRAFT - not for distribution',
  Rect(200, 210, 400, 235),   // the box the text is laid into
  ftCenter,                   // ftLeftJust / ftCenter / ftRightJust
  clRed);

テキストがその中で折り返されて整列されるため、ここでの四角形はテキストノートの場合よりも重要です。ボックスの高さが低すぎるとテキストは下端でクリップされ、狭すぎると意図しない場所で折り返されます。位置合わせは THPDFFreeTextAnnotationJust から取得され、3つの値しかありません。フリーテキストはマークアップ注釈であるため、エディタでファイルを開いた読者は、それを単位として選択、移動、または削除できます。これが、フリーテキストを使用するか、単に TextOut で文字を描画するかを決定する違いです。ラベルを永続的にする必要がある場合は、それを描画します。それが編集上のものであり、削除されることを意図している場合は、注釈にします

何かを指し示すための幾何学図形と線のマークアップ

正方形、円、および線は、言葉で説明するのではなく、領域を指し示すために使用するマークアップです。 AddCircleSquareAnnotation は、 csCircle または csSquareTHPDFCSAnnotationType を介して2つのボックス形状をカバーし、四角形が形状の境界を与えます

// A box drawn around a figure that needs attention
Pdf.CurrentPage.AddCircleSquareAnnotation(
  'Check this region against the source data',
  Rect(50, 300, 120, 360),
  csSquare,
  clGreen);

// A line, given two points rather than a rectangle
var
  StartPt, EndPt: THPDFCurrPoint;
begin
  StartPt.X := 130; StartPt.Y := 360;
  EndPt.X   := 250; EndPt.Y   := 320;
  Pdf.CurrentPage.AddLineAnnotation(
    'Points from the note to the figure',
    StartPt, EndPt,
    clBlue);
end;

線の注釈は四角形のパターンを破っていることに注意してください。線はバウンディングボックスではなくエンドポイントによって定義されるため、2つの THPDFCurrPoint レコード(開始と終了)を受け取ります。色はストロークを設定します。矢印が必要な場合、HotPDFには行末のスタイルを受け入れる AddLineAnnotation のオーバーロードがありますが、プレーンな3つの引数の形式はむき出しの線を描画し、通常コールアウトが望むのはこれです

テキストマークアップのサブタイプは、既にレイアウトした領域で機能します。 AddHighlightAnnotation は、四角形、オプションのコンテンツ、およびデフォルトで黄色になる色を受け取り、蛍光ペンと同じように領域を色付けします。これは実際のテキストの上に配置されるように意図されているため、四角形は描画した単語の境界と一致する必要があります。つまり、通常は推測するのではなく、 TextOut に渡したのと同じ座標からそれを計算します

スタンプのレンダリングはビューアに依存します

スタンプ注釈は、リーダーごとに最も異なって見える可能性が高いものであり、その理由を理解しておく価値があります。 AddStampAnnotation は、 satApprovedsatConfidentialsatFinalsatDraftsatForComment などの値を使用して、 THPDFStampAnnotationType を介して標準スタンプの名前を指定します

Pdf.CurrentPage.AddStampAnnotation(
  'Approved for release on review',
  Rect(50, 400, 200, 440),
  satApproved,
  clGreen);

スタンプ名はリクエストです。PDFは標準のスタンプ名のセットを定義しますが、その背後にあるアートワークは定義しません。そのため、各ビューアは「APPROVED」や「CONFIDENTIAL」の独自のレンダリングを出荷し、認識できない名前については何もレンダリングしないものもいくつかあります。四角形はアートがスケーリングされるボックスを制御し、色はビューアが尊重するかもしれない、またはしないかもしれないヒントです。スタンプがどこでも同じように見える必要がある場合、信頼できるルートは標準スタンプではありません。 TextOut と描画の呼び出しを使用して自分でマークを描画するか、外観を制御できるフリーテキスト注釈として配置します。ビューアの使い慣れた外観が必要で、ばらつきを許容できる場合は、標準のスタンプを使用してください

ファイルの添付は、同じ「四角形+ペイロード」の形に従います。 AddFileAttachmentAnnotation は、説明、埋め込むファイルのパス、ペーパークリップアイコンの四角形、および色を受け取ります。ファイルはPDF内にあり、アイコンは読者がそれを抽出するために使用するハンドルです

注釈とAcroFormフィールドの違い

最も時間を無駄にする混乱は、注釈をフォームフィールドのように扱うことです。どちらも /Annots を介してページにアタッチされ、フォームフィールドは実際には特別な注釈サブタイプ(ウィジェット)であるため、関連しているように見えます。これらは交換可能ではありません。フォームフィールドは値を保持し、名前を持ち、タブ順序に参加し、送信、リセット、またはスクリプト化できます。それらを作成するには、このページの注釈呼び出しではなく、 AddTextFieldAddCheckBox 、および AddPushButton を呼び出します。マークアップ注釈はコメントまたは形状を保持し、送信する値を持たず、入力を収集する必要がある瞬間には間違ったツールです

実用的なテストは簡単です。ユーザーが入力、選択、またはクリックし、ドキュメントにそれを記憶させる場合は、AcroFormフィールドが必要です。ファイルとともに移動するがデータではないメモを残したり、領域をマークしたり、ステータスをスタンプしたりする場合は、注釈が必要です。これらを混同すると、見た目は正しくても動作が間違っているドキュメントが生成されます。つまり、誰も入力できない「フィールド」や、フォームがリセットされると消えてしまうコメントなどです。フィールドタイプ、検証、および送信アクションを備えた対話型の側面は、 AcroFormフィールドとアクションのウォークスルー で取り上げられている独自の主題です

ページを組み立てる

各部分は、HotPDFの他の部分と同じように構成されます。ドキュメントのプロパティを設定し、 BeginDoc を呼び出し、テキストとグラフィックスの呼び出しで必要なページコンテンツを描画し、その上に注釈を追加して、 EndDoc で閉じます。注釈は CurrentPage にアタッチされるため、 AddPage の後は新しいページに着地し、改ページの後に追加した場合、ページ1を意図したノートがページ2に静かに表示されます

Pdf := THotPDF.Create(nil);
try
  Pdf.FileName := 'annotated.pdf';
  Pdf.Compression := cmFlateDecode;
  Pdf.FontEmbedding := True;
  Pdf.BeginDoc;

  Pdf.CurrentPage.SetFont('Arial', [], 11);
  Pdf.CurrentPage.TextOut(50, 740, 0, 'Quarterly figures, draft for review');

  Pdf.CurrentPage.AddTextAnnotation(
    'Confirm the totals before sign-off.',
    Rect(50, 720, 70, 740), False, taComment, clBlue);
  Pdf.CurrentPage.AddFreeTextAnnotation(
    'DRAFT', Rect(450, 720, 540, 745), ftCenter, clRed);
  Pdf.CurrentPage.AddStampAnnotation(
    'For comment', Rect(50, 660, 180, 695), satForComment, clGreen);

  Pdf.EndDoc;
finally
  Pdf.Free;
end;

出力が間違って見えるときに構築しておく価値のある最後の反射神経が1つあります。コードが壊れていると判断する前に、複数のビューアでファイルを開いてください。スタンプと珍しいノートアイコンが通常の犯人であり、注釈はペイントされたピクセルではなく読者へのリクエストであるため、Acrobatと軽量ビューアの違いは、呼び出しのバグではなく、仕様が設計どおりに機能していることがよくあります

ここに示されている注釈の呼び出しは、DelphiおよびC++Builder用のHotPDFコンポーネントの一部です