Phase 4 Iteration 2: sửa text GIỮ NGUYÊN FONT (chuẩn Foxit) + UX edit mượt
Engine: - fontmatch.rs mới: làm sạch tên PostScript/subset, kiểm coverage cmap bằng ttf-parser, match font hệ thống CÙNG HỌ (bảng Windows/macOS, Liberation metric-compatible + fc-match trên Linux, alias base-14 Helvetica→Arial...) - edit.rs: SetText quyết định 3 tầng — (1) sửa TẠI CHỖ giữ nguyên font gốc (charset-subset / base-14+ASCII / cmap phủ đủ, gồm font nhúng + tiếng Việt); (2) thiếu glyph → thay font cùng họ đúng đậm/nghiêng; (3) mới đến fallback. Đổi cỡ chữ = scale matrix neo baseline, không đụng font; fix bug phóng đại kép khi text có matrix scale. ObjectInfo thêm font_family/bold/italic/embedded. SetText/AddText nhận font_family + bold/italic dạng Option (None = giữ nguyên) - annot.rs: fallback Linux có đủ biến thể đậm/nghiêng (DejaVu/Liberation) UI (chuẩn trải nghiệm Foxit): - Double-click sửa CẢ DÒNG (gộp run cùng baseline), commit 1 batch = 1 undo - Ô sửa WYSIWYG: đúng font/cỡ/màu/đậm-nghiêng của run gốc khi gõ - Toolbar Format: dropdown font "(giữ nguyên: X)", nút B/I theo kiểu thật, đổi cỡ/màu/kiểu gửi đúng field đó (null = giữ nguyên → không đổi font) - Kéo di chuyển/resize có phản hồi trực tiếp (live), resize neo góc trên-trái - Dọn file tạm ff_edit_* khi thoát/lưu (command edit_cleanup) Test: 14 test edit (7 mới: giữ font ASCII/base-14, giữ font NHÚNG tiếng Việt, match cùng họ, cỡ chữ neo + hồi quy matrix, bold override, gộp dòng) + 3 unit fontmatch. Toàn bộ suite engine ngoài qpdf: 50/50 xanh (chạy trên Linux). Docs: 12 (iteration 2), 13 (E17–E25), 14 MỚI — phân tích định hướng/công nghệ/ tiến độ so với tham vọng thay Foxit, gap còn lại + giải pháp; README cập nhật. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HgnbPwSoRGNH7LHsDUmRpk
This commit is contained in:
@@ -1,6 +1,76 @@
|
||||
# 12 — Tổng kết Phase 4 (Chỉnh sửa nội dung — Edit) · Iteration 1
|
||||
# 12 — Tổng kết Phase 4 (Chỉnh sửa nội dung — Edit) · Iteration 1 + 2
|
||||
|
||||
> Trạng thái: **lõi MOAT hoạt động**. 43/43 test engine xanh (36 cũ + 7 mới cho edit). Đã chạy app thật, chụp ảnh xác minh: sửa text tiếng Việt WYSIWYG, thêm chữ, xoá đối tượng, undo/redo.
|
||||
> Trạng thái sau Iteration 2: **sửa text GIỮ NGUYÊN FONT (chuẩn Foxit)**.
|
||||
> 50/50 test engine xanh ngoài qpdf (14 test edit + 3 unit fontmatch + 33 test cũ).
|
||||
> Iteration 1: 43/43, đã chạy app thật + chụp ảnh xác minh.
|
||||
|
||||
## Iteration 2 — Giữ font gốc + trải nghiệm Foxit (mới)
|
||||
|
||||
Đóng khoảng cách lớn nhất so với Foxit được chỉ ra khi review: **mọi lần sửa
|
||||
text đều bị đổi sang font hệ thống** (Helvetica → Arial/DejaVu), kể cả khi chỉ
|
||||
đổi cỡ/màu; bold/italic gốc bị mất; sửa theo mảnh run thay vì cả dòng.
|
||||
|
||||
### Engine (`edit.rs` viết lại + `fontmatch.rs` mới)
|
||||
- **`SetText` 3 tầng, ưu tiên GIỮ FONT GỐC** (sửa tại chỗ bằng `FPDFText_SetText`,
|
||||
không xoá/tạo lại):
|
||||
1. *In-place an toàn chắc chắn*: text mới chỉ dùng ký tự đã có trong run; hoặc
|
||||
font **không nhúng** (base-14 Helvetica/Times…) + text mới toàn ASCII
|
||||
(BaseFont khai báo giữ nguyên trong file — đúng hành vi Foxit); hoặc cmap
|
||||
của font (đọc qua `FPDFFont_GetFontData` + `ttf-parser`) phủ đủ ký tự mới
|
||||
→ **font giữ nguyên 100%**, gồm cả font NHÚNG với tiếng Việt.
|
||||
2. *Thiếu glyph thật sự* → thay bằng font hệ thống **CÙNG HỌ, đúng đậm/nghiêng**
|
||||
(`fontmatch::find_family_font_bytes`: bảng family Windows/macOS, Liberation
|
||||
metric-compatible + `fc-match` trên Linux; alias Helvetica→Arial,
|
||||
Times→Times New Roman…), có kiểm coverage trước khi nhận.
|
||||
3. Bất đắc dĩ mới rơi về font mặc định (`find_font_bytes` — nay có đủ biến thể
|
||||
đậm/nghiêng trên cả Linux).
|
||||
- **Đổi cỡ chữ tại chỗ không đụng font**: nhân matrix `[k,0,0,k, e(1−k), f(1−k)]`
|
||||
(neo baseline như Foxit). **Fix bug phóng đại kép**: cỡ chữ nghĩa "hiển thị"
|
||||
(đã nhân matrix scale) — trước đây đặt cỡ 20 lên text có matrix scale ×2 ra 40pt.
|
||||
- `ObjectInfo` thêm `font_family` (đã làm sạch tên PostScript/subset),
|
||||
`font_bold`, `font_italic`, `font_embedded` — nguồn từ `name()` (BaseFont) vì
|
||||
`family()` của font không nhúng trả tên stub nội bộ PDFium ("Chrom Sans OTF").
|
||||
- `SetText`/`AddText` nhận `font_family`/`bold`/`italic` dạng Option — **None =
|
||||
giữ nguyên**; Some = chủ động đổi (đổi font qua tầng 2).
|
||||
- Bẫy mới ghi nhận: `set_matrix` của pdfium-render 0.8.37 là alias deprecated
|
||||
của `apply_matrix` (NHÂN DỒN, không thay thế) — phải tự dựng matrix delta.
|
||||
|
||||
### UI (`main.js` + toolbar)
|
||||
- **Sửa CẢ DÒNG như Foxit**: double-click gom các run cùng baseline liền kề
|
||||
(PDF hay cắt 1 dòng thành nhiều run) → 1 ô sửa cho cả dòng; commit = SetText
|
||||
run đầu + Delete các run còn lại (1 batch, 1 nấc undo).
|
||||
- **WYSIWYG khi gõ**: ô sửa dùng đúng family (CSS xấp xỉ theo `font_family`),
|
||||
cỡ, màu, đậm/nghiêng của run gốc; nền trắng che text cũ.
|
||||
- **Giữ nguyên mặc định**: mọi commit sửa text gửi `null` cho font/cỡ/màu/kiểu
|
||||
— chỉ field người dùng chủ động đổi mới được gửi.
|
||||
- **Toolbar Format kiểu Foxit**: dropdown Font (mặc định "(giữ nguyên: X)"),
|
||||
nút **B**/**I** toggle theo kiểu thật của run (đổi biến thể cùng họ), Cỡ chữ,
|
||||
Màu — đổi thuộc tính KHÔNG đổi font.
|
||||
- **Kéo-thả live**: khung đi theo con trỏ ngay khi kéo (move + resize), thả
|
||||
chuột mới commit; resize neo góc trên-trái đúng như preview.
|
||||
- **Dọn file tạm**: mọi file `ff_edit_*.pdf` của phiên sửa được xoá khi thoát
|
||||
chế độ/lưu (command `edit_cleanup` — chỉ xoá đúng pattern trong %TEMP%).
|
||||
- Hint hiển thị font đang chọn: `Tên font · cỡ pt · font nhúng/hệ thống`.
|
||||
|
||||
### Test mới (7): `edit_roundtrip.rs` 14 test + `fontmatch` 3 unit
|
||||
- `set_text_keeps_original_font` — sửa ASCII trên Helvetica base-14 GIỮ NGUYÊN
|
||||
"Helvetica" (ép ký tự ngoài charset cũ để không ăn may).
|
||||
- `set_text_preserves_embedded_font_vietnamese` — **font NHÚNG + tiếng Việt
|
||||
giữ nguyên font** (case quan trọng nhất với tài liệu Việt).
|
||||
- `vietnamese_on_base14_uses_matched_family` — tiếng Việt trên base-14 (không
|
||||
có glyph Việt để giữ) match đúng họ metric-compatible (Liberation/Arial),
|
||||
không rơi bừa về generic.
|
||||
- `font_size_change_keeps_font_and_anchors`; `font_size_change_respects_matrix_scale`
|
||||
(hồi quy bug phóng đại kép); `bold_override_substitutes_font_and_keeps_text`;
|
||||
`line_merge_batch_set_text_plus_delete` (luồng UI gộp dòng).
|
||||
|
||||
### Đối chiếu FINAL TARGET & RULE
|
||||
- Vướng thư viện (PDFium `set_text` re-encode theo subset) → **không cắt giảm**:
|
||||
kiểm tra coverage bằng chính font bytes + luật charset/ASCII để tận dụng
|
||||
`set_text` an toàn, chỉ thay font khi về mặt vật lý không còn glyph để giữ —
|
||||
và khi thay thì match cùng họ như Foxit. Đúng thứ tự a→c của luật.
|
||||
|
||||
## Iteration 1 (giữ nguyên bên dưới để tham chiếu)
|
||||
|
||||
Phase 4 là tính năng lõi/moat theo `docs/03-roadmap.md`: sửa text & object trực tiếp trên trang — lý do quan trọng nhất để bỏ Foxit.
|
||||
|
||||
@@ -33,8 +103,11 @@ list_objects thấy text trang 1; SetText đổi nội dung (text cũ biến m
|
||||
Bật chế độ Sửa nội dung (overlay 2 đối tượng); double-click dòng 2 → sửa thành "Sửa: nội dung Tiếng Việt" → commit → trang render lại ĐÚNG (dấu chuẩn); Thêm chữ "Dòng chữ MỚI thêm" tại vị trí click; Hoàn tác bỏ chữ vừa thêm (giữ phần sửa); Xoá tiêu đề → còn 1 đối tượng. Ảnh: `tmp-out/phase4-*.png`.
|
||||
|
||||
## 5. Còn lại / follow-up (ghi nhận, không phải thiếu sót — Iteration sau)
|
||||
- **Reflow đoạn nhiều dòng "như Word"** (hiện sửa ở mức text run/dòng — mỗi PdfPageTextObject; đây là điểm khác chính so với Foxit, cần gom run theo baseline + reflow).
|
||||
- Xoay/lật/shear/clip object; tab Format nâng cao (viền, opacity, căn lề, đổi font-family object cũ); z-order arrange; convert text→path.
|
||||
- **Reflow đoạn nhiều dòng "như Word"** — khoảng cách chính còn lại so với Foxit
|
||||
(Iteration 2 đã sửa được CẢ DÒNG; bước tiếp: gom block nhiều dòng theo khoảng
|
||||
cách baseline + đo width bằng hmtx của font (ttf-parser đã có) + tự bẻ dòng).
|
||||
Xem kế hoạch ở `docs/14-foxit-gap-analysis.md`.
|
||||
- Xoay/lật/shear/clip object; tab Format nâng cao (viền, opacity, căn lề); z-order arrange; convert text→path. (Đổi font-family/B/I cho object cũ: ĐÃ XONG ở Iteration 2.)
|
||||
- Đặt ảnh theo đúng tỉ lệ gốc (hiện mặc định 150×112pt, resize bằng kéo handle); preview ảnh trước khi đặt.
|
||||
- Sửa nhiều trang trong 1 phiên lưu (hiện lưu theo trang đang sửa); spell-check; sửa bảng; link text blocks.
|
||||
- Mã hoá UI (nợ từ Phase 3).
|
||||
|
||||
Reference in New Issue
Block a user