Repository navigation
Fix table header boldness checks to use page coordinates - #5235
Merged
veget-able merged 3 commits intoNov 5, 2026
Merged
Conversation
Contributor
|
All contributors have signed the CLA ✍️ ✅ |
Contributor
Author
|
I have read the CLA Document and I hereby sign the CLA |
Contributor
Author
|
recheck |
crunz-ailab
force-pushed
the
fix/table-header-bold-coordinates
branch
from
November 2, 2026 07:51
23fbaa1 to
1228cb2
Compare
julian-smith-artifex-com
force-pushed
the
main
branch
from
November 2, 2026 09:14
773a0d9 to
16c664f
Compare
crunz-ailab
force-pushed
the
fix/table-header-bold-coordinates
branch
from
November 2, 2026 16:10
1228cb2 to
793d91a
Compare
veget-able
approved these changes
Nov 5, 2026
veget-able
left a comment
Collaborator
There was a problem hiding this comment.
Thanks for the fix. Using top/bottom makes the character bounds consistent with the row coordinates.
In my 168-page comparison, most header changes appeared helpful, and Table.extract() was unchanged. I'm happy to approve this coordinate correction.
Contributor
Author
|
@veget-able |
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Summary
Use
top/bottomwhenTable._get_header().row_has_bold()checks whether a cached character is inside a table row. The row rectangle uses top-down page coordinates, but this helper currently compares it with the character's CTM-transformedy0/y1values.On an ordinary unrotated page, this can both miss a genuinely bold first row and treat unrelated, vertically mirrored bold text as belonging to that row. As a result, an otherwise correctly detected table can receive the wrong internal/external header.
This is a separate occurrence of the coordinate mismatch discussed in #5092 and PR #5096. Credit to Hao-ActuaViz for that report and BetterAndBetterII for the
chars_in_rect()patch. This PR only addressesrow_has_bold(); it neither duplicates that patch nor claims to resolve the open-table detection issue.Change and scope
The full-containment predicate, row bounds, and tolerances are unchanged. Nearby or partially overlapping characters do not become eligible simply because they are near a table. There are no changes to snapping, border completion, candidate grouping,
chars_in_rect(), or table geometry.Reproduction and tests
The added parameterized test constructs a closed 2-by-2 grid in memory, with no external PDF dependency. It covers four cases at two vertical positions:
Each case asserts the table bbox, all four cell rectangles, extracted cell text, header names, and
header.external.For the first case, the cell text stays
[['Header A', 'Header B'], ['value A', 'value B']]. Before the fix, the header is incorrectly['Above A', 'Above B']withexternal=True. After the fix, it is['Header A', 'Header B']withexternal=False.Validation
Base:
d2423b1367bcc9721ea7e994e710e5bc7ea91b09.tests/test_tables.py, including the new casesBuild limitation: these runs used current
mainPython sources with the existing PyMuPDF 2.0 compiled components / MuPDF 1.28.5, on macOS with Python 3.12.2 and pytest 7.4.4. They are not a full rebuild of currentmain(whose default MuPDF version is newer), nor a claim that the complete repository suite or upstream CI has passed. Layout and automatic dependency installation were disabled. A source-built CI run is still needed.An additional local comparison of native find_tables(use_layout=False) covered the first 60 pages of three technical manuals (180 pages total). Table counts, table/cell geometry, and extracted cell text were unchanged; only header metadata changed on two pages. This is supplementary local regression evidence, not a guarantee of exhaustive document compatibility. The self-contained synthetic tests above provide the primary reproducible validation. No original manual pages or extracted text are redistributed.
Supporting material
The prepared evidence archive includes the synthetic PDF and its generation/reproduction script, actual before/after results, focused containment tests, the proposed patch, sanitized upstream test logs, an AST isolation audit, and the 180-page comparison summaries. The earlier PyMuPDF 2.0 evidence is clearly separated from the new
main-source validation. No manufacturer PDF content is included.AI tools assisted with investigation, test preparation and execution, and drafting this description. Reported results are from actual local runs; the runtime limitations above are explicit.
Attachments
These files are stored on a separate evidence branch in my fork; they are not included in this PR diff. The links above pin the evidence commit.
Synthetic closed-grid example (page 2 of the PDF):