# 機能設計書 15-フォントアトラス

## 概要

本ドキュメントは、Ghosttyのフォントアトラス機能の設計について記述する。グリフをテクスチャアトラスにキャッシュし、GPUレンダリングの効率を最大化するための機能である。

### 本機能の処理概要

**業務上の目的・背景**：
ターミナルエミュレータでは、大量の文字を高速に描画する必要がある。毎フレームごとに全ての文字をラスタライズするのは非効率であるため、一度ラスタライズしたグリフをテクスチャアトラス（大きな1枚のテクスチャ）にキャッシュする。GPUはアトラス内の領域を参照するだけでグリフを描画でき、大幅なパフォーマンス向上が実現できる。

**機能の利用シーン**：
- 文字のGPUレンダリング時のテクスチャ参照
- 新しい文字のラスタライズ時のキャッシュ登録
- アトラス容量不足時の動的拡張
- フォントサイズ変更時のアトラスクリア

**主要な処理内容**：
1. 指定サイズでのアトラス初期化
2. グリフ用の領域予約（Rectangle Bin Packing）
3. ラスタライズ済みグリフデータの書き込み
4. アトラス満杯時の動的サイズ拡張
5. アトラスのクリアと再利用
6. GPUテクスチャへのアップロード通知

**関連システム・外部連携**：
- FreeType（グリフラスタライズ）
- CoreText（macOSでのグリフラスタライズ）
- Metal/OpenGL/WebGLレンダラー（テクスチャ使用）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインターミナルウィンドウ | 主画面 | グリフテクスチャの描画 |

## 機能種別

キャッシュ管理 / メモリ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| size | u32 | Yes | アトラスサイズ（ピクセル） | 正の整数 |
| format | Format | Yes | ピクセルフォーマット | grayscale/bgr/bgra |
| width | u32 | Yes | 予約領域の幅 | size未満 |
| height | u32 | Yes | 予約領域の高さ | size未満 |

### 入力データソース

- ラスタライズ済みグリフデータ（FreeType/CoreText）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| region | Region | 予約された領域（x, y, width, height） |
| data | []u8 | アトラステクスチャデータ |
| modified | usize | 変更カウンタ |
| resized | usize | リサイズカウンタ |

### 出力先

GPUテクスチャ（レンダラー経由）

## 処理フロー

### 処理シーケンス

```
1. アトラス初期化
   └─ 指定サイズでメモリ確保、ノードリスト初期化
2. 領域予約
   └─ fit関数で空き領域を検索
   └─ 最適なノードを選択（Best Fit）
   └─ ノードの挿入とマージ
3. データ書き込み
   └─ set関数で領域にデータコピー
   └─ modifiedカウンタをインクリメント
4. アトラス拡張（必要時）
   └─ grow関数で新サイズに拡張
   └─ 既存データをコピー
   └─ resizedカウンタをインクリメント
5. GPU同期
   └─ modified/resizedカウンタでGPU更新を検知
```

### フローチャート

```mermaid
flowchart TD
    A[グリフラスタライズ] --> B[reserve呼び出し]
    B --> C{空き領域あり?}
    C -->|Yes| D[領域予約]
    C -->|No| E{拡張可能?}
    E -->|Yes| F[grow実行]
    E -->|No| G[AtlasFull エラー]
    F --> B
    D --> H[set でデータ書き込み]
    H --> I[modified++]
    I --> J[GPU更新検知]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 1pxボーダー | アトラスの端1pxは使用しない | 常時 |
| BR-02 | ノードマージ | 隣接する同Y座標のノードをマージ | 領域予約後 |
| BR-03 | 0サイズ許容 | width=0, height=0の予約は成功する | 予約時 |

### 計算ロジック

データオフセット計算：
- `tex_offset = ((region.y + i) * atlas.size + region.x) * depth`
- `depth = format.depth()` (grayscale=1, bgr=3, bgra=4)

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

該当なし（メモリ上のキャッシュ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| AtlasFull | リソース不足 | 空き領域が見つからない | grow関数で拡張 |
| OutOfMemory | メモリ不足 | アロケーション失敗 | エラー返却 |

### リトライ仕様

AtlasFull時はgrow関数でサイズ拡張後にリトライ可能

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

該当なし

## パフォーマンス要件

- 領域予約は O(n) （nはノード数）
- データ書き込みは O(width * height)
- modified/resizedカウンタでGPU更新を最小化

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

- アトラスデータは信頼されたラスタライズ結果のみ書き込み
- バッファオーバーフローはassertで検証

## 備考

- Rectangle Bin Packing アルゴリズムはJukka Jylanki の実装がベース
- アトラスは常に正方形（width == height）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Atlas.zig | `src/font/Atlas.zig` | Atlas構造体（27-52行目）のフィールド |
| 1-2 | Atlas.zig | `src/font/Atlas.zig` | Format enum（53-68行目）とdepth関数 |
| 1-3 | Atlas.zig | `src/font/Atlas.zig` | Node構造体（70-74行目）とRegion構造体（83-88行目） |

**読解のコツ**: Nodeはアトラス内の空き領域を表し、(x, y, width)で矩形の上端を示す。Regionは予約された領域を(x, y, width, height)で表す。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Atlas.zig | `src/font/Atlas.zig` | init関数（100-120行目） |
| 2-2 | Atlas.zig | `src/font/Atlas.zig` | clear関数（367-376行目） |

**主要処理フロー**:
1. **105行目**: size * size * depth でデータ領域を確保
2. **114行目**: ノードリストをプリアロケート（64ノード）
3. **117行目**: clearでノードを初期化（1pxボーダーを考慮）

#### Step 3: 領域予約処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Atlas.zig | `src/font/Atlas.zig` | reserve関数（136-210行目） |
| 3-2 | Atlas.zig | `src/font/Atlas.zig` | fit関数（215-235行目） |
| 3-3 | Atlas.zig | `src/font/Atlas.zig` | merge関数（238-251行目） |

**主要処理フロー**:
- **153-178行目**: 全ノードを走査してベストフィットを検索
- **182-186行目**: 新しいノードを挿入
- **190-206行目**: 重複ノードの縮小と削除
- **207行目**: 隣接ノードのマージ

#### Step 4: データ書き込みを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Atlas.zig | `src/font/Atlas.zig` | set関数（256-275行目） |
| 4-2 | Atlas.zig | `src/font/Atlas.zig` | setFromLarger関数（280-306行目） |
| 4-3 | Atlas.zig | `src/font/Atlas.zig` | grow関数（314-364行目） |

**主要処理フロー**:
- **264-272行目**: 行ごとにデータをコピー
- **274行目**: modifiedカウンタをインクリメント
- **340-352行目**: grow時に既存データをコピー
- **355-359行目**: 新しい右端領域のノードを追加

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

```
Atlas.init()
    └─ clear() → 初期ノード設定

Atlas.reserve()
    ├─ fit() → 空き領域検索
    ├─ nodes.insert() → ノード追加
    └─ merge() → ノードマージ

Atlas.set()
    └─ fastmem.copy() → データコピー

Atlas.grow()
    ├─ alloc.alloc() → 新領域確保
    ├─ set() → 既存データコピー
    └─ nodes.appendAssumeCapacity() → 新ノード追加
```

### データフロー図

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

グリフデータ ────────▶ reserve() ───────▶ Region (位置情報)
        │
        ▼
Region + データ ────▶ set() ──────────▶ Atlas.data (テクスチャ)
        │
        ▼
Atlas.modified ─────▶ GPUチェック ────▶ テクスチャ更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Atlas.zig | `src/font/Atlas.zig` | ソース | アトラス管理メイン実装 |
| Glyph.zig | `src/font/Glyph.zig` | ソース | グリフデータ構造 |
| SharedGrid.zig | `src/font/SharedGrid.zig` | ソース | フォントグリッド（アトラス参照） |
| generic.zig | `src/renderer/generic.zig` | ソース | アトラスのGPUアップロード |
| fastmem.zig | `src/fastmem.zig` | ソース | 高速メモリコピー |
