| キー | PDFの値 | 現在の状態での役割 |
|---|---|---|
/LW | 数値 | 線幅。w と同じ値を更新 |
/LC | 整数 0 / 1 / 2 | 線端。順に平端・丸端・突出した四角端 |
/LJ | 整数 0 / 1 / 2 | 線接合。順にマイター・丸・面取り |
/ML | 数値 | マイター限界。M と同じ値を更新 |
/D | [[2 3] 1] | 描画長2・空白長3を繰り返し、開始位置を1ずらす |
/CA /ca | 0〜1 | 輪郭/塗りの不透明度 |
/BM | 名前 または 名前の配列 | 背景と描画色を混ぜる方式 |
/SMask | 辞書 または /None | 位置ごとの透明度を与えるマスク、または解除 |
/Font | [font_ref size] | フォント辞書とサイズ |
ブレンドモードは、たとえば /Normal(通常)、/Multiply(乗算)、/Screen(スクリーン)です。配列 [/Future /Multiply /Screen] は優先順位を表し、最初に対応できるモードを使います。この実装では Multiply が選ばれます。対応できる名前のない配列は Normal になります。
/F1 12 TfF1 はリソースの /Font 内を引くための名前です。テキスト状態は名前指定を保持します。
/Font [6 0 R 12]配列の先頭はフォント辞書への参照です。/F1 ではありません。参照を解決して、辞書とサイズ12を保持します。
TypeScriptでは、名前指定と辞書指定を判別可能なユニオンとして表します。type を見れば、次に読める値が name か dictionary かが決まります。
type TextFont =
- | { readonly type: "name"; readonly name: string }
- | { readonly type: "dictionary"; readonly dictionary: PdfDictionary };どちらの指定も、同じ TextState.withFont を通ります。gs の後に Tf が来れば名前指定へ置き換わり、以前の辞書と新しい名前が併存することはありません。文字間隔や行送りなどは保持します。既存の fontName は font から求める読み取り用アクセサで、辞書指定では None を返します。
/F1 12 TfF1 はリソースの /Font 内を引くための名前です。テキスト状態に名前・サイズと取得できた辞書を保持します。
/Font [6 0 R 12]配列の先頭はフォント辞書への間接参照です。オブジェクト6を解決し、辞書とサイズ12を保持します。
TypeScriptの TextFont は、type によって2種類の指定を区別します。
type TextFont =
+ | { readonly type: "name"; readonly name: string; readonly dictionary?: PdfDictionary }
+ | { readonly type: "dictionary"; readonly dictionary: PdfDictionary };
+ どちらの指定も TextState.withFont を通り、現在のフォント指定を置き換えます。文字間隔や行送りは引き継ぎます。fontName は名前指定のときにその名前を返し、辞書指定では None を返します。
q は現在のグラフィックス状態を保存し、Q は直前に保存した状態を復元します。拡張状態も同じ状態に入るため、専用の「拡張状態スタック」は必要ありません。
5 w
q
/GS1 gs % LW=3, ca=0.4
@@ -199,23 +206,25 @@
9 w
Q
Q| 実行したところ | 現在の線幅 | 塗りの不透明度 |
|---|---|---|
最初の 5 w | 5 | 1 |
/GS1 gs | 3 | 0.4 |
9 w | 9 | 0.4 |
内側の Q | 3 | 0.4 |
外側の Q | 5 | 1 |
以下はpdfmodの回復方針です。仕様上不正な値を推奨するものではありません。
| 入力 | 結果 |
|---|---|
<< /LW 3 /Unknown true /ca .4 >> | 未知キーを警告し、線幅3・不透明度0.4を適用 |
<< /CA 2 /LW 3 >> | 範囲外の不透明度だけを警告して無視。以前の不透明度を保持し、線幅3を適用 |
/Missing gs | 名前の不在を警告。状態を保持して次の命令へ進む |
| 選択した辞書の参照先が構文エラー | 原因のエラーをそのまま返す。未解決警告とは区別 |
| 未使用の名前の参照先が構文エラー | 名前ごとにエラーを保持。別の正常な名前の実行は可能 |
警告には gs 命令のバイト位置が付きます。同じ辞書を再度適用した場合は、その命令位置で再び警告します。後続の専用オペレータで警告が重複することはありません。
間接参照の解決は非同期、コンテンツストリームの実行は同期です。最初に現在のスコープの拡張状態を解決し、既定のレジストリを組み立てます。
const prepared = await ExtGStateResources.fromResources(
+06 警告と回復
以下は実行スコープを渡したときのpdfmodの回復方針です。
+ 入力 結果
+ << /LW 3 /Unknown true /ca .4 >>未知キーを警告し、線幅3・不透明度0.4を適用
+ << /CA 2 /LW 3 >>範囲外の不透明度を警告。以前の不透明度を保持し、線幅3を適用
+ /Missing gsEXT_GSTATE_NOT_FOUND。状態を保持して続行
+ 選択した辞書や内部の参照先が構文エラー RESOURCES_RESOLVE_FAILED。原因を報告し、状態を保持して続行
+ 未使用の名前の参照先が構文エラー 取得結果に原因を保持。実行中の警告は追加しない
+
+ 警告には gs 命令のバイト位置が付きます。同じ辞書を再度使うと、新しい命令位置で警告します。
+
+07 実装の使い方
間接参照を非同期で解決し、コンテンツストリームは準備したスコープを使って同期で実行します。
const scope = await ContentStreamResources.fromResources(
resources, resolveRef,
);
-if (!prepared.ok) {
- return prepared;
-}
-
-const registry = OperatorRegistry.createDefault(prepared.value);
-if (!registry.ok) {
- return registry;
-}
-
return ContentStreamInterpreter.execute({
data: contentBytes,
- registry: registry.value,
-});
Result は成功の値と失敗の理由を分ける型です。ok を確認した後でだけ、成功値 value を使えます。準備時はカテゴリ全体を解決しますが、各名前の参照エラーはその名前を使うまで実行エラーになりません。ページやフォームのスコープが変わるときは、そのスコープ用に準備し直してください。
registerGraphicsStateOperators(registry, prepared.value) で、グラフィックス関係だけを登録する方法もあります。/OP、/RI など今回扱わない辞書キーは未対応警告になります。/Type は描画パラメータではないため読み飛ばします。
+ resources: scope,
+});
+ 各カテゴリ・名前の取得結果はスコープに保持されます。ページやフォームの辞書が変わるときは、その辞書を使って準備し直します。/OP や /RI など未対応の辞書キーは個別に警告します。/Type は辞書の種別として読み飛ばします。