# 機能設計書 83-Typeface

## 概要

本ドキュメントは、Avaloniaフレームワークにおける書体定義機能「Typeface」の設計仕様を記述する。Typeface構造体は、フォントファミリー、スタイル、太さ、伸縮の組み合わせを表現し、GlyphTypefaceを取得するための基盤を提供する。

### 本機能の処理概要

Typefaceは、テキストレンダリングに使用するフォントの論理的な表現である。FontFamily（フォントファミリー）、FontStyle（標準/イタリック/斜体）、FontWeight（細字〜極太）、FontStretch（圧縮〜拡張）の4つの属性を組み合わせて、特定の書体を一意に識別する。実際のフォントデータ（GlyphTypeface）は、FontManagerを通じて取得される。

**業務上の目的・背景**：アプリケーションUIにおいて、テキストの見た目はユーザー体験に直結する重要な要素である。Typefaceは、開発者がフォントを宣言的に指定するための抽象化レイヤーを提供し、プラットフォーム間の差異を吸収する。XAMLでのフォント指定やコードでのフォント設定を統一的に扱うことができる。

**機能の利用シーン**：TextBlockやTextBoxでのフォント指定、FormattedTextでの書体設定、コントロールのスタイル定義、リソースディクショナリでのフォントリソース定義で利用される。

**主要な処理内容**：
1. フォント属性（FontFamily, Style, Weight, Stretch）の保持
2. GlyphTypefaceの取得（FontManagerとの連携）
3. 書体の比較と等価性判定
4. フォント名からのスタイル/ウェイト/ストレッチ情報の正規化

**関連システム・外部連携**：FontFamily、FontManager、GlyphTypefaceと連携する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 全テキスト表示画面 | 補助機能 | テキストコントロールで使用される書体定義 |

## 機能種別

データ定義 / ファクトリ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| fontFamily | FontFamily | Yes | フォントファミリー | nullの場合FontFamily.Defaultを使用 |
| style | FontStyle | No | フォントスタイル（デフォルト: Normal） | - |
| weight | FontWeight | No | フォント太さ（デフォルト: Normal） | 0より大きい値 |
| stretch | FontStretch | No | フォント伸縮（デフォルト: Normal） | 1以上の値 |

### 入力データソース

XAMLマークアップ、コードからの直接インスタンス化

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| FontFamily | FontFamily | フォントファミリー |
| Style | FontStyle | フォントスタイル |
| Weight | FontWeight | フォント太さ |
| Stretch | FontStretch | フォント伸縮 |
| GlyphTypeface | GlyphTypeface | 対応するグリフタイプフェース |

### 出力先

TextFormatter、FormattedText、GlyphRun等のテキストレンダリングコンポーネント

## 処理フロー

### 処理シーケンス

```
1. Typefaceインスタンス生成
   └─ FontFamily, Style, Weight, Stretchを設定
   └─ weightが0以下の場合ArgumentException
   └─ stretchが1未満の場合ArgumentException
   └─ fontFamilyがnullの場合FontFamily.Defaultを使用

2. GlyphTypefaceの取得（遅延評価）
   └─ GlyphTypefaceプロパティアクセス時にFontManager.TryGetGlyphTypefaceを呼び出し
   └─ 取得失敗時はInvalidOperationExceptionをスロー

3. 正規化処理（オプション）
   └─ Normalizeメソッドでフォントファミリー名からスタイル情報を抽出
   └─ "Arial Bold Italic"から"Arial"とBold+Italicを分離
```

### フローチャート

```mermaid
flowchart TD
    A[Typeface生成] --> B{weightの検証}
    B -->|>0| C{stretchの検証}
    B -->|<=0| Z[ArgumentException]
    C -->|>=1| D[fontFamilyのnullチェック]
    C -->|<1| Z
    D -->|null| E[FontFamily.Defaultを使用]
    D -->|非null| F[fontFamilyを使用]
    E --> G[プロパティ設定]
    F --> G
    G --> H{GlyphTypeface要求?}
    H -->|Yes| I[FontManager.TryGetGlyphTypeface]
    I --> J{取得成功?}
    J -->|Yes| K[GlyphTypeface返却]
    J -->|No| L[InvalidOperationException]
    H -->|Normalize要求| M[フォント名解析]
    M --> N[スタイル/ウェイト/ストレッチ抽出]
    N --> O[新Typeface生成]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ウェイト制限 | FontWeightは0より大きくなければならない | コンストラクタ呼び出し時 |
| BR-002 | ストレッチ制限 | FontStretchは1以上でなければならない | コンストラクタ呼び出し時 |
| BR-003 | デフォルトフォント | fontFamilyがnullの場合、FontFamily.Defaultを使用 | コンストラクタ呼び出し時 |
| BR-004 | 静的Default | Typeface.Defaultは静的にFontFamily.Defaultで初期化 | アプリケーション起動時 |

### 計算ロジック

**ハッシュコード計算**:
```csharp
hashCode = (FontFamily != null ? FontFamily.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (int)Style;
hashCode = (hashCode * 397) ^ (int)Weight;
hashCode = (hashCode * 397) ^ (int)Stretch;
```

**等価性判定**:
```csharp
FontFamily == other.FontFamily &&
Style == other.Style &&
Weight == other.Weight &&
Stretch == other.Stretch
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentException | weightが0以下の場合 | 1以上の値を指定 |
| - | ArgumentException | stretchが1未満の場合 | 1以上の値を指定 |
| - | InvalidOperationException | GlyphTypefaceの取得に失敗した場合 | FontFamilyが正しくインストールされているか確認 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- Typefaceはreadonly structとして実装され、値型のセマンティクスを持つ
- GlyphTypefaceはプロパティアクセス時に取得（キャッシュはFontManager側で管理）

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

特になし

## 備考

Typefaceは不変（immutable）構造体であり、一度作成すると変更できない。新しい書体が必要な場合は新しいインスタンスを作成する。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Typeface.cs | `src/Avalonia.Base/Media/Typeface.cs` | 構造体定義とDebuggerDisplay属性（8-13行目） |
| 1-2 | FontStyle.cs | `src/Avalonia.Base/Media/FontStyle.cs` | フォントスタイル列挙型 |
| 1-3 | FontWeight.cs | `src/Avalonia.Base/Media/FontWeight.cs` | フォントウェイト列挙型 |
| 1-4 | FontStretch.cs | `src/Avalonia.Base/Media/FontStretch.cs` | フォントストレッチ列挙型 |

**読解のコツ**: TypefaceはIEquatable<Typeface>を実装したreadonly struct。DebuggerDisplayで"Name = {FontFamily.Name}, Weight = {Weight}, Style = {Style}"と表示される。

#### Step 2: コンストラクタを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Typeface.cs | `src/Avalonia.Base/Media/Typeface.cs` | FontFamilyコンストラクタ（21-40行目） |
| 2-2 | Typeface.cs | `src/Avalonia.Base/Media/Typeface.cs` | 文字列コンストラクタ（49-56行目） |

**主要処理フロー**:
1. **26-29行目**: weightの検証（0より大きい）
2. **31-34行目**: stretchの検証（1以上）
3. **36行目**: fontFamilyがnullならFontFamily.Defaultを使用
4. **37-39行目**: プロパティへの代入

#### Step 3: プロパティとGlyphTypeface取得を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Typeface.cs | `src/Avalonia.Base/Media/Typeface.cs` | Defaultプロパティ（58行目）: 静的デフォルトTypeface |
| 3-2 | Typeface.cs | `src/Avalonia.Base/Media/Typeface.cs` | GlyphTypefaceプロパティ（86-98行目）: 遅延取得 |

**主要処理フロー**:
- **90行目**: FontManager.Current.TryGetGlyphTypefaceを呼び出し
- **95-96行目**: 取得失敗時はInvalidOperationExceptionをスロー

#### Step 4: 等価性判定とハッシュコードを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Typeface.cs | `src/Avalonia.Base/Media/Typeface.cs` | ==演算子（100-108行目） |
| 4-2 | Typeface.cs | `src/Avalonia.Base/Media/Typeface.cs` | Equalsメソッド（110-119行目） |
| 4-3 | Typeface.cs | `src/Avalonia.Base/Media/Typeface.cs` | GetHashCode（121-131行目） |

#### Step 5: 正規化処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | Typeface.cs | `src/Avalonia.Base/Media/Typeface.cs` | Normalizeメソッド（145-207行目）: フォント名からスタイル情報を抽出 |

**主要処理フロー**:
- **150-153行目**: スペースがなければ早期リターン
- **162行目**: SpanStringTokenizerでトークン分割
- **177-191行目**: FontStyle, FontWeight, FontStretchをトライパース
- **196-198行目**: マッチした部分を正規化名から削除
- **206行目**: 新しいTypefaceを生成して返却

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

```
Typeface
    │
    ├─ Constructor (FontFamily版)
    │      ├─ weight検証
    │      ├─ stretch検証
    │      └─ プロパティ設定
    │
    ├─ Constructor (string版)
    │      └─ new FontFamily(fontFamilyName)
    │
    ├─ GlyphTypeface (プロパティ)
    │      └─ FontManager.Current.TryGetGlyphTypeface
    │             └─ GlyphTypeface返却 or InvalidOperationException
    │
    ├─ Normalize
    │      ├─ SpanStringTokenizer
    │      ├─ EnumHelper.TryParse<FontStyle>
    │      ├─ EnumHelper.TryParse<FontWeight>
    │      ├─ EnumHelper.TryParse<FontStretch>
    │      └─ new Typeface(normalizedFamilyName, style, weight, stretch)
    │
    └─ Equals / GetHashCode
           └─ 全プロパティの比較/ハッシュ計算
```

### データフロー図

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

FontFamily ─────────────▶ Typeface ──────────────────▶ 書体情報
FontStyle                     │                         (immutable struct)
FontWeight                    │
FontStretch                   │
                              ▼
                        GlyphTypeface取得 ────────────▶ GlyphTypeface
                        (FontManager経由)                (フォント実体)
                              │
                              ▼
                        Normalize ────────────────────▶ 新Typeface
                        (フォント名解析)                  (正規化済み)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Typeface.cs | `src/Avalonia.Base/Media/Typeface.cs` | ソース | メイン構造体実装 |
| FontFamily.cs | `src/Avalonia.Base/Media/FontFamily.cs` | ソース | フォントファミリー定義 |
| FontStyle.cs | `src/Avalonia.Base/Media/FontStyle.cs` | ソース | フォントスタイル列挙型 |
| FontWeight.cs | `src/Avalonia.Base/Media/FontWeight.cs` | ソース | フォントウェイト列挙型 |
| FontStretch.cs | `src/Avalonia.Base/Media/FontStretch.cs` | ソース | フォントストレッチ列挙型 |
| FontManager.cs | `src/Avalonia.Base/Media/FontManager.cs` | ソース | フォント管理 |
| GlyphTypeface.cs | `src/Avalonia.Base/Media/GlyphTypeface.cs` | ソース | グリフタイプフェース |
| EnumHelper.cs | `src/Avalonia.Base/Utilities/EnumHelper.cs` | ソース | 列挙型解析ヘルパー |
