Fix font/size preservation and startup freeze
- WYSIWYG editor: Calculate per-line line-heights based on original PDF spacing (gap between lines) instead of uniform height. Each line now gets its own advance value, preserving the exact layout when editing multi-line text with different font sizes (e.g., 22pt heading + 16pt body). - Startup freeze: Make organize_identity_plan non-blocking. Initialize pagePlan with default identity immediately, then load the real plan in the background. This prevents the UI from freezing when opening large PDFs while PDFium processes all pages. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HgnbPwSoRGNH7LHsDUmRpk
This commit is contained in:
+30
-6
@@ -107,7 +107,14 @@ async function loadDocument(path) {
|
|||||||
updateCurrentPage();
|
updateCurrentPage();
|
||||||
updateZoomLabel();
|
updateZoomLabel();
|
||||||
|
|
||||||
state.pagePlan = await invoke("organize_identity_plan", { path: state.path, password: null }).catch(() => []);
|
// Khởi tạo plan mặc định ngay (tất cả trang theo thứ tự gốc).
|
||||||
|
// Load plan thực tế ở background để không block UI khi mở file.
|
||||||
|
state.pagePlan = state.pages.map((p) => ({ page: p.index, rotate: 0 }));
|
||||||
|
invoke("organize_identity_plan", { path: state.path, password: null })
|
||||||
|
.then((plan) => {
|
||||||
|
state.pagePlan = plan;
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
state.orgSelected = new Set();
|
state.orgSelected = new Set();
|
||||||
state.orgAnchor = null;
|
state.orgAnchor = null;
|
||||||
state.orgThumbs = new Map();
|
state.orgThumbs = new Map();
|
||||||
@@ -2525,24 +2532,41 @@ function startBlockTextEdit(o, lines, ev) {
|
|||||||
// còn bbox PDF ôm sát glyph → đẩy khung lên (advPx − cỡ chữ)/2 cho trùng.
|
// còn bbox PDF ôm sát glyph → đẩy khung lên (advPx − cỡ chữ)/2 cho trùng.
|
||||||
const fs0 = (lines[0].fs || o.font_size || 12) * s;
|
const fs0 = (lines[0].fs || o.font_size || 12) * s;
|
||||||
const topPx = Math.max(0, (p.heightPt - union.top) * s - Math.max(0, (advPx - fs0) / 2));
|
const topPx = Math.max(0, (p.heightPt - union.top) * s - Math.max(0, (advPx - fs0) / 2));
|
||||||
|
// Tính advance cho TỪNG DÒNG dựa trên vị trí gốc trong PDF để giữ layout.
|
||||||
|
const perLineAdvances = [];
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
let linAdvPx;
|
||||||
|
if (i < lines.length - 1) {
|
||||||
|
// Advance = khoảng cách giữa dòng này và dòng tiếp theo (giữ nguyên từ PDF).
|
||||||
|
const gap = lines[i].rect.bottom - lines[i + 1].rect.top;
|
||||||
|
linAdvPx = Math.max(8, gap * s);
|
||||||
|
} else {
|
||||||
|
// Dòng cuối: dùng cỡ chữ × 1.25.
|
||||||
|
linAdvPx = Math.max(8, (lines[i].fs || 12) * s * 1.25);
|
||||||
|
}
|
||||||
|
perLineAdvances.push(linAdvPx);
|
||||||
|
}
|
||||||
|
const totalHeightPx = perLineAdvances.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
Object.assign(ce.style, {
|
Object.assign(ce.style, {
|
||||||
left: leftPt * s + "px",
|
left: leftPt * s + "px",
|
||||||
top: topPx + "px",
|
top: topPx + "px",
|
||||||
width: widthPt * s + "px",
|
width: widthPt * s + "px",
|
||||||
minHeight: lines.length * advPx + 4 + "px",
|
minHeight: totalHeightPx + 4 + "px",
|
||||||
textAlign: centered ? "center" : "left",
|
textAlign: centered ? "center" : "left",
|
||||||
});
|
});
|
||||||
|
|
||||||
// MỖI DÒNG 1 div với đúng cỡ/màu/kiểu của dòng đó (WYSIWYG khi gõ).
|
for (let i = 0; i < lines.length; i++) {
|
||||||
for (const l of lines) {
|
const l = lines[i];
|
||||||
const rep = l.runs.find((r) => (r.text || "").trim()) || l.runs[0] || o;
|
const rep = l.runs.find((r) => (r.text || "").trim()) || l.runs[0] || o;
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.className = "edit-line";
|
div.className = "edit-line";
|
||||||
const t = composeLineText(l.runs);
|
const t = composeLineText(l.runs);
|
||||||
if (t) div.textContent = t;
|
if (t) div.textContent = t;
|
||||||
else div.innerHTML = "<br>";
|
else div.innerHTML = "<br>";
|
||||||
div.style.fontSize = Math.max(6, (l.fs || 12) * s) + "px";
|
const divFs = Math.max(6, (l.fs || 12) * s);
|
||||||
div.style.lineHeight = advPx + "px";
|
div.style.fontSize = divFs + "px";
|
||||||
|
div.style.lineHeight = perLineAdvances[i] + "px";
|
||||||
div.style.fontFamily = cssFontStack(rep.font_family || o.font_family);
|
div.style.fontFamily = cssFontStack(rep.font_family || o.font_family);
|
||||||
div.style.fontWeight = (rep.font_bold != null ? rep.font_bold : o.font_bold) ? "bold" : "normal";
|
div.style.fontWeight = (rep.font_bold != null ? rep.font_bold : o.font_bold) ? "bold" : "normal";
|
||||||
div.style.fontStyle = (rep.font_italic != null ? rep.font_italic : o.font_italic) ? "italic" : "normal";
|
div.style.fontStyle = (rep.font_italic != null ? rep.font_italic : o.font_italic) ? "italic" : "normal";
|
||||||
|
|||||||
Reference in New Issue
Block a user