# 機能設計書 16-Nerd Fonts対応

## 概要

本ドキュメントは、GhosttyのNerd Fonts対応機能の設計について記述する。Nerd Fontsのアイコンやシンボルグリフのスケーリング・配置を最適化し、ターミナル上で美しく表示するための機能である。

### 本機能の処理概要

**業務上の目的・背景**：
Nerd Fontsは、開発者向けのアイコンフォントで、多数のシンボル・アイコングリフを含む。これらのグリフは元のデザインサイズが異なり、そのまま表示すると位置ずれやサイズの不整合が発生する。本機能は、Nerd Fontsパッチャースクリプトから抽出した制約情報を使用して、各グリフを最適なサイズと位置で表示する。

**機能の利用シーン**：
- Powerlineシンボル（矢印、区切り線）の表示
- ファイルタイプアイコンの表示（、等）
- 天気アイコン、Deviconsの表示
- tmux、vim-airline等でのステータスライン装飾

**主要な処理内容**：
1. コードポイントに対する制約情報の取得
2. サイズ制約（fit, cover, stretch等）の適用
3. 水平・垂直アライメントの計算
4. パディングの適用
5. アスペクト比制限の適用
6. グリフの最終サイズと位置の計算

**関連システム・外部連携**：
- Nerd Fontsパッチャー（制約データの元ソース）
- フォントフェイス（グリフラスタライズ）
- レンダラー（制約適用後の描画）

**権限による制御**：
特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインターミナルウィンドウ | 主画面 | Nerd Fontsアイコンの表示 |

## 機能種別

レンダリング前処理 / レイアウト計算

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| cp | u21 | Yes | Unicodeコードポイント | 有効なNerd Fontsコードポイント |
| glyph | GlyphSize | Yes | グリフの元サイズ | 正の値 |
| metrics | Metrics | Yes | フォントメトリクス | 有効なメトリクス |
| constraint_width | u2 | Yes | 使用可能なセル幅 | 1または2 |

### 入力データソース

- nerd_font_attributes.zig（自動生成された制約データ）
- フォントフェイスからのグリフサイズ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| constraint | Constraint | 適用する制約情報 |
| size | GlyphSize | 制約適用後のグリフサイズと位置 |

### 出力先

レンダラーのグリフ描画処理

## 処理フロー

### 処理シーケンス

```
1. コードポイントから制約取得
   └─ getConstraint(cp)でConstraintを取得
2. 制約の適用判定
   └─ doesAnything()でnone以外かチェック
3. スケーリング計算
   └─ scale_factors()でwidth/height係数を計算
4. アライメント計算
   └─ aligned_x(), aligned_y()で位置を計算
5. 最終サイズ計算
   └─ constrain()で最終的なGlyphSizeを返す
```

### フローチャート

```mermaid
flowchart TD
    A[コードポイント取得] --> B{制約あり?}
    B -->|No| C[元のサイズを使用]
    B -->|Yes| D[サイズモード判定]
    D --> E{Size}
    E -->|fit| F[縮小のみ]
    E -->|cover| G[アスペクト比維持で拡大縮小]
    E -->|stretch| H[アスペクト比無視で伸縮]
    E -->|fit_cover1| I[1セル基準でfit/cover]
    F --> J[アライメント計算]
    G --> J
    H --> J
    I --> J
    J --> K[パディング適用]
    K --> L[最終サイズ返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | Powerline特別処理 | 矢印グリフはセル境界をまたぐ | U+E0B0-E0BF |
| BR-02 | center1ルール | マルチセルでも1セル目を基準に中央配置 | center1指定時 |
| BR-03 | max_xy_ratio | アスペクト比が指定値を超えないよう制限 | ratio指定時 |
| BR-04 | ワイドフォント制限 | face_width > 0.9 * face_height なら1セル幅に制限 | stretch時 |

### 計算ロジック

スケール係数計算：
- `target_width = pad_width_factor * metrics.face_width`
- `target_height = pad_height_factor * height_metric`
- `width_factor = target_width / group.width`
- `height_factor = target_height / group.height`

アライメント計算：
- `start`: パディング分だけ端からオフセット
- `end`: 終端からグリフサイズを引いた位置
- `center`: (start + end) / 2
- `center1`: 1セル幅内で中央配置

## データベース操作仕様

該当なし

## エラー処理

### エラーケース一覧

エラーは発生しない（nullを返すのみ）

### リトライ仕様

該当なし

## トランザクション仕様

該当なし

## パフォーマンス要件

- getConstraintは O(1) のswitch文で実装
- 制約計算は単純な算術演算のみ
- フレームレートへの影響なし

## セキュリティ考慮事項

特になし（読み取り専用の制約データ）

## 備考

- nerd_font_attributes.zigはnerd_font_codegen.pyで自動生成
- 対応コードポイントの追加はPythonスクリプトで行う

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | face.zig | `src/font/face.zig` | Constraint構造体（143-227行目）とSize/Align enum |
| 1-2 | face.zig | `src/font/face.zig` | GlyphSize構造体（97-102行目） |

**読解のコツ**: ConstraintはSize, Align, パディング、relative_*の組み合わせ。doesAnything()で実際に処理が必要か判定できる。

#### Step 2: 制約データを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | nerd_font_attributes.zig | `src/font/nerd_font_attributes.zig` | getConstraint関数全体 |

**主要処理フロー**:
1. **10-11行目**: getConstraint関数のシグネチャ
2. **12-500行目**: コードポイントごとのswitch文で制約を返す
3. Powerlineシンボル（U+E0B0-E0D7）は.stretchでセル境界をまたぐ
4. アイコン（U+E300以降）は.fit_cover1でセル内に収める

#### Step 3: 制約適用処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | face.zig | `src/font/face.zig` | constrain関数（240-273行目） |
| 3-2 | face.zig | `src/font/face.zig` | constrainInner関数（276-330行目） |
| 3-3 | face.zig | `src/font/face.zig` | scale_factors関数（333-408行目） |
| 3-4 | face.zig | `src/font/face.zig` | aligned_y, aligned_x関数（411-492行目） |

**主要処理フロー**:
- **249-271行目**: stretchモードはグリッド基準でスケール
- **292-301行目**: グループ境界ボックスの計算（relative_*使用）
- **305-311行目**: スケール係数の適用
- **320-321行目**: アライメントの適用
- **364-396行目**: Size enumごとのスケール計算ロジック

### プログラム呼び出し階層図

```
getConstraint(codepoint)
    └─ switch文でConstraintを返す

Constraint.constrain(glyph, metrics, constraint_width)
    │
    ├─ doesAnything() → falseならそのまま返す
    │
    ├─ [stretch時] constrainInner() with grid調整
    │
    └─ constrainInner()
           ├─ グループ境界計算（relative_*）
           ├─ scale_factors()
           │      ├─ fit: min(1, w_factor, h_factor)
           │      ├─ cover: min(w_factor, h_factor)
           │      ├─ fit_cover1: マルチセルでも1セル基準
           │      └─ stretch: w_factor, h_factor独立
           │
           ├─ aligned_y()
           │      └─ start/end/center/center1
           │
           └─ aligned_x()
                  └─ start/end/center/center1
```

### データフロー図

```
[入力]               [処理]                    [出力]

コードポイント ─────▶ getConstraint() ────▶ Constraint

グリフサイズ ───────▶ constrain() ─────────▶ 調整済みサイズ
        │
        ├─▶ scale_factors() ─▶ (width_factor, height_factor)
        │
        └─▶ aligned_x/y() ───▶ (x, y)位置
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| nerd_font_attributes.zig | `src/font/nerd_font_attributes.zig` | ソース（自動生成） | コードポイント制約マップ |
| face.zig | `src/font/face.zig` | ソース | Constraint構造体と制約適用ロジック |
| generic.zig | `src/renderer/generic.zig` | ソース | getConstraint呼び出し（30行目） |
| nerd_font_codegen.py | (ビルドツール) | Python | 制約データ生成スクリプト |
