SATySFi で「太字」にしたい（satysfi-fss の紹介）

この記事は [SATySFi Advent Calendar 2020](https://adventar.org/calendars/4965) 
 11 日目の記事である。


10 日目 @monaqa『[【入門記事】SATySFi のコマンド記法](https://zenn.dev/monaqa/articles/2020-12-10-satysfi-for-beginner-command-syntax)』
12 日目 @yasuo-ozu『[SATySFi入門とリンク集](https://qiita.com/yasuo-ozu/items/8f57489fa15cc26aedac)』

本稿では SATySFi でフォント選択を行うライブラリ [satysfi-fss](https://github.com/na4zagin3/satysfi-fss) （0.2.0 版）について紹介する。

本稿執筆時点の SATySFi （0.0.5 版）では、フォント選択は各書字体系にフォント名・高さ・大きさを設定する仕組みになっており、LaTeX の New Font Selection Scheme (NFSS) のように、太さ（ウェイト）・文字幅等を独立に設定することはできない。

<!-- gfn さん曰く「日本語組版では、本文書体が明朝体、強調・見出しにはゴシック体といった風で、欧文組版とは考え方が異なるので、現在の SATySFi には NFSS のようなものは実装していない」[^gfn-pc]とのことであった。 -->

[^gfn-pc]: Online.LaTeX 2020 にて

私は SATySfi で欧文組版がしたいので、satysfi-fss を実装することにした。

# 結果
2020-12-12 日中には [Satyrographos](https://github.com/na4zagin3/satyrographos/blob/master/README-ja.md) でインストール可能になるはずである。

```
opam install satysfi-fss
satyrographos install
```

以下のパッケージをインボートすること。

```
@require: fss/fss
@require: fss/fonts
@require: fss/style
```


`\font-set[<font-set>...]{ ... }` でフォントセットを設定し、`\font-style[<style-keyword>...]{ ... }` でフォント軸を設定。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20044/9ab1ba85-0b6c-5dee-967c-e0161f7a8f84.png)


```satysfi
+p{
  \font-style[font-set default-font-set; bold]{
    bold,
    \font-style[italic]{
      bold italic,
    }
    bold,
  }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20044/668ce815-82a9-0f11-b5b6-021ea8402cf0.png)

```satysfi
+font-style[font-set bodoni-star-font-set]<
  +p {
    \font-style[font-size 6pt]{6pt,}
    \font-style[font-size 11pt]{11pt,}
    \font-style[font-size 16pt]{16pt,}
    \font-style[font-size 24pt]{24pt,}
    \font-style[font-size 36pt]{36pt
      \font-style[italic]{italic,}
    }
    \font-style[font-size 48pt]{48pt
      \font-style[bold; italic]{bold italic,}
    }
    \font-style[font-size 72pt]{
      72pt
      \font-style[bold]{bold.}
    }
  }
>

```

# フォント・フォントファミリー
活版組版では、各字形が一つの活字で表現され、一揃いの活字のことを「フォント」、また、異なる大きさ・ウェイト等を持ち関連するフォントの組を「フォントファミリー」と呼んでいた訳である。コンピューターにおける組版でもおおよそ同じである。

以下の軸・属性がよく用いられる。

- 大きさ (font size)
- 太さ・ウェイト (weight)
- 幅 (width)
- 他： italic や oblique 等

# SATySFi におけるフォント
**この節の内容は将来の SATySFi において変更される可能性があることに注意せよ**

SATySFi 0.0.5 において、フォントは「単に OpenType フォントファイルに関連付けられたフォント名 $F$ ではなく、これに拡大率$r$とベースライン調整率$r'$という2つの数値が備えつけられた3つ組 $(F,r,r')$ である」[^satysfi-book-p104]。各対応書字体系（`Latin`、`Kana`、`HanIdeographic`、`OtherScript` の四種）にフォントを設定することになっている。

[^satysfi-book-p104]: SATySFi Book. p104.

フォントを設定する際には、以下のプリミティヴを用いる。

- `set-font-size : length -> context -> context`  
  `set-font-size size ctx` は `ctx` のフォントの大きさを `size` に設定したものを返す。
- `set-font : script -> (string * float * float) -> context -> context`  
  `set-font script (font-name, ratio, raise) ctx` は、 


# フォントセット

以上を踏まえ、satysfi-fss では「フォントの軸等で張られる空間の元 $a$ と書字体系 $s$ とからのフォント $f$ への写像 $\mathit{fs}:(a, s)\mapsto f$」をフォントセット $\mathit{fs}$ とする[^fontset]。

[^fontset]: Emacs における[フォントセット](https://www.gnu.org/software/emacs/manual/html_node/emacs/Modifying-Fontsets.html)に範を取ったものである。

satysfi-fss では内部的には以下の軸を用意している。

- 大きさ (font size)：`set-font-size` プリミティヴで設定される長さ
- 太さ・ウェイト (weight)：light, medium, bold 等々
- 幅 (width)： condensed, normal, expanded 等々
- その他スタイル：italic や oblique 等

フォントセット並びに各軸の値は引き回して各所で部分的に変更したいため、`context` にあってほしい所だが、SATySFi 0.0.5 の `context` に存在するのは大きさのみであるので、その他の値を保持するために以下の `fss-extendened-context` 型を定義する[^extended-context]。

[^extended-context]: 将来の SATySFi で `context` が拡張可能になった暁には `fss-extendened-context` 型を<ruby><rb>態〻</rb><rt>わざわざ</rt></ruby>定義する必要が無くなる。

```satysfi
type fss-extended-context =
  (| context : context ;
     font-set : fss-font-set ;
     font-axes : fss-font-axes ;
  |)
```

# スタイルキーワード
satysfi-fss 0.2.0 では、スタイルの変更は単に `style` (= `fss-extendened-context -> fss-extendened-context`) 型の函数を `\font-style` の引数として与えることで行う。

以下のキーワードが用意されている。

- `font-set : fss-font-set -> style` 指定されたフォントセットに設定
- `font-size : length -> style` 指定された大きさに設定
- `with-font-size : (length -> length) -> style` 現在の大きさを指定された函数に適用し、その返り値を大きさとして設定
- `medium : style` 中字に設定
- `bold : style` 太字に設定
- `upright : style` 立体に設定
- `italic : style` イタリック体に設定

スタイルキーワードの合成には `FssStyle.concat : style list -> style` を用いる[^style-concat]。
[^style-concat]: satysfi-fss 0.2.0 では単なる函数合成である。

# スタイル変更コマンド（`\font-style`、`+font-style`）
スタイル変更コマンド`\font-style[<style-keyword>...]{ inline text }`は、単に現在の `fss-extendened-context` [^context]にスタイルキーワードを適用しフォントセットとフォント軸を更新し、フォント軸をフォントセットに適用し、その結果を以ってフォント選択を行うものである。

[^context]: satysfi-fss 0.2.0 では、`fss-extendened-context` 型の `context` 欄は現在の `context` から取得することになるが、他の欄は大域変数に保存され、故に `context` を保存してもフォントセットやフォント軸の情報は保存されないことに注意せよ。

# 課題
主には以下の課題がある。

- 強調 `\emph` の実装方法。以下のように、各言語で別種の方式が用いられるので、これを適切に実装可能な仕組みを提供する必要がある。
    - 英語等では LaTeX の `\emph` が既定でするように、ローマン体中ではイタリック体、イタリック体中ではローマン体にする。
    - 日本語の或る方式では明朝体中でゴシック体にする。入れ子の場合にどうなるかは私は未だ知らない。
    - 日本語のまた或る様式では圏点を付する。入れ子では圏点の記号を変える。
    - ドイツ語（髭文字）等では隔字体を用いる。入れ子の場合にどうなるかは私は未だ知らない。
- フォントセットをユーザ側で定義する方法を提供せねばならない。上の問題等を解決する際にモデルを変更する可能性があるので、フォントセット定義API提供はその後にしたい。
- 理想的には SATySFi 本体にフォント選択機構が入っているべきであると思うので、satysfi-fss の知見を基に実装の提案をしようと思っている。