SATySFiでフォントを変更する方法

> これは「SATySFi Advent Caleandar 2018」の14日目の記事です。
（13日目は [youz](http://youz.hatenablog.com/entry/2018/12/13/232909)さんでした。15日目も私です。）

# はじめに
**パッケージマネージャが無いため、手動でdist以下を触っていますが、あまり推奨されません。ざぎん氏の作成した[フォントライブラリ](https://qiita.com/na4zagin3/items/627599ca746756e93bc1)を利用するのが良いでしょう。**

好きなフォントをSATySFiで使う方法は[ZRさんの記事](https://qiita.com/zr_tex8r/items/56dee4364b05974d7a54#%E7%95%AA%E5%A4%96%E7%B7%A8%E5%A5%BD%E3%81%8D%E3%81%AA%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88%E3%82%92%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84)で少し触れられているので、少し補足をしていきます。

今回は実際にDS Snowfallという雪が可愛いフォントをSATySFiで使えるように設定するまでします。

DS Snowfallフォントについては以下の配布ページを見てください。

[![DS Snowfallフォント](https://fontmeme.com/fonts/static/214971/ds-snowfall-font-preview.png)](https://www.1001freefonts.com/ds-snowfall.font)

# フォントを用意する

まずはフォントをダウンロードして`~/.satysfi/dist/fonts`というフォルダにフォントを移動させます（dist/フォルダが存在する場所が~/.satysfi/であると仮定しています）。

```
$ wget https://www.1001freefonts.com/d/17743/ds-snowfall.zip
$ unzip ds-snowfall.zip
$ cp DSSnowfall.otf ~/.satysfi/dist/fonts
```

フォントの種類はいくつかありますが、OpenTypeが一番無難です（The SATySFibook p.96参考）。ipaexm.ttfとかを見るにTrueTypeフォントでもできなくは無いと思いますが、エラーが出る可能性もあります。

# フォントハッシュファイルに登録する

`~/.satysfi/dist/hash/fonts.satysfi-hash`を編集して、フォントを登録します。これをしないと使えるようにはなりません。

OpenTypeとTrueTypeの場合は`"bar": <Single {"src": "dist/fonts/bar.otf"}>`という風に登録していきます（フォント名と登録名は一致していなくても良い）。
TrueType Collectionの場合は`"baz": <Collection {"src": "dist/fonts/baz.ttc", "index": n}>`という風にして、「何番目の要素か」を指定する必要があります。
`"src":`のあとのpathはlib-satysfiからのものなので、ここを上手く設定すると、既存のフォントを移動させずに使えるようになります。

今までは`"src-dist"`が使われていたのですが、最新版では警告が出るようになっています。

今回はfonts.satysfi-hashに

```
"DSSnowfall" : <Single: {"src": "dist/fonts/DSSnowfall.otf"}>
```

を追加します。これでDSSnowfallを使うことでDSSnowfall.otfを呼び出すことができます。

# 実際にフォントを変更する

## 局所的に変更する

フォントの変更は`set-font`というプリミティブで行えます。`set-font`という関数は以下の型を持っています。

`set-font` : script → string ∗ float ∗ float → context → context

なのでこのように`\textDS`を定義することでDS Snowfallにフォントを変更することができます。

```
let-inline ctx \textDS it =
    let ctxDS =
        ctx |> set-font Latin (`DSSnowfall`, 1. ,0.)
    in
read-inline ctxDS it
```

`set-font`の第一引数は以下の4つのいずれかを入れます。

- HanIdeographic（漢字）
- Kana（かな）
- Latin（アルファベット）
- OtherScript（その他）

この場合、DS Snowfallフォントはアルファベット系なのでLatinです。

第二引数は`(string * float * float)`の型です。それぞれ、「フォント名」「フォント拡大率」「上下の補正値」です。これに関してはThe SATySFibookの104ページを読んでください。

## 全体を変更する

局所的にではなく、文書全体にDS Snowfallフォントを適用したいという気持ちがあると思いますが、このときは以下のようにします。

### クラスファイルを書き換える

stdja.satyhでは75～79行目・stdjabook.satyhでは94～99行目・stdjareport.satyhでは83～88行目に以下のようなフォントの定義があるので、これを書き換えることで全体のフォントを変更します。

具体的には以下のような記述があるので、

```
  let font-latin-roman  = (`Junicode`   , font-ratio-latin, 0.)
  let font-latin-italic = (`Junicode-it`, font-ratio-latin, 0.)
  let font-latin-sans   = (`lmsans`    , font-ratio-latin, 0.)
  let font-latin-mono   = (`lmmono`    , font-ratio-latin, 0.)
  let font-cjk-mincho   = (`ipaexm`    , font-ratio-cjk  , 0.)
  let font-cjk-gothic   = (`ipaexg`    , font-ratio-cjk  , 0.)
```

これを

```
  let font-latin-roman  = (`DSSnowfall`   , font-ratio-latin, 0.)
  let font-latin-italic = (`Junicode-it`, font-ratio-latin, 0.)
  let font-latin-sans   = (`lmsans`    , font-ratio-latin, 0.)
  let font-latin-mono   = (`lmmono`    , font-ratio-latin, 0.)
  let font-cjk-mincho   = (`ipaexm`    , font-ratio-cjk  , 0.)
  let font-cjk-gothic   = (`ipaexg`    , font-ratio-cjk  , 0.)
```

のように書き換えることでローマン体をDSSnowfallにすることができます。他の書体やフォントについても同じようにすればできます。

ちなみに、ここで定義している`font-latin-roman`等は`set-font`の第二引数になるものです。

### ExDesignクラスファイルを使用する

拙作の[ExDesignクラス](https://github.com/puripuri2100/exdesign)ではデフォルトでフォントを変更する機能があります。

```
fonts : (|
    latin-roman : string;
    latin-bold : string;
    latin-italic : string;
    latin-sans : string;
    latin-mono : string;
    cjk-mincho-l : string;
    cjk-mincho-m : string;
    cjk-mincho-bx : string;
    cjk-gothic-m : string;
    cjk-gothic-bx : string;
    cjk-gothic-eb : string;
    math-font : string;
    ratio-latin : float;
    ratio-cjk : float;
    correction-latin : float;
    correction-cjk : float;
|)
```
の型を持つ`fonts`が`document`のレコード型にあります（レコード型が2重になっているのでこのような変な表現になっています）。

ここにそれぞれフォント名と補正値や拡大率を入れることできちんと変更することができます。今回はこのようにしてみました。

```
fonts = (|
            latin-roman = `DSSnowfall`;
            latin-bold = `Junicode-b`;
            latin-italic = `Junicode-it`;
            latin-sans = `lmsans`;
            latin-mono = `lmmono`;
            cjk-mincho-l = `ipaexm`;
            cjk-mincho-m = `ipaexm`;
            cjk-mincho-bx = `ipaexm`;
            cjk-gothic-m = `ipaexg`;
            cjk-gothic-bx = `ipaexg`;
            cjk-gothic-eb = `ipaexg`;
            math-font = `lmodern`;
            ratio-latin = 1.;
            ratio-cjk = 0.88;
            correction-latin = 0.;
            correction-cjk = 0.;
        |)
```

是非試してください

# 結果

素敵なロゴです

<img width="1224" alt="satysfi-fig-2018-2.png" src="https://qiita-image-store.s3.amazonaws.com/0/222743/236dcf3f-77a2-d0b1-6889-104a8f961053.png">



# さいごに

これでSATySFiでフォントを変える方法がわかったはずなので、ヒラギノが好きな人はヒラギノを使ってみてはどうでしょうか（Macを持っていないのでできるかはわかりませんが）。