# 機能設計書 77-DrawingContext

## 概要

本ドキュメントは、Avaloniaフレームワークにおける描画コンテキスト機能（DrawingContext）の設計仕様を記述する。DrawingContextは、図形、テキスト、画像などの描画命令を発行するためのAPIを提供する抽象クラスである。

### 本機能の処理概要

DrawingContextは、Avalonia描画システムの中核を担う描画命令インターフェースである。線、矩形、楕円、ジオメトリ、画像、テキストなどの描画、クリッピング、変換、不透明度マスクなどの描画状態管理機能を提供する。Control.Render()メソッドからアクセスされ、カスタム描画を実現する。

**業務上の目的・背景**：カスタムコントロールの実装、グラフ・チャートの描画、図形エディタ、ゲーム画面など、標準コントロールでは実現できない描画要件に対応する。DrawingContextにより、低レベルの描画制御が可能になり、高度なビジュアル表現を実現できる。

**機能の利用シーン**：Control.Render()オーバーライドでのカスタム描画、CustomDrawOperationでの特殊描画、Shapesコントロールの内部描画など。

**主要な処理内容**：
1. 線描画（DrawLine）
2. 矩形描画（DrawRectangle、FillRectangle）
3. 楕円描画（DrawEllipse）
4. ジオメトリ描画（DrawGeometry）
5. 画像描画（DrawImage）
6. テキスト描画（DrawText、DrawGlyphRun）
7. 状態管理（PushClip、PushOpacity、PushTransform等）

**関連システム・外部連携**：Controlレンダリングパイプライン、Compositor、Skia描画バックエンドと連携する。

**権限による制御**：本機能は純粋な描画機能であり、特別な権限制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | Custom Drawing | 主画面 | カスタム描画のデモ |
| 73 | Drawing | 主画面 | 図形描画のデモ |
| 80 | LineBounds | 主画面 | 線の境界計算のデモ |

## 機能種別

グラフィックス基盤 / 描画API

## 入力仕様

### 入力パラメータ（主要メソッド別）

#### DrawLine

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pen | IPen | Yes | 線のスタイル | 可視性チェック |
| p1 | Point | Yes | 始点 | - |
| p2 | Point | Yes | 終点 | - |

#### DrawRectangle

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| brush | IBrush? | No | 塗りつぶしブラシ | null可 |
| pen | IPen? | No | 輪郭ペン | null可 |
| rect | Rect | Yes | 矩形範囲 | - |
| radiusX | double | No | X角丸半径 | 0〜Width/2 |
| radiusY | double | No | Y角丸半径 | 0〜Height/2 |
| boxShadows | BoxShadows | No | ボックスシャドウ | - |

#### DrawEllipse

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| brush | IBrush? | No | 塗りつぶしブラシ | null可 |
| pen | IPen? | No | 輪郭ペン | null可 |
| center | Point | Yes | 中心点 | - |
| radiusX | double | Yes | X方向半径 | - |
| radiusY | double | Yes | Y方向半径 | - |

#### DrawGeometry

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| brush | IBrush? | No | 塗りつぶしブラシ | null可 |
| pen | IPen? | No | 輪郭ペン | null可 |
| geometry | Geometry | Yes | 描画するジオメトリ | PlatformImpl必須 |

#### DrawImage

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source | IImage | Yes | 描画する画像 | null不可 |
| sourceRect | Rect | No | 画像内の描画範囲 | - |
| destRect | Rect | Yes | 描画先の範囲 | - |

### 入力データソース

- Control.Render()メソッドのパラメータとして受け取る
- レンダリングパイプラインから生成

## 出力仕様

### 出力データ

本機能は直接的な戻り値を持たない。描画命令はレンダリングシステムに蓄積される。

### 出力先

- Compositor描画キュー
- 最終的には画面に表示

## 処理フロー

### 処理シーケンス

```
1. DrawingContext取得
   └─ Control.Render(DrawingContext context)
2. 状態プッシュ（オプション）
   └─ PushClip/PushOpacity/PushTransform
3. 描画命令発行
   └─ DrawLine/DrawRectangle/DrawEllipse/DrawGeometry/DrawImage/DrawText
4. 状態ポップ（Disposeで自動）
   └─ PushedStateのDispose
5. コンテキストDispose
   └─ すべての状態をクリア
```

### フローチャート

```mermaid
flowchart TD
    A[Render開始] --> B{状態変更必要?}
    B -->|Yes| C[PushClip/PushOpacity/PushTransform]
    B -->|No| D[描画命令発行]
    C --> D
    D --> E{BrushまたはPen有効?}
    E -->|Yes| F[描画実行]
    E -->|No| G[描画スキップ]
    F --> H{追加描画?}
    G --> H
    H -->|Yes| D
    H -->|No| I{状態プッシュあり?}
    I -->|Yes| J[PushedState.Dispose]
    I -->|No| K[Render終了]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-77-01 | ペン可視性 | Pen.Brush != null かつ Thickness > 0 で可視 | DrawLine/DrawGeometry等 |
| BR-77-02 | 角丸制限 | radiusXは0〜Width/2、radiusYは0〜Height/2にクランプ | DrawRectangle |
| BR-77-03 | 状態スタック | PushedStateはスタック順にDisposeする必要あり | Push系メソッド使用時 |

### 計算ロジック

ペンの可視性判定:
```csharp
static bool PenIsVisible(IPen? pen) => pen?.Brush != null && pen.Thickness > 0;
```

角丸のクランプ:
```csharp
radiusX = Math.Min(radiusX, rect.Width / 2);
radiusY = Math.Min(radiusY, rect.Height / 2);
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ArgumentNullException | 引数エラー | DrawImage等でsourceがnull | 有効な画像を指定 |
| InvalidOperationException | 状態エラー | Push/Popの順序が不正 | 正しい順序でDispose |
| ObjectDisposedException | Dispose後アクセス | Dispose後に状態操作 | Dispose前に完了 |

### リトライ仕様

本機能にリトライ仕様は存在しない。

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

本機能にトランザクション管理は存在しない。

## パフォーマンス要件

- 毎フレーム実行されるため高速な実行が必須
- 状態スタックはプール化されている（StateStackPool）
- 不要な描画は早期スキップされる

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

本機能は描画処理のみを担当するため、特別なセキュリティ考慮事項は存在しない。

## 備考

- DrawingContextは抽象クラスであり、プラットフォーム固有の実装が存在
- PushedStateを使用することで、usingパターンで状態管理が可能
- Custom(ICustomDrawOperation)でプラットフォーム固有の描画が可能

---

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

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

### 推奨読解順序

#### Step 1: メインクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DrawingContext.cs | `src/Avalonia.Base/Media/DrawingContext.cs` | 描画コンテキスト抽象クラス |

**主要処理フロー**:
- **23-34行目**: Disposeによる状態スタッククリア
- **43-47行目**: DrawImage（単一引数版）
- **56-60行目**: DrawImage（ソース/デスト矩形版）
- **77-81行目**: DrawLine
- **91-95行目**: DrawGeometry
- **128-145行目**: DrawRectangle
- **198-208行目**: DrawEllipse
- **239-244行目**: DrawText
- **325-331行目**: PushClip
- **370-376行目**: PushOpacity
- **401-407行目**: PushTransform
- **448-451行目**: PenIsVisible判定

#### Step 2: 状態管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DrawingContext.cs | `src/Avalonia.Base/Media/DrawingContext.cs` | PushedState構造体 |

**主要処理フロー**:
- **253-272行目**: PushedState record struct
- **274-318行目**: RestoreState record struct（Pop処理）

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

```
Control.Render(DrawingContext context)
    │
    ├─ context.PushClip(rect)
    │      └─ PushClipCore(rect)
    │
    ├─ context.DrawRectangle(brush, pen, rect)
    │      └─ DrawRectangleCore(brush, pen, rrect, boxShadows)
    │
    ├─ context.DrawLine(pen, p1, p2)
    │      └─ DrawLineCore(pen, p1, p2)
    │
    ├─ context.DrawGeometry(brush, pen, geometry)
    │      └─ DrawGeometryCore(brush, pen, geometry.PlatformImpl)
    │
    ├─ context.DrawImage(source, destRect)
    │      └─ source.Draw(this, sourceRect, destRect)
    │
    └─ PushedState.Dispose()
           └─ RestoreState.Dispose()
                  └─ PopClipCore() / PopOpacityCore() / PopTransformCore()
```

### データフロー図

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

Brush ─────────▶ DrawingContext ─────────▶ 描画キュー
Pen ───────────▶       │                        │
Geometry ──────▶       │                        ▼
Image ─────────▶       │                  Compositor
Text ──────────▶       │                        │
                       │                        ▼
               状態スタック管理            画面表示
               ・Clip
               ・Opacity
               ・Transform
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DrawingContext.cs | `src/Avalonia.Base/Media/DrawingContext.cs` | ソース | 描画コンテキスト抽象クラス |
| IDrawingContextImpl.cs | `src/Avalonia.Base/Platform/IDrawingContextImpl.cs` | ソース | プラットフォーム実装インターフェース |
| CompositionDrawingContext.cs | `src/Avalonia.Base/Rendering/Composition/Drawing/CompositionDrawingContext.cs` | ソース | Composition描画コンテキスト |
| ICustomDrawOperation.cs | `src/Avalonia.Base/Rendering/SceneGraph/ICustomDrawOperation.cs` | ソース | カスタム描画操作インターフェース |
| Brush.cs | `src/Avalonia.Base/Media/Brush.cs` | ソース | ブラシ定義 |
| Pen.cs | `src/Avalonia.Base/Media/Pen.cs` | ソース | ペン定義 |
| Geometry.cs | `src/Avalonia.Base/Media/Geometry.cs` | ソース | ジオメトリ定義 |
| FormattedText.cs | `src/Avalonia.Base/Media/FormattedText.cs` | ソース | 書式付きテキスト |
| GlyphRun.cs | `src/Avalonia.Base/Media/GlyphRun.cs` | ソース | グリフラン |
