From a0dd7cf29339a3e26e1ec141b294cdca019566c5 Mon Sep 17 00:00:00 2001 From: Yuzhong Zhang Date: Fri, 21 Aug 2026 07:13:51 +0000 Subject: [PATCH] Fix chars_in_rect() to use top/bottom instead of CTM y0/y1 Pair top-down rects with character top/bottom, matching has_text(). --- src/table.py | 4 ++-- tests/test_tables.py | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/table.py b/src/table.py index 7b8e2c19c..89040752e 100644 --- a/src/table.py +++ b/src/table.py @@ -200,8 +200,8 @@ def chars_in_rect(CHARS, rect): 1 and rect[0] <= c["x0"] and c["x1"] <= rect[2] - and rect[1] <= c["y0"] - and rect[3] >= c["y1"] + and rect[1] <= c["top"] + and rect[3] >= c["bottom"] for c in CHARS ) diff --git a/tests/test_tables.py b/tests/test_tables.py index 9fbeec387..04b29d2b3 100644 --- a/tests/test_tables.py +++ b/tests/test_tables.py @@ -939,3 +939,23 @@ def test_find_tables_union_no_layout_degrades_to_line_candidates(): finally: pymupdf._get_layout = original_get_layout_fn doc.close() + + +def test_5092(): + """chars_in_rect must pair a top-down rect with top/bottom, not CTM y0/y1. + + A character whose top/bottom sit inside rect, but whose y0/y1 do not, + must still be detected. This matches the has_text() pairing. + """ + from pymupdf.table import chars_in_rect + + char = { + "x0": 10.0, + "x1": 20.0, + "top": 100.0, + "bottom": 110.0, + "y0": 690.0, + "y1": 700.0, + } + rect = (0.0, 90.0, 30.0, 120.0) # top-down: top=90, bottom=120 + assert chars_in_rect([char], rect)