texjporg / tex-jp-build

Minimum source repository to build Japanese TeX processing tools
23 stars 6 forks source link

[dvipdfm-x] \scalebox の縦組時挙動について #2

Closed aminophen closed 7 years ago

aminophen commented 7 years ago

これは forum:961 に関連したものです。

pTeX の縦書きの場合は、PS/PDF の変形の縦と横を交換する必要がある

のですが、現在の dvipdfmx は PostScript special を使用した場合と PDF 用 special を使用した場合で挙動が異なります(PostScript special のほうが期待される出力)。

簡単な対処として「dvipdfmx.def のマクロにパッチする」という方法が @zr-tex8r さんの pxtatescale.sty にありますが、要するに「元のコードにパッチをあてている」だけですので、あまり本質的ではないように思います。そして、最近気づいたのですが、まさに次期バージョンの dvipdfmx.def ではパッチがあたらなくなってしまうことがほぼ確定のようです (latex3/graphics-def@986048a) から、この際 dvipdfmx の本体で対処を考えてはどうかと思いました。

aminophen commented 7 years ago

素朴に pdf special の解釈をひっくり返してみました。

--- texk/dvipdfm-x/spc_util.c   2016-11-26 03:24:24.000000000 +0900
+++ texk/dvipdfm-x/spc_util.c.fix1  2016-12-06 18:36:13.000000000 +0900
@@ -355,13 +355,29 @@
                   double rotate)
 {
   double c, s;
+  int dirmode, temp_dirmode;

   c = cos(rotate);
   s = sin(rotate);

+  dirmode = pdf_dev_get_dirmode();
+  if (dirmode) {
+    temp_dirmode = 1;
+  } else {
+    temp_dirmode = 0;
+  }
+  switch (temp_dirmode) {
+    case 1:
+  M->a =  yscale * c; M->b = yscale * s;
+  M->c = -xscale * s; M->d = xscale * c;
+  M->e = xoffset;     M->f = yoffset;
+   break;
+    default:
   M->a =  xscale * c; M->b = xscale * s;
   M->c = -yscale * s; M->d = yscale * c;
   M->e = xoffset;     M->f = yoffset;
+   break;
+  }
 }

 static int

このパッチをあてると

にある 2 つのテストソース(から \usepackage{pxtatescale} を削除した状態)でうまくいっているようにみえますが、pTeX 以外で使われた場合とか、他のことはあまり考えていません。

zr-tex8r commented 7 years ago

コレって、「新版のdvipdfmx.def」で通用しているんですか? (何となく、pdf:btrans xscale... に相当するところをパッチしているように見えるので)

aminophen commented 7 years ago

通用しませんね。pdf:literal の解釈を変えるのは危険そうな気がして pdf:btrans xscale... の方にパッチしたのですが、でもそれだと意味がないわけで… 同じ目的に使える \special が複数あるとややこしいですね。マクロの方でなんとかするしかないのでしょうか?

aminophen commented 7 years ago

いろいろ考えましたが、私が最初に掲げた pdf:btrans xscale... に対するパッチは(汚いので refactor してからだと思いますが)適用してよいのではないかと思いました。


dvips.def にある scale 関連の ps: special は、現在の dvipdfmx の mpost.c で対策が施されているため縦組でも正常に動作しています。dvips.def からの抜粋:

\def\Gscale@start{\special{ps:  currentpoint currentpoint translate
  \Gscale@x\space \Gscale@y\space scale neg exch neg exch translate}}
\def\Gscale@end{\special{ps:  currentpoint currentpoint translate
  1 \Gscale@x\space div 1 \Gscale@y\space div scale
  neg exch neg exch translate}}

これは現行の dvipdfmx.def の pdf:btrans xscale... という special と等価なはずです。それなのに、現在の dvipdfmx は「ps: なら大丈夫で pdf: ならダメ」という挙動を示しています。

一方、ps: special を「新 dvipdfmx.def」の pdf:literal special に相当する書式で書き直すと(乗除計算が雑ですがそこは無視することにして)

\makeatletter
\def\Gscale@start{\special{ps:  currentpoint currentpoint translate
  [\Gscale@x\space 0 0 \Gscale@y\space 0 0] concat neg exch neg exch translate}}
\def\Gscale@end{%
  \@tempdima\Gscale@x\p@
  \@tempdimb\Gscale@y\p@
  \edef\@reversedapt{\strip@pt\dimexpr256\p@/\@tempdima*256}% 1/\Gscale@x
  %\typeout{\@reversedapt}% for debug
  \edef\@reversedbpt{\strip@pt\dimexpr256\p@/\@tempdimb*256}% 1/\Gscale@y
  %\typeout{\@reversedbpt}% for debug
  \special{ps:  currentpoint currentpoint translate
  [\@reversedapt\space 0 0 \@reversedbpt\space 0 0] concat
  neg exch neg exch translate}}
\makeatother

これは縦組で失敗します。失敗するという点では嬉しくないわけですが、ps:pdf: も失敗なので互換であるという考え方ができます。

結局「pxtatescale.sty を新 dvipdfmx.def の pdf:literal に合うように書き直して配布、dvipdfmx 本体には xscale が使われた場合に縦組対処を施す」というのが ps:pdf: の互換性という観点からはよいと思うのですが、いかがでしょう。

zr-tex8r commented 7 years ago

そもそも、pdf:btrans って何をするものなのでしょうか? 具体的には、pdf:literal で相応の座標変換(cm)を書くのと何が違う? (まあ、コレを言い出すと永遠に進まなくなる気がするけど…)

zr-tex8r commented 7 years ago

自分の感想としては、 「scale演算子の解釈“だけ”変える」 という処置がとれる、というのがそもそも不思議で仕方がないわけなんですよね。

実際に少し試したところだと、 2 1 scale2 0 0 1 0 0 cm となるべきところを、縦組モードの場合は、 2 1 scale1 0 0 2 0 0 cm のように変えている。でもtranslateとかrotateは影響しないようです。 でも、PostScriptのコードとしては 2 1 scale の代わりに [ 2 0 0 1 0 0 ] concat と書いても等価になるはずです。これはどう扱うべきなのか。あるいは、 [ 2 1 -1 1 42 0 ] concat みたいにもっと複雑な場合はどうなのか。 実際には、dvipdfmxのPS解釈器は、このコードには対応していないようです。

この結果から考えてみると、結局、scaleの解釈だけ変えられるのは、そもそも 「dvipdfmxのPS言語の解釈能力が低くて、その使用場面が限られる」 ことが根拠になっている、ような気がしてきます。要するに、 「dvips.defのコードさえ通ればよい」 と考えた、ということです。

もしこの推定が当たっているとするなら、PDF specialで同様の処置をするのは、 極めて危険な気がします。 PDF specialはもっと広範な目的で使われる余地があるからです。

zr-tex8r commented 7 years ago

一つの例ですが、dvipdfmxでは、 pdf:btrans matrix 1 2 3 4 5 6 のように変換行列を直に書くことができるようです。 これはどのような cm 命令を生成すべきなのでしょうか。

aminophen commented 7 years ago

結局、scaleの解釈だけ変えられるのは、そもそも 「dvipdfmxのPS言語の解釈能力が低くて、その使用場面が限られる」 ことが根拠になっている、ような気がしてきます。要するに、 「dvips.defのコードさえ通ればよい」 と考えた、ということです。

(変え「られる」という言葉は「コードの上で実現可能である」ではなく「結果として得られる全挙動が期待どおりと見込める」という意味ですよね、念のため。)

私のパッチは「コードの上で実現可能である」を pdf: の xscale と yscale に持ち込んだものです。とりあえずそうしてみたのは、ps: について scale 演算子の解釈“だけ”変えていることが、今のところ問題視されていないように思えたからです。

しかし、その前提に、仰るような「dvipdfmxのPS言語の解釈能力が低くて、その使用場面が限られる」という条件があるのだとすれば

もしこの推定が当たっているとするなら、PDF specialで同様の処置をするのは、 極めて危険な気がします。 PDF specialはもっと広範な目的で使われる余地があるからです。

は妥当な主張のように思えてきました。

aminophen commented 7 years ago

dvipdfmx の解釈を変えるのではなく、「新旧の dvipdfmx.def が通るように」を目指した新しい pxtatescale.sty は以下のようになります。

% pxtatescale.sty
\NeedsTeXFormat{pLaTeX2e}
\ProvidesPackage{pxtatescale}[2017/01/16 v0.3]
\def\pxqtg@pkgname{pxtatescale}
\@ifpackageloaded{graphics}{}{%else
  \PackageError\pxqtg@pkgname{Package 'graphics' not loaded}\@ehc}
\begingroup
\def\pxqtg@patch@status{1}%
\def\pxqtg@try@patch#1#2#3{%
  \edef\pxqtg@tempcsname{\string#1}%
  \def\pxqtg@temp{#2}\ifx#1\pxqtg@temp
    \gdef#1{#3}%
    \def\pxqtg@patch@status{0}%
  \fi}
% first trial (new definition)
\pxqtg@try@patch\Gscale@start
  {\special{pdf:btrans}%
   \special{pdf:literal \Gscale@x\space 0 0 \Gscale@y\space 0 0 cm}}
  {\special{pdf:btrans}%
   \special{pdf:literal
   \iftdir \Gscale@y\space 0 0 \Gscale@x\space
   \else   \Gscale@x\space 0 0 \Gscale@y\space
   \fi 0 0 cm}}
\ifnum\pxqtg@patch@status=\z@\else
  % second trial (old definition)
  \pxqtg@try@patch\Gscale@start
    {\special{pdf:btrans xscale \Gscale@x\space yscale \Gscale@y}}%
    {\special{pdf:btrans
      \iftdir xscale \Gscale@y\space yscale \Gscale@x
      \else   xscale \Gscale@x\space yscale \Gscale@y
      \fi}}
\fi
\ifnum\pxqtg@patch@status=\z@
  \PackageInfo\pxqtg@pkgname{Patch applied to \pxqtg@tempcsname}%
\else
  \PackageWarningNoLine\pxqtg@pkgname{Patch cannot be applied to \pxqtg@tempcsname}%
\fi
\endgroup

これを公開する、という方向でよいでしょうか。

aminophen commented 7 years ago

dvipdfmx の挙動は変えないこととし、r43009 で pxtatescale.sty が収録されたので close しましょう。