さいきん流行りの Typst は、レポートや論文を書くために利用されたりしてきているらしいです。
構文はそれなりに簡単で遊んでいるだけでも楽しいので、レポートや論文を書かない人も遊んでみると良いでしょう。LaTeX よりも敷居は低いと思います
本記事では、そんな Typst の数式で遊んでいたときに見つけた、フォントに関するちょっとしたテクニックと不思議な挙動について紹介します。
本記事は Typst 0.10.0 (70ca0d25) です。また、physica 0.9.0 を使用しています。
@zr_tex8r 様からのコメントを経て、全体を通して加筆修正しました。
これらのコメントによってより良い記事に繋がりました。誠にありがとうございます。
本記事の情報はバージョン 0.10.0 のみで再現されます。これ以降のバージョンでは再現されない可能性があることに注意してください。
0.11.0 での対応は zr-tex8r 様のコメント 参照してください。
Typst と physica の “ℏ”
Typst には planck.reduce
によって “ℏ” を出力することが出来ます。
“ℏ” は、多くのフォントで横棒が斜めであり、LaTeX における \hslash
のようなスタイルになっています。
一方で、physica パッケージから hbar
が提供されています。hbar
は planck.reduce
と異なり、横棒が水平な記号が出力されます。
LaTeX における \hbar
のようなスタイルです。
このようにスタイルの違いがあるので、横棒が水平な記号を出したいと思って physica の hbar
を使うと、とんでもない結果を得る可能性があります。
実はこの physica (0.9.0) の hbar
、かなり曲者でビックリ実装がなされています。
コードを見てみると、physica では hbar
を ℎ (U+210E) に 取り消し線 を組み合わせる形で以下のように 実装されています。
#let hbar = (
sym.wj,
move(
dy: -0.08em,
strike(
offset: -0.55em,
extent: -0.05em,
sym.planck
)
),
sym.wj
).join()
この実装では strike
の変更をもろに受けてしまうため、以下のように取り消し線を赤色に変更したりすると、hbar
の横線も赤色になってしまいます……
#set strike( stroke: 3pt + red )
strike
をそのまま使う人にとっては問題ありませんが、ちょっとでも変更する人にとっては大きな問題になる可能性があります。
Unicode 上の “ℏ”
Typst にしても LaTeX にしても、横棒が斜めと水平の “ℏ” を異なる記号として利用しようとしています。
しかし、Unicode 上の ℏ (U+210F) は、横棒が “斜め” か “水平” かは問わず、同じ文字として登録されています。
どちらのスタイルになっているかはフォントに依存しています。
そのため、フォントによっては元の字形と代替字形を入れ替えられる Stylistic set (ss) や Character variant (cv) があります。
これを指定することでスタイルを変更することが、スタンダードな方法になると思います。
フォントの代替字形を利用する
フォントによっては “ℏ” の代替字形が収録されています。
例えば、STIX Two Math では ss03 (stylistic set 03) に “ℏ” の代替字形が収録されています。
Typst では、このようなフォントの機能を features
パラメタ や stylistic-set
パラメタ を利用することで有効にすることが出来ます。
STIX Two Math の ss03 を有効にする場合は、次のようにします。これによって planck.reduce
の横棒が水平な記号に代わります。
#show math.equation: set text(
font: "STIX Two Math",
stylistic-set: 03
)
もしも、planck.reduce
を hbar
として利用したい場合は、次のようにしてしまえば良いです。
#let hbar = math.planck.reduce
複数の機能を有効にする場合は、features
パラメタを利用すると良いです。列挙すれば有効になります。
#show math.equation: set text(
font: "STIX Two Math",
features: (
"ss01", // cal(a) の代替字形
"ss03", // planck.reduce の代替字形
"cv03" // emptyset の代替字形
)
)
これらの機能は、フォントによって番号が異なるため注意してください。
hbar
だけに Stylistic set を有効にする
planck.reduce
とは別に hbar
を利用したい場合もあるかも知れません。
次のようにすると、ss03 が指定された planck.reduce
が hbar
として定義されます。
math.class
は数学記号の種類を指定します。"normal"
は通常の数学記号です。
#show math.equation: set text(font: "STIX Two Math")
#let hbar = math.class(
"normal",
text(
font: ("STIX Two Math", "_foo"),
// "_foo" はダミーフォントです
stylistic-set: 03
)[#math.planck.reduce]
)
これによって、同一文書内で planck.reduce
と hbar
が別字形の記号として出力されます。
指定フォントには _foo
というダミーフォントが含まれていますが、これがないとなぜか上手くいきません。
バグなのか何なのかも分からない(かつユーザー側にデメリットが特にない)ので、これは Issue として報告した方が良さそうだぞと思う人は報告してください。
筆記体を 2 種類出したい
Stylistic set 繋がりとして、筆記体に関しても 2 種類出す方法を紹介します。
LaTeX では \mathcal
と \mathscr
があるように、2 つの筆記体(ないしは花文字)があります。
これらも “ℏ” と同じように Unicode 上では同じ文字コードとして扱われており、そのスタイルはフォントによって異なります。また、Stylistic set によってそのスタイルを変更できるフォントがあります。
STIX Two Math では ss01 に cal(a)
の代替字形があるので、以下のように scr(a)
を定義すれば良いです。
#show math.equation: set text(font: "STIX Two Math")
#let scr(a) = math.class(
"normal",
text(
font: ("STIX Two Math", "_foo"),
stylistic-set: 01,
)[#math.cal(a)]
)
ただし、hbar
のときと同じようにダミーフォントを指定しておく必要があります。
以前までの方法との違い
加筆修正前後で、hbar
や scr
の定義にどのような違いがあったのかを書き残しておきます。
本記事では加筆修正前、hbar
をまず以下のように定義していました。
#let hbar = text(
font: "STIX Two Math",
stylistic-set: 03,
)[#math.planck.reduce]
しかし、この方法では hbar
の周囲に余分なスペースが生じてしまっていました。
これは、次のように書いていることと同じ状況になっていたためです。
$
i
#text(font: "STIX Two Math", stylistic-set: 03)[#math.planck.reduce]
c
$
#math.planck.reduce
がテキスト(複数文字)と同じ扱いとなっていたために、hbar
とその他の数学記号との間にスペースを取るようになっていました。
これに対応するため、以前の本記事では h(0pt)
を使って次のようにスペースを取り除いていました。
#let hbar = (
h(0pt),
text(
font: "STIX Two Math",
styilstic-set: 03
)[#math.planck.reduce],
h(0pt)
).join()
しかし、この方法では hbar
の周囲のすべてのスペースを取り除いてしまうため、関係演算子や ,
・:
等との適切なスペースも取り除いてしまって(忘れてしまって)いました。
次の図を確認してください。
h(0pt)
で調整した hbar
では、= hbar
や , hbar
、:hbar:
の間で適切なスペースが挿入されていません。
一方で、math.class
を利用した hbar
では planck.reduce
と同じ適切なスペースが挿入されています。
余談
Typst さっぱり分かんないね。でも楽しいから良っか
しかしながら実際は「もっと注意深く ドキュメント を読め」です(自戒)
ところで、Typst のコードを Fenced code block で表現するときの指定言語って、どの言語を指定すると良いのでしょうか。
Rust で実装されていることもあって、本記事では rust
を指定していますが、やはり #
が変な感じになります。
GitHub.com では typst
がすでに Linguist に登録されているので、GitHub であれば気にしなくても済むのですが……