PDF ファイルからベクター グラフィックスを抽出し、対応する SVG ファイルを作成しようとしています。この目的のために、xpdf ライブラリでSVGOutputDev ( https://github.com/immateriel/pdf2svg/blob/master/SVGOutputDev.cc ) を使用しています。現在、SVGOutputDev はクリップ パス抽出を実装していません。同じ実装を試みています。クリップ パス定義自体を抽出することはできますが、これらの定義のどれが通常のストロークまたは塗りつぶし領域に適用されるかを判断できません。たとえば、http://pastebin.com/jTdzv3YZを参照してください。PDFのページから抽出したSVGと、抽出中に見られる一連のPDFグラフィックコマンドの対応するダンプ。その SVG からわかるように、複数のクリップ パスと 1 つの四角形の塗りつぶし領域があります。塗りつぶされた四角形が定義される前に複数のクリップ パスが定義されていても、直前に定義された円形のクリップ パスのみ四角形の定義は、四角形に関連付けられていることが期待されます (さまざまな PDF リーダーで PDF ページがどのようにレンダリングされたかによって、白の背景に黒く塗りつぶされた円が 2 つだけ表示されます)。問題は、どのクリップ パスが PDF で定義された通常の塗りつぶし/ストローク領域に関連付けられているかをどのように知るかということです。参考までに、PDF 仕様書の関連セクションを調べましたが、あまり明確ではありませんでした (「クリッピング パス操作は、最後のパス構築演算子の後、パス オブジェクトを終了するパス描画演算子の前に表示される場合があります。ただし、クリッピング パス オペレータはペイント オペレータの前に表示されますが、表示された時点でクリッピング パスを変更するのではなく、後続のペイント オペレータの効果を変更します。
1 に答える
問題は、どのクリップ パスが PDF で定義された通常の塗りつぶし/ストローク領域に関連付けられているかをどのように知るかということです。
簡単に言えば、フィルまたはストローク操作の実行時に定義されたすべてのクリップ パス領域の交差が適用されますが、Q (状態の復元) 演算子で無効にされたものは例外です。
したがって、サンプルファイルの分析
塗りつぶされた四角形が定義される前に複数のクリップ パスが定義されていても、四角形定義の直前に定義された円形のクリップ パスのみが四角形に関連付けられることが期待されます(さまざまな PDF リーダーで PDF ページがどのようにレンダリングされたかによって、白い背景に黒く塗りつぶされた 2 つの円のみ)
間違っています:最後のクリップ領域ではなく、長方形定義の前のすべてのクリップ領域の交点が現在のクリップ領域を定義します。これらの各クリップ領域は前の領域に含まれているため、交差の結果は実際にこれら 2 つの円で構成されます。
ドキュメントでは:
グラフィックス状態には、ペイント オペレータの影響を受けるページの領域を制限する現在のクリッピング パスが含まれます。このパスの閉じたサブパスは、ペイントできる領域を定義します。
最初のクリッピング パスには、ページ全体が含まれます。
[Clipping Path Operators] 現在のパスと交差することで現在のクリッピング パスを変更し、[非ゼロの巻き数規則 / 偶奇規則] を使用して、どの領域がクリッピング パス内にあるかを判断します。
現在のクリッピング パスを拡大したり、現在のクリッピング パスを参照せずに新しいクリッピング パスを設定したりする方法はありません。ただし、クリッピング パスはグラフィックス状態の一部であるため、クリッピング パスの変更とこれらのオブジェクトの描画を q 演算子と Q 演算子のペアで囲むことにより、その効果を特定のグラフィックス オブジェクトに限定できます (8.4.2 を参照)。 「グラフィックス状態スタック」)。Q オペレーターを実行すると、クリッピング パスは、クリッピング パスが変更される前に q オペレーターによって保存された値に戻ります。
(現在の PDF 仕様ISO 32000-1のセクション 8.5.4 )
実際の動作:ドキュメントのページのコンテンツ ストリームを見てみましょう (Mediabox [0, 0, 595, 842] があります)。
q
q
グラフィックス状態を 2 回押します。
0 842 m
0 0 l
595 0 l
595 842 l
h
W
n
メディア ボックス全体に相当するクリップ パスを定義します。
1 w
2 J
0 j
10 M
[]0 d
一般的なグラフィックス状態プロパティ (線幅、線キャップ スタイル、線結合スタイル、マイター リミット、破線パターン) を定義します。
q
今度は、明示的に設定されたクリップ パスとその他のグラフィック プロパティを使用して、グラフィック ステートを再度プッシュします。
0 718.5 m
595 718.5 l
595 123.5 l
0 123.5 l
0 718.5 l
h
W
n
メディア ボックス全体と同じ幅の長方形を含むクリップ パスを定義しますが、124 ユーザー空間単位の高さの上下のストライプを切り取ります。このクリップ パスは、以前に設定したクリップ パスに完全に含まれているため、ここでは交差がこのクリップ パスと等しくなります。したがって、現在有効なクリップ領域は、この小さい方の長方形です。
0 718.5 m
595 718.5 l
595 123.5 l
0 123.5 l
0 718.5 l
h
W
n
前のものと同一のクリップ パスを定義します。したがって、それらを交差させても何も変わりません。
148.75 668.92 m
93.98 668.92 49.58 624.52 49.58 569.75 c
49.58 514.98 93.98 470.58 148.75 470.58 c
203.52 470.58 247.92 514.98 247.92 569.75 c
247.92 624.52 203.52 668.92 148.75 668.92 c
h
347.08 470.58 m
292.32 470.58 247.92 426.18 247.92 371.42 c
247.92 316.65 292.32 272.25 347.08 272.25 c
401.85 272.25 446.25 316.65 446.25 371.42 c
446.25 426.18 401.85 470.58 347.08 470.58 c
h
W
n
2 つの円サブパスで構成されるクリップ パスを定義します。これら 2 つの円は交差しません。したがって、「非ゼロ巻数規則」と「偶奇規則」の違いに対処する必要はありません。さらに、円は現在のクリップ領域内に含まれています。したがって、新しいクリップ領域はこれら 2 つの円で構成されます。
0 0 0 rg
49.58 668.92 m
545.42 668.92 l
545.42 173.08 l
49.58 173.08 l
49.58 668.92 l
h
f
これにより、現在のクリッピング領域を含む塗りつぶされた黒い四角形が描画されます。したがって、クリッピング領域全体 (つまり、2 つの円) が黒く塗りつぶされます。
Q
q
これにより、グラフィックスの状態が最後にプッシュされた状態に復元されます。つまり、後続の操作のクリッピング パスは、メディア ボックス全体を含む最初のパスです。このグラフィックス状態が再度プッシュされます。
0 718.5 m
0 123.5 l
595 123.5 l
595 718.5 l
h
W
n
上部と下部のバーを切り取るクリッピング パスが再び定義されます...
Q
q
...そして、復元状態操作によってすぐに削除されます。状態が再びプッシュされます。
0 718.5 m
0 123.5 l
595 123.5 l
595 718.5 l
h
W
n
Q
q
また同じ...
0 718.5 m
0 123.5 l
595 123.5 l
595 718.5 l
h
W
n
Q
q
... そしてまた。
0 842 m
0 0 l
595 0 l
595 842 l
h
W
n
これにより、メディア ボックス全体を囲むクリッピング パスが再び定義されます。とにかくこれが現在のクリッピング パスなので、交差しても何も変わりません。
Q
Q
Q
以前にスタックにプッシュされたすべてのグラフィックス状態が再び削除されます。