Files
pdfcraft/crates/render
e8e275cbd4 Text extraction: honour /ActualText, so Thai from Chrome PDFs is searchable (#1217)
* Text extraction: honour /ActualText, so Thai from Chrome PDFs is searchable

Chrome (Skia) writes /ActualText around each Thai, Indic or Arabic cluster
whose shaped glyphs (a tone mark moved clear of a vowel, a ligature) have no
Unicode of their own. Text extraction ignored it, so those marks were lost:
"น้ำหนัก" came out as "นาหนัก", "เป็น" as "เปน", and searching for any
such word found nothing.

- hayro-interpret patch (25): Device::actual_text hands the device a
  marked content sequence's /ActualText, inline or named in /Properties.
- TextDevice turns the glyphs of a replacement into one glyph carrying the
  replacement text, boxed around them. The outermost replacement wins, an
  empty one stands for no text, and one spanning several lines or writing
  directions keeps per-glyph text so selection and lines still work.
- Canva draws text twice (outline or shadow) and marks only one drawing:
  the unmarked redraw at the same places takes the same replacement, so the
  existing redraw detection still drops the copy.

Checked on 1,114 real-world PDFs against the previous build, with pdftotext
as the reference: 957 extract byte-identical text, 157 change and all of
them read closer to the reference (exact matches 3 -> 122), none got worse,
none newly fail, and total extraction time is unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Text extraction: bound the work of the ActualText redraw dedupe

`TextDevice::finish()` compared every replacement with every unmatched glyph
in up to 4096 grid cells, so a hostile page stacking ~10^5 glyphs and ~10^5
replacements at one spot meant ~10^10 comparisons (a hang). It now charges
each visited cell and each candidate run against a per-page budget
(`MAX_REDRAW_WORK`, 2^22) and stops deduplicating once it is spent; redraws
found so far are still merged. A regression test feeds 100,000 replacements and
100,000 non-matching glyphs at one place.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: git-monchiant <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-12 03:28:27 -04:00
..