LoginSignup
4
2

Typst の数式で Stylistic set したい話

Last updated at Posted at 2023-12-11

さいきん流行りの Typst は、レポートや論文を書くために利用されたりしてきているらしいです。

構文はそれなりに簡単で遊んでいるだけでも楽しいので、レポートや論文を書かない人も遊んでみると良いでしょう。LaTeX よりも敷居は低いと思います :blush:


本記事では、そんな 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 が提供されています。hbarplanck.reduce と異なり、横棒が水平な記号が出力されます。
LaTeX における \hbar のようなスタイルです。

compare planck.reduce and hbar (physica)

このようにスタイルの違いがあるので、横棒が水平な記号を出したいと思って 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 の横線も赤色になってしまいます…… :cry:

#set strike( stroke: 3pt + red )

Impact of changing strikethrough

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.reducehbar として利用したい場合は、次のようにしてしまえば良いです。

#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.reducehbar として定義されます。
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]
  )

compare planck.reduce and hbar (ss03)

これによって、同一文書内で planck.reducehbar が別字形の記号として出力されます。

指定フォントには _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)]
  )

compare cal and scr

ただし、hbar のときと同じようにダミーフォントを指定しておく必要があります。

以前までの方法との違い

加筆修正前後で、hbarscr の定義にどのような違いがあったのかを書き残しておきます。

本記事では加筆修正前、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
$

hbar defined by ss03

#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 の周囲のすべてのスペースを取り除いてしまうため、関係演算子や ,: 等との適切なスペースも取り除いてしまって(忘れてしまって)いました。

次の図を確認してください。

compare hbar

h(0pt) で調整した hbar では、= hbar, hbar:hbar: の間で適切なスペースが挿入されていません。
一方で、math.class を利用した hbar では planck.reduce と同じ適切なスペースが挿入されています。

余談

Typst さっぱり分かんないね。でも楽しいから良っか :upside_down:

しかしながら実際は「もっと注意深く ドキュメント を読め」です(自戒)


ところで、Typst のコードを Fenced code block で表現するときの指定言語って、どの言語を指定すると良いのでしょうか。

Rust で実装されていることもあって、本記事では rust を指定していますが、やはり # が変な感じになります。

GitHub.com では typst がすでに Linguist に登録されているので、GitHub であれば気にしなくても済むのですが…… :thinking:

4
2
7

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
4
2