Commit Graph
14 Commits
Author SHA1 Message Date
adminandClaude Fable 5 74f161a627 Dot 1 "edit chuan moi PDF": CID/Identity-H font, format TUNG CHU, edit OCR, bu metrics, splash, Open-with
Build Windows portable / build (push) Canceled after 0s
1) fontfix v2 (PDF tu Word/InDesign): tong hop bang name/post khi subset
   thieu (OTS bat buoc); font CID/Identity-H KHONG co cmap -> dung cmap
   (3,1) fmt4 tu /ToUnicode x /CIDToGIDMap (Identity: GID=CID; stream 2B/CID
   parse tu descendant font); chan GID >= numGlyphs (maxp). tounicode.rs tra
   FontMapping {code_to_uni, is_cid, cid_to_gid}.

2) Format TUNG CHU trong o sua (chuan Word/Foxit): boi den -> B/I (nut
   toolbar khong cuop focus + Ctrl+B/I). UI tach span theo vung chon, dat
   data-bold/italic-override; commit gui override tung doan (RichSegDto
   bold/italic). Engine: bang style rich key theo (run nguon, override) -
   doi bien the thi lay font BIEN THE THAT cung ho (fontmatch -> builtin ->
   substitute), khong dung lai font goc. Test:
   rich_seg_bold_italic_override_uses_variant_font.

3) Edit file OCR (scan + text an): khoi toan run render-mode INVISIBLE ->
   ve rect TRANG che vung chu cu tren anh + ve text moi HIEN mau den (ca 4
   duong ve: rich chinh/fallback tu, 1-style chinh/fallback). Test:
   ocr_invisible_block_becomes_visible_with_cover.

4) Bu metrics kieu Adobe Sans MM trong o sua: span mang data-pdfw (be rong
   that tren trang); fitEditLinesToPdf them pass letter-spacing de moi nhom
   style chiem DUNG quang goc khi font thay the lech metrics (>2%); kep
   +/-18% co chu.

5) Khoi dong het "do": cua so tao AN (visible:false), UI show() ngay khi
   frontend san sang + man splash che phan nap dau; luoi an toan Rust hien
   cua so sau 4s neu JS chet som.

6) Open with FoFreeXit.exe: co che argv (initial_file) van hoat dong - loi
   nam o registry Applications tro exe CU (ban portable bi di chuyen/ghi
   de) lam Windows hien lai hop chon app. Fix tu chua: moi lan khoi dong
   dang ky lai HKCU (Applications command + ProgID FoFreeXit.pdf +
   OpenWithProgids .pdf) tro exe hien tai, chay nen qua reg.exe.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-10 16:44:06 +07:00
adminandClaude Fable 5 c885567b26 Fix de chu DOC khi luu: vong no pad_y=8 nuot nham DONG KE TREN khoi reflow
Build Windows portable / build (push) Canceled after 0s
Bug thu 2 cua "luu xong de len text khac" (bug 1 - de NGANG trong dong - da
fix bang mep muc that): vong no doc 8pt (sinh ra de bat dau tieng Viet ve
bang op roi) nuot ca run cao co chu cua DONG KE TREN khi gian dong sat
(~13-14pt): tam muc run dong tren lot vao bbox+8pt -> ca cau bi xoa,
first_baseline troi len 1 dong -> khoi ve lai de len vi tri dong tren, sot
manh mono dau dong (tam cao hon nguong chut).

Tai hien tren file that cua user (trang 2, khoi "Cac thuoc tinh HttpOnly..."
nuot dong "Path=/ khien refresh token..." ngay tren). Ban dau ket luan nham
la "file nhiem artifact" - DINH CHINH trong docs/12: file sach, Path=/ la
dau bullet hop le.

Fix: vung no 8pt chi duoc nuot op NHO (cao < 0.6 x median cao run trong
khoi - manh dau); op cao co chu phai co tam trong bbox LOI. Test hoi quy
reflow_tight_leading_does_not_swallow_line_above (gian dong 13pt, khoi 2
dong duoi, dong tren phai song sot + dong moi khong cham muc dong tren).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-10 10:33:54 +07:00
adminandClaude Fable 5 f0b4de9af1 Edit mode: zoom + chuyển trang + dòng lẫn nhiều style (thường/đậm/mono)
Build Windows portable / build (push) Canceled after 0s
3 vấn đề user báo trong chế độ Sửa nội dung:

1. ZOOM: stage sửa trước đây cứng 820px — nút +/-, dropdown %, Vừa rộng/
   Vừa trang và Ctrl+lăn chuột đều vô tác dụng. Giờ editZoom riêng (kế thừa
   zoom viewer khi vào): co giãn ảnh + overlay NGAY (CSS, mượt), render nét
   PDFium sau 220ms ngừng thao tác; mọi nút zoom/fit + Ctrl+wheel hoạt động;
   fix flex-center overflow (margin auto) để zoom to không cắt mép trái.

2. CHUYỂN TRANG: nút ▲▼/ô nhập trang trước đây chỉ điều khiển viewer đang
   ẩn. Giờ goToPage/gotoPrev/Next nhận biết edit mode → switchEditPage
   (đóng ô sửa đang mở, giữ nguyên undo/thay đổi các trang khác vì dùng
   chung editBase).

3. DÒNG LẪN STYLE (thường + đậm/mono): ô sửa trước áp 1 style/dòng nên
   "windowsInitialPassword" đậm hiện thành chữ thường, commit còn ép cả
   dòng về 1 font. Giờ:
   - UI: mỗi nhóm run liền kề cùng style = 1 SPAN riêng (đúng font/cỡ/màu
     từng phần khi gõ); commit đọc theo đoạn style (text node trần mượn
     style span kề); >=2 style gửi kèm richLines.
   - Engine: ReflowText thêm rich (Vec<Vec<RichSeg>>) — resolve thang
     giữ-font RIÊNG cho từng style-run (probe token gốc/nhúng lại bytes/
     builtin/cùng họ), token hoá theo từ giữ style + glue giữa đoạn dính
     liền, bẻ dòng chung cả khối, vẽ mỗi cụm cùng-style thành 1 object
     đúng font/cỡ/màu, tự kiểm + fallback từng từ như đường 1-style.
   - fitEditLinesToPdf: đo text node sâu trong span; hiệu chỉnh cỡ scale
     cả span. Tầng-0 token gốc tắt khi KHỐI có run nested (trước chỉ xét
     anchor — token vô hiệu sau khi mở lại document hậu phẫu thuật).
   - Test: fixture 1 dòng Helvetica + Courier-Bold → sửa phần thường,
     phần mono giữ nguyên BaseFont Courier-Bold, cùng baseline đúng thứ tự.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-10 09:03:32 +07:00
adminandClaude Fable 5 390fb82dd6 Fix cỡ chữ ÂM với file toạ độ lật (Canva): pdfium-render lấy vertical scale = matrix.d CÓ DẤU — chuẩn hoá .abs() tại mọi điểm đọc cỡ trong engine (list/geo/anchor/inplace/capture). Cỡ âm làm UI kẹp ô sửa về 6px (sai vị trí/style) và reflow đo bề rộng âm → không bẻ dòng, chữ mới văng khỏi trang (cổng pass vì ít pixel) → 'text biến mất'. Kèm 2 test fixture form MA TRẬN LẬT (cỡ dương ~24, reflow đặt chữ đúng vùng cũ)
Build Windows portable / build (push) Canceled after 0s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 18:15:23 +07:00
adminandClaude Fable 5 26701b9242 PHẪU THUẬT stream form: sửa/xoá text TRONG Form XObject không cần mở gói
Build Windows portable / build (push) Canceled after 0s
Iteration 4b — giải pháp triệt để cho file Canva (thay cổng chặn của 4a):
module formsurgery (lopdf) xoá đúng op vẽ chữ (Tj/TJ/'/") của run bị thay
trong stream form — mọi byte khác giữ NGUYÊN (không đụng generator lossy
của PDFium); chữ mới vẽ ở CẤP TRANG như thường.

- Map PDFium ↔ stream: text-child thứ k của form ↔ show-op thứ k; form con
  thứ n ↔ Do-trỏ-form thứ n. Mỗi mức có BẤT BIẾN kiểm đếm (số op == số
  object PDFium thấy) — lệch là từ chối, không đoán mò. '/" thay bằng
  T*/Tw+Tc+T* để giữ hiệu ứng vị trí cho chữ sau.
- apply_edits: run nested trong ReflowText/Delete → phẫu thuật ở pha A2 rồi
  MỞ LẠI document (index cấp trang không đổi); tầng-0 reflow (token gốc)
  tắt cho anchor nested (token vô hiệu sau mở lại) → đi tầng nhúng bytes/
  cùng họ. SetText/Transform nested vẫn từ chối rõ (UI chặn với hint).
- CỔNG AN TOÀN mới: page_render_mismatch_masked — mọi thay đổi pixel phải
  nằm TRONG vùng khối sửa (band reflow + rect run xoá); lệch ngoài vùng
  >0.5% → huỷ output, giữ nguyên file gốc.
- UI: bỏ auto-flatten (không cần nữa), sửa nested trong suốt qua đúp chuột;
  hint 1 dòng cố định + ellipsis + title (hết cảnh trang nhảy lên xuống do
  thanh công cụ co giãn); chặn-với-thông-điệp cho đổi thuộc tính/kéo khối
  trong form.
- Test: fixture form thêm dòng 2 + path đỏ; 2 test phẫu thuật (delete/reflow
  giữ nguyên phần khác, form còn nguyên); SetText nested vẫn bị từ chối.
  Flatten + cổng cũ giữ nguyên engine-side (có test riêng).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 07:46:39 +07:00
adminandClaude Fable 5 5c53c1f987 Cong an toan cho mo goi form: so render truoc/sau (page_render_mismatch), lech >0.5% pixel -> huy + chan sua voi thong diep ro. E2E tren CV Canva that phat hien generator PDFium lossy (font subset trung ten bi gop lam mat glyph, anh inline bi bo, z-order xao tron) - khong ship flatten mu quang; ke hoach iteration sau (phau thuat stream bang lopdf) ghi trong docs.
Build Windows portable / build (push) Canceled after 0s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 03:22:41 +07:00
adminandClaude Fable 5 8c6a819aa8 Fix assert test reflow form: cum tu tim kiem vat qua cho be dong - so khop tren ban chuan hoa khoang trang (chuc nang reflow da chay dung, extract ra 6 dong)
Build Windows portable / build (push) Canceled after 0s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 02:32:21 +07:00
adminandClaude Fable 5 d4b09e0ed8 Form XObject vòng 4 — kiến trúc cuối: MỞ GÓI form ra cấp trang trước khi sửa
Build Windows portable / build (push) Canceled after 0s
Kết luận sau 3 vòng CI + đọc nguyên văn source PDFium: PDFium hiện KHÔNG ghi
lại được stream của Form XObject — CPDF_PageContentManager chỉ biết key
/Contents (trang), form là stream tự thân nên nội dung regenerate rơi vào
key /Contents vô nghĩa trên dict form, stream thật giữ nguyên. Mọi cách sửa
"trong form" đều không thể lưu.

- Engine mới: flatten_form_xobjects — rút từng con khỏi form
  (FPDFFormObj_RemoveObject), nhân ma trận form vào con, chèn lại vào TRANG,
  xoá form rỗng; lặp <=4 vòng cho form lồng form. Hiển thị y hệt, mọi object
  thành cấp trang, sửa bằng đường page-level đã test kỹ.
- Tauri: command edit_flatten_to_temp; UI loadEditPage thấy object nested →
  tự mở gói một lần rồi nạp lại (bản mở gói không tính là "có thay đổi").
- apply_edits: gỡ toàn bộ đường sửa-trong-form (NestedRecreate, rút con,
  đánh thức trang — đã chứng minh không thể lưu); op nhắm vào object trong
  form khi chưa flatten → lỗi rõ "trang chưa được mở gói" (có test).
- Test viết lại theo flow flatten: 6 test (liệt kê nested, flatten giữ vị
  trí/nội dung, settext/reflow/delete sau flatten, từ chối op nested).
Docs 12-phase4-summary.md cập nhật kết luận + giới hạn (mất clip/ExtGState
mức form khi flatten; cấu trúc file đổi khi lưu).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 02:26:30 +07:00
adminandClaude Fable 5 e66252681c Sửa được text nằm trong Form XObject (file Canva/Illustrator) + CI chạy test
Build Windows portable / build (push) Canceled after 0s
File Canva gói toàn bộ nội dung trang vào 1 Form XObject nên chế độ sửa
không thấy gì để sửa. Engine giờ liệt kê PHẲNG đệ quy vào form
(FPDFFormObj_CountObjects/GetObject qua pdfium-render), mỗi mục có path
[i,j,...] + tích ma trận form để quy toạ độ/cỡ chữ về trang; index của
ObjectInfo/EditOp = vị trí trong danh sách phẳng (trang không form thì
trùng index trang — tương thích ngược, UI không đổi cách gửi op).

- SetText in-place/substitute + ReflowText + Delete hoạt động với run trong
  form; xoá trong form = set_text chuỗi rỗng (FPDFFormObj_RemoveObject chưa
  mở ở wrapper cho pdfium_7543), object mới vẽ ở cấp trang với matrix đã
  compose.
- Đã xác minh trước: PDFium regenerate stream form khi con bị sửa
  (ProcessForm / HasDirtyStreams) — canary test round-trip kèm theo.
- ObjectInfo thêm nested/expanded; UI bỏ khung form phủ trang + chặn kéo
  run trong form (Transform chưa hỗ trợ).
- 4 test integration mới với fixture Form XObject tự dựng bằng lopdf
  (dev-dependency mới); CI thêm bước cargo test -p ff-engine trước build
  (máy dev không có Rust — CI là nơi duy nhất chạy test), cache thêm target/.
Chi tiết: docs/12-phase4-summary.md (Iteration 4).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 01:41:21 +07:00
adminandClaude Fable 5 58cba1f415 Sửa 3 lỗi edit inline vòng 2 (file thật Word-export): hết □ thay dấu cách, dòng không vỡ khi thêm ký tự, ô sửa WYSIWYG đúng cỡ từng dòng
Chẩn đoán □: PDFium FPDFText_LoadFont nạp LẠI font subset rồi SetText map
U+0020 ra .notdef (hộp vuông) dù cmap font CÓ glyph space (đã probe cả 2
subtable) — lỗi PDFium với font nạp động, không phải do font.

Engine (edit.rs):
- Tầng 0 mới của thang font reflow: DÙNG LẠI chính font object gốc trong
  PDF (PdfFontToken của run neo, không nạp lại) — glyph + charcode map gốc
  xử lý dấu cách chuẩn, file không phình; chỉ chọn sau khi PROBE ghi/đọc-lại
  toàn bộ text mới thành công (tạo object nháp → so text → gỡ + mem::forget)
- Ghi từng dòng xong ĐỌC LẠI NGAY tự kiểm; PDFium vẫn vứt ký tự → gỡ và ghi
  lại TỪNG TỪ tự đặt vị trí bằng advance hmtx (không bao giờ ghi glyph dấu
  cách) — lưới an toàn cuối cho font lạ
- Dòng cứng (\n từ ô sửa) NỞ tới +35% bề rộng khối (chặn mép trang) trước
  khi bẻ lại — hộp text tự nở như Foxit; khối căn giữa nở đều quanh tâm
- line_styles theo baseline gốc: dòng cứng thứ i giữ ĐÚNG CỠ dòng gốc thứ i
  (tiêu đề 22.5/20pt không bị ép cả khối về 1 cỡ)

UI (main.js + styles.css):
- Ô sửa cả đoạn đổi textarea → contenteditable plaintext-only: MỖI DÒNG GỐC
  = 1 div đúng font/cỡ/màu/đậm-nghiêng CỦA DÒNG ĐÓ, khối căn giữa hiện căn
  giữa (nở đều 2 phía quanh tâm), khung bù lệch dọc line-box → chữ trong ô
  TRÙNG vị trí chữ gốc khi mở; con trỏ đặt đúng điểm đúp (caretRangeFromPoint);
  Enter xuống dòng, Ctrl+Enter/blur áp dụng, Esc huỷ, dán luôn chữ thuần

Kiểm chứng file thật: "HỢP"→"HỢPP" giữ đúng 2 dòng căn giữa cỡ 22.5/20,
font BAAAAA+TimesNewRomanPS-BoldMT gốc, dấu cách nguyên vẹn, render khớp
bản gốc. Test: +2 hồi quy (giữ cỡ từng dòng; dòng nở không bẻ) → edit 21/21,
các suite annot/organize/redact/form xanh. Docs 12 (mục vá vòng 2), 13
(E39–E42).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HgnbPwSoRGNH7LHsDUmRpk
2026-07-16 16:15:04 +00:00
adminandClaude Fable 5 c8f22b091f Sửa edit inline với PDF Word-export: khung theo dòng, sửa cả đoạn giữ xuống dòng, hết chồng chữ
Chẩn đoán trên file thật (Word xuất): tiêu đề 2 dòng bị cắt thành 41 run
per-word/per-char xen run rỗng kích thước 0, cỡ 22.5pt + 20pt trộn nhau,
bbox chữ có dấu (Ạ, Ợ) tụt thấp hơn hẳn chữ thường.

UI (main.js):
- clusterTextLines: gom run thành DÒNG theo GIAO DỌC ≥50% chiều cao nhỏ
  (miễn nhiễm dấu tiếng Việt) + tách cột theo hở ngang; gắn run rỗng vào dòng
  chứa nó. Overlay vẽ 1 khung/DÒNG (file thật: 231 ô vụn → 18 khung);
  chọn/kéo/xoá/đổi thuộc tính tác động CẢ DÒNG (batch ops, editSelRuns)
- paragraphLines mới trên nền cluster: dòng kề nhau (hở ≤1.3× chiều cao),
  giao ngang ≥30%, cỡ chữ ≤1.8× (tiêu đề 22.5/20pt vẫn 1 đoạn), khoá nhịp ±35%
- Đúp LUÔN mở ô sửa CẢ ĐOẠN, mỗi dòng gốc = 1 dòng textarea (giữ và sửa được
  cả xuống dòng); đúp trúng KHE giữa các từ vẫn mở (hit-test theo điểm trên
  overlay); click/chọn chữ trong ô sửa di chuyển con trỏ, KHÔNG thoát edit
  (stopPropagation + guard .edit-inline ở onEditStageClick); ô che kín chữ cũ,
  line-height đúng nhịp dòng, scrollIntoView

Engine (edit.rs ReflowText):
- TỰ NỞ danh sách run: mọi text object có tâm trong union bbox (+2pt) của các
  run được đưa đều bị thay — không bao giờ sót run rỗng/lệch bbox → hết cảnh
  chữ mới chồng chữ cũ
- Phát hiện khối CĂN GIỮA (tâm mọi dòng ≈ tâm khối, có dòng thụt trái) →
  dòng mới đặt x = tâm khối − w/2 (đo hmtx) — tiêu đề căn giữa giữ căn giữa

Kiểm chứng với file thật (cục bộ): 39 run tiêu đề xoá sạch 0 mảnh sót, 2 dòng
mới căn giữa lệch tâm trang <5pt, extract sạch chữ cũ; grouping đúng khi đúp
mọi từ của cả 2 dòng lẫn header 8pt per-char.

Test: 2 test hồi quy mới (nở indices bắt run giữa bị sót; giữ căn giữa đo
bằng fixture tự căn) → edit 19/19, toàn bộ engine 75/75 ngoài qpdf-fixture.
Docs: 12 (mục vá theo phản hồi), 13 (E34–E38).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HgnbPwSoRGNH7LHsDUmRpk
2026-07-16 10:49:59 +00:00
adminandClaude Fable 5 fed43b2fb7 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
2026-07-15 01:34:34 +00:00
adminandClaude Fable 5 1285a8d6ae 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
2026-07-14 16:58:22 +00:00
admin e442a9f678 Phase 3 (Organize + robust save) + Phase 4 (Edit content); update docs
Engine:
- organize.rs: build_document(plan) core — insert/delete/rotate/crop/extract/merge/split
- watermark.rs: watermark + header/footer via PdfPages::watermark, CID Unicode fonts
- qpdf.rs: QPDF CLI wrapper — repair corrupt files, re-encrypt after edits, ensure_openable
- edit.rs: MOAT — list_objects + apply_edits (SetText VN, Transform, Delete, Add/ReplaceImage)
- Tests: organize/watermark/qpdf_safety/edit roundtrip — 43/43 engine tests green

UI (Tauri): "Tổ chức trang" mode (grid + drag-reorder + multi-select), "Sửa nội dung"
mode (WYSIWYG object overlay, edit-in-place), global undo/redo, robust file open.

Corpus: add encrypted.pdf + corrupt-truncated.pdf fixtures.

Docs: mark Phase 1-4 done in roadmap; document QPDF setup + engine module layout in
05-dev-setup; add 10-13 phase summaries & user-test checklists; README status.
2026-07-14 22:07:38 +07:00