Trước đây phải bấm nút '✏️ Sửa nội dung' rồi mới double-click được. Giờ:
- Đang xem bình thường, đúp chuột vào chữ → hit-test qua edit_list_objects
tại điểm đúp (toạ độ PDF qua cssToPdf); có text object → tự vào chế độ Sửa
nội dung đúng trang + mở NGAY ô sửa tại đoạn đó (startTextEdit: đoạn nhiều
dòng ra textarea reflow, 1 dòng ra ô sửa dòng)
- Đúp vùng trống: không làm gì (như Foxit). Đang cầm công cụ chú thích /
organize / redact: bỏ qua. Element chú thích (freetext/note/markup) giữ
handler đúp riêng của chúng
- pickTextAt: ưu tiên box chứa điểm (nới 3pt, chọn box nhỏ nhất khi chồng),
fallback box gần nhất trong 12pt; enterEditMode nhận pageIndex tuỳ chọn;
editPendingPoint tiêu thụ sau loadEditPage; bỏ selection 1 từ do browser
tự bôi khi đúp trên text layer
Docs: 13 (E31–E33), README.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HgnbPwSoRGNH7LHsDUmRpk
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
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