aminophen/dviout-util

dvispc: Flatten nested annotation

Opened this issue · 2 comments

dvipdfmx は,pdf:bann 〜 pdf:eann がネストされると

dpxlink.dvi -> dpxlink.pdf
[1
dvipdfmx:warning: Can't begin an annotation when one is pending.
dvipdfmx:warning: Interpreting special command bann (pdf:) failed.
dvipdfmx:warning: >> at page="1" position="(196.512, 119.253)" (in PDF)
dvipdfmx:warning: >> xxx "pdf:bann<</Type/Annot/Subtype/Link/Border[0 0 0]/H/I/C[0 1 1..."
dvipdfmx:warning: >> Reading special command stopped around >><</Type/Annot/Subtype/Link/Border[0 0 0]/H/I/C[0 1 1]/A<</S/...<<
][2
dvipdfmx:warning: Tried to end an annotation without starting one!
dvipdfmx:warning: Interpreting special command eann (pdf:) failed.
dvipdfmx:warning: >> at page="2" position="(207.866, 657.235)" (in PDF)
dvipdfmx:warning: >> xxx "pdf:eann"
]

のように警告が出る。dvispc の開発版はアノテーションのスタックを扱えるので,

  • bann 〜 eann の内部で bann が出たら一旦 eann で前のアノテーションを閉じて,eann が出たら再度 bann で元どおり再開する。

としたい。

なお,pdf:nolink による中断 (suspend),pdf:link による再開 (resume) がある場合(例示ソース)は,これだけでは支障があるかもしれないため要確認。

今のところ考えていること:

  • オプション -f を新設し,Flatten nested annotation (EXE2FLAT) する。
    • 引数の扱いや i/o など多くは,既存の Page-independent (EXE2INDEP) を流用できるはず。
  • EXE2INDEP と EXE2FLAT は「同時実行も可,一方のみ実行も可」とするのが良いだろう。
    • 準備段階として texjporg/tex-jp-build@707044b では,ビットフラグを用いてモードを扱うように改修した(まだ #if 0 ... #endif でコードを隠してあるが)。
      • モード (f_mode) の初期値は 0
      • モードオプション無指定時(=デフォルト)は EXE2INDEP (1) ヘフォールバック
      • -c のみ明示指定 → EXE2INDEP (1)
      • -f のみ明示指定 → EXE2FLAT (2)
      • -c-f の両方を明示指定 → EXE2INDEP + EXE2FLAT (3)
      • その他のモード (EXE2CHECK, EXE2SPECIAL, EXE2TEXT, EXE2DVI) はこれらと排他的。
  • EXE2FLAT が有効な時は,
    • bann 〜 eann の内部 (pdf_annot_depth > 0) で
      • bann が出たら,一旦 eann で前のアノテーションを閉じる。(ただし,下記のとおり nolink で既に閉じた後ならば何もしない)
        • その後で eann が出たら,再度 bann で元どおり再開する。(ただし,下記のとおり link で既に再開した後ならば何もしない)
      • nolink が出たら,それを消して代わりに eann でアノテーションを閉じる。
        • その後で link が出たら,それを消して再度 bann で元どおり再開する。
      • ここで nolink / link を消す必要があるのは,dvipdfmx ではスタックの特定階層に限らず大域的に(より外側の階層にも内側の階層にも)効いてしまうため。特に nolink を残してしまうと,リンクが改ページをまたぐ途中の脚注で起こりうる bann -> nolink -> bann -> eann -> link -> eann という構造で,内側の bann -> eann にリンクが付かなくなってしまうと思われる。
    • bann 〜 eann と関係ない場所で nolink / link が出たら,それは消すべきか残すべきか?
  • このような処理を加えることで,「元々の DVI にあったネスト数」と「処理途中・処理後のネスト数」が変わってくる。EXE2INDEP かつ EXE2FLAT な場合は対策が必要。
    • EXE2INDEP によって各ページの最後に発行される eann の数・次ページの最初に発行される bann の数は,高々 1 個にならなければおかしい。

オプション -f を新設し

他にも似たような修正機能をつける可能性があるので,flatten nested annotation だけで一つのオプションを占有するのではなく,汎用的なオプションをつける方が良いのではという気がしてきた。

→ というわけで 95529d6 でオプション全体に対するビットフラグ化を revert し,代わりに EXE2INDEP モードの機能を拡張することを想定して名称を EXE2MODIFY に変更した。

  • オプション -m[flags] を新設し,「何を修正するか」をビットフラグで指定できるようにする。
    • デフォルト値は 1 (-m1) とし,make page-independent を示す(後方互換)。
    • -m0 ならば何もしない。special に関する修正は行わないが,それとは別に -z (append empty pages) が使える分には良かろう。
    • -m2 ならば flatten nested annotation を示す。
    • -m4 ならば tidy up paper size specials を示す???
      • 別途 -P0 -P1 -P2 でそれぞれ「用紙サイズ special を全部無視」「最後の special が勝つ(dvipdfmx・新しい dvips 互換)」「最初の special が勝つ(古い dvips 互換)」
      • 例えば「-m4 のフラグを立てる場合は,別途 -P オプションも付けなければならない(違反するとエラー終了)」という仕様にする? それとも,-m4 を増設せずに -P なしだと「用紙サイズ special は何も触らない,-P ありなら上記のとおり(0~2)とする?
  • EXE2MODIFY,EXE2CHECK の両モードに対して -m[flags] が有効とする。つまり,EXE2CHECK で「修正が必要かどうか」を判定する際に -m[flags] が指定されていれば,その項目だけの修正有無をチェックすることができる。