-nf preserves every Td/Tm horizontal offset from the original document
(tuned for the original font's glyph advances) while drawing Helvetica
12pt glyphs. When the original font was smaller or narrower, adjacent
glyphs can land within ~2pt of each other. Rendering is merely cramped,
but PDFBox's PDFTextStripper default heuristic
suppressDuplicateOverlappingText (a faux-bold dedup) then silently drops
one of the overlapping glyphs during TEXT EXTRACTION.
Observed in the field: a customer PDF (MuseoSans-300 at 8pt) extracts
"prepared" as "prepard" from the normalized page - one 'e' rendered
1.7pt from its neighbor and was deduped by the stripper. Verified the
content stream itself carries the full text byte-for-byte; disabling the
heuristic recovers all characters.
Affects both the pre- and post-decoder-port engines identically (the
positioning logic is shared and unchanged). Fixing the overlap itself
means recomputing horizontal advances for the replacement font's metrics
- real typesetting work, intentionally out of scope for the decoder port.
Impact ranking: cosmetic for Eyes pixel comparison (both sides of a
comparison overlap identically), but anything downstream that EXTRACTS
text from normalized output may see dropped characters.
-nf preserves every Td/Tm horizontal offset from the original document
(tuned for the original font's glyph advances) while drawing Helvetica
12pt glyphs. When the original font was smaller or narrower, adjacent
glyphs can land within ~2pt of each other. Rendering is merely cramped,
but PDFBox's PDFTextStripper default heuristic
suppressDuplicateOverlappingText (a faux-bold dedup) then silently drops
one of the overlapping glyphs during TEXT EXTRACTION.
Observed in the field: a customer PDF (MuseoSans-300 at 8pt) extracts
"prepared" as "prepard" from the normalized page - one 'e' rendered
1.7pt from its neighbor and was deduped by the stripper. Verified the
content stream itself carries the full text byte-for-byte; disabling the
heuristic recovers all characters.
Affects both the pre- and post-decoder-port engines identically (the
positioning logic is shared and unchanged). Fixing the overlap itself
means recomputing horizontal advances for the replacement font's metrics
Impact ranking: cosmetic for Eyes pixel comparison (both sides of a
comparison overlap identically), but anything downstream that EXTRACTS
text from normalized output may see dropped characters.