Closed aminophen closed 2 years ago
うーーん ざっと読んだ限りの印象では、あまりに複雑すぎて私は乗り気にならない感じです。
現状、upTeXの実装では、内部コードが upTeX のとき、
upTeXの内部バッファは kcatcode(5bit) + UTF32もどき(24bit) になっていて
内部バッファから dvi に書き込む際に toDVI()
でUTF32もどき(24bit) (最大 0xFFFFFF, 本来のUTF32は32bitで最大 0x001FFFFF) にしています。
で、この関数は文字コード 0x1FFFFF以下の場合は素通ししているだけなので、
pTeXの内部バッファの和文文字コードの範囲 0x2020..0x7F7F もtoDVI()はそのまま使えます。
またupTeXエンジンから出力後、DVI以降(dviware)は、フォント名と文字コードは常にセットで管理されているのでupTeXの文字コード(UTF32もどき)とpTeXの文字コード(JIS)が同じdviファイルに混在していても安全に処理できます。
それに加え、TeXエンジン内部のもともとの考え方として、フォント名と文字コードのセットがきちんと管理できていれば文字コードの混在は厭わないという思想に思えます。
なのであまり複雑にせずとも対応できそうな気がします。入力側の手当てをどうするのかが課題になりそうですが。
ただ、kcatcodeとかglueとかの文字コードの対応関係は内部UCS(UTF32もどき)と内部JISでは別物なのは確かです。 今回のご提案はそこをprimitiveで切り替えたいということでしょうか?
今回のご提案はそこをprimitiveで切り替えたいということでしょうか?
はい,例えば
% 内部コード uptex で処理
\ifnum\jis"2121="3000 \else \expandafter\end \fi
\font\x=jis \x あい)\inhibitglue お
\font\y=upjisr-h \y あい)\inhibitglue お
\end
のようなものが jis.tfm は JIS で,upjisr-h は Unicode であるという混在に対応できるようにということです。
背景としては,いずれ「内部コード EUC/SJIS な (u)pTeX」は LaTeX3 の激しい変更に耐えきれなくなり,内部 Unicode 一択になることが近い将来起こりうることを懸念しています。万が一そのようなことが起こっても,従来の pTeX 用の TFM を使い回すことができるようにという保険を作っておくのはどうか,と思い立ったので issue を立てました。
関連: https://github.com/texjporg/platex/issues/98 (l3str-convert), https://github.com/texjporg/tex-jp-build/issues/147 (l3regex), https://github.com/h20y6m/plexpl3/issues など。
なるほど。LaTeX3が内部Unicode一択になった場合にも pTeX の TFM が動くエミュレーションという点が狙いということですね。
今のpTeXや「upTeXの内部EUC動作」の実装では、 [α] 入力がUTF-8だとしてもptexencが SJIS/EUC (8bit可変長)に変換後、入力バッファに突っ込み、 [β] さらに(u)pTeXエンジンの入り口で16bit JIS の内部コード(0x2020..0x7F7F) に変換 [γ] (u)pTeXエンジンは 16bit JISを前提にglueなどの処理 となっています。
私の理解では、 [α]のEUC/SJISをやめたい、 LaTeX3が内部Unicode化が進展した場合、[β]あたりまでUnicodeのままでいてくれた方がpLaTeXが追従しやすい、 [γ]のtfmの情報へのアクセスの時点でJISに変換できれば(u)pTeXの内部バッファがUnicodeでも大丈夫
ということでしょうか。
TeX users slack (texuser.slack.com) で今日から話をしているだけなので私もまだ考えがまとまっていませんが,概ねそのように考えています。以下のような「非互換な仕様変更」も想定しつつ,まずは「非互換な仕様変更には該当しない改良」に手をつけようというのが本件「pTeX の JIS-encoded TFM が動くエミュレーション」です。
〜 Slack を読んでいない方へ & アーカイブが 90 日で消えるので補足 〜
現状の LaTeX3 では regression test(大量に用意されたテストファイル入力 .lvt に対するログ .tlg を比較)の仕組みが (u)pTeX に対しては機能していません。
その理由は恐らく
が理解されないためだと思われます。和文(CJK)文字トークンの catcode が 16〜18(19) であることも考慮されておらず「カテゴリーコードは 16 進 1 桁」を前提にしたインタフェースが構築されています(参考)。
このような状況から (u)pTeX の後方互換性を放棄してでも 和文文字トークンの扱いならびに ptexenc の仕様 (https://github.com/texjporg/tex-jp-build/issues/147) などを見直していく必要があるのではないか,ということを考えています。この大規模な話については別の場としましょう。
[A1] 組版時に \jfont/\tfont で読み込む段階でエンコード矯正するための
\font [in <encoding>] <control sequence><equals><file name><at clause>
という書式を導入する。 この書式が使われた場合は,メトリック情報を記憶する段階で内部コードに合うように toUCS(fromJIS()) あるいは toJIS(fromUCS()) し
ここまでは 'emulate_jfm' ブランチで出来た気がします。
変換できない文字は無視する 新書式を使わない場合に TFM の文字コード範囲から JIS-encoded か Unicode かを(完璧ではないにせよ)自動判定しても良いかもしれない
これについてはまだです。
次は
[A2] DVI 出力時には,エンコード矯正が行われた TFM については set2 や set3 での出力時に元のエンコードに戻して書き込む。変換できない文字は無視する。
に取り組みます。(まだ考えられていませんが,文字ノードを作る時に文字コード変換するので,恐らく「禁則ペナルティがどうなるか」「\jcharwidowpenalty」「\lastnodechar」についてはきちんとテストする必要があると思います)
このissueの冒頭のご提案もかなり大規模な話と感じます。 どこかで区切ってupTeXに入れるにしても中途半端では禍根を残しそうで不安です。 もう少しここで議論を続けてみます。
上記[γ]で文字コードはUnicodeだがアクセス先のTFMはJISで見る、ということは仕様として可能とは思いますがかなり直感に反します。
\char"A7B5
は、 現在のpTeX(内部EUC)では、「0xA7B5 (U+0423) У Cyrillic Capital Letter U」 現在のupTeX(内部UCS)では、「U+A7B5 ꞵ Latin Small Letter Beta」 が出ます。新しいエミュレート版ではどちらが適切?
その理由は恐らく
- (u)pTeX が「和文(CJK)文字トークン」という独特の物が存在し,また文字コードが中途半端に 0--255 ではないこと(e.g.「`あ」できるのに「\catcode`あ」できない)
が理解されない
思いつきですが、その対策として例えばupTeXの仕様の追加で 「catcodeが11で文字コードがある値(例えば0x2E00以上)より大きい場合は漢字トークンとみなす」 「catcodeが12で文字コードがある値より大きい場合はCJK記号トークンとみなす」 のようなものを用意し、それらに対しては 「`あ」できて「\catcode`あ」できてしかもCJKトークンである という風にするのはいかがでしょうか?
文字コードはUnicodeだがアクセス先のTFMはJISで見る
現に pTeX は「エンジンの内部コード EUC/SJIS だけど TFM 読取や DVI 書出の文字コードは JIS」な訳ですから,ここでコード変換が起こるのは直感的であると思います。また,トークンの話についてはこれとは無関係なので issue を分けるつもりです。
ご提示の \char"A7B5
の例も,私の [A1] [A2] を行っても出力は何も変わりません。
のままです。もう少しわかりやすく [A1][A2] を例示すると,例えば \font in jis \X=min10
としたときに,普通に min10.tfm を読むのではなく,あたかも
手動で「現min10.tfm(JIS) →(ptftopl)→ 仮temp.pl →(uppltotf)→ 新min10.tfm(Unicode)」として得られる「新 min10.tfm」を読んだような状態
を作りたいということです。
[A2] DVI 出力時には,エンコード矯正が行われた TFM については set2 や set3 での出力時に元のエンコードに戻して書き込む。
これも https://github.com/texjporg/tex-jp-build/commit/4baff60d0428f8d8e0e4a9846ba046068a4fb98f にて完了。ということで次は
変換できない文字は無視
に取り組みます。
新書式を使わない場合に TFM の文字コード範囲から JIS-encoded か Unicode かを(完璧ではないにせよ)自動判定しても良いかもしれない 文字ノードを作る時に文字コード変換するので,恐らく「禁則ペナルティがどうなるか」「\jcharwidowpenalty」「\lastnodechar」についてはきちんとテストする必要がある
これらは時間かかりそうです。
禁則ペナルティがどうなるか \lastnodechar
こちらは影響を受けないようです(ノードリストを作るタイミングでは未変換・それよりはるか後のDVI に書き出すタイミングで変換しているため)。
「catcodeが11で文字コードがある値(例えば0x2E00以上)より大きい場合は漢字トークンとみなす」 「catcodeが12で文字コードがある値より大きい場合はCJK記号トークンとみなす」
この特定の値については #135 からだと思いますが,あちらは「OFM に定義された最大の文字コード」だから良かったものの,今回のようなものには使えないように思います。(例えば 0xB7 (U+00B7) は uptex-fonts でも和文扱いを想定した中黒です)
変換できない文字は無視する
017aeab4cbef02 で試してみました.例えば
\kcatcode"D8=16\relax
\font in jis\x=jis \x ó
のように文字コード JIS の TFM 下で JIS 範囲外の文字を使うと DVI には set2 0 が書かれますが,これで良いのかは検討の余地ありです.
文字コード JIS の TFM 下で JIS 範囲外の文字を使うと DVI には set2 0 が書かれます
確かにそのとおりで,これは
手動で「現jis.tfm(JIS) →(ptftopl)→ 仮jis.pl →(uppltotf)→ 新jis.tfm(Unicode)」として得られる「新 jis.tfm」を読んだような状態
とは違いますが,むしろ「範囲外の文字は出力できない」で良いと思っています。出力できないときにどうするのが良いかですが,思いつくのは以下でしょうか。
Missing character: There is no ^^a1 in font cmr10!
を真似て破棄する従来は JFM では「存在しない文字はない (\nullfont できない)」という仕様でしたので,前者のまま(豆腐を出力する)方が無難?
catcode の話は、こちらの主題の JIS-encoded TFMのエミュレートの話とは別にissue を立てました。 [upTeX] catcodeが15以下のCJKトークン #150
どちらでも適切といえると思いますが、私の好みでは後者です。(実装の手間は考えずに言っています) 今回のケースでは文字コード変換前は Unicode の範囲で正規の文字にもかかわらず変換漏れで出なくなった感じがして、事情はあるにせよ変換できないまま黙って豆腐を出力するのはよろしくないように思えます。 ただ、実装の手間が大変という理由から見送りでもいいようにも思います。
- DVI に set2 0 を書く(現在 017aeab の挙動)
- Missing character: There is no ^^a1 in font cmr10! を真似て破棄する
DVI→PDF の過程で「実フォントに該当グリフはなかった」ではなく,TeX→DVI という実フォントに依存しない状況での変換漏れなので,「黙って豆腐」には違和感を覚えます.
U+XXXX は pTeX 用 JFM hogem では出力できませんので,豆腐(もしくは〓)に置き換えます.
みたいな警告を出すのに +1 です(ノード破棄もあまりしたくないなあ,という印象).
U+XXXX は pTeX 用 JFM hogem では出力できませんので,豆腐(もしくは〓)に置き換えます.
みたいな警告
https://github.com/texjporg/tex-jp-build/commit/e1068d4d7663de4db894577a12f2c6fb2a2e3f4a で入れました.
お二方ともコメントありがとうございます。確かに「黙って豆腐」は良くないですね。ノード破棄すると dvipdfmx で字が詰まってしまうのも気になりますので,破棄せずに警告 https://github.com/texjporg/tex-jp-build/commit/e1068d4d7663de4db894577a12f2c6fb2a2e3f4a で良いと思います。ありがとうございます。
迷っていますが Missing character: There is no ^^a1 in font cmr10!
が \tracinglostchars
によって出力制御できるようなので,試しに https://github.com/texjporg/tex-jp-build/commit/66a0ed9b288429acb2a7528c7b71ead8555345b7 でやってみました。ノード破棄ではないので lost という名前が合っていない気がしますが,これだけのためにプリミティブを増やすのもどうかと思うのと,euptex では \tracinglostchars=3
にすると警告でなくエラーに出来る点は使えそうに思いました。ただし,警告が発するタイミングは Missing character ではノード生成時であるのに対し,非 JIS の方は \shipout でノードの DVI 出力時であることが異なります。
https://github.com/texjporg/tex-jp-build/commit/ee0a8c19be85699d3881ebc825e8ceac7a948464 で \ptextracingfonts
というプリミティブを追加してみました。pdfTeX の \pdftracingfonts
と同じ書式でフォント名とサイズを表示(もちろん font expansion には非対応)し,
in jis
/ in ucs
が指定された場合は JIS/Unicode の情報を表示としてみました。 テストケース: https://gist.github.com/aminophen/6715ae7fce5e03ddecccf06e7569682a
※ LuaTeX にも \tracingfonts
があるけど LaTeX の \tracingfonts
と衝突しているらしい
※ XeTeX の \XeTeXtracingfonts
は読み込んだフォントの所在ディレクトリを返す別物らしい
https://github.com/texjporg/tex-jp-build/commit/c93a8f750a157339bbe6600d921be244b52f09d0 で \ptexfontname というのも実装してみました。\ptextracingfonts と共通のコードを利用して
としました。これで,プログラミング的に「そのフォントが JIS コードと Unicode のどちらで DVI 出力されるか」を知ることができます。
なお "in jis" 及び "in ucs" による TFM 読込においては,新しい font identifier は発行されません。従って,同じ TFM を同じサイズで複数回読み込んだ場合は「最初のエンコード」が常に使われ,2回目以降でエンコード指定を変えても無視されます。
%#!ptex
\font\x=min10
\font in jis\y=min10 % => min10 は無指定時のエンコードのまま
\font in ucs\z=min10 % => min10 は無指定時のエンコードのまま
%#!ptex
\font in ucs\x=umin10
\font\y=umin10 % => umin10 は Unicode のまま
\font in jis\z=umin10 % => umin10 は Unicode のまま
参考:tex.web の @<If this font has already been loaded...@>
を参照。ここではフォント (TFM) 名と読込サイズ (at) が同じフォントを読込済扱いしているが,ここに和文エンコード (JIS/Unicode) のチェックを追加していないため,このような挙動になる。(これで問題ないという判断)
ptex-manual の方も 'emulate_jfm_tracingfonts' ブランチで文書化してみました。
https://github.com/texjporg/ptex-manual/commit/4e840e1783899205a5792d29b506b874d4fdfe28
期待通りに動いているようです。
大丈夫そうなので,後ほどコミットします。結局追加したのは
\font [in jis/ucs]
書式\tojis
プリミティブ\ptextracingfonts
プリミティブ\ptexfontname
プリミティブの 4 点です。
r64800 問題があったら reopen しましょう。
upTeX で内部コードに依らず min10 や jis のような「文字コード JIS なレガシーな TFM」を使える状態にしておくと,pTeX から upTeX への乗り換えを進める上で良いのではないかと思ったのでメモしておきます。
単純に [1] だけを実装しても [2] で DVI に書き込むコードと実在の TFM の文字コードが不一致だと破綻するので,順番としては以下の方が良いのかもしれません。
\font [in <encoding>] <control sequence><equals><file name><at clause>
という書式を導入する。set2
やset3
での出力時に元のエンコードに戻して書き込む。実装案は作れそうなので,やってみます。
なお,これを実現すれば upLaTeX に JY1 / JT1 をエミュレートする機能を乗せることもできるかもしれません。これは upTeX 本体実装を作った後に考えます。