Skip to content

openpdf-renderer: support Tr text rendering mode (fixes invisible OCR text layers rendering as visible) - #1603

Open
andreasrosdalw wants to merge 2 commits into
LibrePDF:masterfrom
andreasrosdalw:feature/renderer-text-render-mode
Open

openpdf-renderer: support Tr text rendering mode (fixes invisible OCR text layers rendering as visible)#1603
andreasrosdalw wants to merge 2 commits into
LibrePDF:masterfrom
andreasrosdalw:feature/renderer-text-render-mode

Conversation

@andreasrosdalw

@andreasrosdalw andreasrosdalw commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • OpenPdfCorePageRenderer (the openpdf-core-backed Java2D rasterizer used by OpenPdfCoreRenderer) never parsed the Tr operator, so text was always filled regardless of the active PDF §9.3.3 text rendering mode.
  • This is a real, user-visible bug: scanned-PDF / OCR pipelines (e.g. Tesseract-generated PDFs) very commonly lay an invisible (Tr 3) searchable text layer directly on top of a page-image XObject. Without honoring Tr, that invisible text was incorrectly rendered as visible black glyphs on top of the scanned image.
  • Adds full Tr handling: mode 0 fill (previous/default behavior), mode 1 stroke (via Font.createGlyphVector + BasicStroke using the current stroke color/width/dash/join), mode 2 fill+stroke, and modes 3/7 invisible (skip painting entirely). Modes 4-6 (which additionally add glyphs to the clipping path) fall back to their 0-2 fill/stroke behavior — text clipping isn't implemented, called out explicitly in code and README.
  • Updated openpdf-renderer/README.md's operator-support tables and text-rendering section to document Tr support and the clip-mode caveat.

Previously the renderer always filled text regardless of the active PDF
§9.3.3 text rendering mode, so invisible text (Tr 3), which scanned-PDF /
OCR pipelines rely on to lay a searchable text layer over a page-image
XObject, would incorrectly render as visible glyphs on top of the image.
Add Tr parsing plus fill/stroke/invisible handling (modes 4-7, which also
add glyphs to the clip path, degrade to their 0-2 fill/stroke behavior
since text clipping isn't implemented). Update the README operator tables
and docs to match.
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 7 complexity · 6 duplication

Metric Results
Complexity 7
Duplication 6

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Consolidated into LibrePDF#1607 along with the README updates for LibrePDF#1604, LibrePDF#1605,
and LibrePDF#1606, so these four independent PRs (all based on master) don't each
carry their own overlapping README.md diff and risk merge conflicts with
each other depending on merge order.
andreasrosdalw added a commit to andreasrosdalw/OpenPDF that referenced this pull request Jul 28, 2026
Consolidated into LibrePDF#1607 along with the README updates for LibrePDF#1603, LibrePDF#1605,
and LibrePDF#1606, so these four independent PRs (all based on master) don't each
carry their own overlapping README.md diff and risk merge conflicts with
each other depending on merge order.
andreasrosdalw added a commit to andreasrosdalw/OpenPDF that referenced this pull request Jul 28, 2026
Consolidated into LibrePDF#1607 along with the README updates for LibrePDF#1603, LibrePDF#1604,
and LibrePDF#1606, so these four independent PRs (all based on master) don't each
carry their own overlapping README.md diff and risk merge conflicts with
each other depending on merge order.
andreasrosdalw added a commit to andreasrosdalw/OpenPDF that referenced this pull request Jul 28, 2026
Consolidated into LibrePDF#1607 along with the README updates for LibrePDF#1603, LibrePDF#1604,
and LibrePDF#1605, so these four independent PRs (all based on master) don't each
carry their own overlapping README.md diff and risk merge conflicts with
each other depending on merge order.
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant