# 機能設計書 51-PushFont

## 概要

本ドキュメントは、ImGuiライブラリのPushFont関数の設計仕様を定義する。PushFontはフォントとフォントサイズをスタックにプッシュし、後続のウィジェット描画に使用するフォントを一時的に変更するための機能である。

### 本機能の処理概要

PushFont関数は、指定されたフォントとフォントサイズを現在のフォントスタックにプッシュし、後続の描画操作で使用されるフォントを変更する。

**業務上の目的・背景**：GUIアプリケーションでは、異なる部分で異なるフォントやサイズを使用する必要がある。例えば、タイトルは大きなフォント、説明文は小さなフォントを使用するなど、視覚的な階層構造を作成するためにフォントの動的切り替えが必要となる。PushFont/PopFontのスタック機構により、ネストされたUI構造でのフォント管理を簡潔に実現できる。

**機能の利用シーン**：
- ウィンドウタイトルや見出しに大きなフォントを使用する場合
- コードやログ表示に等幅フォントを使用する場合
- 異なる言語の文字セットを持つフォントを切り替える場合
- UIの特定セクションで異なるフォントスタイルを適用する場合

**主要な処理内容**：
1. 現在のフォント状態（フォント、スケーリング前サイズ、スケーリング後サイズ）をスタックに保存
2. NULLフォントが指定された場合は現在のフォントを維持
3. フォントサイズが0の場合は現在のサイズを維持
4. 新しいフォントとサイズを現在のコンテキストに設定

**関連システム・外部連携**：フォントアトラスシステムと連携し、ImFontオブジェクトを通じてフォントデータにアクセスする。バージョン1.92以降、フォントサイズの動的変更に対応している。

**権限による制御**：特になし。すべてのコンテキストで利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 8 | Font Atlas | 主機能 | フォントのプッシュ |

## 機能種別

スタック操作 / スタイル変更

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| font | ImFont* | Yes | 適用するフォント。NULLの場合は現在のフォントを維持 | NULLは現在のフォントとして処理 |
| font_size_base_unscaled | float | Yes | スケーリング前の基本フォントサイズ。0.0fの場合は現在のサイズを維持 | >= 0.0f |

### 入力データソース

- フォントアトラスに事前登録されたImFontオブジェクト
- style.FontSizeBaseを基準とするフォントサイズ値

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| なし | void | 戻り値なし |

### 出力先

- ImGuiContext.FontStack（フォントスタック）
- ImGuiContext.Font（現在のフォント）
- ImGuiContext.FontSizeBase（スケーリング前のフォントサイズ）
- ImGuiContext.FontSize（スケーリング後のフォントサイズ）

## 処理フロー

### 処理シーケンス

```
1. コンテキストの取得
   └─ グローバルコンテキストGImGuiを参照
2. NULLフォントチェック
   └─ font == NULLの場合、現在のフォント(g.Font)を使用
3. アサーションチェック
   └─ フォントがNULLでないこと、font_size_baseが0以上であることを確認
4. 現在の状態をスタックに保存
   └─ Font, FontSizeBase, FontSizeをFontStackにプッシュ
5. フォントサイズ調整
   └─ font_size_base == 0.0fの場合、現在のg.FontSizeBaseを使用
6. 新しいフォントを設定
   └─ SetCurrentFont関数で新しいフォントとサイズを適用
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{font == NULL?}
    B -->|Yes| C[font = g.Font]
    B -->|No| D[fontをそのまま使用]
    C --> E[ASSERT: font != NULL]
    D --> E
    E --> F[ASSERT: font_size_base >= 0.0f]
    F --> G[FontStackに現在の状態をプッシュ]
    G --> H{font_size_base == 0.0f?}
    H -->|Yes| I[font_size_base = g.FontSizeBase]
    H -->|No| J[font_size_baseをそのまま使用]
    I --> K[SetCurrentFont呼び出し]
    J --> K
    K --> L[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-51-01 | Push/Popペアリング | PushFontは必ずPopFontとペアで使用する | 常時 |
| BR-51-02 | NULLフォント処理 | NULLフォント指定時は現在のフォントを維持 | font == NULL |
| BR-51-03 | ゼロサイズ処理 | サイズ0指定時は現在のサイズを維持 | font_size_base == 0.0f |
| BR-51-04 | スケーリング非適用 | GetFontSize()の値をそのまま渡すとスケーリングが二重適用される | 常時 |

### 計算ロジック

実効フォントサイズの計算:
```
実効フォントサイズ = font_size_base * style.FontScaleMain * style.FontScaleDpi * その他スケーリング係数
```

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

該当なし（メモリ内操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ASSERT | アサーション | font == NULL（内部処理後） | NULLフォント指定時の内部処理を確認 |
| ASSERT | アサーション | font_size_base < 0.0f | 0以上の値を指定 |

### リトライ仕様

該当なし

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

該当なし（メモリ内操作のみ）

## パフォーマンス要件

- スタック操作のため、O(1)の時間計算量
- フレームごとに複数回呼び出されることを想定した軽量実装

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

- 無効なフォントポインタの使用によるメモリアクセス違反に注意
- フォントアトラスの破棄後にフォントを使用しないこと

## 備考

- バージョン1.92（2025年6月）以降、フォントサイズの動的変更に対応
- 旧API（font引数のみ）は1.92で非推奨化され、互換性レイヤーで変換される

---

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

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

### 推奨読解順序

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

フォントスタックの管理に使用されるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_internal.h | `imgui_internal.h` | ImFontStackData構造体の定義（895-900行目） |
| 1-2 | imgui.h | `imgui.h` | ImFont構造体の概要とPushFont関数シグネチャ（521行目） |

**読解のコツ**: ImFontStackDataは3つのメンバ（Font, FontSizeBeforeScaling, FontSizeAfterScaling）を持ち、スタック復元時に必要な情報を保持している。

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

PushFont関数の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.cpp | `imgui.cpp` | PushFont関数の実装（9075-9087行目） |

**主要処理フロー**:
1. **9077行目**: グローバルコンテキストの取得
2. **9078-9079行目**: NULLフォントチェックと現在フォントへのフォールバック
3. **9080-9081行目**: アサーションによる入力検証
4. **9083行目**: 現在の状態をFontStackにプッシュ
5. **9084-9085行目**: サイズ0の場合の現在サイズへのフォールバック
6. **9086行目**: SetCurrentFont呼び出しで新フォント適用

#### Step 3: 関連関数を理解する

SetCurrentFont関数とPopFont関数の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.cpp | `imgui.cpp` | PopFont関数の実装（9089-9096行目） |
| 3-2 | imgui.cpp | `imgui.cpp` | SetCurrentFont関数（フォント設定の実装） |

**主要処理フロー**:
- **9092行目**: スタックアンダーフローチェック
- **9093-9094行目**: スタックから状態を復元
- **9095行目**: スタックからポップ

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

```
ImGui::PushFont(ImFont* font, float font_size_base)
    │
    ├─ g.FontStack.push_back(...)  // 状態保存
    │
    └─ SetCurrentFont(font, font_size_base, 0.0f)
           │
           └─ 内部フォント状態の更新
```

### データフロー図

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

ImFont* font        ───▶ NULLチェック              ───▶ g.Font
                         アサーション検証
                              │
float font_size     ───▶ ゼロチェック              ───▶ g.FontSizeBase
                         SetCurrentFont呼び出し          g.FontSize
                              │
現在のフォント状態  ───▶ スタックプッシュ          ───▶ g.FontStack
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | PushFont関数の宣言（521行目） |
| imgui.cpp | `imgui.cpp` | ソース | PushFont関数の実装（9075-9087行目） |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ImFontStackData構造体の定義（895-900行目） |
