Phase 4 Iteration 3: reflow đoạn văn 'như Word' (EditOp::ReflowText)

Engine:
- EditOp::ReflowText { indices, text }: engine tự suy hình học từ các run
  (lề trái/bề rộng từ bounds, baseline từ matrix.f gom cụm ±1pt, khoảng cách
  dòng = median hiệu baseline); bẻ dòng greedy đo bằng hmtx của font thật
  (fontmatch::wrap_lines + char_advance, ttf-parser); \n = ngắt dòng cứng,
  từ quá dài cắt theo ký tự, dòng rỗng giữ nhịp baseline
- Giữ font theo thang 4 mức nhất quán với iteration 2: (1) font nhúng parse
  được + phủ đủ glyph → nhúng lại chính bytes đó; (2) family base-14 + ASCII
  → font chuẩn PDF qua FPDFText_LoadStandardFont (BaseFont giữ tên chuẩn,
  không nhúng, file không phình; đo bằng font metric-compatible); (3) font
  hệ thống cùng họ; (4) fallback. FontLoad enum Bytes/Builtin cho pha nạp font
- Dòng mới giữ phần tuyến tính matrix của run neo (scale/nghiêng), Tf =
  unscaled run neo → cỡ hiển thị không đổi

UI + Tauri:
- paragraphLines: gom đoạn nhiều dòng (baseline cách đều ±25%, cỡ chữ tương
  đồng, giao ngang ≥30%); double-click đoạn ≥2 dòng → textarea sửa CẢ ĐOẠN
  WYSIWYG (đúng font/cỡ/màu/kiểu + line-height đúng nhịp baseline)
- Enter = xuống dòng cứng · Ctrl+Enter/bấm ra ngoài = áp dụng · Esc = huỷ;
  1 commit = 1 op reflowText = 1 nấc undo
- DTO reflowText (indices) trong Tauri

Test: 3 integration mới (wrap giữ font nhúng + tiếng Việt + baseline đều;
hard break; base-14 giữ BaseFont Helvetica chuẩn) + 3 unit wrap_lines.
Toàn bộ suite engine ngoài qpdf: 52/52 xanh.

Docs: 12 (Iteration 3 + giới hạn v1), 13 (E26–E30), 14 (mục 3.1 → đã giải,
cập nhật thứ tự việc tiếp theo), README.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HgnbPwSoRGNH7LHsDUmRpk
This commit is contained in:
2026-07-15 01:34:34 +00:00
co-authored by Claude Fable 5
parent c2076c0da6
commit fed43b2fb7
10 changed files with 713 additions and 41 deletions
+9
View File
@@ -41,6 +41,15 @@ cargo run
| E24 | Sửa text tiếng Việt trên file có font nhúng (file Word xuất PDF) | Đúng dấu **và giữ nguyên font nhúng** (mở lại ở Foxit xem tên font trong Edit) | |
| E25 | Sửa nhiều lần rồi thoát chế độ sửa (không lưu) | Không còn file `ff_edit_*.pdf` rác trong thư mục %TEMP% | |
## Bổ sung Iteration 3 — Sửa cả đoạn với reflow "như Word"
| # | Thao tác | Kỳ vọng | KQ |
|---|----------|---------|----|
| E26 | Bấm đúp vào 1 đoạn văn NHIỀU dòng | Textarea phủ CẢ ĐOẠN, nội dung ghép đủ các dòng, đúng font/cỡ/màu | |
| E27 | Thêm 1 câu dài vào giữa đoạn → Ctrl+Enter (hoặc bấm ra ngoài) | Chữ tự bẻ dòng lại trong đúng bề rộng khối, không tràn phải, khoảng cách dòng giữ nguyên, **font giữ nguyên** | |
| E28 | Trong textarea bấm Enter giữa chừng rồi áp dụng | Vị trí Enter thành xuống dòng cứng (đoạn tách dòng tại đó) | |
| E29 | Xoá bớt chữ cho đoạn ngắn lại → áp dụng | Đoạn co lại còn ít dòng hơn, không sót dòng cũ | |
| E30 | Hoàn tác (Ctrl+Z) sau 1 lần reflow | Cả đoạn quay về nguyên trạng trong 1 bước | |
## Mẫu phản hồi
```
[Mã] (vd E16) — Phần mềm mở: <Foxit/Adobe/Chrome> — Hiện tượng: <mô tả> —