# 機能設計書 13-リガチャサポート

## 概要

本ドキュメントは、Ghosttyのリガチャ（合字）サポート機能の設計について記述する。HarfBuzzライブラリを使用したテキストシェーピングにより、プログラミングフォントのリガチャを正確に表示する機能である。

### 本機能の処理概要

**業務上の目的・背景**：
プログラミング用フォント（Fira Code、JetBrains Mono、Cascadia Code等）は、`->`, `=>`, `!=`, `<=` などの文字列を美しい合字（リガチャ）として表示する機能を持つ。ターミナルエミュレータでこれらのリガチャを正しく表示するためには、高度なテキストシェーピング処理が必要となる。本機能はHarfBuzzを使用してフォントのOpenType機能を活用し、リガチャを含む複雑なテキストレイアウトを実現する。

**機能の利用シーン**：
- プログラミングフォントでのコーディング
- 矢印演算子（`->`, `=>`）の美しい表示
- 比較演算子（`!=`, `<=`, `>=`）の合字表示
- ユニコード結合文字の正確なレンダリング

**主要な処理内容**：
1. テキストランの識別と分割
2. HarfBuzzバッファへのコードポイント追加
3. フォント機能（features）の適用
4. テキストシェーピングの実行
5. グリフインデックスと位置情報の取得
6. セルへのマッピングとレンダリング座標の計算

**関連システム・外部連携**：
- HarfBuzz（テキストシェーピングエンジン）
- FreeType（フォントラスタライザ）
- フォントコレクション（フォント管理）
- レンダラー（グリフ描画）

**権限による制御**：
特になし。フォント機能設定で無効化可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインターミナルウィンドウ | 主画面 | リガチャを含むテキストの表示 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| opts | Options | Yes | シェーピングオプション | 有効な設定 |
| features | [][]const u8 | No | フォント機能リスト | 有効なOpenType機能タグ |
| cells | Slice | Yes | ターミナルセル配列 | 有効なセルデータ |
| grid | *SharedGrid | Yes | フォントグリッド | 初期化済み |

### 入力データソース

- ターミナルのテキストセル（terminal.RenderState.Cell）
- フォントコレクション（font.Collection）
- 設定ファイル（font-feature設定）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| cells | []shape.Cell | シェーピング結果のセル配列 |
| x | u16 | セルのX位置 |
| x_offset | i16 | X方向オフセット |
| y_offset | i16 | Y方向オフセット |
| glyph_index | u32 | グリフインデックス |

### 出力先

レンダラーのセルバッファ

## 処理フロー

### 処理シーケンス

```
1. シェーパー初期化
   └─ HarfBuzzバッファ作成、フォント機能パース
2. ランイテレータ取得
   └─ RunIterator作成、シェーピング境界設定
3. テキストラン処理
   └─ 各ランごとに以下を実行
      3.1 バッファ準備
          └─ HarfBuzzバッファをリセット、方向設定
      3.2 コードポイント追加
          └─ セルからUnicodeコードポイントを抽出
      3.3 シェーピング実行
          └─ HarfBuzz.shape()呼び出し
      3.4 結果変換
          └─ グリフ情報と位置情報をセルに変換
4. 結果返却
   └─ シェーピング済みセル配列を返す
```

### フローチャート

```mermaid
flowchart TD
    A[シェーパー初期化] --> B[フォント機能パース]
    B --> C[ランイテレータ取得]
    C --> D{次のラン?}
    D -->|Yes| E[HarfBuzzバッファ準備]
    E --> F[コードポイント追加]
    F --> G[HarfBuzz.shape実行]
    G --> H[グリフ情報取得]
    H --> I[セルへ変換]
    I --> D
    D -->|No| J[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | LTR強制 | RTLテキストもLTRとして処理 | シェーピング時 |
| BR-02 | クラスタレベル | characters粒度でクラスタ管理 | シェーピング時 |
| BR-03 | デフォルト機能 | calt, dlig等のデフォルト機能を適用 | 特に無効化されない限り |
| BR-04 | クワーク対応 | 一部フォントでデフォルト機能を無効化 | quirks_disable_default_font_features |

### 計算ロジック

位置計算：
- `x_offset`: run_offset.x - cell_offset.x + (pos.x_offset >> 6)
- `y_offset`: run_offset.y + (pos.y_offset >> 6)
- 26.6固定小数点から整数への変換（+32して>>6）

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| HarfbuzzFailed | シェーピングエラー | 位置情報取得失敗 | エラー返却 |

### リトライ仕様

リトライなし。エラー時はシェーピングなしで文字を表示。

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

該当なし

## パフォーマンス要件

- HarfBuzzバッファの再利用によるアロケーション削減
- テキストランごとの効率的なバッチ処理
- フレームレートへの影響を最小化

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

- フォントデータの検証はHarfBuzz/FreeTypeに委譲
- 悪意のあるフォントによるバッファオーバーフローの防止

## 備考

- RTLサポートは将来の拡張として検討中
- CoreTextバックエンドでは別の実装を使用

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | shape.zig | `src/font/shape.zig` | Cell構造体（40-57行目）、Options構造体（59-67行目） |
| 1-2 | harfbuzz.zig | `src/font/shaper/harfbuzz.zig` | Shaper構造体（22-58行目） |

**読解のコツ**: shape.CellはX位置とオフセット、グリフインデックスを持つシンプルな構造。Shaperはhb_bufとhb_featsを再利用する設計。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | harfbuzz.zig | `src/font/shaper/harfbuzz.zig` | init関数（61-93行目） |
| 2-2 | harfbuzz.zig | `src/font/shaper/harfbuzz.zig` | runIterator関数（113-121行目） |

**主要処理フロー**:
1. **63-84行目**: フォント機能のパース（default_features + カスタム機能）
2. **87-92行目**: HarfBuzzバッファとシェーパーの初期化
3. **113-121行目**: RunIteratorの作成

#### Step 3: シェーピング処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | harfbuzz.zig | `src/font/shaper/harfbuzz.zig` | shape関数（130-258行目） |
| 3-2 | harfbuzz.zig | `src/font/shaper/harfbuzz.zig` | RunIteratorHook（262-298行目） |

**主要処理フロー**:
- **133-149行目**: フォント取得とHarfBuzzシェーピング実行
- **154-159行目**: グリフ情報と位置情報の取得
- **163-167行目**: ランオフセットとセルオフセットの管理
- **170-242行目**: グリフ情報からセルへの変換、クラスタ管理
- **244-251行目**: アドバンス（進行量）の蓄積
- **265-280行目**: prepare()でバッファ初期化、LTR方向設定

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

```
Shaper.init()
    │
    ├─ FeatureList.appendSlice(default_features)
    │
    └─ harfbuzz.Buffer.create()

Shaper.runIterator()
    │
    └─ RunIterator { hooks: RunIteratorHook }

Shaper.shape(run)
    │
    ├─ grid.lock.lock()
    │
    ├─ collection.getFace(font_index)
    │
    ├─ harfbuzz.shape(face.hb_font, hb_buf, hb_feats)
    │
    ├─ hb_buf.getGlyphInfos()
    │
    ├─ hb_buf.getGlyphPositions()
    │
    └─ cell_buf変換ループ
           ├─ クラスタ管理
           ├─ オフセット計算
           └─ cell_buf.append()
```

### データフロー図

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

Terminal Cells ─────▶ RunIterator ──────▶ TextRun
        │
        ▼
TextRun + Font ─────▶ harfbuzz.shape() ──▶ GlyphInfo[] + GlyphPos[]
        │
        ▼
GlyphInfo/Pos ──────▶ 座標変換 ──────────▶ shape.Cell[]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| shape.zig | `src/font/shape.zig` | ソース | シェーピングインターフェース定義 |
| harfbuzz.zig | `src/font/shaper/harfbuzz.zig` | ソース | HarfBuzzシェーパー実装 |
| coretext.zig | `src/font/shaper/coretext.zig` | ソース | CoreTextシェーパー実装（macOS） |
| noop.zig | `src/font/shaper/noop.zig` | ソース | シェーピングなし実装 |
| run.zig | `src/font/shaper/run.zig` | ソース | テキストラン管理 |
| feature.zig | `src/font/shaper/feature.zig` | ソース | フォント機能管理 |
| Cache.zig | `src/font/shaper/Cache.zig` | ソース | シェーピングキャッシュ |
