Skip to content

Commit 2c3745c

Browse files
artizclaude
andcommitted
fix(pdf): reconstruct zero-width space boxes as word separators
pdfium gives generated spaces a zero-width loose box at a wrong baseline. Dropping them (to fix the 2305-pg9 jumble) also dropped real word-separator spaces, merging words (`Information systems` → `Informationsystems`, `high-quality` → `highquality`). Now reconstruct a degenerate space by spanning the gap to the next glyph on the same line, so the sanitizer keeps it as a separator. A wrap (different baseline) or a touching gap is left alone. 2206 272→264, 2203 255→253, 2305v1 56→54, normal_4pages 76→74; the 4 exact PDFs unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent a9be45c commit 2c3745c

1 file changed

Lines changed: 28 additions & 0 deletions

File tree

crates/fleischwolf-pdf/src/pdfium_backend.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,34 @@ fn glyphs(b: &dyn PdfiumLibraryBindings, tp: FPDF_TEXTPAGE, fetch_font: bool) ->
399399
out.swap(i, i + 1);
400400
}
401401
}
402+
// Reconstruct degenerate (zero-width) loose space boxes by spanning the gap to
403+
// the next glyph on the same line, so the sanitizer keeps them as word
404+
// separators rather than dropping them (which would merge `Information systems`
405+
// → `Informationsystems`). pdfium gives generated spaces a zero-width box at a
406+
// wrong baseline; a wrap (different baseline) or a touching gap is left alone.
407+
for i in 0..out.len() {
408+
if out[i].ch != ' ' || (out[i].lr - out[i].ll).abs() >= 0.5 {
409+
continue;
410+
}
411+
let prev = out[..i]
412+
.iter()
413+
.rev()
414+
.find(|g| g.ch != ' ' && g.ll.is_finite())
415+
.map(|g| (g.lr, g.lb, g.lt));
416+
let next = out[i + 1..]
417+
.iter()
418+
.find(|g| g.ch != ' ' && g.ll.is_finite())
419+
.map(|g| (g.ll, g.lb));
420+
if let (Some((plr, plb, plt)), Some((nll, nlb))) = (prev, next) {
421+
let line_h = (plt - plb).abs().max(1.0);
422+
if (plb - nlb).abs() < line_h * 0.5 && nll > plr + 0.5 {
423+
out[i].ll = plr;
424+
out[i].lr = nll;
425+
out[i].lb = plb;
426+
out[i].lt = plt;
427+
}
428+
}
429+
}
402430
out
403431
}
404432

0 commit comments

Comments
 (0)