2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LuaTeXの数式用追加プリミティブについて

Posted at

これは「TeX & LaTeX Advent Caleandar 2024」の17日目の記事です。
(16日目はやまいもさんの『行分割アルゴリズムの話。』、18日目はzr_tex8rさんです。)

はじめに

昨今、pTeXの実体がupTeXになったり、XeTeXを元にした新たな日本語用エンジンであるnpTeXの開発が始まったりと日本語の(La)TeX事情は着実に変化しつつあります。一方世界に目を向ければ事実上LaTeX3への移行が始まり、アクセシビリティへの対応のためにXeTeXがほぼ見放され、pdfTeXですら将来的に非推奨になりそうな気配があります。1
本記事は、昨今のTeX開発で起こっている変化から最も遠いところのエンジンであるLuaTeXにおける数学用の追加プリミティブについての記事です。

本記事では、LuaTeXで数式を扱う利用者にとっての実質的な最小構成となっているであろうLuaLaTeX+unicode-mathの利用を前提として話を進めます。2ただ、ここで紹介するのがプリミティブである以上、LaTeX文書中でそのまま使うのはあまり行儀が良くないので、プリアンブルなどで適当にラップするなどしましょう。

数式用追加プリミティブとは

(La)TeXの一部のコマンド(マクロ)は、エンジンによって定義されているものがあり、それらは一般にプリミティブと呼ばれます。プリミティブと一口に言っても、初めから定義されていたもの、時代とともに追加されていったもの、そして各エンジンが独自に定義したものなど様々なものがあります。
その中でも今回取り上げるのは、LuaTeXで独自に追加されたプリミティブのうち、特に数式用の機能を持つプリミティブ(のごく一部)です。紹介順やグループ分けはかなり適当なので、改善案があればぜひお知らせください。
より詳しいことが知りたければLuaTeXマニュアルを参照してください。3

とりあえずの結論

  • innerscriptを使うとスペーシングがちょっと良くなる
  • プリアンブルに\NewDocumentCommand{\sfrac}{o m m}{{{#2} \Uskewed / \IfValueT{#1}{#1} {#3}}}を追加すると\sfrac{a}{b}によってa/bの形で分数を書ける
  • もともとあったプリミティブを拡張した追加プリミティブは大抵LaTeX内部で適切に使われている(≒実際に目にすることはない)
  • LuaTeXのマニュアルにない情報はLuaMetaTeXかConTeXtのマニュアルに書いてある

文書作成者も使えそうなもの

Uleft / Umiddle / Uright

それぞれ初めのUを除いたコマンドの拡張です。4
heightdepthaxisnoaxisexactclassの6つのオプションを受け付けますが、意味のわかりやすい最初の2つ以外を使う機会は多分ありません。
使用例:

\Uleft height 40pt depth 15pt \{

Umathaccent

基本的にはunicode-mathがよしなにラップしているので気にする必要はありませんが、フォント独自の特殊なアクセントなどが存在していて、それを利用したいという稀有な状況であれば使うかもしれません。

オプション 引数 意味
both top fixed overlay アクセントの位置
fixed アクセントの長さを固定する
fraction 整数 n アクセントの長さを中身のn/1000倍にする

使用例:

\Umathaccent top 0 0 "305 fraction 1000 {}

Uskewed / Uskewedwithdelim

スラッシュを用いた、a/bの形の分数を作るコマンドです。5
フォントのパラメーターを参照して位置を調整するので、xfracパッケージのsfracコマンドよりも適切な見た目になります。オプションとしてexactaxisが存在します。
筆者はUskewedのラップとして

\NewDocumentCommand{\sfrac}{o m m}{{{#2} \Uskewed / \IfValueT{#1}{#1} {#3}}}

と定義しています。
使用例:

{ {1} \Uskewedwithdelims / () exact noaxis {2} }

伸長コマンド

Unicodeに登録のある一部の長い矢印はlongrightarrowなどのコマンドで利用できますが、OpenTypeフォントにはグリフを伸ばす仕組みが存在しているので、フォントによっては可変長の矢印を使うことができます。基本的には

\Uhextensible width 1cm 0 "2192

などとすることで事足ります。グリフを正確に伸ばせなかった場合の位置調整用オプションとしてleftmiddlerightがあります。
その他、mathtoolsに存在するxlongrightarrowなどに近い効果を持ったプリミティブ

  • Uunderdelimiter
  • Uoverdelimiter
  • Udelimiterover
  • Udeoimiterunder
    が追加されています。ただし、mathtoolsのものとは違って上下同時に文字を入れたり、自動で長さを調節させたりはできないので注意してください。
    使用例:
\mathrel{\Uunderdelimiter width 2.5cm 0 "2192 {\text{A function with a very long name}}}

また、Uhextensibleと同様にUvextensibleも存在しますが、ドキュメントへの記載はありません。
使用例:

\Uvextensible height 2.2em depth 1.5em \Udelimiter 0 0 "222B

これらの伸長コマンドや(U)leftなどは、いずれもOpenTypeフォント内のMATHテーブルにしたがってグリフを配置します。したがって、波括弧の突起や~などを左右(上下)に偏らせる、といったことはできません。またこのとき、構築に用いられたグリフはそれぞれが元の記号と同様のコードポイントを持つものとして扱われるので、出力されたPDFにおいては例えば↔↔↔↔↔↔↔↔↔↔↔↔↔↔↔↔↔↔↔↔↔↔↔↔のような文字情報が記録されています。よって、たとえ1行に収まった数式であろうと単純にコピーして正しい文字列が得られる保証はありません。6

Uradical / Uroot

それぞれ初めのUを除いたコマンドの拡張で、根号を取り扱います。sqrtコマンドの定義中に現れるsqrtsign\Uradical \symoperators "0221A\scan_stop:で置き換えられているので何もせずにデフォルトで利用されるはずです。使い方は以下の通りですが、初めの2引数は整数値("0など)を取ります。

\Uradical <フォントファミリー> <根号の記号> <中身>
\Uroot <フォントファミリー> <根号の記号> <次数> <中身>

Ustack

TeXの記法であるために推奨されないa \over bによる分数の記述などの、どこまでを分子・分母として扱うかがわからないという問題点を解決するコマンドで、

\Ustack {a \over b}

というように使います。7実際にはamsmathがLuaTeX用にはきちんとこちらを使うようになっているので気にしなくても良いです。overなどをどうしても使いたい人はこれも使ってください。

その他

その他文書作成者にも稀に使う機会がありそうなプリミティブです。

プリミティブ 備考
crampeddisplaystyle
crampedtextstyle
crampedscriptstyle
crampedscriptscriptstyle
Ustartmath \(と同様8
Ustopmath \)と同様8
Ustartdisplaymath \[と同様8
Ustopdisplaymath \]と同様8
Usuperscript ^のエイリアス
Usubscript _のエイリアス
Unosuperscript ^{\textstyle ###}にあたる?
Usubscript _{\textstyle ###}にあたる?

通常の文書作成には使わないもの

追加プリミティブの中には、もちろん内部動作などに影響を及ぼすものも存在します。大抵の人にとって使う機会はまず訪れないでしょうが、一応紹介しておきます。

Umath<1><2>spacing

<1><2>には数式中の記号種別(ord/binなど)が入り、それらの間にどれだけの空白を挿入するかを規定するパラメーターです。
とりあえずinnerscriptはこのあたりをいい感じにしてくれます。

一覧
  • Umathordordspacing
  • Umathordopspacing
  • Umathordbinspacing
  • Umathordrelspacing
  • Umathordopenspacing
  • Umathordclosespacing
  • Umathordpunctspacing
  • Umathordinnerspacing
  • Umathopordspacing
  • Umathopopspacing
  • Umathopbinspacing
  • Umathoprelspacing
  • Umathopopenspacing
  • Umathopclosespacing
  • Umathoppunctspacing
  • Umathopinnerspacing
  • Umathbinordspacing
  • Umathbinopspacing
  • Umathbinbinspacing
  • Umathbinrelspacing
  • Umathbinopenspacing
  • Umathbinclosespacing
  • Umathbinpunctspacing
  • Umathbininnerspacing
  • Umathrelordspacing
  • Umathrelopspacing
  • Umathrelbinspacing
  • Umathrelrelspacing
  • Umathrelopenspacing
  • Umathrelclosespacing
  • Umathrelpunctspacing
  • Umathrelinnerspacing
  • Umathopenordspacing
  • Umathopenopspacing
  • Umathopenbinspacing
  • Umathopenrelspacing
  • Umathopenopenspacing
  • Umathopenclosespacing
  • Umathopenpunctspacing
  • Umathopeninnerspacing
  • Umathcloseordspacing
  • Umathcloseopspacing
  • Umathclosebinspacing
  • Umathcloserelspacing
  • Umathcloseopenspacing
  • Umathcloseclosespacing
  • Umathclosepunctspacing
  • Umathcloseinnerspacing
  • Umathpunctordspacing
  • Umathpunctopspacing
  • Umathpunctbinspacing
  • Umathpunctrelspacing
  • Umathpunctopenspacing
  • Umathpunctclosespacing
  • Umathpunctpunctspacing
  • Umathpunctinnerspacing
  • Umathinnerordspacing
  • Umathinneropspacing
  • Umathinnerbinspacing
  • Umathinnerrelspacing
  • Umathinneropenspacing
  • Umathinnerclosespacing
  • Umathinnerpunctspacing
  • Umathinnerinnerspacing

フォント依存のパラメーター

LuaTeXではOpenTypeフォントに元から対応していて、さらにunicode-mathを利用することによりOpenType Mathをフル活用できるようになります。ではOpenTypeフォント内のMATHテーブルの情報をどう扱っているのか、フォント(の中身)に興味のある方なら一度は考えたことがあるでしょう。
実は、LuaTeXではOpenTypeフォントの活用のために数式組版処理が見直されていて、多くのパラメーターがハードコーディングではなくなりました。その中にはフォントの情報を用いて自動設定されるパラメーターも多くあります。OpenTypeフォントでなくともTFMから多くのパラメーターが自動で設定されるので、普通に生きていればまず使うことはないでしょう。

一覧
  • Umathquad
  • Umathaxis
  • Umathoperatorsize
  • Umathoverbarkern
  • Umathoverbarrule
  • Umathoverbarvgap
  • Umathunderbarkern
  • Umathunderbarrule
  • Umathunderbarvgap
  • Umathradicalkern
  • Umathradicalrule
  • Umathradicalvgap
  • Umathradicaldegreebefore
  • Umathradicaldegreeafter
  • Umathradicaldegreeraise
  • Umathstackvgap
  • Umathstacknumup
  • Umathstackdenomdown
  • Umathfractionrule
  • Umathfractionnumvgap
  • Umathfractionnumup
  • Umathfractiondenomvgap
  • Umathfractiondenomdown
  • Umathfractiondelsize
  • Umathskewedfractionvgap
  • Umathskewedfractionhgap
  • Umathlimitabovevgap
  • Umathlimitabovebgap
  • Umathlimitabovekern
  • Umathlimitbelowvgap
  • Umathlimitbelowbgap
  • Umathlimitbelowkern
  • Umathnolimitsubfactor
  • Umathnolimitsupfactor
  • Umathunderdelimitervgap
  • Umathunderdelimiterbgap
  • Umathoverdelimitervgap
  • Umathoverdelimiterbgap
  • Umathsubshiftdrop
  • Umathsupshiftdrop
  • Umathsubshiftdown
  • Umathsubsupshiftdown
  • Umathsubtopmax
  • Umathsupshiftup
  • Umathsupbottommin
  • Umathsupsubbottommax
  • Umathsubsupvgap
  • Umathspaceafterscript
  • Umathconnectoroverlapmin

TeXのプリミティブを拡張するもの

LuaTeXではTeXと比較してレジスタが大幅に拡張され、さらにコードポイントとしてUnicode全体を扱うようになっています。この仕様を後方互換性を維持したまま実現するために、いくつかのプリミティブが拡張されて語頭にUを付加した別名のプリミティブとして追加されています。これらのプリミティブは引数にも若干の変更が加えられていますが、筆者自身がよく理解できていないので詳細はLuaTeXのマニュアルを参照してください。

一覧
  • Umathchardef
  • Umathcharnumdef (*, **)
  • Umathcode
  • Udelcode
  • Umathchar
  • Umathaccent
  • Udelimiter
  • Umathcharnum
  • Umathcodenum
  • Udelcodenum

(*): mathchardef0x8000を超える入力がなされた場合はUmathcharnumdefとして扱われる

その他

上で紹介した他にもいくつかのプリミティブが存在します。筆者が理解している範囲でプリミティブの効果を記載しますが、備考に記載のないものや引数などはマニュアルを参照してください。

一覧
プリミティブ 備考
mathsurroundskip
mathsurroundmode mathsurroundmathsurroundskipの挙動の制御9
mathscriptboxmode 上(下)付き数式内テキスト周りのカーニングの制御?
mathscriptcharmode 上(下)付き数式内テキストにおけるカーニングの制御?
mathrulethicknessmode undocumented
mathflattenmode
prerelpenalty
prebinoppenalty
mathpenaltiesmode
mathdelimitersmode
variablefam
predisplaygapfactor 別行立て数式前の空白(em単位)
mathdefaultsmode
Udelimiter
mathstyle
Umathcharclass
Umathcharfam
Umathcharslot
mathdir
mathoption デバッグ用?
mathdirection
suppressmathparerror
matheqnogapstep 数式と番号の間の空白
matheqnogapstep
mathdisplayskipmode
mathscriptsmode
mathnolimitsmode
mathitalicsmode
mathrulesmode
matheqdirmode
mathrulesfam undocumented

おわりに

本記事では各プリミティブについて詳しい仕様に踏み込んだ解説をすることは叶わず、一覧を挙げてその効果の概略を記すことしかできませんでした。LuaTeXの追加プリミティブについてさらに知りたければLuaTeXのマニュアルを見れば良い……と言い切れればよかったのですが、実際にはLuaTeXのマニュアルには以下のようにいくつかの注意点があります。

  • 一部のプリミティブについて説明が記載されていない
  • 組版結果の違いのサンプルがあるべき場所で、正しく異なる組版結果が出ていない場合がある
  • 一部のサンプルコードがConTeXt用になっている

これらの要因から、LuaTeXについて知りたい場合でもLuaMetaTeX10のマニュアルを見るか、ConTeXtのプリミティブマニュアルあるいは低レベル組版マニュアルを見る必要があるなど、その調査は困難を極めます。11
余談ですが、LuaTeXのソースコードを覗いてみると、C言語のコードに混じってコメントアウトされた解説がTeXで書かれています。筆者はこれをタイプセットした文書をついに見つけられなかったのですが、この解説を文書化したもの、あるいは文書化する方法をご存知の方がいらっしゃればご連絡ください。

Lua(La)TeXと日本語TeXのさらなる発展を祈ります。皆様も良きTeXライフを。

  1. XeTeXが見放されるのは開発の停滞も大きな要因になっているようですが、npTeXがリリースされた暁にはアクセシビリティ対応の責を追うことになるのでしょうか?

  2. この要件を満たさない場合に記事の内容が全く役に立たないことを意味しません。

  3. いくつかドキュメントに記載のないプリミティブも存在しますが……

  4. 何故かLuaTeX中ではluatexではなくtexコマンドとして登録されています。もしかしてpdfTeXにもある?

  5. タグ付けは部分的に対応しているようで、mmlファイル上ではbevelled="true" linethickness="0"mfracとして、すなわち線の幅が0の傾いた分数として出力されます。(xfracsfracを利用すると数式内テキスト内数式で直接a/bと入力したかのような出力になります)

  6. タグ付きPDFを生成する際に自動生成されるmmlファイルにおいては(横方向についてstretchy="false"とされて伸長の情報が欠けてしまいますが)きちんと1字だけになっています。

  7. overの他にatopoverwithdelimsatopowithdelimsとも利用できるようです。Uskewed等については未検証です。

  8. 細かいことをいえばエラーの出る場面などが異なる他、正常なタグ付けを行うことができません。 2 3 4

  9. 執筆時現在のマニュアル(LuaTeX 1.18 / 2024年2月版)では表の組版結果が正しくありませんが、LuaMetaTeXのマニュアル(LuaMetaTeX 2.11.02 / 2024年2月版)では正しく出力されています。

  10. LuaTeXと並行して開発が進む派生版で、主にConTeXt向けのエンジンのようです。LuaTeXとは袂を分かつようで、変更点をLuaTeXに逆輸入するといったことは基本的に考えられていないみたいです。

  11. もちろん、一部のプリミティブはさらに変更が加えられていたり、あるいは削除されたりしているので、そのままLuaTeXで使えるとは限らず注意が必要です。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?