# 機能設計書 224-CalcTextSize

## 概要

本ドキュメントは、Dear ImGuiライブラリにおける`CalcTextSize`関数の機能設計書である。この関数は、指定されたテキストの描画サイズ（幅と高さ）を計算するためのユーティリティ関数である。

### 本機能の処理概要

`CalcTextSize`関数は、現在設定されているフォントとフォントサイズを使用して、テキスト文字列の描画時のサイズを計算する機能を提供する。複数行テキストにも対応し、テキスト折り返しやIDセパレータ（##）以降のテキスト非表示にも対応している。

**業務上の目的・背景**：GUIアプリケーション開発において、テキストの配置やウィジェットのサイズ計算には、テキストが描画される際の実際のサイズを事前に知る必要がある。本機能は、レイアウト計算、カスタムウィジェットの実装、動的なコンテンツサイズ調整などで不可欠な情報を提供する。特に、選択可能アイテムの幅決定、ボタンサイズの計算、カスタム描画領域の設計などに活用される。

**機能の利用シーン**：
- Selectableウィジェットの幅を特定のテキストに合わせて設定
- カスタムウィジェットのサイズ計算
- テキストの中央揃え・右揃えの位置計算
- 動的に変化するテキストに応じたレイアウト調整
- テーブルの列幅計算
- リストボックス内のアイテム幅決定

**主要な処理内容**：
1. テキスト終端位置の決定（##以降を隠す場合はFindRenderedTextEndで計算）
2. 空テキストの場合はフォントサイズ高さのみ返却
3. ImFont::CalcTextSizeAを使用してテキストサイズを計算
4. 結果を丸めて返却

**関連システム・外部連携**：フォントアトラス（ImFontAtlas）とベイク済みフォント（ImFontBaked）が内部的に使用される。

**権限による制御**：特にない。いつでも呼び出し可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | Widgets | 参照画面 | ウィジェットサイズ計算 |
| 26 | Tables | 参照画面 | テーブル列幅計算 |

## 機能種別

計算処理（読み取り専用）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| text | const char* | Yes | 計算対象のテキスト（NULL終端またはtext_endで範囲指定） | NULL不可 |
| text_end | const char* | No | テキスト終端位置。NULLの場合はNULL終端文字列として扱う | - |
| hide_text_after_double_hash | bool | No | ##以降のテキストを無視するかどうか。デフォルトfalse | - |
| wrap_width | float | No | 折り返し幅。-1.0fの場合は折り返しなし。デフォルト-1.0f | - |

### 入力データソース

- 現在のImGuiコンテキストのフォント（g.Font）
- 現在のImGuiコンテキストのフォントサイズ（g.FontSize）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | ImVec2 | テキストの描画サイズ。x=幅、y=高さ |

### 出力の特性

- 空テキストの場合：ImVec2(0.0f, font_size)を返す
- 幅は0.99999fを加算した後に切り捨て（実質的に切り上げ）
- 複数行テキストの場合、高さは行数 * 行高さになる

### 出力先

呼び出し元への戻り値として返却

## 処理フロー

### 処理シーケンス

```
1. ImGuiコンテキストからフォント情報を取得
   └─ g.Fontとg.FontSizeを参照
2. 表示終端位置の決定
   ├─ hide_text_after_double_hash=trueの場合
   │   └─ FindRenderedTextEndで##以降を除外
   └─ falseの場合
       └─ text_endをそのまま使用
3. 空テキストチェック
   └─ text == text_display_endの場合はImVec2(0, font_size)を返却
4. フォントのCalcTextSizeAメソッドを呼び出し
   └─ font_size, FLT_MAX, wrap_width, text, text_display_endを渡す
5. 幅の丸め処理
   └─ text_size.x = IM_TRUNC(text_size.x + 0.99999f)
6. 結果を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[フォント・フォントサイズ取得]
    B --> C{hide_text_after_double_hash?}
    C -->|Yes| D[FindRenderedTextEndで終端検索]
    C -->|No| E[text_endを使用]
    D --> F{空テキスト?}
    E --> F
    F -->|Yes| G["return ImVec2(0, font_size)"]
    F -->|No| H[CalcTextSizeA呼び出し]
    H --> I[幅の丸め処理]
    I --> J[結果返却]
    G --> K[終了]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 空テキストの高さ | 空テキストでも高さはフォントサイズを返す | text == text_display_end |
| BR-002 | 幅の切り上げ | 幅は0.99999fを加算後に切り捨て（実質切り上げ） | 常時 |
| BR-003 | ##非表示 | ##以降のテキストは非表示計算可能 | hide_text_after_double_hash=true |

### 計算ロジック

```cpp
// 幅の丸め処理
text_size.x = IM_TRUNC(text_size.x + 0.99999f);
```

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| なし | - | 本関数はエラーを発生させない | - |

### リトライ仕様

なし

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

該当なし

## パフォーマンス要件

- ImFontBaked構造体のIndexAdvanceXベクターを使用した高速計算
- グリフ情報のキャッシュフレンドリーな設計
- 大量のテキストサイズ計算はUIのボトルネックになりやすいため、キャッシュを活用

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

特になし

## 備考

- この関数はウィジェット内部でも多用されている
- ImFont::CalcTextSizeAはより低レベルな計算を行う
- グローバルフォントスケールが適用された後のサイズを返す

---

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

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

### 推奨読解順序

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

まず、フォントに関する構造体を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | ImFontBaked構造体（3800-3820行目付近）- CalcTextSize用のキャッシュ構造 |
| 1-2 | imgui.h | `imgui.h` | ImFont::CalcTextSizeA宣言（3881行目） |

**読解のコツ**: ImFontBakedのIndexAdvanceXはグリフの進行幅を直接インデックスアクセス可能な形式でキャッシュしており、CalcTextSizeの高速化に寄与している。

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

CalcTextSize関数のAPI宣言と実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.h | `imgui.h` | 関数宣言（1046行目） |
| 2-2 | imgui.cpp | `imgui.cpp` | 関数実装（6105-6129行目） |

**主要処理フロー**:
1. **6107行目**: `ImGuiContext& g = *GImGui;` - コンテキスト取得
2. **6110-6113行目**: テキスト表示終端の決定
3. **6117-6118行目**: 空テキストチェックと早期リターン
4. **6119行目**: `font->CalcTextSizeA(...)` - 実際のサイズ計算
5. **6126行目**: 幅の丸め処理

#### Step 3: 内部実装を理解する

ImFont::CalcTextSizeAの詳細を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_draw.cpp | `imgui_draw.cpp` | CalcTextSizeA実装 |

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

```
ImGui::CalcTextSize()
    │
    ├─ FindRenderedTextEnd()（オプション）
    │      └─ ##を探して表示終端を決定
    │
    └─ ImFont::CalcTextSizeA()
           │
           ├─ ImFontBaked::IndexAdvanceX参照
           │
           └─ CalcWordWrapPosition()（折り返し時）
```

### データフロー図

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

text            ───▶ 表示終端位置決定 ───┐
text_end               │                │
hide_text_...          │                ▼
                       │         CalcTextSizeA
wrap_width      ───────┴──────▶        │
                                       │
g.Font          ───────────────▶      │
g.FontSize      ───────────────▶      │
                                       ▼
                              幅の丸め処理 ───▶ ImVec2(width, height)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | CalcTextSize関数宣言 |
| imgui.cpp | `imgui.cpp` | ソース | CalcTextSize関数実装 |
| imgui_draw.cpp | `imgui_draw.cpp` | ソース | ImFont::CalcTextSizeA実装 |
| imgui_demo.cpp | `imgui_demo.cpp` | デモ | 使用例（2338行目、5695行目等多数） |
