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).
|
||||
|
||||
@@ -28,6 +28,19 @@ cargo run
|
||||
| E15 | **Lưu thay đổi nội dung** → chọn nơi lưu | Tạo file PDF mới; app mở lại file đó | |
|
||||
| E16 | Mở file đã lưu ở **Foxit/Adobe/Chrome** | Nội dung đã sửa hiển thị đúng (text, ảnh, **tiếng Việt đúng dấu**), file không hỏng | |
|
||||
|
||||
## Bổ sung Iteration 2 — GIỮ FONT + sửa cả dòng (chuẩn Foxit)
|
||||
| # | Thao tác | Kỳ vọng | KQ |
|
||||
|---|----------|---------|----|
|
||||
| E17 | Bấm đúp 1 dòng text bị cắt thành nhiều mảnh (PDF xuất từ Word thường vậy) | Ô sửa phủ **CẢ DÒNG** (không chỉ 1 mảnh), nội dung ghép đủ | |
|
||||
| E18 | Sửa 1 từ trong dòng, Enter | **Font giữ nguyên y hệt** phần còn lại của trang (so bằng mắt + panel chọn hiện tên font cũ) | |
|
||||
| E19 | Trong ô sửa đang gõ | Chữ trong ô hiển thị **đúng font/cỡ/màu/đậm-nghiêng** của dòng (WYSIWYG khi gõ, không phải font hệ thống chung chung) | |
|
||||
| E20 | Chọn text → chỉ đổi **Cỡ chữ** hoặc **Màu** | Font KHÔNG đổi, nội dung không đổi, vị trí neo không trôi | |
|
||||
| E21 | Chọn text → bấm **B** (Đậm) | Chữ thành đậm **cùng họ font** (Times → Times Bold, không nhảy sang Arial) | |
|
||||
| E22 | Chọn text → đổi **Font** trong dropdown | Chữ đổi đúng family chọn; dropdown mặc định hiển thị "(giữ nguyên: <font gốc>)" | |
|
||||
| E23 | Kéo di chuyển / kéo handle resize | Khung **đi theo con trỏ NGAY khi kéo** (live), thả chuột mới ghi nhận | |
|
||||
| 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% | |
|
||||
|
||||
## Mẫu phản hồi
|
||||
```
|
||||
[Mã] (vd E16) — Phần mềm mở: <Foxit/Adobe/Chrome> — Hiện tượng: <mô tả> —
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
# 14 — Phân tích khoảng cách so với Foxit: định hướng, công nghệ, tiến độ
|
||||
|
||||
> Trả lời câu hỏi chiến lược: *"Với tham vọng thay thế Foxit, đạt chất lượng
|
||||
> tương đương hoặc hơn về trải nghiệm và tính năng, thì định hướng, công nghệ
|
||||
> và tiến độ hiện tại có đáp ứng được không? Có vấn đề gì khiến các tính năng
|
||||
> không đáp ứng được như Foxit không?"*
|
||||
>
|
||||
> Cập nhật lần đầu: sau Phase 4 Iteration 2 (giữ font khi sửa text).
|
||||
|
||||
## 1. Kết luận ngắn
|
||||
|
||||
**Định hướng và công nghệ: ĐÁP ỨNG ĐƯỢC, không có rào cản chết người.**
|
||||
Stack Rust + Tauri + PDFium + QPDF đủ trần năng lực để đạt (và ở vài điểm vượt)
|
||||
Foxit cho toàn bộ lộ trình Phase 1–8. Lý do tin được điều đó:
|
||||
|
||||
- **PDFium là engine của Chrome** — render/parse text/font ngang hàng engine
|
||||
thương mại; Foxit bán chính engine của họ cho Google làm gốc PDFium. Ta đứng
|
||||
trên cùng một nền engine với đối thủ.
|
||||
- Những chỗ PDFium *không* expose đủ (ví dụ annotation appearance, /W width
|
||||
của font Type0, coverage cmap khi sửa text) đều đã xử lý được bằng cách
|
||||
**tự thao tác tầng PDF object qua `lopdf`/`ttf-parser`** (annot.rs,
|
||||
fontmatch.rs) — đúng thứ tự leo thang của FINAL TARGET & RULE, và đã chứng
|
||||
minh trong code chứ không phải giả định.
|
||||
- Các bài toán "khó nhất" của một PDF editor (sửa text giữ font, tổ chức trang
|
||||
an toàn, file hỏng/mã hoá) đã có lời giải chạy được + test.
|
||||
|
||||
**Tiến độ: đúng hướng nhưng mới đi ~40% quãng đường tính năng.** Phase 1–4
|
||||
(viewer, annotate, organize, edit lõi) là "core thay Foxit cho cá nhân" và đã
|
||||
xong ở mức lõi. Phần "đáng tiền doanh nghiệp" (bảo mật/chữ ký số, form, OCR,
|
||||
convert) chưa bắt đầu — đó là các phase 5–7 theo roadmap, không phải rủi ro
|
||||
công nghệ mà là khối lượng việc.
|
||||
|
||||
## 2. Những vấn đề TỪNG khiến tính năng không đạt chuẩn Foxit — và cách đã giải
|
||||
|
||||
| Vấn đề | Hậu quả với người dùng | Giải pháp đã áp dụng (đã có test) |
|
||||
|---|---|---|
|
||||
| PDFium `set_text` re-encode theo font subset → mất glyph ngoài subset | Sửa text là **đổi font toàn bộ run** (Times → Arial), lệch hẳn tài liệu; chỉ đổi cỡ/màu cũng đổi font; mất đậm/nghiêng | **Iteration 2**: quyết định 3 tầng — (1) sửa TẠI CHỖ giữ nguyên font khi chắc chắn an toàn (charset-subset / base-14 + ASCII / cmap của font bytes phủ đủ); (2) thiếu glyph thật → thay font **cùng họ** metric-compatible (bảng family + fc-match + alias base-14); (3) mới đến font mặc định. Đổi cỡ = scale matrix, không đụng font |
|
||||
| Cỡ chữ hiển thị vs Tf size lẫn lộn khi matrix có scale | Đặt cỡ 20 trên text scale ×2 → chữ 40pt (phóng đại kép) | Quy ước cỡ = "hiển thị"; in-place scale matrix neo baseline; tạo lại thì quy đổi ngược Tf trước khi áp matrix. Test hồi quy riêng |
|
||||
| PDF cắt 1 dòng nhìn thấy thành nhiều text run | Double-click chỉ sửa được 1 mảnh chữ — trải nghiệm vụn | UI gom run cùng baseline liền kề → sửa **cả dòng**; commit 1 batch (SetText + Delete) = 1 nấc undo |
|
||||
| Ô sửa inline dùng font mặc định của WebView | Đang gõ không giống kết quả (không WYSIWYG) | Ô sửa nhận đúng family/cỡ/màu/kiểu của run (CSS xấp xỉ theo `font_family` engine trả về) |
|
||||
| Kéo-thả không có phản hồi trực tiếp | Cảm giác "lag", không giống Foxit | Khung đi theo con trỏ ngay khi kéo; thả mới commit |
|
||||
| Annotation FreeText hiển thị sai width tiếng Việt ở viewer khác | File ghi ra "xấu" ở Acrobat | Tự dựng /W (widths) cho font Type0 nhúng bằng `ttf-parser` (Phase 2) |
|
||||
| PDFium segfault khi Drop object đã remove | Crash khi xoá object | `std::mem::forget` object đã tách (đã ghi memory + comment) |
|
||||
| File hỏng/mã hoá làm hỏng luồng lưu | Mất file người dùng | QPDF repair + mã hoá lại an toàn (Phase 3), test riêng |
|
||||
|
||||
**Bài học chung:** chưa gặp vấn đề nào *không giải được* trên stack này. Mọi
|
||||
"thư viện không hỗ trợ" đến nay đều xử lý được bằng đọc source thư viện + thao
|
||||
tác tầng PDF object trực tiếp.
|
||||
|
||||
## 3. Khoảng cách CÒN LẠI so với Foxit + giải pháp cụ thể
|
||||
|
||||
Xếp theo mức độ ảnh hưởng trải nghiệm:
|
||||
|
||||
### 3.1 Reflow đoạn văn nhiều dòng ("sửa như Word") — GAP LỚN NHẤT CÒN LẠI
|
||||
- **Hiện tại:** sửa được cả dòng (Iteration 2), chưa tự bẻ dòng lại cả đoạn.
|
||||
- **Foxit:** click vào đoạn → gõ → chữ tự chảy xuống dòng trong khối.
|
||||
- **Giải pháp (Iteration 3, khả thi với stack hiện tại):**
|
||||
1. Gom block: các dòng có baseline cách đều (±20%), cùng lề trái/phải giao nhau.
|
||||
2. Đo width chính xác tầng engine bằng `hmtx` của đúng font bytes
|
||||
(`ttf-parser` đã có trong cây phụ thuộc; với font không nhúng thì đo bằng
|
||||
font hệ thống đã match — chấp nhận sai số như chính Foxit).
|
||||
3. UI: textarea phủ block; engine nhận `ReflowBlock { runs, new_text, box }`
|
||||
→ tự bẻ dòng theo width, sinh dãy SetText/AddText/Delete với baseline
|
||||
spacing gốc.
|
||||
4. Nghiệm thu so với Foxit: gõ giữa đoạn 5 dòng → không tràn box, giãn dòng
|
||||
giữ nguyên, font giữ nguyên.
|
||||
- **Rủi ro:** đoạn justify (giãn từ) và kerning → v1 chấp nhận căn trái/đều
|
||||
theo heuristic, như mức "Edit Text" thường của Foxit.
|
||||
|
||||
### 3.2 Hiệu năng phiên sửa trên file rất lớn
|
||||
- **Hiện tại:** mô hình "materialize tức thì" — mỗi thao tác lưu toàn bộ tài
|
||||
liệu ra file tạm mới rồi render lại. Đúng tuyệt đối (WYSIWYG thật, undo chắc
|
||||
chắn), nhưng file vài trăm MB sẽ trễ nhìn thấy được ở mỗi thao tác; Foxit
|
||||
chỉnh trong RAM và lưu 1 lần.
|
||||
- **Giải pháp theo nấc (không phá kiến trúc):**
|
||||
1. (rẻ) Giữ document PDFium mở suốt phiên sửa trong Tauri state, áp op
|
||||
in-memory, chỉ render lại trang — bỏ chu kỳ load-từ-đĩa mỗi op; save ra
|
||||
temp chỉ để làm mốc undo (có thể async).
|
||||
2. (vừa) Undo bằng danh sách op thay vì snapshot file: replay từ gốc khi
|
||||
undo (op rẻ vì in-memory).
|
||||
3. (nếu cần) Incremental save của QPDF cho file khổng lồ.
|
||||
- **Ghi chú:** với file văn phòng thông thường (<20MB) mô hình hiện tại đã đủ
|
||||
mượt; nấc 1 chỉ là việc tổ chức lại Tauri command, không đổi engine.
|
||||
|
||||
### 3.3 Lưu file sau sửa: font nhúng full + object rác
|
||||
- **Hiện tại:** khi phải thay font (tầng 2/3), font mới nhúng **nguyên cả file
|
||||
TTF** (Arial ~1MB); object bị thay vẫn nằm lại file dưới dạng rác (đã tách
|
||||
khỏi trang nên không hiển thị, nhưng tốn dung lượng). Foxit subset font khi
|
||||
lưu và dọn object rác.
|
||||
- **Giải pháp:** bước "Lưu tối ưu" chạy khi save: (1) subset font nhúng theo
|
||||
đúng glyph dùng thật — tự viết được trên `ttf-parser` (đã dựng /W thủ công ở
|
||||
annot.rs, subset TTF là bài quen thuộc: lọc glyf/loca/cmap/hmtx); (2) chạy
|
||||
`qpdf --object-streams=generate` (đã có sẵn qpdf.rs) để dọn rác + nén object
|
||||
stream. Đưa vào Phase 5 cùng nhóm "lưu file vững".
|
||||
|
||||
### 3.4 Độ phủ font hệ thống khi thay thế
|
||||
- **Hiện tại:** bảng family phổ biến (Windows ~16 họ, macOS, Linux
|
||||
Liberation + fc-match). Font ngoài bảng → fallback mặc định.
|
||||
- **Giải pháp:** Windows dùng DirectWrite/GDI enumeration (crate `font-kit`
|
||||
hoặc đọc registry Fonts) để match theo TÊN THẬT của mọi font đã cài thay vì
|
||||
bảng tĩnh; giữ bảng tĩnh làm fallback offline. Việc nhỏ, độc lập, làm khi
|
||||
chạm phải file thực tế đầu tiên không match.
|
||||
|
||||
### 3.5 Các tính năng Foxit chưa bắt đầu (không phải rào cản kỹ thuật)
|
||||
| Nhóm | Đường đi đã chốt trong roadmap | Rủi ro công nghệ |
|
||||
|---|---|---|
|
||||
| Bảo mật, redaction, chữ ký số PAdES (Phase 5) | QPDF (mã hoá AES-256 sẵn), redaction = xoá object thật (đã có nền edit.rs), ký số qua `cryptographic-message-syntax`/`rustls` + incremental update | Trung bình — byte-range + incremental update phải chuẩn; có spec rõ, test bằng Acrobat |
|
||||
| Form AcroForm (Phase 6) | PDFium có FPDF_FORMFILL đầy đủ (fill/flatten); tạo field mới bằng lopdf | Thấp-trung bình |
|
||||
| OCR (Phase 7) | Tesseract (tiếng Việt có traineddata chuẩn) + lớp text ẩn — kỹ thuật giống watermark.rs đã làm | Thấp, chủ yếu là chất lượng tiền xử lý ảnh |
|
||||
| Convert Office↔PDF (Phase 7) | LibreOffice headless; PDF→Word "đủ dùng" trước | PDF→Word giữ layout hoàn hảo là bài khó với CẢ Foxit — đặt kỳ vọng "tương đương Foxit" chứ không hơn |
|
||||
| So sánh PDF, in ấn, installer (Phase 8) | render diff đã có nền; Tauri bundler | Thấp |
|
||||
|
||||
## 4. Đánh giá định hướng công nghệ (giữ hay đổi?)
|
||||
|
||||
**GIỮ.** Đánh giá lại từng lựa chọn sau 4 phase:
|
||||
|
||||
- **PDFium qua `pdfium-render`**: đúng đắn. Đã 2 lần tưởng "không làm được"
|
||||
(annotation appearance, giữ font khi sửa) và cả 2 lần đều giải được bằng
|
||||
API sẵn có + tự bù tầng PDF object. Trần năng lực còn xa.
|
||||
*Lưu ý vận hành:* `pdfium-render` 0.8.37 có API deprecated đổi nghĩa
|
||||
(`set_matrix` = apply, không phải replace) — đã ghi chú trong code; khi nâng
|
||||
version cần đọc CHANGELOG cẩn thận.
|
||||
- **Tauri/WebView UI**: đủ mượt cho viewer (lazy render 1000+ trang đã chứng
|
||||
minh ở Phase 1). Điểm cần canh: thao tác chuột mô phỏng trong WebView2 khó
|
||||
test tự động → bù bằng checklist test tay (docs/13) — chấp nhận được.
|
||||
- **QPDF sidecar**: gọn, đúng việc (repair/mã hoá/nén), không cần thay.
|
||||
- **Rust workspace tách engine/UI**: cho phép test engine không cần UI — chính
|
||||
là lý do 50 test tự động chạy được trong CI/Linux dù app nhắm Windows.
|
||||
|
||||
**Điều KHÔNG nên làm:** tự viết engine PDF từ đầu, hay chuyển C++/Qt để "giống
|
||||
Foxit hơn" — chi phí khổng lồ, không giải quyết gap nào ở mục 3.
|
||||
|
||||
## 5. Tiến độ so với đích + thứ tự việc đề xuất
|
||||
|
||||
Đã xong (lõi, có test): Viewer ✅ · Annotate ✅ · Organize + lưu vững ✅ ·
|
||||
**Edit text/object giữ font ✅ (iteration 2)**.
|
||||
|
||||
Thứ tự đề xuất tiếp theo, bám giá trị người dùng:
|
||||
1. **Iteration 3 của Edit: reflow đoạn** (mục 3.1) — hoàn tất lời hứa "sửa như
|
||||
Word", gap trải nghiệm cuối cùng của tính năng moat.
|
||||
2. **Phase 5 Bảo mật + "Lưu tối ưu"** (mục 3.3 gộp vào đây): mã hoá UI (nợ
|
||||
Phase 3), redaction thật, subset font, dọn rác, chữ ký số.
|
||||
3. Phase 6 Form → Phase 7 OCR/Convert → Phase 8 phát hành (theo roadmap).
|
||||
4. Song song, rải theo từng phase: mở rộng font matching (3.4) và nấc 1 của
|
||||
hiệu năng phiên sửa (3.2) khi chạm file lớn thực tế.
|
||||
|
||||
## 6. Checklist FINAL TARGET & RULE cho chính tài liệu này
|
||||
- [x] Đối chiếu từng tính năng với hành vi Foxit làm chuẩn nghiệm thu.
|
||||
- [x] Không đề xuất cắt giảm tính năng nào; mọi gap đều kèm giải pháp cụ thể.
|
||||
- [x] Giải pháp theo đúng thứ tự: dùng API thư viện → bù tầng PDF object → tự viết.
|
||||
- [x] Mỗi gap có tiêu chí nghiệm thu so với Foxit (mục 3).
|
||||
Reference in New Issue
Block a user