Ratexの0.5.0版において「本物のXeTeX/LuaTeXをサポートする」方針に転向したため、0.4版におけるpdfTeXの独自拡張は放棄されたようである。従って、本記事の内容の大部分1は0.5版以降には当てはまらない。
Rustで実装された新しいTeXエンジン(およびTeXシステム)2である「Ratex」が少し話題になっている。というわけで、チョットだけRatexのTeXエンジンの仕様を調べてみたのでその内容をまとめておく。
「Ratexとは何者か」については別の記事を参照してほしい。
- Rust製TeX「ratex」で日本語PDFを作る:v0.4.0でxeCJKが通るように。Typst・LuaLaTeXとの速度比較(Zenn/清水団)
- 今更だがRatexの0.3.0版で日本語する件について(マクロツイーター)
Ratexはビルダーなどの周辺ツールを内蔵していて単体でTeXシステムの役割を果たすが、以下の記述では「RatexのTeXエンジンの部分」のことを単に「Ratex」と呼ぶ。
以下で記述する“仕様”はRatexの0.4.3版の動作(およびソースコード)を見て推定したものである。公式の裏付けはないことに注意されたい。
必要な前提知識
- TeX言語/TeXエンジンの広範な知識
基本仕様
RatexはpdfTeXを拡張した独自仕様のエンジンとして設計されている。つまり、LaTeXの世界においては基本的にpdfLaTeX互換のエンジン3として振る舞う。
- レジスタの個数などの“既存の”エンジン差異については、原則的にpdfTeXと同じである。
- 文字コードの範囲は原則的に0~255である(例外は後述)。
- TeXソースの字句解析の結果はpdfTeXと同じである。Ratexには「Unicode文字トークン」が存在するが、字句解析の結果としては出現しない。
従って、以降の解説では「pdfTeXと異なる部分」を対象とする。
エンジンがRatexであるかの判定
Ratexは独自仕様のエンジンであるため、パッケージ実装者としては、実行中のエンジンがRatexであることを判定したい場合があるだろう。
0.4.x版ではRatexの独自の拡張プリミティブが追加されているので、この存在を調べることでエンジンがRatexかを判定できる。実際に公式が用意したパッケージの中で\RatexUnicodeVersionがエンジン判定に利用されているので、これに合わせるとよさそうである。
\ifdefined\RatexUnicodeVersion
% Ratexである
\fi
もちろん、必要に応じてプリミティブ判定を行ってもよい。
0.4.0版より前の版は、ほぼpdfTeXの範囲内の動作しか起こらないし、そもそも実用している人がいない4ので、気にする必要はないだろう。
\font プリミティブの拡張
XeTeXやLuaTeXと同様に、RatexではOpenTypeフォントを直接(TFMを介さずに)使用できる。OpenTypeフォントを指定できるように\fontプリミティブが拡張されている。
\font‹トークン›=‹フォント指定› ‹at句›
% "‹at句›"は例えば"at 15pt"や"scaled 1200"など
元祖TeXでは‹フォント指定›の部分に指定できるのは「TFM名」であるが、Ratexはそれに加えて以下の何れかの「OpenTypeフォント指定」の書式が指定できる。
% Ratex書式
ratex:‹名前›
ratex:‹名前›:‹オプション›,…
% XeTeX互換の書式
[‹名前›]
[‹名前›]:‹オプション›,…
- フォント指定全体を
" "で囲える5。囲わないと一部の文字(空白など)を指定に含められないので、普通は囲いを付ける。 -
‹名前›と‹オプション›は{ }で囲える。 -
‹名前›には「フォントファミリ名」または「フォントファイルのファイル名」を書く。XeTeX・LuaTeX(luaotfload)と同様である。 -
‹オプション›はコンマ区切りで複数指定可能で、以下の何れかを指定する。-
Style=‹値›: スタイルを指定する。
※有効な値はRegular、Italic、Slanted、Bold、BoldItalic等。 -
Weight=‹値›: ウェイトを指定する。
※有効な値はThin、ExtraLight、Light、Regular、Medium、Bold、ExtraBold、Black等6。
※‘StyleとWeight`は、フォントファミリ名を指定した場合に適切なフォントファイルをファミリから選択するために用いられる。 - fontspecのオプション指定: その指定を適用する。
※例えばFontIndex=1やKerning=Offという指定ができる。 -
+‹フィーチャ名›: そのOpenTypeフィーチャを有効化する。 -
-‹フィーチャ名›: そのOpenTypeフィーチャを無効化する。
-
OpenType指定の\fontの使用の例を示す。Ratex用fontspecパッケージの内部では、安全のために" "と{ }で囲われた形式が使われている。
\font\fA=ratex:InconsolataN:Scale=0.9
\font\fB="ratex:Harano Aji Gothic:Ligatures=TeX,+jp90"
% fontspecが使う形式
\font\fB="ratex:{Harano Aji Gothic}:{Ligatures=TeX},{+jp90}"
ネイティブテキストモード
現在のフォントがOpenTypeフォントのとき「ネイティブテキストモード」が有効になる。
- 一部のプリミティブに存在する「(入力側でなく)フォント側の文字コード」を表す引数の有効範囲は、ネイティブテキストモードが有効の場合は0~0x10FFFFで無効の場合は0~255になる。該当する引数は以下の通り。
-
\char/\RatexLiteralCharの引数。 -
\Ucharcatの第1引数。
-
- chardefトークンの文字コードの範囲も0~0x10FFFFとなる。
\chardefで紐づける値の有効範囲は常に(ネイティブテキストモードが無効でも)0~0x10FFFFである。 - ネイティブテキストモードが有効状態に応じて挙動が変わるプリミティブが他にもあるかもしれない7(未調査
)。 - ネイティブテキストモードが有効であるかは
\RatexNativeTextModeで判定できる。 - ネイティブテキストモードが有効の場合、同一フォントでの文字の連続する版面出力は内部のノードリスト8上で単一のノードになる。これはXeTeXと同様で、このノードのレンダリングはOpenTypeレンダラに任せられる。(プリミティブの仕様は後述。)
Unicode文字トークン
Ratexの文字トークンにおける文字コードの範囲はpdfTeXと同じで0~255であるが、Ratexではこの通常の文字トークンの他に「Unicode文字トークン」が存在する。概念的にはupLaTeXの「和文文字トークン」に少し似ている。
- Unicode文字トークンの文字コードの範囲は128~0x10FFFFである。128~255の文字コードについては通常の文字トークンとUnicode文字トークンの両方が存在し、両者は
\ifx-非等価である。 - Unicode文字トークンはカテゴリコードをもつ9。
- upLaTeXとは異なり、TeXソースの字句解析でUnicode文字トークンが生じることはない。Unicode文字トークンを生成する手段には以下のものがある。
-
\RatexUTFviii: バイト列をUnicode文字トークンに変換する。カテゴリコードは12になる。 -
\Ucharcat: 文字コードとカテゴリコードを指定してUnicode文字トークンを生成する。
-
- カテゴリコードが11か12の10Unicode文字トークンを実行すると、現在のフォントの当該の文字コードの文字が版面に出力される。現在フォントが旧来のTFMである場合も文字コードが255以下11のUnicode文字トークンは受け付けられる。
Ratex版fontspecパッケージ12は、inputencのutf8エンコーディングにおける全範囲のUnicode文字の実装13を以下の手順の処理に置き換えることで、Unicode文字の入力をフォントの文字出力に結び付けている14。
- ネイティブテキストモードが無効なら従来のinputencの処理にフォールバックして終わる。
- 入力のUTF-8バイト列について、
\RatexUTFviii{‹バイト列›}を実行する。 - そのトークン列が展開されると入力文字コードのUnicode文字トークンとなる。
- その文字トークンが実行されて所望の入力文字が出力される。
参考:CJK文字出力時の自動フォント切替
詳細については未調査(のまま機能自体が消滅
)
Unicodeの文字のうち、漢字や仮名などの一部の文字(予め決められている)は「CJK文字」と見なされていて、RatexではCJK文字の出力時にフォントを自動的に切り替える機能が備わっている。Ratex版xeCJKパッケージはこのフォント切替機能を利用している。
CJK文字を含む文字列を版面に出力した際に、もし\ratex@cjkfontという制御綴にfontdefトークンが入っていたならば、連続するCJK文字の部分だけ\ratex@cjkfontのフォントに切り替わり、前後に欧文空白の空き15が入る。
% `ratex@cjkfont`がfontdefトークンの場合にこれを出力すると…
Ratex is superアレ!
% 実際にはこれと同等の出力になる.
Ratex is super {\ratex@cjkfont アレ} !
\ratex@cjkfontがfontdefトークンでない場合はCJK文字について特別な処理は行われない。
Ratex独自の拡張プリミティブの一覧
Ratex独自の拡張プリミティブについて、その仕様を説明する。
- 展開可能プリミティブについては「展開結果のトークン列の内容」を記述する。
- 文字列として記述された場合、実際には
\the-文字列を表す。 - 数値・寸法・グルー値の場合、典型表現16の
\the-文字列を表す。
- 文字列として記述された場合、実際には
-
\RatexUnicodeVersion:[展開可能] 常に1を返す。- 何らかのバージョンだろうけど、詳細は不明。
- エンジン判定に利用できる。
-
\RatexNativeTextMode:[展開可能] ネイティブテキストモードが有効なら1、無効なら0。 -
\RatexUTFviii{‹バイト列›}:[展開可能] カテゴリコードが12で文字コードが「引数のUTF-8バイト列に対応するUnicode符号値」であるUnicode文字トークン。 -
\RatexLiteralChar ‹文字コード›: 現在のフォントで引数の文字コードに対応する文字を版面に出力する。- 引数の有効範囲はネイティブテキストモードが有効なら0~0x10FFFF、無効なら0~255。
- 先述の通り、
\charも(引数範囲が拡張されるので)同じ用途で用いられる。両者の違いについては不明
-
\ratexcjktext{‹面番号›} ‹文字コード›: (よくわからない
)
- CJKパッケージの文字出力の周りでRatex用の独自処理としてこの命令が追加されている。例えば、U+26C4の文字(つまり面番号
26のサブフォントの文字コード196の文字)を出力する際には、直前に\ratexcjktext{26}196、直後に\ratexcjktext{}0を実行している。 - この命令自体はRatex独自のwhatsitノードを出力しているらしい。
- CJKパッケージの文字出力の周りでRatex用の独自処理としてこの命令が追加されている。例えば、U+26C4の文字(つまり面番号
pdfTeX以外の拡張プリミティブの一覧
pdfTeXにはない他のTeXエンジンの拡張プリミティブでRatexがサポートしているものの一覧。現状で該当するものは全てXeTeXのプリミティブである。
-
\Ucharcat‹文字コード› ‹カテゴリコード›:[展開可能] 引数の文字コードとカテゴリコードをもつ文字トークン。文字コードが128以上の場合はUnicode文字トークン、127以下の場合は通常の文字トークンになる。
※ちなみに、\Ucharはサポートしていない。 -
\filesize{‹ファイル名›}:[展開可能] 引数のファイルのファイルサイズ。-
\filesizeは\pdffilesizeの「XeTeX流の名前」である。 -
\pdffilesizeと全く同じ動作だが別のプリミティブとして存在する。
-
この他に、初期状態で以下の「XeTeX流の名前」の制御綴にプリミティブがコピー20されている。
-
\randomseedには\pdfrandomseedプリミティブが入っている。 -
\setrandomseedには\pdfsetrandomseedプリミティブが入っている。
まとめ
Ratex完全に理解した![]()
-
0.5.0版においても当てはまる部分(pdfTeXと異なる部分)は「
\ratexcjktextプリミティブ」「\Ucharcatプリミティブ」「\filesizeプリミティブ」「CJK8.chrのファイル差替」が該当する。 ↩ -
「XeLaTeXモード」「LuaLaTeXモード」のようなものも構想にはありそうだが、現在は未実装である。 ↩
-
0.4.0版の2週間ほど後にもう0.5.0版がリリースされたので、結局0.4.x版も実用されずに終わった模様
↩ -
ちなみに、
" "で囲う指定は現在の通常のTeXエンジンでもサポートされている。さらに通常のエンジンでは{ }で囲う指定も可能だが、こちらはRatexではサポートされていない。 ↩ -
この9個の値はOpenTypeのウェイト値の100から900まで(100刻み)に対応する。その他の有効な値はこれらの別名である。 ↩
-
逆に言うと、OpenTypeフォントを使わなければネイティブテキストモードは無効なので、既存のプリミティブの動作はpdfTeXと変わらないことになる。 ↩
-
版面に出力されたデータを保持する内部データ構造。 ↩
-
カテゴリコードをもつ文字コードの範囲、すなわち「
\catcodeの引数の有効範囲」は0~255であることに注意。 ↩ -
その他のカテゴリコードのUnicode文字トークンはちゃんとそのカテゴリコードのものとして機能するようである。 ↩
-
Ratexでは現在のフォントにない文字を版面に出力しようとするとエラーになる。TFMのフォントには文字コードが256以上の文字は当然存在しないので、これもエラーになる。 ↩
-
RatexではTeX Liveのファイル群が「バイナリに内蔵」されているが、
fontspec.styやUTF8.chr(CJKパッケージの構成物)等の一部のファイルは、Ratex用の独自実装を記述した独自のファイルに置き換えられている。 ↩ -
端的にいうと
\DeclareUnicodeCharacterのこと。ただし全範囲を一斉に定義する必要があるので、実際には内部マクロを再定義している。 ↩ -
つまり、fontspecを読み込まないと、たとえOpenTypeフォントを現在フォントに設定したとしても非ASCII文字の入力はそのままでは受け付けられない。 ↩
-
現状では和欧文間空白を入れるべきでない場所でも空きが入る。この空白以外のCJKの行組版用の調節は行われないようである。 ↩
-
例えば、数値42なら
42、寸法−1ptなら-1.0pt。 ↩ -
数値リテラルの
`‹文字›において‹文字›の部分に書けるものと同じである。 ↩ -
変換先はUnicode文字トークンであるため、文字コードが127以下の文字は不可である。 ↩
-
字句解析の結果として、
^^c7は文字コードが0xC7の文字トークンになり、\^^b4は制御綴(その制御綴名は0xB4の文字1つからなる)になる。 ↩ -
\filesizeとは異なり、こちらはコピーなので元のプリミティブと\ifx-等価である。 ↩