# Double Buffer Architecture Research v14
## Focus: v5 實作規格 — 精確的修改清單

---

## 新增全域變數

### usrfont_c.c
```c
int g_bBufferValid = 0;  /* 1 = s_hdcPaintBuf has valid content from last frame */
```

---

## 修改 1：PaintText — 跳過 capture

### gtwvt.c PaintText（目前的 v4 code）
```c
{ extern int g_bSharedPaint;
  if( g_bSharedPaint )
  {
     // ★ 現在：永遠 capture
     BitBlt( s_hdcPaintBuf ← hdcScreen, ps.rcPaint );
     hdc = g_hPaintBuf;   // 等等，g_hPaintBuf 還沒設...
  }
```

### 問題：v4 的 capture 和 g_hPaintBuf 設定時序

目前 v4 的流程：
1. PaintText capture: BitBlt(s_hdcPaintBuf ← screen, ps.rcPaint)
2. PaintText TextOut → s_hdcPaintBuf
3. PaintText 結尾：g_hPaintBuf = s_hdcPaintBuf（跳過 BitBlt 到螢幕）
4. ScanAndDrawUda：hdcDraw = g_hPaintBuf → 直接畫 UDA
5. ScanAndDrawUda：writeback g_hPaintBuf → screen

v5 修改 step 1：
```c
extern int g_bBufferValid;
extern int g_bSharedPaint;

if( g_bSharedPaint && g_bBufferValid )
{
   /* v5: skip capture — buffer has valid content from last frame */
   hdc = s_hdcPaintBuf;
   bUseMemDC = 2;
}
else if( g_bSharedPaint )
{
   /* Shared mode, buffer not valid — need capture */
   BitBlt( s_hdcPaintBuf ← hdcScreen, ps.rcPaint );
   hdc = s_hdcPaintBuf;
   bUseMemDC = 2;
}
else
{
   /* Original path */
   ...
}
```

---

## 修改 2：buffer 重建時重設 g_bBufferValid

### gtwvt.c PaintText（buffer 重建 if 區塊內）
```c
if( !s_hdcPaintBuf || rcClient.right != s_nPaintBufW || rcClient.bottom != s_nPaintBufH )
{
   // delete + recreate buffer
   ...
   extern int g_bBufferValid;
   g_bBufferValid = 0;  /* v5: new buffer needs capture */
}
```

---

## 修改 3：writeback 成功後設 g_bBufferValid = 1

### usrfont_scan.c ScanAndDrawUda（writeback BitBlt 後）

在 v4 的 writeback 區塊後加：
```c
if( g_hPaintBuf )
{
   BitBlt( hdc ← g_hPaintBuf, dirty rows );
   extern int g_bBufferValid;
   g_bBufferValid = 1;  /* v5: buffer now valid for next frame */
}
```

也在早期返回的 writeback 後設：
```c
if( g_hPaintBuf )
{
   BitBlt( hdc ← g_hPaintBuf, dirty rows );
   extern int g_bBufferValid;
   g_bBufferValid = 1;
}
```

---

## 修改 4：WM_DISPLAYCHANGE 重設

### usrfont_wndproc.c（可選）

如果需要處理顯示模式變化：
```c
if( msg == WM_DISPLAYCHANGE )
{
   extern int g_bBufferValid;
   g_bBufferValid = 0;
}
```

不確定 GTWVT 是否處理 WM_DISPLAYCHANGE。
此修改可延後（極少發生的情境）。

---

## 修改總結

| 檔案 | 位置 | 修改 | 行數 |
|------|------|------|------|
| usrfont_c.c | 全域宣告 | `int g_bBufferValid = 0` | 1 |
| gtwvt.c | PaintText capture | g_bBufferValid 時跳過 BitBlt | 5 |
| gtwvt.c | PaintText buffer 重建 | `g_bBufferValid = 0` | 2 |
| usrfont_scan.c | writeback 後 | `g_bBufferValid = 1`（3 處） | 6 |
| **總計** | | | **~14 行** |

---

## 風險評估

| 風險 | 機率 | 影響 | 緩解 |
|------|------|------|------|
| buffer 未初始化顯示垃圾 | 極低 | 高 | g_bBufferValid=0 強制 capture |
| Resize 後殘留舊內容 | 低 | 中 | buffer 重建時 g_bBufferValid=0 |
| WM_DISPLAYCHANGE 後 DC 不相容 | 極低 | 高 | 重設 g_bBufferValid（可延後） |
| g_bBufferValid 在錯誤時機被設為 1 | 低 | 中 | 只在成功 writeback 後設 |

**整體風險：低。** 14 行修改，有 g_bBufferValid=0 的安全回退。
