From 63cfd37cb5f50e75c5f57eea4e2ddcf60631bfcf Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Wed, 21 Oct 2026 17:49:40 +0100 Subject: [PATCH 1/2] tests/test_annots.py: test_5201(): new. Currently expects error with mupdf>=1.28.5. --- tests/test_annots.py | 84 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/tests/test_annots.py b/tests/test_annots.py index ab139795e..c1d29b48e 100644 --- a/tests/test_annots.py +++ b/tests/test_annots.py @@ -890,3 +890,87 @@ def words(page): print(i) assert results == expected + + +def test_5201(): + print() + path1 = os.path.normpath(f'{__file__}/../../tests/test_5201_out1.pdf') + path2 = os.path.normpath(f'{__file__}/../../tests/test_5201_out2.pdf') + with pymupdf.open() as document: + page = document.new_page() + + def show_text(prefix): + ''' + Returns rawdict and also print out blocks, lines, spans and chars. + ''' + text = page.get_text('rawdict') + for i_b, block in enumerate(text['blocks']): + print(f'block {i_b}') + for i_l, line in enumerate(block['lines']): + print(f' line {i_l}') + for i_s, span in enumerate(line['spans']): + print(f' span {i_s}') + for i_c, char in enumerate(span['chars']): + print(f' char {i_c}') + print(f' {prefix}{char["origin"]=} {char["bbox"]=} {char["c"]=}') + return text + + def chars_g(text): + ''' + Generator for each char in rawdict. + ''' + for block in text['blocks']: + for line in block['lines']: + for span in line['spans']: + for char in span['chars']: + yield char + + def chars(text): + ''' + Returns list of each char in rawdict. + ''' + return list(chars_g(text)) + + def show_chars(chars, prefix): + ''' + Show chars. + ''' + for char in chars: + print(f'{prefix}origin={str(char["origin"]):<32} bbox={str(char["bbox"]):<80} {char["c"]=}') + + page.insert_text((20, 40), 'This is the example text') + page.insert_text((20, 60), 'This is the example text') + page.insert_text((20, 80), 'This is the example text') + text1 = show_text('1: ') + document.save(path1) + print(f'Have saved to {path1=}') + + page.add_redact_annot((50, 70, 120, 80)) + page.apply_redactions() + text2 = show_text('2: ') + document.save(path2) + print(f'Have saved to {path2=}') + + # Detect/show differences in origin and bbox of last three characters. + chars1 = chars(text1)[-3:] + chars2 = chars(text2)[-3:] + show_chars(chars1, '1: ') + show_chars(chars2, '2: ') + num_errors = 0 + for i in range(3): + char1 = chars1[-3+i] + char2 = chars2[-3+i] + x1 = list(char1['origin']) + list(char1['bbox']) + x2 = list(char2['origin']) + list(char2['bbox']) + d = [i2 - i1 for (i1, i2) in zip(x1, x2)] + for dd in d: + print(f'{dd=}') + if abs(dd) >= 0.1: + num_errors += 1 + + print(f'{num_errors=}') + if pymupdf.mupdf_version_tuple >= (1, 28, 5): + # Bug introduced in mupdf-1.28.5. + assert num_errors + else: + assert num_errors == 0 From 5237572661542c9d0d5abc672115c477c4472c8f Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Thu, 22 Oct 2026 16:10:35 +0100 Subject: [PATCH 2/2] tests/test_mupdf_regressions.py: test_mupdfcpp64_dll_symbols(): new. Checks whether mupdfcpp64.dll contains symbol fz_argv_from_wargv. --- tests/test_mupdf_regressions.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/test_mupdf_regressions.py b/tests/test_mupdf_regressions.py index 316ec7c81..ffed361c1 100644 --- a/tests/test_mupdf_regressions.py +++ b/tests/test_mupdf_regressions.py @@ -1,7 +1,10 @@ -import pymupdf import os +import platform + +import pymupdf import gentle_compare + scriptdir = os.path.abspath(os.path.dirname(__file__)) @@ -93,3 +96,20 @@ def test_3376(): ok = gentle_compare.gentle_compare(words0_e, words1) assert ok + + +def test_mupdfcpp64_dll_symbols(): + print() + if platform.system() != 'Windows': + print(f'test_mupdfcpp64_dll_symbols(): Not running on non-windows') + return + p = f'{pymupdf.__path__[0]}/mupdfcpp64.dll' + assert(os.path.isfile(p)), f'Not found: {p}' + with open(p, 'rb') as f: + content = f.read() + fz_argv_from_wargv_in_mupdfcpp64_dll = b'fz_argv_from_wargv' in content + print(f'{fz_argv_from_wargv_in_mupdfcpp64_dll=}') + if pymupdf.mupdf_version_tuple >= (1, 29): + assert fz_argv_from_wargv_in_mupdfcpp64_dll + else: + assert not fz_argv_from_wargv_in_mupdfcpp64_dll