dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- Yoshihiro AOKI の投稿
返信数: 13
dvipdfmxの仕様についてお伺いさせてください。

下記のTeXソース(このメッセージの末尾)で,\char 3つで「T」「e」「X」と印字されますが(合計3zw),
文字送りがJFMと一致しませんでした。

VFはotfパッケージからお借りしたものです。

具体的には
  ===TeX      ===
のように文字が詰まって印字されます

JFMでは3文字がそれぞれ1zwなので,
  ===T  e  X  ===
となることを想像していました。

これはdvipdfmxの仕様でしょうか。

---
dvipdfmxのvf.cでは0xf2(LONG_CHAR)エントリの文字幅はskip_bytesで捨てており,

  /* Skip over TFM width since we already know it */
  skip_bytes (4, vf_file);

とあります(似たような箇所が複数箇所)。それ以降は私には追いかけられなかったのですが,結果的に3zw進んでいるので直接の原因ではないと思いました。

---
また,論点がずれますが,LONG_CHARエントリのSET2に続けてRIGHTを置いてもRIGHTは必ず無視されるようでした。
  LONG_CHAR
  SET2<XXXX>
  RIGHT3<XXXXXX>
のような並びのときです。

---
さらに,
  LONG_CHAR
  SET2<XXXX>
  SET2<1>
のように本来の文字の後ろにCID 1(空白)を付け足したVFを作ったところ,「TeX」という文字列が「右から左」に印字されるという現象もありました。dvipdfmxのlr_modeはデフォルトでは「右から左」なのでしょうか(RIGHTが効かないこととも関連がありますでしょうか)。

---
いずれにしろ,SET2で(同一フォントで?)非全角文字を連続で置いたとき,JFMの文字幅が1文字ずつ反映されないように思います(JFMの文字幅が反映されるほうが自然だと思います)。

また,VFにあるはずのRIGHT等(スキップ関連?)が無視される理由が分かりません(逆に通常の和文JFMで括弧などが正常に印字されることに対して合致しない挙動のようにも思いますが,頭がこんがらかってしまいました。

主なテストはTeX Live 2021で行い,メッセージ末尾のTeXソースはTeX Live 2023でも確認しました。mapファイルは「ヒラギノ」「リュウミン」1書体ずつで確認しましたが結果は同じでした(埋め込むOpenType依存ではなさそうです)。

TeX Live 2023 (Windows 11, ARM64):
  e-pTeX 3.141592653-p4.1.0-230214-2.6 (utf8.sjis) (TeX Live 2023)
  kpathsea version 6.3.5
  ptexenc version 1.4.3

  This is dvipdfmx Version 20220710 by the DVIPDFMx project team,
  modified for TeX Live,
  an extended version of dvipdfm-0.13.2c developed by Mark A. Wicks.

TeX Live 2021 (macOS Ventura, universal-darwin):
  e-pTeX 3.141592653-p3.9.0-210218-2.6 (utf8.euc) (TeX Live 2021)
  kpathsea version 6.3.3
  ptexenc version 1.3.9

  This is dvipdfmx Version 20210318 by the DVIPDFMx project team,
  modified for TeX Live,
  an extended version of dvipdfm-0.13.2c developed by Mark A. Wicks.

以下,TeXソースです。
---
% encoding: utf-8
\documentclass{jarticle}

\begin{document}

\parindent0zw

\font\f=cidjmr2-h at20pt
\f

===%
\char\jis"4448 % 槌 => T
\char\jis"4459 % 潰 => e
\char\jis"444C % 通 => X
===%

\end{document}
Yoshihiro AOKI への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- Z. R. の投稿

自分はdvipdfmxの開発者ではないので、以下は想像ですが……。

おそらく、dvipdfmxの仕様としては
「(VFではない)TFM/JFMの文字の字幅(tとする)とそれに対応する物理フォントのグリフの字幅(pとする)が食い違うのは想定外(異常状態)であり、その場合の結果は未定義
なのだと思います。

※同様の状況で物理フォントがType1の場合(欧文TFMに限るのかもしれない)は警告が出ます。なのでdvipdfmxがこの状況を異常と見なしているのは確かでしょう。
※OpenTypeの場合に警告を出していない理由は、そもそも「dvipdfmxはOpenTypeのグリフの字幅を読んでいない」からと推測しています。

そしてこの状況での実際の動作としては
「字幅が(pではなく)tの文字を出力したと想定して次の処理に進む。なのでPDFのテキストストリームが続く場合は、その中の以降の文字は(p−t)だけずれる。ストリーム内に字幅が食い違う文字が複数ある場合はずれが蓄積される
となります。

※文字出力(SETCHAR/PUTCHAR)と水平移動(LEFT/RIGHT)のみが連続する箇所は1つのテキストストリームにまとめられます。

なお、VFについては「VFの仕様に従ってDVI命令列に展開」(と同値の動作)をしているはずです。このため、「字幅が食い違っているのをVFで補正する」ことはできません(テキストストリームが続く限りはずれは累積するので)。

Z. R. への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- Z. R. の投稿

「ずれが累積する」のを回避する裏技として、
「TeX側で“文字ではない不可視なもの”を出力することで、テキストストリームを強制的に終わらせる」
という方法があります。一旦テキストストリームを終わらせてしまえば、次に何か出力する際にはページ内絶対位置が指定されるので「ずれ」が解消されるわけです。

ただし“文字ではない不可視なもの”はTeXやdvipdfmxの側で最適化されて消えてしまう可能性があることに注意が必要です。例えば「幅がゼロの罫(\vrule width 0pt)」ではTeXはDVIに何も出力しません。現状のdvipdfmxの実装では「空のPostScript special(\special{ps:})」はテキストストリームを切ってくれるようです。

\font\fA=uprml-h \fA
% \kchar`A でuprml-hの0x65の文字(OpenTypeの'A'のグリフ)
% が出力される. JFM上では全角幅だが実際のグリフ幅は違う.
\par\noindent 
\vrule \kchar`A \kchar`B \kchar`C \vrule
\def\PS{\special{ps:}}% 空のPostScript special
\par\noindent 
\vrule \kchar`A \PS \kchar`B \PS \kchar`C \vrule
\bye
Z. R. への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- Yoshihiro AOKI の投稿
Z. R. さん,詳細の返信をありがとうございます。

TeX ファイルレベルで
・\hskip0mm
・\hskip1sp
はだめで,VFのSET2の後ろに
・XXX ""
・POST
・DIR
などは警告出たりうまくいかないので(VFとはしては異常ですが試してみました),
・XXX "ps:"
かなぁと思っていました。

ただ,JFMを1zwではく本来の文字幅に合わせると,今度は「文字が重なってしまう」(紙面上の「累積」は正しい)のが謎で単純なストリームなら素直に文字が並ぶことを期待してしまいます。\fboxで1文字ずつ囲むと印字は正しいのでJFMのwidthが間違っているようではなさそうでした。PDFストリームの知識もなく,よくわからない現象というのが正直なところです(画像添付)。

dvipdfmxのvf.cのvf_set_char(),dvi.cのset_charを見てみましたがよくわかりませんでした。

余談ですが,OTFパッケージの仮名プロポーショナルのコッソリ版もテストファイルの表示は正常に見えましたが,「累積」を考えると,文章を組んだ際にうまくいかないような気がします(OTFパッケージをきちんとインストールしていないのでテストできていないです)。

---
VFの非全角文字に対して都度「ps:」を入れるとファイルサイズが(さらに)肥大してしまい美しくないですが,使う頻度から考えると現実的な解かもしれません...。
添付 sc01.png
Yoshihiro AOKI への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- 本田 知亮 の投稿
お久しぶりです.人違いならご容赦を

dvips経由でps2pdfでPDFにしてみました.
この状態が期待される形なのかなと思います.

dvipsの作ったPSを読むと,
文字幅を考えて「座標指定,文字」を繰り返していますので
期待のものだ(ずれていない)と思います(絶対的な配置).
dvipsは和文に関しては文字幅を想定して配置してますが
欧文はそうなってない(PSの中で「(abc)」みたいにまとめる)ようです
(相対的な配置).

dvipdfmxは,Z.R.さんご指摘の通り,
和文も欧文も相対的な配置を行い,
欧文に関しては文字幅チェックしてるのだと思います
(結構頻繁にtfmの幅とグリフの幅違う旨の警告をみます).

#じつは,いい加減に作った従属欧文のtfmでdvipsではOKでも
#dvipdfmxでは盛大に重なるものを生成したことあります.
添付 dvips.png
本田 知亮 への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- Yoshihiro AOKI の投稿
本田さん

ご無沙汰しております。返信ありがとうございます。

そうなんですね。
dvipdfmx的な発想は理解できました。
ありがとうございます。

ちょうどいい機会なので、やりたかったことを「源ノフォント」でひとまず一式作って、テストしようと思います。

ありがとうございます。
Yoshihiro AOKI への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- Z. R. の投稿

とりあえず、自分の手元で試してうまくいっているものを上げておきます。

  • 和文VFexampleは「JISの0x2341~2347(全角英字のA~G)をotfパッケージのotf-cjmr-hの0x22~28(つまりCIDの34~40、プロポーショナル幅英字のA~G)にマップ」するもの。
  • otf-cjmr-hの0x22~28は「幅が異常な文字」であるため、それを出力した直後にps:のspecialを吐くようにする。
  • TeX Liveに入っているjfmutilというツールを使って「jfmutil zvp2vf example」を実行すると、example.zvpからexample.tfmとexample.vfが生成される。
Z. R. への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- Yoshihiro AOKI の投稿
Z. R. さんありがとうございます。

zipファイルの添付もできるのですね...。古い人間なのでTeX Liveもどんどん先へ行ってしまい、コミュニティに出てくるのが苦手でなんだかそわそわしています。

jfmutilという手もすっかり頭から抜け落ちており、ovf2ovp探したりしていました^^;

ありがとうございます。拝見します。
Yoshihiro AOKI への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- Yoshihiro AOKI の投稿
Z. R. さんのアドバイス通り ps: を入れるようにしようと思います。ありがとうございました(添付PDF)。

本田さんから従属欧文のお話があったのでT1エンコーディングを模したCMAPを添付しました。こういうイメージでしょうか? PDFにサンプルを追加しましたが,TFM(と,このCMAP)のみ用意すればVF不要で使えるシンプルな構成で,私的にはこれでいけそうな気がしています。(原ノ味にプロポーショナル欧文はないようですね)
Yoshihiro AOKI への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- 本田 知亮 の投稿
なんかすごいのきました (@_@)
ぜひ公開してください.
tfmとmapをみたいです.
従属はZ.R.さんのpxacid.plがとても便利なので(この場を借りてZ.R.さんに御礼を),
ヘビーに使ってますが選択肢が増えるととてもうれしいです.

ものはついでで,
RyuminPro-LのGSUBとかGPOSをのぞいてみたのですが,
普通のリガチャは f 関係だけですね
(https://github.com/adobe-type-tools/Adobe-Japan1/tree/master/GSUB/aj17-gsub.feaみてもそう).
面白いリガチャはいっぱいあります.
GPOSをみてもそもそもペアカーニングがない気がします.
GSUBよりもGPOSが読みにくいので,読み切れてないだけかもしれません.
本田 知亮 への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- Yoshihiro AOKI の投稿
一例としてリュウミンPr6-Regularのファイル類とtestfont.pdf(4ページ)を添付します。私はZ. R.さんのツールをきちんと追えていないです...。あと,T1用のtestfontがあるのかもわからず,添付PDFは旧来のtestfontで作っています)

(1)
私の作ったTFMはカーニングは含めていないです。T1が期待するリガチャは含めてあります。T1配列のAFMを作り(つまりafm2tfmを使います),CMAPもT1配列にしてしまえば,VFは要らないだろうと思ったらうまくいった感じです。縦組みはTeXやdvipdfmxがきちんと90度回転してくれるようで,縦組用文字のCIDを使った-V系のCMAPも作ったのですが無駄に終わりました。なので,-Hしか含めていないです。

afm2tfmはFig Height(MetaFont Bookの冒頭の図で言及されている)を踏襲して数字の高さが揃う気がしています(でも,私の力ではafm2tfm.cにそのような操作は見受けられなかったです^^;)。AFDKOでしたっけ,あのあたりのツールでは数字の高さをglyph通りに拾ってきますが,例えば丸数字を合成で作るときに数字ごとに高さがゆれると中身の文字ごとに微調整が必要ですし,脚注など行間がタイトなときに赤字で数字を修正しただけで行間(lineskipの挿入有無)が揺れてしまったりと,良い結果にはならず,そのためのFig Height(の統一)だと思うのですが,一般的にはあまり意識されていない気がします。「5」の横線にヒゲが付いてヒュッっと持ち上がったようなデザインの数字がありますが,そのヒゲの出っ張りは「glyphの高さ」としてはみなさないほうが良い,というそういう観点です。

(2)
私はOpenTypeのテーブル情報にも疎く,その辺も加味したいなぁという思いはあるのですが,「長文の英文」のために従属欧文を使う経験がなかったので(そもそも,その実用に耐えるのかと懐疑的です),一旦ペアカーニングは無視しています。従属がどうしても欲しくなるのは見出し等限定的な用途じゃないかという考えですが,OTFがカーニング情報を持っているのならなんとかしたい気もします。

(3)
TeXコミュニティに還元という意味で何かできるといいなとは思っているのですが,私自身古い人間で,もうZ. R.さんが種々のツールを作っておられますし,できることはないのかなぁと。原の味フォントは半角幅の英数字を持っていますが,あれはglyph幅をすべて0.5zwにしたTFMに90ms-RKSJ-H等をマッピングすれば使用できると思うので,私にできることはなさそうだなぁという結論に至りました。
Yoshihiro AOKI への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- 本田 知亮 の投稿
ありがとうございます.
まだ中は拝見していませんが,ダウンロードさせていただきました.
私も古いので,testfontはOT1で回すし,まいっかとOT1しか使わないとかやります(^^;

>AFDKOでしたっけ,あのあたりのツールでは数字の高さをglyph通りに拾ってきますが,

いまのAFDKOはpythonのパッケージになってますね.
Winで動くかそうとするとVC++ ver.14以降入れろとか言ってる来るので放置して(WSLにubuntuとか入れればいいんでしょうけど),
pythonのfonttoolsでOTFの中身(テーブル類)をつまみ読みしてますが,
正直読んでるだけではよくわからないです.

>従属がどうしても欲しくなるのは見出し等限定的な用途じゃないかという考えですが,OTFがカーニング情報を持っているのならなんとかしたい気もします。

これは同意見です.たまに本文で従属というのがあるのですが,
欧文主体のもので従属はないと思っていますし,実際,要求された経験はないです
Z. R. への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- Yoshihiro AOKI の投稿
Z.R.さんのjfmutilをお借りしてupjisr-hq.vfを見ていたですが,
HT:DPが9:1になっていました。

(TYPE D 0
(CHARWD R 1.0)
(CHARHT R 0.9)
(CHARDP R 0.1)
(MAP
(SETCHAR)
)
)

-hqはTeXは読まないようですが,88:12に揃えてしまっても問題ないでしょうか。

あと,「”」(U+2018)など4文字について
 upjisr-h.vf -> upjisr-hq.vf -> uprml-hq.tfm > UCS2
とVFからVFを経由していますが,
 upjisr-h.vf -> uprml-hq.tfm > UCS2
だとまずいのでしょうか(すみません,未確認です)。
upjisr-hq.vfはVF的なことは何もしていなさそうです。

(MAPFONT D 0
(FONTNAME uprml-h)
)
(MAPFONT D 2
(FONTNAME upjisr-hq)
)

のID 2のフォントをuprml-hq(.tfm)にすれば,vfを1つ減らせる気がします。
Yoshihiro AOKI への返信

Re: dvipdfmxの非全角幅のCID文字の扱い,VFの扱い

- Yoshihiro AOKI の投稿
Z.R.さん,jfmutil.plを使わせていただきました。

VTITLEに空白文字を入れたかったので,一旦「_」で入力して,手元では1,560行目に下を追加しました。

$chds[2] =~ s/_/ /g;

2000年過ぎからこのようなツールを作っておられたことと,zvpがものすごくコンパクトなことに驚きました(私は数学脳がないのでZ.R.さんの発想に頭が追いつかないです)。

私がなにか還元できるとしたら,以前添付したT1配列のCMAPくらいしかなく,申し訳ありません。

ありがたく使わせていただきます。