# 機能設計書 81-FormattedText

## 概要

本ドキュメントは、Avaloniaフレームワークにおける書式付きテキスト処理機能「FormattedText」の設計仕様を記述する。FormattedTextクラスは、テキストのレイアウト計算、測定、および描画を行う中核的なテキスト処理エンジンである。

### 本機能の処理概要

FormattedTextは、プログラマがMIL（Media Integration Layer）ビジュアルにテキストを追加するための機能である。テキストの書式設定（フォント、サイズ、色、スタイルなど）を柔軟に制御し、複数行テキストのレイアウト処理、テキストの測定、トリミング、ジオメトリ構築などの高度なテキスト処理機能を提供する。

**業務上の目的・背景**：GUIアプリケーションにおいて、テキストの表示は最も基本的かつ重要な機能の一つである。FormattedTextは、単純なテキスト表示から複雑な書式付きテキスト（太字、イタリック、下線、異なるフォントサイズの混在など）まで対応し、国際化対応やRTL（Right-to-Left）テキストもサポートする。これにより、開発者は多言語対応のリッチなテキストUIを実現できる。

**機能の利用シーン**：TextBlockコントロールでのテキスト表示、カスタム描画でのテキストレンダリング、テキスト測定によるレイアウト計算、テキストベースのジオメトリ生成（アウトライン文字など）で利用される。

**主要な処理内容**：
1. テキスト文字列と書式プロパティ（フォント、サイズ、色）の受け取り
2. テキストランの管理とSpanVector/SpanRiderによる範囲別書式の適用
3. TextFormatterを使用した行単位のレイアウト計算
4. 最大幅・最大高さ・最大行数による制約とトリミング処理
5. テキストメトリクス（Width、Height、Baseline等）の計算とキャッシュ
6. BuildGeometry/BuildHighlightGeometryによるジオメトリ構築
7. DrawingContextへのテキスト描画

**関連システム・外部連携**：TextFormatter、GlyphRun、Typeface、DrawingContextと連携してテキスト処理を実現する。

**権限による制御**：特になし（UIレンダリング機能のため権限制御は不要）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 78 | FormattedText | 主画面 | FormattedText描画のデモ。テキストレイアウトと測定 |
| 79 | TextFormatter | 主画面 | TextFormatterのデモ。高度なテキストフォーマット |

## 機能種別

計算処理 / テキストレンダリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| textToFormat | string | Yes | 表示するテキスト文字列 | null許容 |
| culture | CultureInfo | Yes | テキストのカルチャ | nullの場合ArgumentNullException |
| flowDirection | FlowDirection | Yes | テキストの流れる方向 | 有効なFlowDirection列挙値 |
| typeface | Typeface | Yes | 使用する書体 | - |
| emSize | double | Yes | フォントのemサイズ（1/96インチ単位） | 0より大きく、MaxFontEmSize以下。NaN不可 |
| foreground | IBrush? | No | テキストの前景ブラシ | - |

### 入力データソース

プログラムコードからの直接インスタンス化。TextBlockなどのコントロールから内部的に使用される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Width | double | テキストの幅（末尾空白を除く） |
| WidthIncludingTrailingWhitespace | double | テキストの幅（末尾空白を含む） |
| Height | double | テキストの高さ |
| Baseline | double | 最初の行のベースライン位置 |
| Extent | double | テキストの実際の描画範囲の高さ |
| OverhangAfter | double | ベースライン後のオーバーハング |
| OverhangLeading | double | 先頭方向のオーバーハング |
| OverhangTrailing | double | 末尾方向のオーバーハング |

### 出力先

DrawingContextへの描画、Geometryオブジェクトの生成

## 処理フロー

### 処理シーケンス

```
1. コンストラクタでFormattedTextインスタンス生成
   └─ テキスト、カルチャ、書体、サイズ、前景色を設定
   └─ GenericTextRunPropertiesを作成し_formatRunsに登録
   └─ GenericTextParagraphPropertiesを作成

2. 書式設定メソッドによる部分書式の適用（オプション）
   └─ SetForegroundBrush: 前景色の変更
   └─ SetFontFamily: フォントファミリの変更
   └─ SetFontSize: フォントサイズの変更
   └─ SetFontWeight: フォント太さの変更
   └─ SetFontStyle: フォントスタイルの変更
   └─ SetTextDecorations: 下線等の装飾の設定

3. メトリクス取得（遅延計算）
   └─ Height/Width等のプロパティアクセス時にDrawAndCalculateMetricsを実行
   └─ LineEnumeratorでテキスト行を列挙
   └─ 各行のメトリクスを累積

4. 描画またはジオメトリ構築
   └─ Draw: DrawingContextへテキストを描画
   └─ BuildGeometry: テキストのアウトラインジオメトリを構築
   └─ BuildHighlightGeometry: 選択範囲のハイライトジオメトリを構築
```

### フローチャート

```mermaid
flowchart TD
    A[FormattedText生成] --> B[書式ラン初期化]
    B --> C{部分書式設定?}
    C -->|Yes| D[SetForegroundBrush等]
    D --> E[InvalidateMetrics]
    E --> C
    C -->|No| F{メトリクス取得?}
    F -->|Yes| G[DrawAndCalculateMetrics]
    G --> H[LineEnumeratorで行列挙]
    H --> I[行ごとにTextFormatter.FormatLine]
    I --> J[メトリクス累積計算]
    J --> K[CachedMetrics返却]
    F -->|描画要求| L[Draw/BuildGeometry]
    L --> M[DrawingContextへ描画]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | フォントサイズ制限 | emSizeは0より大きく、MaxFontEmSize以下でなければならない | コンストラクタ、SetFontSize呼び出し時 |
| BR-002 | テキストトリミング | MaxTextWidth/MaxTextHeight/MaxLineCountを超えた場合、Trimmingプロパティに従い省略記号を表示 | テキストが制約を超える場合 |
| BR-003 | 行高制限 | 最終行は全体がMaxTextHeight内に収まる必要がある | 複数行テキストの場合 |
| BR-004 | メトリクスキャッシュ | 書式変更時はメトリクスを無効化し、次回アクセス時に再計算 | SetXXXメソッド呼び出し時 |

### 計算ロジック

**emサイズ変換定数**:
- DefaultRealToIdeal = 28800.0 / 96 = 300.0
- DefaultIdealToReal = 1 / DefaultRealToIdeal
- IdealInfiniteWidth = 0x3FFFFFFE
- RealInfiniteWidth = IdealInfiniteWidth * DefaultIdealToReal

**最大フォントサイズ**:
MaxFontEmSize = RealInfiniteWidth / GreatestMultiplierOfEm（GreatestMultiplierOfEm = 100）

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

### 操作別データベース影響一覧

該当なし（メモリ上での処理のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentNullException | cultureがnullの場合 | 有効なCultureInfoを渡す |
| - | ArgumentOutOfRangeException | emSizeが0以下、MaxFontEmSize超過、またはNaNの場合 | 有効なemSize値を指定 |
| - | InvalidEnumArgumentException | flowDirectionが無効な値の場合 | 有効なFlowDirection列挙値を使用 |
| - | ArgumentOutOfRangeException | MaxTextWidthが負の値の場合 | 0以上の値を指定 |
| - | ArgumentOutOfRangeException | MaxTextHeightが0以下またはNaNの場合 | 0より大きい有効な値を指定 |
| - | ArgumentOutOfRangeException | MaxLineCountが0以下の場合 | 1以上の値を指定 |

### リトライ仕様

該当なし（同期処理のため）

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

該当なし（メモリ上での処理のみ）

## パフォーマンス要件

- メトリクス計算は遅延評価（Lazy）で行われ、必要になるまで計算されない
- 一度計算されたメトリクスはCachedMetricsにキャッシュされる
- 書式変更時のみInvalidateMetrics()でキャッシュを無効化
- BlackBoxメトリクスは別途計算が必要な場合のみ計算される

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

特になし（ローカルUIレンダリング機能のため）

## 備考

FormattedTextはWPF互換のAPIを提供しているが、内部実装はAvaloniaのTextFormatterを使用している。

---

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

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

### 推奨読解順序

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

まず、FormattedTextで使用される書式管理のデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | フィールド定義（27-44行目）: _text, _formatRuns, _defaultParaPropsなどの基本構造 |
| 1-2 | GenericTextRunProperties | `src/Avalonia.Base/Media/TextFormatting/` | テキストランの書式プロパティを保持する構造 |
| 1-3 | GenericTextParagraphProperties | `src/Avalonia.Base/Media/TextFormatting/` | 段落レベルの書式プロパティを保持する構造 |

**読解のコツ**: SpanVector/SpanRiderはテキストの部分範囲に対する書式を効率的に管理するデータ構造。WPFの設計を踏襲している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | コンストラクタ（54-98行目）: テキストと初期書式の設定 |

**主要処理フロー**:
1. **62-65行目**: culture nullチェック
2. **67行目**: flowDirection検証
3. **69行目**: emSize検証（ValidateFontSize）
4. **71行目**: テキスト文字列を_textに保存
5. **73-81行目**: GenericTextRunPropertiesを作成
6. **83行目**: _formatRunsに書式を登録
7. **85-95行目**: GenericTextParagraphPropertiesを作成
8. **97行目**: メトリクスを無効化

#### Step 3: 書式設定処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | SetForegroundBrush（152-200行目）: 前景色の部分変更ロジック |
| 3-2 | FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | SetFontFamily（262-345行目）: フォントファミリの部分変更 |

**主要処理フロー**:
- **165-199行目**: SpanRiderで該当範囲を走査し、新しいプロパティで置換

#### Step 4: メトリクス計算処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | Metricsプロパティ（1219-1228行目）: 遅延評価でDrawAndCalculateMetricsを呼び出し |
| 4-2 | FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | DrawAndCalculateMetrics（1588-1671行目）: 実際のメトリクス計算 |
| 4-3 | FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | LineEnumerator（706-966行目）: テキスト行の列挙処理 |

**主要処理フロー**:
- **1600行目**: LineEnumeratorを使用して行を列挙
- **1616-1655行目**: 各行のメトリクスを累積計算
- **1643-1646行目**: Width, WidthIncludingTrailingWhitespaceの最大値を追跡

#### Step 5: 描画処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | Draw（1472-1499行目）: DrawingContextへの描画 |
| 5-2 | FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | BuildGeometry（1349-1380行目）: テキストジオメトリの構築 |

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

```
FormattedText
    │
    ├─ Constructor
    │      ├─ ValidateFontSize
    │      ├─ ValidateFlowDirection
    │      ├─ GenericTextRunProperties
    │      └─ GenericTextParagraphProperties
    │
    ├─ SetXXX（書式設定）
    │      ├─ ValidateRange
    │      ├─ SpanRider（範囲走査）
    │      └─ InvalidateMetrics
    │
    ├─ Metrics（プロパティ）
    │      └─ DrawAndCalculateMetrics
    │             ├─ LineEnumerator
    │             │      ├─ TextFormatter.FormatLine
    │             │      └─ TextLine.Draw
    │             └─ CachedMetrics
    │
    └─ Draw / BuildGeometry
           ├─ LineEnumerator
           └─ DrawingContext / GeometryGroup
```

### データフロー図

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

テキスト文字列 ────────▶ FormattedText ────────────────▶ テキストメトリクス
書式情報                       │                          (Width, Height等)
(Typeface,emSize等)            │
                               ▼
                         TextFormatter ────────────────▶ 描画結果
                         FormatLine                      (DrawingContext)
                               │
                               ▼
                         TextLine ─────────────────────▶ ジオメトリ
                         (行データ)                       (Geometry)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | ソース | メインクラス実装 |
| TextFormatter.cs | `src/Avalonia.Base/Media/TextFormatting/TextFormatter.cs` | ソース | テキスト行フォーマッタ |
| TextLine.cs | `src/Avalonia.Base/Media/TextFormatting/TextLine.cs` | ソース | フォーマット済みテキスト行 |
| GenericTextRunProperties.cs | `src/Avalonia.Base/Media/TextFormatting/GenericTextRunProperties.cs` | ソース | テキストラン書式プロパティ |
| GenericTextParagraphProperties.cs | `src/Avalonia.Base/Media/TextFormatting/GenericTextParagraphProperties.cs` | ソース | 段落書式プロパティ |
| SpanVector.cs | `src/Avalonia.Base/Utilities/SpanVector.cs` | ソース | 範囲別データ管理 |
| SpanRider.cs | `src/Avalonia.Base/Utilities/SpanRider.cs` | ソース | SpanVector走査ヘルパー |
| Typeface.cs | `src/Avalonia.Base/Media/Typeface.cs` | ソース | 書体定義 |
