フォントの基本とグリフの調べ方

# はじめに
* 「いま使っているフォントには、どこまで定義されているのだろう？」となったとき、様々な読み書きのツールが存在する
* フォントの形式って何があって、静的・動的フォントとは何か、そしてどのような方法でフォントの中身を見ることができるか示す

# フォントファイルの形式
まず、フォントファイルの形式って何があるんだっけ？という復習
## TrueType (ttf)
* 開発者
    * 1990年前半にApple, Microsoftが開発
* 特徴
    * Windows, Macどちらにも使えるが互換性はない
    * OpenTypeより文字セットが少なめ
    * グリフの輪郭はベジエ曲線（2次ベジエ曲線）を使用して定義
        * 600 dpis程度が限界
    * 価格は安価な場合が多い

## OpenType (otf)
* 開発者
    * 1990年後半Microsoft, Adobeが開発、後にAppleも賛同
* 特徴
    * Windows, Macどちらにも使えて互換性がある
    * TrueTypeより文字セットは多め
    * TrueTypeの拡張版で、より多くの機能を持つ
        * 合字、プロポーショナルメトリクス（文字詰め）など
    * グリフの輪郭は3次ベジエ曲線（CFFアウトライン）を使用できるため、拡縮に強い

# フォントファイル
次に解析のための題材として、Noto Sans Japaneseのフォントをダウンロードしてみる

https://fonts.google.com/noto/specimen/Noto+Sans+JP

```
.
├── NotoSansJP-VariableFont_wght.ttf
├── OFL.txt
├── README.txt
└── static
    ├── NotoSansJP-Black.ttf
    ├── NotoSansJP-Bold.ttf
    ├── NotoSansJP-ExtraBold.ttf
    ├── NotoSansJP-ExtraLight.ttf
    ├── NotoSansJP-Light.ttf
    ├── NotoSansJP-Medium.ttf
    ├── NotoSansJP-Regular.ttf
    ├── NotoSansJP-SemiBold.ttf
    └── NotoSansJP-Thin.ttf

```
* `static`フォルダ以下にあるスタティックフォントと、フォルダ直下にあるバリアブルフォントに分かれる
* スタティック（静的）フォント
    * Bold, SemiBoldといった、個々のスタイルのフォントファイル
    * スタイルの数だけフォントファイルが増える
* ダイナミック（可変）フォント
    * 2016年にAdobe, Apple, Google, Microsoftが発表したフォントの規格
    * その名の通りダイナミックに、太さや字幅などを調整できる
    * ファイルサイズが小さめ
        * スタティックフォントで定義していた中間的なフォント定義が不要になるため
    * 古いグラフィックツールやブラウザにしか対応していない場合あり
    * フォント解析ツールとかに読み込ませると、ダイナミックフォントは太さなどを色々と試せる

# フォント解析ツール
Noto Sans Japaneseをダウンロードして、ttfファイルを下記のサービスやツールを使って読み込ませてみた。ここでは解析結果ではなく、概要だけを記す

## FontDrop!
https://fontdrop.info/
* Viktor Nübelという会社のサービス
* フォントをドラッグ＆ドロップするだけで、タブごとにグリフ・合字・テキスト例など、色んな情報を出してくれる
* 個人的には1番見やすい気がする

## Opentype.js
https://opentype.js.org/
* フォント読み書きの[オープンソース](https://github.com/opentypejs/opentype.js)のツール
* [Font Inspector](https://opentype.js.org/font-inspector.html)と[Glyph Inspector](https://opentype.js.org/glyph-inspector.html)に分かれ、それぞれフォントを読み込むことで、フォントやグリフの情報を表示してくれる
* グリフの頂点情報も表示してくれる

## Vertical-metrics
https://vertical-metrics.netlify.app/
* 開発元は分からなかったが、上記2つとはちょっと毛色が違い、各グリフの主に高さを解析してくれる
* フォントを読み込ませ、テキストを入力するとAscender, capHeightといった、フォントの高さ情報を詳細に表示してくれる

## FontForge
https://fontforge.org/en-US/
* フォント読み書きの[オープンソース](https://github.com/fontforge/fontforge)
* ブラウザではなくアプリケーションプログラムとして動くツール
* フォントの解析というよりは、フォントの作成がメインのツールのよう
* Linux用にもAppImageを提供しており、下記のような感じで実行できる
    * `./FontForge-2023-01-01-a1dad3e-x86_64.AppImage`
* UIがちょっと古いが、ツールの中でPythonのスクリプトを動かすことも可能

# プログラムで解析する
* 「グリフの最大高さを調べたい」「グリフの最小高さを調べたい」などといったときは、コードを書いて解析した方が良い場合もありそう
* ということで、Pythonでどんな感じで分析できそうかやってみた

### サンプルコード
```python
from fontTools.ttLib import TTFont

def get_max_and_min_height_glyph(ttf_path):
    # フォントファイルを読み込む
    font = TTFont(ttf_path)

    # 文字マップとグリフテーブルを取得
    cmap = font.getBestCmap()
    glyf_table = font['glyf']

    # 最大高さと最小高さの初期値を設定
    max_height = 0
    min_height = float('inf')

    # 最大・最小高さのグリフ名と文字の初期値を設定
    max_height_glyph_name = None
    min_height_glyph_name = None
    max_height_char = None
    min_height_char = None

    print(f"グリフの数: {len(glyf_table.glyphs.keys())}")

    # cmapをループして各グリフを調べる
    for codepoint, glyph_name in cmap.items():
        glyph = glyf_table[glyph_name]

        # グリフにyMaxとyMinが存在するかを確認
        if hasattr(glyph, 'yMax') and hasattr(glyph, 'yMin'):
            # 高さを計算
            height = glyph.yMax - glyph.yMin

            # 最大高さを更新
            if height > max_height:
                max_height = height
                max_height_glyph_name = glyph_name
                max_height_char = chr(codepoint)

            # 最小高さを更新
            if height < min_height:
                min_height = height
                min_height_glyph_name = glyph_name
                min_height_char = chr(codepoint)

    # 結果を表示
    print(f"最小の高さを持つグリフ: {min_height_glyph_name}, 文字: {min_height_char}, 高さ: {min_height}")
    print(f"最大の高さを持つグリフ: {max_height_glyph_name}, 文字: {max_height_char}, 高さ: {max_height}")

ttf_path = './NotoSansJP-Bold.ttf'
get_max_and_min_height_glyph(ttf_path)
```
```
グリフの数: 17808
最小の高さを持つグリフ: SF100000, 文字: ─, 高さ: 40
最大の高さを持つグリフ: uni3031, 文字: 〱, 高さ: 1882
```
* ライブラリの順は `pip3 install fonttools` のみ
* `NotoSansJP-Bold`を読み込ませてみたところ、それらしい値を出力してくれていそうだった

# 参考文献
* [TrueTypeとOpenTypeの見分け方と違い](https://note.com/9ninece/n/n7f6d84fd53cc)