diff --git a/fitz/fitz.i b/fitz/fitz.i index 10773f573..5b464361f 100644 --- a/fitz/fitz.i +++ b/fitz/fitz.i @@ -4625,6 +4625,7 @@ if basestate: old_annots[k] = v page._erase() # remove the page page = None + TOOLS.store_shrink(100) page = self.load_page(pno) # reload the page # copy annot refs over to the new dictionary diff --git a/src/__init__.py b/src/__init__.py index 8cb815d93..75ff1a8fa 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -5040,8 +5040,23 @@ def reload_page(self, page: "struct Page *") -> "struct Page *": pno = page.number # save the page number for k, v in page._annot_refs.items(): # save the annot dictionary old_annots[k] = v + + # We need to set `page.this` to `None` here in order to force the + # `mupdf::FzPage` to be removed from the MuPDF document's internal + # list, so that when `self.load_page()` is called below, its call of + # `fz_load_page()` will create a new `mupdf::FzPage`. + # + # This only works if the MuPDF `fz_page`'s reference count is 1. User + # code will have to work fairly hard to break this, by somehow making + # a copy of the mupdf::FzPage itself; for example making a copy in + # Python will usually create a new Python object that refers to the + # same mupdf::FzPage and this not increment the MuPDF reference count. + # + assert page.this.m_internal.refs == 1 + page.this = None page._erase() # remove the page page = None + TOOLS.store_shrink(100) page = self.load_page(pno) # reload the page # copy annot refs over to the new dictionary diff --git a/tests/resources/test_2596.pdf b/tests/resources/test_2596.pdf new file mode 100644 index 000000000..96498a0fc Binary files /dev/null and b/tests/resources/test_2596.pdf differ diff --git a/tests/test_general.py b/tests/test_general.py index e7dcdb517..9e78b17e5 100644 --- a/tests/test_general.py +++ b/tests/test_general.py @@ -539,3 +539,17 @@ def test_2692(): clip=fitz.Rect(0,0,10,10), ) + +def test_2596(): + """Cconfirm correctly abandoning cache when reloading a page.""" + doc = fitz.Document(f"{scriptdir}/resources/test_2596.pdf") + page = doc[0] + pix0 = page.get_pixmap() # render the page + _ = doc.tobytes(garbage=3) # save with garbage collection + + # Note this will invalidate cache content for this page. + # Reloading the page now empties the cache, so rendering + # will deliver the same pixmap + page = doc.reload_page(page) + pix1 = page.get_pixmap() + assert pix1.samples == pix0.samples