fix(text): keep unique /PlacedPDF bodies instead of suppressing them - #896
Merged
Conversation
InDesign wraps placed artwork in /PlacedPDF marked content, and pdf_oxide suppresses that text to drop decorative overlays and duplicated draft galleys (PMC8100493). The keep/suppress decision used only a char-count ratio: keep when placed text is >=800 chars AND non-placed text is < 1/3 of it. On spreads where the whole page body is placed (a floor-plan / marketing PDF: room labels, dimensions, disclaimer) but a comparable amount of unique text also sits outside the region, the 3:1 test fails and the ENTIRE page body is suppressed - extract_text/extract_spans return nothing while pdftotext/pymupdf extract the full page. The ratio is a crude proxy for the real signal, which is duplication: a draft-galley overlay REPEATS the surrounding text, whereas a placed page body is mostly unique. Replace the second half of the test with an actual duplication check (gate 3): once placed text clears the size gate but does not dominate, keep it unless a majority of its word tokens also appear in the non-placed text. Whole-body-placed (MATEC) still keeps via the dominance gate; minority/duplicate overlays still suppress. Measured on a 468-doc consensus content-F1 sample: 3 docs recovered (one placed floor-plan 0.51 -> 0.99, another 0.89 -> 1.00), no regressions; mean +0.0013. Two unit tests added for the gate-3 branches. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Anthony J. (Tony) Bufort <ajbufort@ajbconsulting.us>
yfedoseev
approved these changes
Jul 19, 2026
yfedoseev
left a comment
Owner
There was a problem hiding this comment.
Approved — reviewed and regression-passed; in the merge queue. (Formal approval to supersede the earlier review state and record sign-off.)
ajbufort
marked this pull request as ready for review
July 20, 2026 08:05
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
InDesign wraps placed artwork in
/PlacedPDFmarked content, and the text extractor suppresses that text to drop decorative overlays and duplicated draft galleys (the PMC8100493 case). The keep/suppress decision inplaced_pdf_text_dominatesused only a character-count ratio:i.e. keep placed text only when it is substantial and the non-placed text is a small (< 1/3) minority of it.
That heuristic misfires on spreads where the publisher places the entire page body inside
/PlacedPDF(a floor-plan / marketing PDF: room labels, dimensions, disclaimer) but a comparable amount of unique text also sits outside the region (headers, callouts). The 3:1 dominance test fails, so the whole page body is suppressed -extract_text/extract_spansreturn nothing, while pdftotext and PyMuPDF extract the full page.Concretely, on a 6-page InDesign floor-plan spread, two whole pages returned 0 spans where poppler returns 768 and 825 words.
extract_charsalready recovered ~3400 chars on those pages, so the loss was purely in this suppression gate.Fix
The char-count ratio is a crude proxy for the real signal, which is duplication: a draft-galley overlay repeats the surrounding text, whereas a placed page body is mostly unique. This keeps the two cheap gates and replaces the ratio's second job with an actual duplication check:
placed_chars < 800-> suppress (decorative figure; unchanged).other*3 < placed) -> keep (whole-body-placed, MATEC; unchanged).Gate 3's tokenisation runs only after gates 1 and 2, so the common single-column path stays allocation-free.
Measured
On a 468-doc consensus content-F1 sample: 3 docs recovered (a placed floor-plan 0.51 -> 0.99, another 0.89 -> 1.00, a third +0.01), no regressions, mean +0.0013. The change only ever affects pages carrying the
/PlacedPDFtag.Tests
test_placed_pdf_kept_when_unique_body_amid_comparable_outside- the recovered case.test_placed_pdf_suppressed_when_large_duplicate_overlay- a full-size placed duplicate still suppressed.placed_pdftests (MATEC keep, minority-overlay suppress, no-op without tag) unchanged and passing.Full gate on this branch off
main:cargo test --lib(5744 passed),cargo test --doc(139 passed),cargo clippy --libclean,cargo fmt --checkclean.