Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TikZのパターンがSVG化の際に欠ける #64

Closed
doraTeX opened this issue Nov 25, 2015 · 159 comments
Closed

TikZのパターンがSVG化の際に欠ける #64

doraTeX opened this issue Nov 25, 2015 · 159 comments

Comments

@doraTeX
Copy link
Owner

doraTeX commented Nov 25, 2015

現象

次のソースを TeX2img でSVG化すると,パターンが欠ける。

\documentclass[dvipdfmx]{article}
\usepackage{tikz}
\usetikzlibrary{patterns}
\pagestyle{empty}
\begin{document}
\begin{tikzpicture}
\filldraw[pattern = north east lines] (0,0) rectangle (5,5);
\end{tikzpicture}
\end{document}

# 原因

#34 で,mudraw の最新バージョン対応のために -l オプションを外したことが原因。
TeX2img.app に内包されている旧バージョンの mudraw は -l オプションを受け入れる。#34 の改修前のように,-l を付けておけば,パターンも無事に保持される。

# 対策

GUI版については,.app に内包されている旧バージョンの mudraw を使っているので,-l を付けるように戻せばよいだろう。
CUI版については,

  • GUI版がインストールされている場合はその中の mudraw を優先的に使い,-l オプションを付ける。
  • GUI版がインストールされておらず,新バージョンの mudraw のみインストールされている場合は,やむなく -l なしで実行する。

とするのが最善か?

# 検討事項

新バージョンの mudraw でも旧バージョンの -l に相当することはできないものか?

@doraTeX doraTeX added the bug label Nov 25, 2015
@doraTeX
Copy link
Owner Author

doraTeX commented Nov 25, 2015

#34 で,mudraw の最新バージョン対応のために -l オプションを外したことが原因。
TeX2img.app に内包されている旧バージョンの mudraw は -l オプションを受け入れる。#34 の改修前のように,-l を付けておけば,パターンも無事に保持される。

いや,どうもそういう単純な話でもないようで,マシンを変えてみると再現性がなかったりする模様……。
再現条件をもう少し細かく調べてみないと原因・対策は分からない。

@doraTeX
Copy link
Owner Author

doraTeX commented Nov 25, 2015

-l の有無は無関係だった模様。
ソースのコンパイルを,standalone クラスを使うか preview パッケージを使うかして tikpicture だけを切り出したPDFを出力するようにしておけば,斜線パターンが保持されることを発見。
standalone / preview をかませることで mudraw が扱いやすい PDF が生成されるようだが,詳細は不明……。

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

#68 の方法を応用することで,この問題も解決できそうです。

現状,gs 9.15 以上での pdfwrite を用いたアウトライン化SVG生成は

pdfwrite でアウトライン化PDF生成 → mudrawでSVG変換

としていますが,これを

eps2write(または pdfwrite + pdftops)でアウトライン化EPS生成 → EPSの冒頭に /oldstroke /stroke load def stroke {strokepath fill} def を追加 → epstopdf でPDFに戻す → mudrawでSVG変換

という経路を経れば,patternsライブラリによるパターンのアウトライン化が可能でした。

できればEPSを経由しない方が望ましいのですが……。
pdfwrite のときに一緒に /oldstroke /stroke load def stroke {strokepath fill} def をできないものでしょうか。

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dNoOutputFonts -sOutputFile=out.pdf -dAutoRotatePages=/None -c ".setpdfwrite /oldstroke /stroke load def /stroke {strokepath fill} def" -f in.pdf

では Syntax error になってしまいました。

GPL Ghostscript 9.18 (2015-10-05)
Copyright (C) 2015 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Error: /syntaxerror in -file-
Operand stack:
   stroke
Execution stack:
   %interp_exit   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   --nostringval--   --nostringval--   false   1   %stopped_push   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push
Dictionary stack:
   --dict:1193/1684(ro)(G)--   --dict:0/20(G)--   --dict:79/200(L)--
Current allocation mode is local
GPL Ghostscript 9.18: Unrecoverable error, exit code 1

@aminophen
Copy link

あれれ、この話のときは pdfwrite で出来ていたのですが…

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

実はその話のときも,自分は一度も「pdfwrite と同時のパスのアウトライン化」というものに成功したことがありませんでした……。
自分が何か勘違いしているのか,MacとWindowsの違いなのか……?

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

現状の変換経路では,「パスのアウトライン化」を行うのは,改造版 pstoedit にかける直前の EPS に対してのみとなっていますので,「pdfwrite と同時のパスのアウトライン化」の必要は幸い生じておりませんでした。
ですが,SVG出力などにおいてもパスのアウトライン化を行っておく方が無難ということになれば,「pdfwrite と同時のパスのアウトライン化」の手法をきちんと確立しておいた方がよさそうですね。

@aminophen
Copy link

いま Mac で .dashpath のやつ(=破線のストロークを実線のストロークに分割)を試しましたが、これは Windows と同じで可能でした。

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf -c ".setpdfwrite /oldstroke /stroke load def /stroke {.dashpath [] 0 setdash oldstroke}def" -f in.pdf 

あれれ…とよくみたら @doraTeX さんのコマンドは stroke/stroke になっていないじゃないですか!

 /oldstroke /stroke load def stroke {strokepath fill} def

ではなく

 /oldstroke /stroke load def /stroke {strokepath fill} def

が正しいです。

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf -c ".setpdfwrite /oldstroke /stroke load def /stroke {strokepath fill} def" -f in.pdf 

@aminophen
Copy link

OS によらず pdfwrite / eps(2)write で -c オプションを使えばパスのアウトライン化や破線ストロークの分割が一発で可能なことを確認しました。これで安心です。

ところで、ここで触れたように、PDF などの形式でもストロークをアウトライン化する選択肢があってもよいかもと思っています。仮にこれを付けた場合、SVG もその設定状態に応じて変えるというのがよいでしょうか。

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

pdfwrite のときに一緒に /oldstroke /stroke load def stroke {strokepath fill} def をできないものでしょうか。

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dNoOutputFonts -sOutputFile=out.pdf -dAutoRotatePages=/None -c ".setpdfwrite /oldstroke /stroke load def /stroke {strokepath fill} def" -f in.pdf

あれれ…とよくみたら @doraTeX さんのコマンドは stroke が /stroke になっていないじゃないですか!

すみません,1回目の方ではコピペをミスしました。
ですが,2回目のコマンドラインの方では正しく /stroke となっており,こちらの実験も /stroke で行っています。

Ghostscript のバージョンはいくつで実験しておられますでしょうか。
こちらでは,

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dNoOutputFonts -sOutputFile=out.pdf -dAutoRotatePages=/None -c ".setpdfwrite /oldstroke /stroke load def /stroke {strokepath fill} def" -f in.pdf

は,gs 9.16 (MacPorts) では成功,9.18(Richardのページで配布しているものを美文書インストーラ方式でインストールしたもの)では上記のエラー,という結果になっています。

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

なお,gs 9.16 では,stroke 改変付き pdfwrite 自体はとおるものの,それを mudraw にかけてもやはりパターンが欠けます。

gs 9.16 の環境で,in.pdf (テキスト保持PDFとして切り出したもの)に対して以下の一連のコマンドを実験してみました。

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out1.pdf -c ".setpdfwrite /oldstroke /stroke load def /stroke {strokepath fill} def" -f in.pdf 
/Applications/TeX2img.app/Contents/Resources/mupdf/mudraw -o out1.svg out1.pdf

gs -dNOPAUSE -dBATCH -sDEVICE=eps2write -sOutputFile=out2.eps -dCompressPages=false -dASCII85EncodePages=true -f in.pdf 
echo "/oldstroke /stroke load def /stroke {strokepath fill} def" | cat - out2.eps > out2-modified.eps
epstopdf -outfile=out2.pdf out2-modified.eps 
/Applications/TeX2img.app/Contents/Resources/mupdf/mudraw -o out2.svg out2.pdf

/Applications/TeX2img.app/Contents/Resources/pdftops/pdftops -eps in.pdf out3.eps
echo "/oldstroke /stroke load def /stroke {strokepath fill} def" | cat - out3.eps > out3-modified.eps
epstopdf -outfile=out3.pdf out3-modified.eps 
/Applications/TeX2img.app/Contents/Resources/mupdf/mudraw -o out3.svg out3.pdf

この実験では,pdftops を経由する out3.svg のみでパターンが保持されました。

@aminophen
Copy link

gs 9.16 (MacPorts) では成功,9.18(Richardのページで配布しているものを美文書インストーラ方式でインストールしたもの)では上記のエラー,という結果になっています。

すみません、gs9.18 はソースからのビルドが Mac で通らず試せなかったため gs9.16 オンリーで実験していました。gs9.18 での実験はビルド環境が整っている Windows であとで試してみます。

gs 9.16 では,stroke 改変付き pdfwrite 自体はとおるものの,それを mudraw にかけてもやはりパターンが欠けます。

確かに SVG になったときにパターンがみえるのは out3.svg だけですね。out3.pdf をよくみると、パターンにカーソルをあてると文字のように選択できて xxxxxxxx... となります。不思議。

どちらももう少し調べてみます。

@aminophen
Copy link

よく考えたら私の Lion ならマスクメロン版 Ghostscript.app が使えるなと思って、gs9.18 を入手することに成功しました。ところが

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dNoOutputFonts -sOutputFile=out.pdf -dAutoRotatePages=/None -c ".setpdfwrite /oldstroke /stroke load def /stroke {strokepath fill} def" -f in.pdf

はエラーなく終了しました(できたファイルは gs9.16 のものと同じ見た目)。

Error: /syntaxerror in -file-
Operand stack:
   stroke

が再現しません。あれ?

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

美文書方式でインストールした gs 9.16 の環境でも同じエラーが発生しました。
どうやら,バージョンではなくインストールの仕方が影響しているようです。

@aminophen
Copy link

美文書方式でインストールした gs 9.16 の環境でも同じエラーが発生しました。
どうやら,バージョンではなくインストールの仕方が影響しているようです。

えっ… それは困りました… 美文書では gs のライブラリのどれかが正しく読まれなくなっている可能性があるということですよね?

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

美文書インストーラでは,/Applications/TeXLive/mactexaddons/share/ghostscript/9.16 以下に Resourcesfonts など一式を入れます。
そして,MacTeX のインストーラが /usr/local/bin に入れようとするファイル一式(gs実行バイナリやps2pdf など)を,/Applications/TeXLive/mactexaddons/bin に入れます。
そして,/Applications/TeXLive/mactexaddons/bin に,gs という名で次のスクリプトを設置します。

#!/bin/bash

GHOSTSCRIPT_PREFIX=${MACTEXADDONS_PREFIX:-/Applications/TeXLive/mactexaddons}

case $(uname -m) in
    x86_64) __gs=${GHOSTSCRIPT_PREFIX}/bin/gs-noX11-64Bit;;
    *)      __gs=${GHOSTSCRIPT_PREFIX}/bin/gs-noX11;;
esac

$__gs \
    -I ${GHOSTSCRIPT_PREFIX}/share/ghostscript/9.16/Resource/Init \
    -I ${GHOSTSCRIPT_PREFIX}/share/ghostscript/9.16/Resource/Font \
    -I ${GHOSTSCRIPT_PREFIX}/share/ghostscript/9.16/lib \
    -I ${GHOSTSCRIPT_PREFIX}/share/ghostscript/9.16/fonts \
    -I ${GHOSTSCRIPT_PREFIX}/share/ghostscript/fonts \
    $@

これにより,/usr/local/bin を汚さずに済んでいます。
しかし,gsのバイナリ自体は,/usr/local/bin/usr/local/share を参照するようにビルドされており,この gs 呼び出しスクリプトでは,-I でそれにパスを追加して gs を機能させているのですが,この偽装が -c .setpdfwrite には通用しないのかもしれません。

@aminophen
Copy link

aminophen commented Dec 11, 2015

なるほど… だとすると美文書の gs はひょっとして .setpdfwrite パラメタが効かない(たとえば ps2pdf が不十分な PDF を吐き出す)可能性があるのではないでしょうか?

ところで -c というのは gs のインタフェースにない PostScript のパラメタをいろいろ実行するためのもので、「.setpdfwrite」とか「/stroke の再定義」とかがそれぞれパラメタです。.setpdfwrite というパラメタが何をやっているのかは忘れてしまいましたが、pdfwrite するときに付けたほうがよいパラメタをまとめて与えるための何かだった気がします(gs のドキュメントによるとパフォーマンスが上がるとかなんとかなのでたいしたことはなさそうですが)。

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

なるほど… だとすると美文書の gs はひょっとして .setpdfwrite パラメタが効かない(たとえば ps2pdf が不十分な PDF を吐き出す)可能性があるのではないでしょうか?

その可能性はありますが,通常のPSファイルに対する ps2pdf であれば,問題なくPDFが出力できています。(美文書インストーラを作成したときにもテストは行いました。)

@aminophen
Copy link

.setpdfwrite の効果はパフォーマンスが上がる程度と gs のドキュメントに書かれていますので、たかだかその程度で済んだというところだと思います。

美文書だけのために pdfwrite に /stroke の再定義を封じられるのは変なので、美文書の gs サポートは諦めるほかない気がします。バイナリを /Applications/TeXLive/mactexaddons に抱え込む前提であれば、それにあわせて rebuild するべきだったということでしょうか…

@aminophen
Copy link

なんとか美文書のような特殊な方法でインストールされた gs でも -c による拡張を使える方法があればよいわけですね(-c による拡張を全面的に封じられているとすればそれはかなりまずい)。美文書環境の再現法はこれでわかりましたので試すことはできますが、見込みは薄いです。

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

うーん,自分が美文書gsユーザであることもあり,美文書gsの利用を封じられるのは厳しいです……。
それよりは,EPS経由のルートを利用し,pdfwrite でのパスのアウトライン化を行うのを回避する方がありがたいです。

バイナリを /Applications/TeXLive/mactexaddons に抱え込む前提であれば、それにあわせて rebuild するべきだったということでしょうか…

インストール先をインストーラで柔軟に変更できる設計にするために,「MacTeXのgsビルド+ラッパースクリプト」という構成をとっていました。

@aminophen
Copy link

aminophen commented Dec 11, 2015

インストール先をインストーラで柔軟に変更できる設計にするために,「MacTeXのgsビルド+ラッパースクリプト」という構成をとっていました。

そういえば Unix 的インストールと Mac 的インストールがありましたね。それだとしょうがないか…

EPS経由のルートを利用し,pdfwrite でのパスのアウトライン化を行うのを回避する方がありがたいです。

ではその方向で進めましょう。

-c による拡張を使えるようにする回避策」の探索も、別の task として後々考えることとします。

@aminophen
Copy link

aminophen commented Dec 11, 2015

-c による拡張を使えるようにする回避策」の探索も、別の task として後々考える

早速できてしまいました。ただし一手間かかります。この方法は、gs のドキュメントに書かれている -c オプションの解説に登場する equivalent な方法です。

たとえば、以下を pdfLaTeX でコンパイルして出てくる dash.pdf を stroke から strokepath fill に変換することを考えます。

% dash.tex
\documentclass{article}
\usepackage{tikz}
\pagestyle{empty}
\begin{document}
\begin{tikzpicture}
\draw[dashed](0,0)--(1,0);
\draw[dashed](2,0)--(1,1);
\end{tikzpicture}
\end{document}

この場合、次の内容の set-strokepath.ps ファイルを適当な場所に置きます:

.setpdfwrite /oldstroke /stroke load def /stroke {strokepath fill} def

そして、コマンドは以下のようにします(gs-bibun というのは先ほどの教えていただいたシェルスクリプトです):

$ gs-bibun -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dNoOutputFonts -sOutputFile=dash-out.pdf -dAutoRotatePages=/None /path/to/set-strokepath.ps dash.pdf

そうすると、出てくる dash-out.pdf はストロークのアウトラインがとられた状態になります。

コマンドの見た目は以前に登場した「gs で PDF / PS / EPS を結合する」と同じですが、PS にページ描画命令が入っていないため、以上の作業が可能になります。

もちろん

$ gs-bibun -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dNoOutputFonts -sOutputFile=out.pdf -dAutoRotatePages=/None -c ".setpdfwrite /oldstroke /stroke load def /stroke {strokepath fill} def" -f in.pdf

を実行すると

GPL Ghostscript 9.18 (2015-10-05)
Copyright (C) 2015 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Error: /syntaxerror in -file-
Operand stack:
   stroke
Execution stack:
   %interp_exit   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   --nostringval--   --nostringval--   false   1   %stopped_push   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push
Dictionary stack:
   --dict:1193/1684(ro)(G)--   --dict:0/20(G)--   --dict:79/200(L)--
Current allocation mode is local
GPL Ghostscript 9.18: Unrecoverable error, exit code 1

を再現することもできていますので、gs-bibun を作成したテスト法は合っているつもりです。

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

そういえば Unix 的インストールと Mac 的インストールがありましたね。

「Mac風」「Unix風」の2つのテンプレートを選べるほか,そのテンプレートを土台として,テキストボックスの内容を書き換えることで,インストール先はユーザが任意にカスタマイズできるようになっています。
そういう事情で,ラッパースクリプトが必須となるわけです。

外部 ps を経由する方法でうまくいくことは確認できました。
これで「美文書 gs では -c を用いたカスタマイズができない」という問題を回避することができて幸いでした。

ただし,

gs 9.16 では,stroke 改変付き pdfwrite 自体はとおるものの,それを mudraw にかけてもやはりパターンが欠けます。

確かに SVG になったときにパターンがみえるのは out3.svg だけですね。out3.pdf をよくみると、パターンにカーソルをあてると文字のように選択できて xxxxxxxx... となります。不思議。

という問題は依然として変わりませんでした。

美文書方式 gs 9.18 + 外部 ps 方式で pdfwrite で in.pdf をアウトライン化し,それを mudraw で svg にしても,SVG上はやはりパターンが欠けてしまいました。

そもそも,mudraw にかける以前の問題として,

gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dNoOutputFonts -sOutputFile=dash-out.pdf -dAutoRotatePages=/None stroke.ps in.pdf

によって生成する dash-out.pdfを Illustrator で開くと,次のようになり,見た目が全く異なります。

2015-12-11 19 29 13

そして,この模様の部分はアウトライン化されていません。

つまり,

.setpdfwrite /oldstroke /stroke load def /stroke {strokepath fill} def

では,「パスのアウトライン化」は可能でも,「塗りパターンのアウトライン化」はできていないことが分かります。

「塗りパターンのアウトライン化」を行う PostScript コードはあるのでしょうか?

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

dash-out.pdf を Illustrator で開くと,次のようになり,見た目が全く異なります。

そもそも,最初の in.pdf 自体が,Preview / Acrobat で開いた場合(斜線に見える)と,Illustrator で開いた場合(斜め破線に見える)で見た目が違いますね……。

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

以前言及したように,previewパッケージを経由しておく方法も試してみました。

\documentclass[dvipdfmx]{article}
\usepackage{tikz}
\usetikzlibrary{patterns}
\pagestyle{empty}
\usepackage[dvipdfmx,tightpage,active]{preview}
\PreviewEnvironment{tikzpicture}
\begin{document}
\begin{tikzpicture}
\filldraw[pattern = north east lines] (0,0) rectangle (5,5);
\end{tikzpicture}
\end{document}

生成PDF :in-preview.pdf

  • Preview / Acrobat で開いた場合の見え方(斜線に見える)と,Illustrator で開いた場合の見え方(斜め破線に見える)は in.pdf と同様。
  • mudraw にかけても塗りパターンは保持される。(ただし微妙につなぎ目が欠けて見える)

2015-12-11 20 08 02

@aminophen
Copy link

外部 ps を経由する方法でうまくいくことは確認できました。
これで「美文書 gs では -c を用いたカスタマイズができない」という問題を回避することができて幸いでした。

これは奥村先生に一応お伝えしておいたほうがよいと思いました。あとでこちらから伝えておきます。(そもそも今まで上がってこなかったということは、gs の猛者は美文書ユーザにいなかった?)

パターンが変わるという問題は、なんだか mudraw のせいではなさそうなので、あとでそれも調べてみます。(昨日アドベントカレンダーの記事を書き始めたばかりで間に合わせるのに必死です…)

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

このgsのパッケージングを行ったのは山本さんなので,山本さんにもご一報を入れる必要があるでしょうね。

@doraTeX
Copy link
Owner Author

doraTeX commented Dec 11, 2015

あと,もちろん著者であられる黒木さんにも。

@aminophen
Copy link

そうなのですね。では山本さんにもお知らせしておきます。もちろん黒木さんも。

@aminophen
Copy link

Mac 版の EMF については、この方法が最善なのだろうという結論です(出力はこれ)。再掲すると

EMF 出力;gs 9.15 以上の場合

TeX → PDF →[pdfTeXでクロップ+余白付与]→ PDF(ここで Quartz API で背景塗り&ロンダリング)→[gs pdfwrite]→ アウトライン化PDF →[pdftops]→ EPS →[stroke修正処理を仕込んでからpstoedit]→ EMF

  • 必要条件である「テキスト部分のアウトライン化」と「eps2emf 入力用 EPS の準備(ストローク修正済み)」を満たしています(パターンだけ Type3 フォントのまま)。
  • pdftops によって Type3 フォントでエミュレートした文字はそのまま eps2emf に渡るため、アウトライン化による変色を防止できています。Type3 フォントが残ってはいますが、ストローク修正は済んでいるため見た目は同じになります。
  • 逆に、パターンから変換された Type3 フォントをアウトライン化しようとするとビットマップ化してしまう危険がありますが、これも防止できています。

EMF 出力;gs 9.15 未満の場合

TeX → PDF →[pdftops]→ EPS →[stroke修正処理を仕込んでからepstopdf]→ PDF →[pdfTeXでクロップ+余白付与]→ PDF(ここで Quartz API で背景塗り&ロンダリング)→[gs epswrite]→ EPS →[pstoedit]→ EMF

  • 必要条件である「テキスト部分のアウトライン化」と「eps2emf 入力用 EPS の準備(ストローク修正済み)」を満たしています(しかもパターンもアウトライン化済み)。
  • pdftops で最初に Type3 フォントでエミュレートしてはいますが、ストローク修正の結果としてその後のアウトライン化でも変色しない効果が得られるようです。
  • 細かいパターン塗りが存在する状態で epswrite を先にかけてしまうと、epswrite がパターンをビットマップ化してしまいます。ビットマップ化してしまうと pstoedit がビットマップは駄目だと警告を吐いてパターンを消してしまうのですが、pdftops とそれに続く stroke 修正処理によってどうやらビットマップ化を防げるようです。

「ストローク修正の結果としてその後のアウトライン化でも変色しない効果が得られる」というのは新しい知見のようです(この変色は、通常のフォントが fill で描かれているのに対してエミュレートの Type3 フォントは stroke で描かれていることが原因;すなわち「Type3 フォントでエミュレートした場合は必ず stroke 修正を行うべき」)。「pdftops とそれに続く stroke 修正処理によってどうやらビットマップ化を防げる」というのも新しいかも。

@aminophen
Copy link

いま、PDF のアウトライン化のベストプラクティスを考えています。すぐ上の Mac 版 EMF 出力で得た知見をもとに考えると、「gs9.15 未満でパターンがどうしてもビットマップ化してしまう」という問題を防ぐには以下のようにする必要がありそうです:

アウトライン化 PDF 出力;gs 9.15 以上の場合

TeX → PDF →[pdfTeXでクロップ+余白付与]→ PDF(背景塗り&ロンダリング)→[gs pdfwrite]→ アウトライン化PDF

  • 要するに、現状の変換経路です。
  • この変換経路ではパターンは完全に元のパターンのまま残ります。
  • 上記のアウトライン化 PDF から別の形式に変換する際に
    • 破線に困る場合は、上記に続いて pdfwrite で .dashpath をかませます。
    • 破線にもストロークにも困る場合は、上記に続いて pdfwrite で strokepath をかませます。

PDF 出力の場合、pdftops を通してしまうと勝手に Type3 フォントでエミュレートされてしまうのでパターンが失われて不都合です。したがって、パターンを残せる上記の経路が妥当でしょう。

アウトライン化 PDF 出力;gs 9.15 未満の場合

TeX → PDF →[pdftops]→ EPS →[stroke修正処理を仕込んでからepstopdf]→ PDF →[pdfTeXでクロップ+余白付与]→ PDF(背景塗り&ロンダリング)→[gs epswrite]→ EPS →[epstopdf]→ PDF

  • 現状の変換経路とは異なります。
  • 細かいパターン塗りが存在する状態で epswrite を先にかけてしまうと、epswrite がパターンをビットマップ化してしまいます。すなわち、パターンをパターンのまま保持することは不可能です。そこで、pdftops とそれに続く stroke 修正処理によってビットマップ化を防止する方がメリットが大きいと思われます。(ただし、他の副作用がないかどうかは未確認)
  • 上記のアウトライン化 PDF から別の形式に変換する際には、既に strokepath をかませているためこのまま他の形式に変換できます。

アウトライン化 PDF 出力;gs 9.15 未満の場合(次善の策)

TeX → PDF →[pdfTeXでクロップ+余白付与]→ PDF(背景塗り&ロンダリング)→[gs epswrite]→ EPS →[epstopdf]→ PDF

  • 要するに、現状の変換経路です。
  • この変換経路ではパターンはビットマップ化されてしまいますが、pdftops なしでは gs のアウトライン化失敗を受け入れるほかはないでしょう。
  • 上記のアウトライン化 PDF から別の形式に変換する際に
    • 破線に困る場合は、上記に続いて pdfwrite で .dashpath をかませます。
    • 破線にもストロークにも困る場合は、上記に続いて pdfwrite で strokepath をかませます。

古い gs でもパターンをアウトライン化できた方がよければ pdftops を使うのがよさそうですが、「古い gs のバージョンではパターンは今はサポート外」としてしまうのも一理あると思っています。gs 単独で「ビットマップ化されない安全なテキストのアウトライン化」を実現できればむしろ pdftops を使わない方がベストになるはずですし、もう少し真面目に探してみます。

@abenori
Copy link

abenori commented Dec 23, 2015

こちらはpdfiumdraw直接の線でそのまま考えていますが,いろいろ試しても外の塗りは出ないので,いったんあきらめます…….状況が起こりにくくなるように,--scale=10をはずそうかと.ちと不便ですが,きちんと描画されないよりはましなので.または解像度レベルにあわせるかなぁとも思っていますが.

@aminophen
Copy link

状況が起こりにくくなるように,--scale=10をはずそうかと.ちと不便ですが,きちんと描画されないよりはましなので.または解像度レベルにあわせるかなぁとも思っていますが.

EMF はだいぶしんどいですね… いろいろ試していただいてありがとうございます。--scale=10 を外すと右上が消えやすくなるという話は余白機能で対処することにします。

@abenori
Copy link

abenori commented Dec 23, 2015

https://onedrive.live.com/redir?resid=4FABCB4EC4FA1E70!16825&authkey=!ANYoMX5Yq7PLXU4&ithint=folder%2cexe

今のところの最新をおいておきます.だめなことがわかっているの以外は大丈夫そうですが,もう少しテストしていったん出します.(たぶん今年最後……)何か気がついたことがあれば.

@aminophen
Copy link

あけましておめでとうございます。本年もよろしくお願いいたします。

時間が空いてしまいましたが、SVG への対応については

SVG を「PDF 生成経路に続いて“パッチ適用 mudraw”に通す」ほうがわかりやすいと思いました。

確かに,pdftops の極めてデリケートな性質に依存するよりも,それによってこの問題を根本的に解決することができれば,それに越したことはありませんね。

Mac での mudraw のビルドに成功したら教えてください……😓

Mac 版の mudraw のビルドと変換経路を元に戻すという話だった気がしましたので、mudraw のビルドを試してみました。Lion 環境で素朴に mupdf-1.7a-source.tar.gz を展開して

$ cd mupdf-1.7a-source
$ make build=release NOX11=yes

とすると一応ビルドは通るみたいです。できた mudraw を otool で見ると依存ライブラリは

  • /usr/lib/libSystem.B.dylib
  • /usr/lib/libcrypto.0.9.8.dylib

でした(ということは port には依存していないようだが、libcrypto がまずい…? どうすればよいのでしょう)。ソースに abenori さんのパッチ svg-device.patch をあてればパターンの translate が直るということのようです。なお、mupdf-1.8-source.tar.gz で同じことをやろうとするとなぜか X11 を無効にできず、Makerules の HAVE_X11 ?= yes のところを no に変えて

# Mac OS X doesn't have pkg-config so we hard code paths.
else ifeq "$(OS)" "MACOS"

HAVE_X11 ?= no
HAVE_GLUT ?= yes

としたらビルドは通りました。(mutool というのしかできませんが、単に mudraw の機能が mutool に統合されただけですので、リネームまたはシンボリックリンクで mudraw にできます)。

ちなみに、PDF → PDF の文字アウトライン化を PostScript 藝で試そうとしましたが、どうもうまくいきません。素直に考えれば showtrue charpath fill に再定義すればよいはずなのですが、(EPS の冒頭への追記ならうまくいく場合もありますが)PDF への作用はできないようでした。

@doraTeX
Copy link
Owner Author

doraTeX commented Jan 7, 2016

あけましておめでとうございます。
昨年は大変お世話になりました。本年も TeX2img をよろしくお願いします。

さて,mupdf のビルド法の調査ありがとうございます。
お陰様で,こちらでもビルドに成功し,Ver. 2.1.5 beta 9 が完成しました。

新機能

  • SVGの生成経路を,gs 9.15 以上・未満どちらについても,Ver. 2.1.4 のときの変換経路図のものに復元しました。
  • mudraw を「mupdf 1.8 + パッチ」のものに変更しました。その結果,テキスト保持・アウトライン化のどちらについても,パターンの保持が可能になりました。
  • 従来は MacPorts 由来の libcrypto (Ver. 1.0.0) に依存していたのでそれを同梱していましたが,今回のビルド法だとシステム標準の libcrypto (Ver. 0.9.8) を利用できるようになったので,libcypto の同梱をやめました。その結果,TeX2img.app のサイズを 2MB 削減することに成功しました。
  • SVGZ形式での出力に対応しました。(SVGZ形式での出力 #73)
  • ~ が入った入出力パスに対応しました。(GUI版の入出力パスにおいて ~/Desktop/ のようなパス表記を許す #72)
  • 文字情報パネルを微修正しました。
    • 一文字の情報を表示する際に,Unicodeブロック名を表示するようにしました。
    • タブやリターンなどの制御文字の情報を表示させたとき,制御文字名が正しく表示されるようにしました。

これで,SVGパターン塗り問題が一気に解決したのではないでしょうか。😄
まだテストが不十分なので,要テストですが。

@aminophen
Copy link

Ver. 2.1.5 beta 9 を試しました。libcrypto がなくなって軽くなったのでよかったです😃 SVGZ 形式での出力、~ が入った入出力パス、文字情報パネルの改善は確認しました。

結局、本トピックで経路としては変わったのは EMF だけということですね。アウトライン化 PDF / SVG のパターン塗りが gs9.15 未満でたまにビットマップ化されるのは対処が面倒だし、Win/Mac ともにしょうがないということで。

mupdf のパッチ版が translate 修正に成功しているかどうか今手元ではわかりません… 後で出来たSVG を Windows に持っていってチェックします…(ビルド済み dmg で配布されている Inkscape 0.91 が Lion でクラッシュ&MacPorts のは依存ライブラリ libvisio-0.1 のビルドで落ちる😥)

@abenori
Copy link

abenori commented Jan 7, 2016

2 * sdev->tiles->step.y

というところがいい加減(特に根拠無し)なので,きちんと考えた方が良いかもしれないです.たぶん塗りつぶし一つ一つの高さぴったりにするのが良いのですが,sdev->tiles->step.yはそれよりちょっと小さい気がしています.

@doraTeX
Copy link
Owner Author

doraTeX commented Jan 8, 2016

ちなみに,前回 mupdf のビルドができなかったのは,El Capitan で OpenSSL のヘッダファイルが提供されなくなったことが原因だったようです。
今回は,Snow Leopard を入れた仮想マシン上でビルドすることで成功しました。

@doraTeX
Copy link
Owner Author

doraTeX commented Jan 8, 2016

なお,あべさんのおっしゃっていた

とりあえずmupdf\source\pdf\pdf-on-run.cのTILEの#defineを外してやるとタイルの繰り返しを展開してたくさんのパスとして処理してくれるようになるようです.

この方法でやると,パターンがアウトライン化されて,斜線のつなぎ目が綺麗になりますね。
その代わり,ファイルサイズが激増します。

パターンのアウトライン化をしない場合

2016-01-08 11 31 29

- 斜線のつなぎ目が見える - ファイルサイズ 62KB - レンガは綺麗

パターンのアウトライン化をした場合

2016-01-08 11 31 42

- 斜線のつなぎ目が見えず綺麗 - ファイルサイズ 633KB - レンガの模様に微妙につなぎ目が見える

これらの結果は,Safari, Chrome, Firefox のいずれでも同様でした。

どちらがよいでしょうか……。

@aminophen
Copy link

PDF / PS のパターンは本来 SVG のパターンへと変換されるべきで、MuPDF がパターンの分割をバグ認定したうえで修正したのは妥当でしょう。これを昔のものに戻すのは良くないと思います。

@doraTeX
Copy link
Owner Author

doraTeX commented Jan 8, 2016

なるほど,そうでした。
では,テスト結果も概ね問題なさそうですので,そろそろ Ver. 2.1.5 のリリースと行きましょうか。

@aminophen
Copy link

端が微妙に切れるのは大した問題ではないと思います。(もしかするとこれと関係?)というわけでリリースよろしくお願いします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants