Closed aminophen closed 8 years ago
eps(2)write でできた EPS の冒頭に例の再定義を書いても、どうやら破線の変形はできないようです… d
というオペレータに元の setdash
が格納されて、以降はもっぱらそちらが描画に使われているので、こちらをどうにかして再定義しないといけないということでしょうかね? まだよくわからないのですが、ここに少しずつストックしていきます。
setdash
が明示的に使われた PS / EPS ファイルについては、上記の二行を冒頭に書き込んで gs にかけるだけで破線パス変形が完了します。例:PSBlueBook (Tutorial and Cookbook) の例示コード5:
%!PS-Adobe-2.0
%%Title: Blue Book Program 5, on page 145
%%Creator: Adobe Systems Incorporated
%%CreationDate: Thu Dec 28 13:19:30 PST 1989
%%EndComments
/oldsetdash /setdash load def % <= 追加(ここでなくファイル冒頭に
/setdash {oldsetdash .dashpath [] 0 oldsetdash} def % 書き込んでも可)
/centerdash
{ /pattern exch def
/pathlen pathlength def
/patternlength 0 def
pattern
{ patternlength add /patternlength exch def
} forall
pattern length 2 mod 0 ne
{ /patternlength patternlength 2 mul def } if
/first pattern 0 get def
/last patternlength first sub def
/n pathlen last sub cvi patternlength idiv def
/endpart pathlen patternlength n mul sub
last sub 2 div def
/offset first endpart sub def
pattern offset setdash % <= ここに setdash 登場
} def
/pathlength
{ flattenpath
/dist 0 def
{ /yfirst exch def /xfirst exch def
/ymoveto yfirst def /xmoveto xfirst def }
{ /ynext exch def /xnext exch def
/dist dist ynext yfirst sub dup mul
xnext xfirst sub dup mul add sqrt add def
/yfirst ynext def /xfirst xnext def }
{}
{ /ynext ymoveto def /xnext xmoveto def
/dist dist ynext yfirst sub dup mul
xnext xfirst sub dup mul add sqrt add def
/yfirst ynext def /xfirst xnext def }
pathforall
dist
} def
5 setlinewidth
newpath
72 500 moveto 378 500 lineto
[30] centerdash stroke
newpath
72 400 moveto 378 400 lineto
[30 50] centerdash stroke
newpath
72 300 moveto 378 300 lineto
[30 10 5 10] centerdash stroke
newpath
72 200 moveto 378 200 lineto
[30 15 10] centerdash stroke
newpath
225 390 300 240 300 arc
[40 10] centerdash stroke
showpage
eps(2)write は d
や D
というオペレータに setdash
を格納し、そちらを使って描画するようです。したがって、これらの d
や D
の定義を変更する必要があります。以下は epswrite の場合:
/!{bind def}bind def
/#{load def}!
/d/setdash #
これが定義されているので、ソース中ではもっぱら d
が使われます。
pdftopsによる出力EPSの場合はいかがでしょうか。 サンプル
これの場合,途中に
/d { setdash } def
と定義されています。
(これに対して .dashpath
を適用させる試みをいくつかやってみましたが,今のところ成功していません。)
まだ gs9.10 の epswrite の場合しか試していませんが、どうやら
「S
というオペレータを P stroke
から P .dashpath [] 0 setdash stroke
に再定義」
が有効みたいです。
S
というオペレータ自身は gs がプリアンブル(と呼ぶことにします)で定義しますので、ここよりも後で再定義する必要があります。しかも、P
というオペレータもやはりプリアンブルで定義されています。S
というオペレータの再定義が必要十分かは検証していません。また、これによって起きる副作用もまだ調べていません(が、副作用はたぶんないはず)。もしかすると直接 stroke
という PostScript 本来のオペレータを再定義することでも可能かもしれませんが、未確認です(stroke
を使う他のオペレータに影響しないことを確認する必要あり)。
S
オペレータにたどり着くまでの経緯メモ…昨日作った dash.ps をパス変形せずに epswrite (gs9.10) に通してみました。
%!PS-Adobe-2.0
newpath
50 600 moveto 420 600 lineto
[ 40 20 ] 0 setdash stroke
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 50 599 420 601
%%HiResBoundingBox: 50.000000 599.500000 420.000000 600.500000
%...................................
%%Creator: GPL Ghostscript 910 (epswrite)
%%CreationDate: 2015/12/05 14:02:31
%%DocumentData: Clean7Bit
%%LanguageLevel: 2
%%EndComments
%%BeginProlog
% This copyright applies to everything between here and the %%EndProlog:
% Copyright (C) 2013 Artifex Software, Inc. All rights reserved.
%%BeginResource: procset GS_epswrite_2_0_1001 1.001 0
/GS_epswrite_2_0_1001 80 dict dup begin
/PageSize 2 array def/setpagesize{ PageSize aload pop 3 index eq exch
4 index eq and{ pop pop pop}{ PageSize dup 1
5 -1 roll put 0 4 -1 roll put dup null eq {false} {dup where} ifelse{ exch get exec}
{ pop/setpagedevice where
{ pop 1 dict dup /PageSize PageSize put setpagedevice}
{ /setpage where{ pop PageSize aload pop pageparams 3 {exch pop} repeat
setpage}if}ifelse}ifelse}ifelse} bind def
/!{bind def}bind def/#{load def}!/N/counttomark #
/rG{3{3 -1 roll 255 div}repeat setrgbcolor}!/G{255 div setgray}!/K{0 G}!
/r6{dup 3 -1 roll rG}!/r5{dup 3 1 roll rG}!/r3{dup rG}!
/w/setlinewidth #/J/setlinecap #
/j/setlinejoin #/M/setmiterlimit #/d/setdash #/i/setflat #
/m/moveto #/l/lineto #/c/rcurveto #
/p{N 2 idiv{N -2 roll rlineto}repeat}!
/P{N 0 gt{N -2 roll moveto p}if}!
/h{p closepath}!/H{P closepath}!
/lx{0 rlineto}!/ly{0 exch rlineto}!/v{0 0 6 2 roll c}!/y{2 copy c}!
/re{4 -2 roll m exch dup lx exch ly neg lx h}!
/^{3 index neg 3 index neg}!
/f{P fill}!/f*{P eofill}!/s{H stroke}!/S{P stroke}!
/q/gsave #/Q/grestore #/rf{re fill}!
/Y{P clip newpath}!/Y*{P eoclip newpath}!/rY{re Y}!
/|={pop exch 4 1 roll 1 array astore cvx 3 array astore cvx exch 1 index def exec}!
/|{exch string readstring |=}!
/+{dup type/nametype eq{2 index 7 add -3 bitshift 2 index mul}if}!
/@/currentfile #/${+ @ |}!
/B{{2 copy string{readstring pop}aload pop 4 array astore cvx
3 1 roll}repeat pop pop true}!
/Ix{[1 0 0 1 11 -2 roll exch neg exch neg]exch}!
/,{true exch Ix imagemask}!/If{false exch Ix imagemask}!/I{exch Ix image}!
/Ic{exch Ix false 3 colorimage}!
/F{/Columns counttomark 3 add -2 roll/Rows exch/K -1/BlackIs1 true>>
/CCITTFaxDecode filter}!/FX{<</EndOfBlock false F}!
/X{/ASCII85Decode filter}!/@X{@ X}!/&2{2 index 2 index}!
/@F{@ &2<<F}!/@C{@X &2 FX}!
/$X{+ @X |}!/&4{4 index 4 index}!/$F{+ @ &4<<F |}!/$C{+ @X &4 FX |}!
/IC{3 1 roll 10 dict begin 1{/ImageType/Interpolate/Decode/DataSource
/ImageMatrix/BitsPerComponent/Height/Width}{exch def}forall
currentdict end image}!
/~{@ read {pop} if}!
end def
%%EndResource
/pagesave null def
%%EndProlog
%%Page: 1 1
%%BeginPageSetup
GS_epswrite_2_0_1001 begin
/pagesave save store 197 dict begin
0.1 0.1 scale
%%EndPageSetup
gsave mark
Q q
0 0 5950 0 0 8420 ^ Y
[ 400 200 ] 0 d
10 w
K
500 6000 3700 0 S
cleartomark end end pagesave restore
showpage
%%PageTrailer
%%Trailer
%%Pages: 1
出てきた dash-out.eps は可読性が低いので、手作業で翻訳して読みやすくしました。オペレータ名を短縮するためのプリアンブル定義部分を排除します:
--- dash-out.eps.orig Sun Dec 06 16:58:47 2015
+++ dash-out.eps Sun Dec 06 17:48:19 2015
@@ -19,39 +19,6 @@
{ pop 1 dict dup /PageSize PageSize put setpagedevice}
{ /setpage where{ pop PageSize aload pop pageparams 3 {exch pop} repeat
setpage}if}ifelse}ifelse}ifelse} bind def
-/!{bind def}bind def/#{load def}!/N/counttomark #
-/rG{3{3 -1 roll 255 div}repeat setrgbcolor}!/G{255 div setgray}!/K{0 G}!
-/r6{dup 3 -1 roll rG}!/r5{dup 3 1 roll rG}!/r3{dup rG}!
-/w/setlinewidth #/J/setlinecap #
-/j/setlinejoin #/M/setmiterlimit #/d/setdash #/i/setflat #
-/m/moveto #/l/lineto #/c/rcurveto #
-/p{N 2 idiv{N -2 roll rlineto}repeat}!
-/P{N 0 gt{N -2 roll moveto p}if}!
-/h{p closepath}!/H{P closepath}!
-/lx{0 rlineto}!/ly{0 exch rlineto}!/v{0 0 6 2 roll c}!/y{2 copy c}!
-/re{4 -2 roll m exch dup lx exch ly neg lx h}!
-/^{3 index neg 3 index neg}!
-/f{P fill}!/f*{P eofill}!/s{H stroke}!/S{P stroke}!
-/q/gsave #/Q/grestore #/rf{re fill}!
-/Y{P clip newpath}!/Y*{P eoclip newpath}!/rY{re Y}!
-/|={pop exch 4 1 roll 1 array astore cvx 3 array astore cvx exch 1 index def exec}!
-/|{exch string readstring |=}!
-/+{dup type/nametype eq{2 index 7 add -3 bitshift 2 index mul}if}!
-/@/currentfile #/${+ @ |}!
-/B{{2 copy string{readstring pop}aload pop 4 array astore cvx
-3 1 roll}repeat pop pop true}!
-/Ix{[1 0 0 1 11 -2 roll exch neg exch neg]exch}!
-/,{true exch Ix imagemask}!/If{false exch Ix imagemask}!/I{exch Ix image}!
-/Ic{exch Ix false 3 colorimage}!
-/F{/Columns counttomark 3 add -2 roll/Rows exch/K -1/BlackIs1 true>>
-/CCITTFaxDecode filter}!/FX{<</EndOfBlock false F}!
-/X{/ASCII85Decode filter}!/@X{@ X}!/&2{2 index 2 index}!
-/@F{@ &2<<F}!/@C{@X &2 FX}!
-/$X{+ @X |}!/&4{4 index 4 index}!/$F{+ @ &4<<F |}!/$C{+ @X &4 FX |}!
-/IC{3 1 roll 10 dict begin 1{/ImageType/Interpolate/Decode/DataSource
-/ImageMatrix/BitsPerComponent/Height/Width}{exch def}forall
-currentdict end image}!
-/~{@ read {pop} if}!
end def
%%EndResource
/pagesave null def
@@ -63,12 +30,12 @@
0.1 0.1 scale
%%EndPageSetup
gsave mark
-Q q
-0 0 5950 0 0 8420 ^ Y
-[ 400 200 ] 0 d
-10 w
-K
-500 6000 3700 0 S
+grestore gsave
+0 0 5950 0 0 8420 3 index neg 3 index neg counttomark 0 gt{counttomark -2 roll moveto counttomark 2 idiv{counttomark -2 roll rlineto}repeat}if clip newpath
+[ 400 200 ] 0 setdash
+10 setlinewidth
+0 255 div setgray
+500 6000 3700 0 counttomark 0 gt{counttomark -2 roll moveto counttomark 2 idiv{counttomark -2 roll rlineto}repeat}if stroke
cleartomark end end pagesave restore
showpage
%%PageTrailer
なにがどこでどうなっているのか分かりませんが、最後の方の
500 6000 3700 0 counttomark 0 gt{(中略)}if stroke
を
500 6000 3700 0 counttomark 0 gt{(中略)}if .dashpath [] 0 setdash stroke
に変更すると破線のパス変換ができました。これをまた元通りに翻訳しなおして比べることで、冒頭の再定義にたどり着きました。
さらに簡略化して、S
より根源的な PostScript の本来のオペレータである「stroke
を再定義する方法」にたどりつきました。こちらのほうが昨日の setdash
を再定義する方法より強力な気がしますので、汎用性は高そうですが副作用がないかどうか慎重に調べる必要があります。手元では gs9.10 の epswrite で作った EPS の冒頭に以下の二行を加える方法がうまくいきます。
/oldstroke /stroke load def
/stroke {.dashpath [] 0 setdash oldstroke} def
おおっ,お見事な発見です! pdftops が吐き出すEPS,および eps2write が吐き出すEPSについても,その2行を加えて eps2write に通すことで,破線のパス変換に成功しました!
ありがとうございます😏 .dashpath
というオペレータは破線以外に対して何もしないと例の仕様書に書かれていますし、今の私の理解では「stroke
の再定義をしても破線以外のパスには影響しない」です。ただ、何か勘違いしているかもしれないのでもう少しいろいろ試していただけると助かります。
EMF 以外の場合はパス変形せずに出力してくれたほうがスッキリしますので、採用する場合ば EMF 限定でお願いします。
ところで、肝心の EMF は破線を描けるようになりましたか?
setdash
の再定義より stroke
の再定義のほうがよっぽど素直でしたね… なんで最初 setdash
を再定義しようと考えたのだろう?ところで、肝心の EMF は破線を描けるようになりましたか?
はい,大丈夫です😄
もう一つ面白いことを発見しました。先ほどの stroke
オペレータですが、gs 独自の .dashpath
の代わりに PS 標準の strokepath
を使えばストロークのアウトラインをとれます。
/oldstroke /stroke load def % 以降で一度も使っていないけどまあ保存しておこう ;)
/stroke {strokepath fill} def
これは破線のみならずあらゆるストローク(太さを持った線分)のアウトラインをとり、その中を塗ります(というつもりです)。ただ、なんか見た目が変わっている気がします… 再定義の中身をもっと検討すれば調節できるかもしれませんが。
おおっ,それも朗報です! パスのアウトラインがとれれば,「Wordに貼ったときに線が太くなってしまう」という現象も防げるかもしれません。
どうやら stroke
をstrokepath fill
に機械的に置き換える方法は、一種の常套手段として正解のようですね。例えばここにも登場しますし、他にも検索すると各所で使われていました。
パスのアウトライン化にメリットがあるのなら、それを PDF などの他のベクター画像形式でも適用するとよいかも…と思ったのですが、ついこの前 #66 で gs9.15 以上を極力 pdfwrite 経由のアウトライン化に変更したばかりで、これは諦めざるを得ないかもしれません。とりあえず「アウトライン化 EMF」限定で .dashpath
を適用するのが妥当でしょうか。(あるいはまた専用の経路を増やす=半透明がない画像なら有用?)
/oldstroke /stroke load def
/stroke {strokepath fill} def
を試してみたら,期待以上の結果が得られました!
よくわかっていませんが,pdfiumdrawにかます前にこんなんすればいいんでしょうか? gswin32c -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf -c ".setpdfwrite /oldstroke /stroke load def /stroke {.dashpath [] 0 setdash oldstroke}def" -f in.pdf
pdfiumdrawにかます前にこんなんすればいいんでしょうか?
はい、そういうことです。pdfwrite でも、しかもコマンドラインオプションでも成功するっぽいので、#66 の変更を保持したままパス変形も可能ですね!
ここまで詰めれば「ストロークのアウトライン化 ON」という新機能も可能かもしれませんね。
PDF →[epswrite(.dashpath)]→ EPS →[pdfwrite]→ PDF →[pdfiumdraw]→ EMF
PDF →[pdfwrite(.dashpath)]→ PDF →[pdfiumdraw]→ EMF
PDF →[epswrite(strokepath)]→ EPS →[eps2emf]→ EMF (どうやら .dashpath だとストロークが汚くなるので NG)
PDF →[epswrite(strokepath)]→ EPS →…
PDF →[pdfwrite(strokepath)]→ PDF →…
完全に現状維持(パス変形なし)。
こんなのが思いつくわけですが…もしこれが可能なら、経路をほとんど変えることなくオプション一つ(-c
オプションの中身を増やすかどうか)で制御できますね。
とりあえずEMF生成直前に.dashpathをかますようにしてみました. PDF -(pdftex)-> PDF -(gs -dNoOutputFonts)-> PDF -(gs .dashpath)-> PDF -> EMF としています.(--with-textの時は最初のgsがなくなる.)テキストを保持しない場合はgsが二度起動されてまとめられる気がしますが,ちと面倒なのでまぁこれで.
\begin{tikzpicture}
\draw[dashed](0,0)--(1,0);
\end{tikzpicture}
もきちんと出ますね.これはいい.
とりあえずEMF生成直前に.dashpathをかますようにしてみました.
gs9.10 で試したのですが、pdfiumdraw に入る前の PDF が A4 サイズに戻ってしまいました。gs9.18 で試すと大丈夫でしたので、#66 関連の経路変更の際にどこか失敗しているのだと思います。gs9.18 による破線の変形は成功していました。
Mac 版の変換経路図によると、いままで eps2emf に食わせる EPS は gs でアウトライン化していたはずですが、これをやめて pdftops でテキスト保持のままの EPS が(strokepath fill
が追記されたうえで) eps2emf に渡るということですか?
多分そうですね.複数回試行することにします.(プロセスの間でやりとりするのはやっぱり難しい…….)
複数回試行するものをおいておきましたが,そもそも原因はマルチスレッドで同期をとっていない部分があることな気がしてきたので,それも直しておきました.念のため複数回の試行も行うようにしてあるので,これで安定するのではないかと思います.
紙サイズがだめなのはまだ調べていないです.
Mac 版の変換経路図によると、いままで eps2emf に食わせる EPS は gs でアウトライン化していたはずですが、これをやめて pdftops でテキスト保持のままの EPS が(strokepath fill が追記されたうえで) eps2emf に渡るということですか?
すみません,図のミスです。後で直します。
紙サイズがだめなのはまだ調べていないです.
ありそうなのは EPS から PDF に戻すときに pdfwrite に -dEPSCrop を付いていないとかですかね。ともかく、今日の午後以降にまとめていろいろ試してみます。Mac / Win ともに、ようやくまとまったテストをしてみようと思います。
Mac 版の TeX2img.app を ~/Desktop/te st
に置いて起動して GUI テストしていたところ
$ /Users/macuser/Desktop/te st/TeX2img.app/Contents/Resources/mupdf/mudraw -o "te st.svg" "temp7C759262223F-outline.pdf" 1 2>&1
が何も実行しませんでした。内包プログラムを呼ぶときにクオートされていないことが原因で、アプリ本体が空白パスにある場合に失敗するわけです(上の場合は te を呼んで失敗し、エラーを吐かずに処理終了)。クオートを入れたほうがよいですね。
なるほど,そのケースを忘れていました。 2.1.4 beta 2 を作りました。
mudraw だけでなく eps2emf もですね。
2.1.4 beta 3 です。今度こそ!
EMF 生成の変換経路ですが、beta 3 は
stroke
を再定義]→[eps2emf] → EMFstroke
を再定義]→[eps2emf] → EMFなんだか少し冗長な気がしますが、どうでしょう?
-c
オプションで gs 一発(gs9.15 以上なら pdfwrite と同時・以下なら epswrite と同時)で出来そうですが、手動のほうが楽ということですか?そのあたりは,他の画像形式の生成経路を極力借用しているためにそうなっています。 その冗長性を排除するために,EMF生成の場合だけは入り口からずっと専用経路を通るように設計し直すことにしましょう。
epstopdf を呼んでいるのは,一旦PDFにしてから pdftops にかけることで,後半の経路をgs 9.15 以上と 9.14 以下で共有するためでした。
epstopdf を呼んでいるのは,一旦PDFにしてから pdftops にかけることで,後半の経路をgs 9.15 以上と 9.14 以下で共有するためでした。
なるほど… epstopdf をなんとかしてスキップできないですかね😥
EMF生成の場合だけは入り口からずっと専用経路を通るように
この方針で考えていますが,
でそれぞれ専用の経路を用意せねばならないっぽくて結構大変です……。
epstopdf をなんとかしてスキップできないですかね
あれ、よく見ると遅いのは epstopdf ではなく epswrite でした… なんかたまにログに表示される順番が違っているだけかもしれません。複数ページ処理しているとたまにログの順番が違っていることに気づきました。
そういうことなら、epstopdf はスムーズに進んでいますので、経路自体はこのままでいきましょう。
Processing pages 1 through 1.
Processing pages 1 through 1.
Processing pages 1 through 1.
Processing pages 1 through 1.
Processing pages 1 through 1.
Page 1
Page 1
Page 1
Page 1
Page 1
のようにログがときどき増幅したことがあったような…
それぞれ専用の経路を用意せねばならないっぽくて結構大変です……。
いや,意外とシンプルに実装できるかも?もう少々お待ちください。
EMF生成に専用経路を用意し,#70 にも対応した,Ver. 2.1.4 beta 4 を作成しました。
ちょっととりあえずおいておきます.時間がとれていない……
すみません… 頭が混乱しそうなので Mac 版が理解できてから Win 版をテストさせてください。Mac 版の開発中に少しずつスキームの改善点が出てきていますので、それを踏まえて後日確認します。
(ベータ版は入手しましたので、しばらくはあまり中身を考えずに利用させていただきながら、気づいたときにお知らせする感じです。)
ちょっとずつ手を入れています.とりあえずアニメーション設定のUIを入れました.もう限界だったのでタブを増やしました……
同じURLに上書きしています.
改造版 pstoedit を用いたEMF生成の品質が上がったので,Inkscape を用いた補助ツール eps2emf.app へのリンクを配布サイトから外しました。 あの補助ツールで生成したEMFは,パスにベジエ曲線が使えて綺麗なのですが,Officeに貼り付けるととんでもなくぼけるという致命的な問題がありました。Officeに貼り込めないのならEMFの意義がありませんので,TeX2img本体による改造版 pstoedit を用いたEMF生成機能で十分でしょう。
Win 版をようやく試し始めました。いま気づいている点を挙げます:
gs9.14 以下でアウトライン化 PDF が全く何も描画されない
あーやっぱり……gs 9.18でも古いバージョンの経路にすると出なくて,きちんと古いバージョンならば動くかと無駄な期待をしたのですが.何でなのかわかっていないです.確か-dEPSCropをつけた段階で消えたとおもいます.(その後おえていません.)
確か-dEPSCropをつけた段階で消えたとおもいます.
だとすると、rewriteBB する値が違っているのかなと疑っています。PDF を最初に pdfcrop してそのあと epswrite にかける場合、最初に取得した bb(これが pdfcrop に使われる)では駄目で、再度 bbox を算出する必要が生じます。再算出した bbox で EPS を rewriteBB して -dEPSCrop 付きで PDF に戻す、ならクロップできそうです。
そういえば常にcropするようにしたことを忘れていました……後で直してみます.
たぶんこれで大丈夫かと.
おお、ビンゴでした。クロップ範囲がおかしい件・ロンダリングの件ともに問題なくなりました。.dashpath
も綺麗にできているようです。しかし EMF 出力で
\[
\left( \int _0 ^\infty \frac{\sin x}{\sqrt{x}} dx \right) ^2
= \sum _{k=0} ^\infty \frac{(2k)!}{2^{2k} (k!)^2} \frac{1}{2k+1}
= \prod _{k=1} ^\infty \frac{4 k^2}{4 k^2 - 1}
= \frac{\pi}{2}
\]
破線のテストです。
\begin{tikzpicture}
\draw[dashed](0,0)--(1,0);
\end{tikzpicture}
が、画像の右のほうが消えてなくなってしまいました。
画像の右のほうが消えてなくなってしまいました。
TeX2img Win 1.6.8 に同梱されている pdfiumdraw はちゃんと描画できましたが、いま Onedrive にある pdfiumdraw は右端が消えるということに気づきました。
pdfium自身は,Debug版はパッチがあたっていない状態でビルドされてしまっていたようです.リビルドしました.
.dashpath,Ghostscirptの9.20あたりで消えたみたいです./stroke {strokepath fill} def
に変更するのが落としどころでしょうか.変なことにならないかな.
消えたんですか…。おっしゃる通りそれが最善だと思います。
57 で話題に出た「破線の見た目が EMF でおかしい」という問題の解決策を考案しました(調査レポート)。Ghostscript 独自に拡張された PostScript operator のひとつである
.dashpath
を使います。以下の2行のコードを PS / EPS ファイルの冒頭に加え、出来上がった PS / EPS を gs の eps(2)write または pdfwrite デバイスに通します:
追記 (2015-12-06) より強力な方法を見つけました(出典)。上記の2行ではなく、下記の2行を PS / EPS ファイルの冒頭に加えます:
すると、元のファイルにあった“空でない破線配列 (dash array) を適用した一本の線分を描画する命令”は、新しいファイルでは“空の破線配列を適用したバラバラの線分を描画する命令”に置き換わります。こうすると、EMF 変換しても破線の見た目が保たれるのではないかと期待しています。
Windows 版はだいぶ状況が改善して EMF でも破線が綺麗に出てくる場合が増えたようですが、Mac 版は特に破線が苦手だったと思います。上の方法を使って、EMF 出力の場合だけ
のようにすればうまくいくかもしれません。ただし、任意の PS / EPS ファイルで上記の再定義法が適用できるかは未確認です。