# 機能設計書 14-フォント管理

## 概要

本ドキュメントは、Ghosttyのフォント管理機能の設計について記述する。システムフォントの検出・ロード、フォールバックフォントの管理を行い、適切なフォントでテキストをレンダリングするための基盤機能である。

### 本機能の処理概要

**業務上の目的・背景**：
ターミナルエミュレータでは、ユーザーが指定したフォントを使用してテキストを表示する必要がある。しかし、指定されたフォントがシステムに存在しない場合や、特定の文字（絵文字、CJK文字等）をサポートしていない場合がある。フォント管理機能は、プラットフォームごとのフォント検出API（Fontconfig、CoreText）を抽象化し、フォールバックチェーンを構築することで、あらゆる文字を適切なフォントで表示できるようにする。

**機能の利用シーン**：
- ユーザー指定フォントのロードと検証
- 未サポート文字のフォールバックフォント検索
- 太字・斜体スタイルのフォント解決
- 絵文字フォントの自動選択
- CJK文字の適切なフォント選択

**主要な処理内容**：
1. Descriptorによるフォント検索条件の指定
2. プラットフォーム固有のフォント検出（Fontconfig/CoreText）
3. フォントマッチングとスコアリング
4. DeferredFaceによる遅延ロード
5. フォントコレクションの管理
6. コードポイントベースのフォールバック解決

**関連システム・外部連携**：
- Fontconfig（Linux）
- CoreText（macOS）
- FreeType（フォントラスタライズ）
- HarfBuzz（テキストシェーピング）

**権限による制御**：
特になし。システムフォントへのアクセスはOSの権限に従う。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインターミナルウィンドウ | 主画面 | フォントによるテキスト表示 |

## 機能種別

データ管理 / システム連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| family | ?[:0]const u8 | No | フォントファミリー名 | 有効な文字列 |
| style | ?[:0]const u8 | No | フォントスタイル名 | 有効な文字列 |
| codepoint | u32 | No | 必須対応コードポイント | 有効なUnicode |
| size | f32 | No | フォントサイズ（ポイント） | 正の数値 |
| bold | bool | No | 太字フィルター | - |
| italic | bool | No | 斜体フィルター | - |
| monospace | bool | No | 等幅フィルター | - |
| variations | []Variation | No | バリエーション軸 | 有効な軸設定 |

### 入力データソース

- 設定ファイル（font-family設定）
- システムフォントデータベース

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| face | DeferredFace | 遅延ロードされるフォントフェイス |
| iterator | DiscoverIterator | マッチしたフォントのイテレータ |

### 出力先

フォントコレクション（font.Collection）

## 処理フロー

### 処理シーケンス

```
1. Descriptor作成
   └─ 検索条件（ファミリー、スタイル、特性）を設定
2. Discover初期化
   └─ プラットフォーム固有の検出器を初期化
3. フォント検索
   └─ discover/discoverFallbackでマッチング実行
4. スコアリングとソート
   └─ CoreTextの場合、特性マッチでスコア計算
5. イテレータ取得
   └─ DiscoverIteratorでマッチ結果を順次取得
6. DeferredFace作成
   └─ 遅延ロード用のフェイスを作成
```

### フローチャート

```mermaid
flowchart TD
    A[Descriptor作成] --> B{プラットフォーム}
    B -->|Linux| C[Fontconfig検索]
    B -->|macOS| D[CoreText検索]
    C --> E[パターンマッチング]
    D --> F[スコアリングとソート]
    E --> G[イテレータ作成]
    F --> G
    G --> H[DeferredFace生成]
    H --> I[Collectionに追加]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | モノスペース優先 | モノスペース特性を持つフォントを優先 | 検索時 |
| BR-02 | CJKフォント選択 | CJK文字はシステムロケールを考慮 | コードポイント0x4E00-0x9FFF |
| BR-03 | LastResort除外 | CoreTextのLastResortフォントを結果から除外 | フォールバック時 |
| BR-04 | スタイルマッチ | bold/italicフラグは特性と文字列の両方でマッチ | スコアリング時 |

### 計算ロジック

スコア計算（CoreText）：
- `codepoint`: 最高優先度、コードポイントサポートで+1
- `monospace`: モノスペース特性で+1
- `exact_style`: スタイル完全一致で+1
- `italic`: イタリック一致で+1
- `bold`: ボールド一致で+1
- `fuzzy_style`: スタイル部分一致でスコア加算
- `glyph_count`: 同点時はグリフ数で決定

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

該当なし（システムフォントキャッシュを参照）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| FontConfigFailed | 検索エラー | Fontconfig検索失敗 | エラー返却 |

### リトライ仕様

リトライなし。エラー時は組み込みフォントにフォールバック。

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

該当なし

## パフォーマンス要件

- フォント検索はキャッシュを活用
- DeferredFaceで必要時までロードを遅延
- フォントコレクションで一度ロードしたフェイスを再利用

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

- システムフォントディレクトリ以外からのフォント読み込みは制限
- フォントファイルの検証はFreeType/CoreTextに委譲

## 備考

- Fontconfigパターン文字列（"Fira Code-14:bold"形式）もサポート
- バリエーション軸（wght, ital等）の指定でバリアブルフォント対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | discovery.zig | `src/font/discovery.zig` | Descriptor構造体（29-107行目）の各フィールド |
| 1-2 | discovery.zig | `src/font/discovery.zig` | Score packed struct（585-614行目）のスコアリング構造 |

**読解のコツ**: Descriptorはフォント検索の条件を表し、Scoreはマッチング結果の優先度を表す。packed structで数値比較可能にしている点がポイント。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | discovery.zig | `src/font/discovery.zig` | Discover型の選択（15-24行目） |
| 2-2 | discovery.zig | `src/font/discovery.zig` | Fontconfig.discover関数（257-283行目） |
| 2-3 | discovery.zig | `src/font/discovery.zig` | CoreText.discover関数（347-376行目） |

**主要処理フロー**:
1. **15-24行目**: ビルドオプションでバックエンド選択（Fontconfig/CoreText）
2. **257-283行目**: Fontconfigでパターン作成→検索→イテレータ作成
3. **347-376行目**: CoreTextでディスクリプタ作成→コレクション検索→ソート

#### Step 3: フォールバック処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | discovery.zig | `src/font/discovery.zig` | CoreText.discoverFallback関数（378-440行目） |
| 3-2 | discovery.zig | `src/font/discovery.zig` | discoverCodepoint関数（444-543行目） |

**主要処理フロー**:
- **392-394行目**: CJK統合漢字（U+4E00-U+9FFF）の特別処理
- **521-538行目**: LastResortフォントの除外処理
- **527-538行目**: CTFontCreateForStringでコードポイント対応フォント取得

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

```
Discover.discover() / discoverFallback()
    │
    ├─ Descriptor.toFcPattern() [Fontconfig]
    │      └─ fontconfig.Pattern.create()
    │
    ├─ Descriptor.toCoreTextDescriptor() [CoreText]
    │      └─ macos.text.FontDescriptor.createWithAttributes()
    │
    ├─ FontCollection.createWithFontDescriptors()
    │
    ├─ sortMatchingDescriptors()
    │      └─ Score.score() → Score.int() 比較
    │
    └─ DiscoverIterator.next()
           └─ DeferredFace 生成
```

### データフロー図

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

設定(font-family) ──▶ Descriptor作成 ───▶ 検索条件

検索条件 ───────────▶ フォント検索 ────▶ マッチ結果リスト
                           │
                           ▼
マッチ結果 ─────────▶ スコアリング ───▶ ソート済みリスト
                           │
                           ▼
ソート済みリスト ───▶ イテレータ ─────▶ DeferredFace
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| discovery.zig | `src/font/discovery.zig` | ソース | フォント検出メイン実装 |
| DeferredFace.zig | `src/font/DeferredFace.zig` | ソース | 遅延ロードフェイス |
| Collection.zig | `src/font/Collection.zig` | ソース | フォントコレクション管理 |
| face.zig | `src/font/face.zig` | ソース | フォントフェイス定義 |
| main.zig | `src/font/main.zig` | ソース | フォントモジュールエントリ |
| CodepointResolver.zig | `src/font/CodepointResolver.zig` | ソース | コードポイント解決 |
