コンテンツにスキップ

Content: テキスト + 構造化コンテンツモデル

Content モジュールは、テキスト表示演算子、テキスト状態演算子、テキストの影、ドキュメントレベルの JavaScript、およびマーク付きコンテンツのプロパティ辞書を構築します。レイアウトとコンテンツストリームの間に位置するレイヤーです。

Terminal window
composer require nextpdf/core:^3

Content は、resolve(解決)済みのテキストを PDF 演算子へ変換するためのプリミティブを保持します。TextRenderer が中心的なコンポーネントです。文字列のテキスト表示演算子と、その前に配置するテキスト状態演算子を構築します。Tj 演算子は、現在のフォントとその他のテキスト関連グラフィックスパラメーターを使用して、文字列のグリフを描画します(ISO 32000-2 §9)。TextRenderer は、有効な TypographyMode に基づき、単一の表示演算子または位置指定された TJ 配列のいずれかを選択します。モードが TJ 配列を使用する場合は、カーニング調整を適用します。

テキスト状態は完全にモデル化されています。setTextRenderingMode()TextRenderingMode 列挙型を受け取ります。その 8 つのケースは、ISO 32000-2 のテキストレンダリングモード、すなわち塗りつぶし、ストローク、塗りつぶし後ストローク、非表示、および 4 つのクリップバリアント(Table 104)と 1 対 1 で対応します。レンダラーは、ストローク幅、文字間隔と単語間隔、水平方向の伸張、テキストの上下位置、右から左への方向、オプションの Hyphenator も制御します。buildTextStateOperators() を呼び出すと、蓄積された状態が単一の演算子ブロックとして出力されます。

TextShadow は値オブジェクトであり、色、ユーザー単位での X および Y オフセット、不透明度を保持します。レンダラーはこれを利用して、オフセットされた 2 回目の描画パスを出力します。デフォルトのオフセットは控えめな 0.5/−0.5、不透明度は 0.5 で、CSS スタイルのソフトシャドウに合わせています。

JavaScriptManager はドキュメントレベルのスクリプティングを担います。includeJs() はドキュメントスクリプトを登録します。addJsObject() は名前付きのスクリプトオブジェクトを登録します。writeJavaScript() / writeOpenAction() は、それらをカタログと OpenAction にシリアライズします。マネージャーは、すべてのスクリプト本体を出力前に検証し、PDF 文字列としてエンコードします。

PropertiesRegistry は、マーク付きコンテンツのプロパティストアです。register() は、プロパティ辞書に対して安定したタグインデックスを返します。registerOcg() / registerOcgs() は、オプショナルコンテンツグループをオブジェクト番号で関連付けます。writeProperties() は、レジストリをページのリソース辞書にシリアライズします。これは、ContentStream モジュールがプロパティリストを伴うマーク付きシーケンスを開く際に参照するデータです。

2 つの画像デコーダーがここに存在するのは、これらが PDF ネイティブのパススルー形式であるためです。JBig2LoaderJpxLoader は、JBIG2 および JPEG 2000 のセグメント構造を解析し、ピクセルをラスタライズすることなく ImageData を返します。エンコードされたバイト列は、変更されないままビューアーに渡されます。JBIG2 ソースが個別のグローバルセグメントを保持している場合、JBig2Loader はそれを画像 XObject 上の /JBIG2Globals ストリーム参照を介して埋め込みます。in-stream/in-line 形式は、従来どおりラウンドトリップし続けます。これは構造的な配線のみであり、グローバルバイト列はラスタライズもデコードもされず、そのまま渡されます。

クラス主要メソッド役割
TextRendererbuildTextShowOperator(), buildTextStateOperators(), setTextRenderingMode(), setTextStrokeWidth(), setTextShadow(), setFontSpacing(), setWordSpacing(), setFontStretching(), setTextRise(), setRTL(), setHyphenation()テキスト表示 + テキスト状態演算子のビルダー
TextRenderingMode(列挙型)Fill, Stroke, FillStroke, Invisible, FillClip, StrokeClip, FillStrokeClip, ClipISO 32000-2 のテキストレンダリングモード
TextShadow__construct(Color, offsetX, offsetY, opacity)オフセット描画パスの値オブジェクト
JavaScriptManagerincludeJs(), addJsObject(), hasJavaScript(), writeJavaScript(), writeOpenAction()ドキュメントレベル JavaScript のカタログ配線
PropertiesRegistryregister(), getTagIndex(), registerOcg(), registerOcgs(), getAll(), writeProperties()マーク付きコンテンツ + OCG のプロパティストア
JBig2Loaderload(), loadFromString(), parseSegments()JBIG2 パススルーデコーダー
JpxLoaderload(), loadFromString(), parseBoxes()JPEG 2000 パススルーデコーダー

完全な PHPDoc テーブルを取得するには、composer docs:generate-api-php -- --module=Content を実行してください。

ソース:examples/28-text-rendering.php

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Content\TextRenderer;
use NextPDF\Content\TextRenderingMode;
$renderer = new TextRenderer();
$renderer
->setTextRenderingMode(TextRenderingMode::FillStroke)
->setTextStrokeWidth(0.3)
->setWordSpacing(0.5);
$stateOps = $renderer->buildTextStateOperators();

これは、ソフトシャドウとハイフネーターを追加し、呼び出し側が指定するエスケープ関数(ADR-015 の正規の PdfStringEscaper シーム)を使用して表示演算子を構築します。

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Content\TextRenderer;
use NextPDF\Content\TextShadow;
use NextPDF\Graphics\Color;
use NextPDF\Support\PdfStringEscaper;
$renderer = new TextRenderer();
$renderer
->setTextShadow(new TextShadow(Color::rgb(0, 0, 0), 0.4, -0.4, 0.45))
->setRTL(false);
$showOp = $renderer->buildTextShowOperator(
text: 'Quarterly report',
fontKey: 'F1',
metrics: $fontMetrics,
escapeSegment: static fn (string $s): string => PdfStringEscaper::escapeLiteral($s),
);
$pageContent = $renderer->buildTextStateOperators() . $showOp;
  • buildTextShowOperator() は、空の入力に対して空文字列を返します。空の Tj を出力しないでください。レイアウトが空のランを生成する可能性がある場合は、上流側でガードしてください。
  • エスケープコールバックは必須であり、文字列の安全性を担います。正規の PdfStringEscaper::escapeLiteral()(ADR-015)を渡してください。不完全なエスケーパーは、構文的に壊れたリテラル文字列を生成します。
  • TextShadow::offsetY は、左上原点では負の値が下方向を表します。正の Y は影を上方向に押し上げますが、これが意図されることはまれです。
  • JavaScriptManager はスクリプト入力を検証します。無効なスクリプト本体は登録時に拒否され、書き込み時に黙って破棄されることはありません。
  • JBig2LoaderJpxLoader は、ラスタライズを一切行いません。これらはエンコードされたバイト列を検証し、そのまま通過させます。破損したセグメントは、空白の画像ではなく解析エラーとして表面化します。
  • PropertiesRegistry::register() は辞書単位でべき等であり、同一のプロパティ辞書は 1 つのタグインデックスを再利用します。

演算子の構築は文字列長に対して O(n) であり、タイポグラフィモードが TJ 配列を使用する場合は、加えて O(n) のカーニングパスがかかります。ここにはレイアウトやシェーピングのコストは含まれません。それらは Typography モジュールと Layout モジュールに留まります。JavaScript とプロパティのシリアライズは O(entries) です。パススルー画像ローダーは O(bytes) の解析で、デコードコストはゼロです。これが、スキャンドキュメントのワークロードにおけるこれらの主な利点です。リファレンスワークロードの performance_budget は、実時間 1500 ms、ピークメモリ 64 MB です。

JavaScriptManager は、信頼できないテンプレートに由来する可能性のあるスクリプト本体を受け付けます。すべての本体を検証し PDF 文字列としてエンコードしますが、それでもドキュメント JavaScript はアクティブコンテンツの攻撃面です。信頼できない出力では無効化するか、/modules/core/security/ で説明されているサニタイズ経路で取り除いてください。JBig2LoaderJpxLoader は信頼できないセグメント構造を解析します。入力サイズと解析時間を制限し、ソースがユーザー指定の場合は制約付きワーカー内で抽出を実行してください。テキストエスケープの境界は、呼び出し側が指定するコールバックです。制御バイトがリテラル文字列から抜け出せないよう、常に正規のエスケーパーを渡してください。

このモジュールは、ISO 32000-2 §9 のテキストモデルに整合するテキスト表示演算子とテキスト状態演算子を出力します。これには、Tj 演算子のセマンティクスと、TextRenderingMode 列挙型が反映する Table 104 のレンダリングモードが含まれます。これらは実装上の事実です。演算子の形は src/Content/TextRenderer.phpTextRenderingMode 列挙型によって生成され、tests/Unit/Content/TextRenderer*JavaScriptManagerIsoTest、および PropertiesRegistryTest によって検証されています。これらは、エンドツーエンドの PDF 2.0 準拠を保証するものではありません。文字列エスケープの契約は、ADR-015 および ISO 32000-2 §7.3.4.2 に従います。JBIG2 および JPEG 2000 のパススルー経路は、エンコードされたストリームを変更せずに保持します。個別の JBIG2 グローバルセグメントは、画像 XObject 上の /JBIG2Globals ストリーム参照として埋め込まれます。これはデコード忠実性の主張ではなく、構造的な配線として検証されています。ドキュメントレベルの準拠は、/modules/core/conformance/ のオラクルおよびゴールデンスイートによって検証されます。