From 6b5097dc846762afbf35b615ba6b50e1d294d25d Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Wed, 7 Dec 2022 16:35:00 +0000 Subject: [PATCH 1/6] tests/: added some low-level tests. --- tests/test_general.py | 4 ++++ tests/test_pixmap.py | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/tests/test_general.py b/tests/test_general.py index 96fef8dab..a332b8abc 100644 --- a/tests/test_general.py +++ b/tests/test_general.py @@ -120,3 +120,7 @@ def test_bug1971(): page.get_drawings() doc.close() +def test_default_font(): + f = fitz.Font() + assert str(f) == "Font('Noto Serif Regular')" + assert repr(f) == "Font('Noto Serif Regular')" diff --git a/tests/test_pixmap.py b/tests/test_pixmap.py index e29431a83..ec78253bb 100644 --- a/tests/test_pixmap.py +++ b/tests/test_pixmap.py @@ -88,3 +88,24 @@ def test_setalpha(): # confirm correct the alpha bytes t = bytearray([samples[i] for i in range(3, len(samples), 4)]) assert t == alphas + +def test_color_count(): + pm = fitz.Pixmap(imgfile) + assert pm.color_count() == 40624 + +def test_memoryview(): + pm = fitz.Pixmap(imgfile) + samples = pm.samples_mv + assert isinstance( samples, memoryview) + print( f'{samples=} {samples.itemsize=} {samples.nbytes=} {samples.ndim=} {samples.shape=} {samples.strides=}') + assert samples.itemsize == 1 + assert samples.nbytes == 659817 + assert samples.ndim == 1 + assert samples.shape == (659817,) + assert samples.strides == (1,) + +def test_samples_ptr(): + pm = fitz.Pixmap(imgfile) + samples = pm.samples_ptr + print( f'{samples=}') + assert isinstance( samples, int) From 7ef172daf9c22615a1fe38e3808b9f75e91910ce Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Fri, 9 Dec 2022 14:31:14 +0000 Subject: [PATCH 2/6] setup.py: made OS-detection more consistent. Use just platform.system(). --- setup.py | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/setup.py b/setup.py index decd14d5d..3a0d4135f 100644 --- a/setup.py +++ b/setup.py @@ -518,14 +518,23 @@ def get_mupdf(): extra_link_args = [] extra_compile_args = [] +log( f'platform.system()={platform.system()!r}') +log( f'sys.platform={sys.platform!r}') + +linux = platform.system() == 'Linux' +openbsd = platform.system() == 'OpenBSD' +freebsd = platform.system() == 'FreeBSD' +darwin = platform.system() == 'Darwin' +windows = platform.system() == 'Windows' or platform.system().startswith('CYGWIN') + if 'sdist' in sys.argv: # Create local mupdf.tgz, for inclusion in sdist. get_mupdf_tgz() if ('-h' not in sys.argv and '--help' not in sys.argv - and ( - 'bdist_wheel' in sys.argv + and (0 + or 'bdist_wheel' in sys.argv or 'build' in sys.argv or 'bdist' in sys.argv or 'install' in sys.argv @@ -560,7 +569,7 @@ def get_mupdf(): log( f'Building mupdf.') shutil.copy2( 'fitz/_config.h', f'{mupdf_local}include/mupdf/fitz/config.h') - if platform.system() == 'Windows' or platform.system().startswith('CYGWIN'): + if windows: # Windows build. devenv = os.environ.get('PYMUPDF_SETUP_DEVENV') if not devenv: @@ -587,9 +596,9 @@ def get_mupdf(): flags += ' verbose=yes' env = '' make = 'make' - if os.uname()[0] == 'Linux': + if linux: env += ' CFLAGS="-fPIC"' - if os.uname()[0] in ('OpenBSD', 'FreeBSD'): + if openbsd or freebsd: make = 'gmake' env += ' CFLAGS="-fPIC" CXX=clang++' @@ -646,13 +655,6 @@ def get_mupdf(): if unix_build_dir: library_dirs.append( unix_build_dir) - log( f'sys.platform={sys.platform!r}') - - linux = sys.platform.startswith( 'linux') or 'gnu' in sys.platform - openbsd = sys.platform.startswith( 'openbsd') - freebsd = sys.platform.startswith( 'freebsd') - darwin = sys.platform.startswith( 'darwin') - if mupdf_local and (linux or openbsd or freebsd): # setuptools' link command always seems to put '-L # /usr/local/lib' before any that we specify, @@ -703,13 +705,13 @@ def get_mupdf(): library_dirs.append("/opt/homebrew/lib") - if sys.platform.startswith( 'freebsd'): + if freebsd: libraries += [ 'freetype', 'harfbuzz', ] - else: + elif windows: # Windows. assert mupdf_local if word_size() == 32: @@ -725,6 +727,9 @@ def get_mupdf(): ] extra_link_args = ["/NODEFAULTLIB:MSVCRT"] + else: + assert 0, 'Unrecognised OS' + if linux or openbsd or freebsd or darwin: extra_compile_args.append( '-Wno-incompatible-pointer-types') extra_compile_args.append( '-Wno-pointer-sign') @@ -742,13 +747,6 @@ def get_mupdf(): include_dirs += local_dirs.get("include_dirs", []) library_dirs += local_dirs.get("library_dirs", []) - if 1: - # Diagnostics. - log( f'library_dirs={library_dirs}') - log( f'libraries={libraries}') - log( f'include_dirs={include_dirs}') - log( f'extra_link_args={extra_link_args}') - log( f'include_dirs={include_dirs}') log( f'library_dirs={library_dirs}') log( f'libraries={libraries}') From c69f6ac19766958aa0dbdc2c634e93ed4bb5fcd8 Mon Sep 17 00:00:00 2001 From: "Jorj X. McKie" Date: Fri, 9 Dec 2022 10:35:28 -0400 Subject: [PATCH 3/6] Several Bug Fixes Fix #2110 (Discussion item #2111): File `__main__.py` - also include the font's xref in the generated file name. Fix #2094: File `helper-device.i' - also ensure equality of x coordinates of relevant corners before assuming a rectangle. Fix #2087: File `fitz.i`- if JPX image format is already known, make sure to read the decoded image stream, instead of raw stream in the other cases. --- fitz/__main__.py | 2 +- fitz/fitz.i | 12 +++++++++--- fitz/helper-devices.i | 44 +++++++++++++++---------------------------- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/fitz/__main__.py b/fitz/__main__.py index acda5700c..19305941b 100644 --- a/fitz/__main__.py +++ b/fitz/__main__.py @@ -512,7 +512,7 @@ def extract_objects(args): if ext == "n/a" or not buffer: continue outname = os.path.join( - out_dir, fontname.replace(" ", "-") + "." + ext + out_dir, f"{fontname.replace(' ', '-')}-{xref}.{ext}" ) outfile = open(outname, "wb") outfile.write(buffer) diff --git a/fitz/fitz.i b/fitz/fitz.i index 52fa03031..c2a21f2fd 100644 --- a/fitz/fitz.i +++ b/fitz/fitz.i @@ -2775,14 +2775,16 @@ if len(pyliste) == 0 or min(pyliste) not in range(len(self)) or max(pyliste) not if (pdf_is_jpx_image(gctx, obj)) { img_type = FZ_IMAGE_JPX; + res = pdf_load_stream(gctx, obj); ext = "jpx"; } if (JM_is_jbig2_image(gctx, obj)) { img_type = FZ_IMAGE_JBIG2; + res = pdf_load_stream(gctx, obj); ext = "jb2"; } - res = pdf_load_raw_stream(gctx, obj); if (img_type == FZ_IMAGE_UNKNOWN) { + res = pdf_load_raw_stream(gctx, obj); unsigned char *c = NULL; fz_buffer_storage(gctx, res, &c); img_type = fz_recognize_image_format(gctx, c); @@ -2795,9 +2797,10 @@ if len(pyliste) == 0 or min(pyliste) not in range(len(self)) or max(pyliste) not res = fz_new_buffer_from_image_as_png(gctx, img, fz_default_color_params); ext = "png"; - } else /*if (smask == 0)*/ { + } else { img = fz_new_image_from_buffer(gctx, res); } + fz_image_resolution(img, &xres, &yres); width = img->w; height = img->h; @@ -2835,7 +2838,8 @@ if len(pyliste) == 0 or min(pyliste) not in range(len(self)) or max(pyliste) not fz_catch(gctx) { Py_CLEAR(rc); - Py_RETURN_NONE; + fz_warn(gctx, fz_caught_message(gctx)); + Py_RETURN_FALSE; } if (!rc) Py_RETURN_NONE; @@ -12332,6 +12336,7 @@ struct Archive } return (struct Archive *) arch; } + Archive(PyObject *a0=NULL, const char *path=NULL) { fz_archive *arch=NULL; @@ -13566,6 +13571,7 @@ struct Story return ret; } + void draw( struct DeviceWrapper* device, PyObject* matrix=NULL) { fz_matrix ctm2 = JM_matrix_from_py( matrix); diff --git a/fitz/helper-devices.i b/fitz/helper-devices.i index e4253bfe9..b19dda3a5 100644 --- a/fitz/helper-devices.i +++ b/fitz/helper-devices.i @@ -101,6 +101,7 @@ jm_checkrect() dev_linecount = 0; // reset line count long orientation = 0; fz_point ll, lr, ur, ul; + fz_rect r; PyObject *rect; PyObject *line0, *line2; PyObject *items = PyDict_GetItem(dev_pathdict, dictkey_items); @@ -109,15 +110,13 @@ jm_checkrect() line0 = PyList_GET_ITEM(items, len - 3); ll = JM_point_from_py(PyTuple_GET_ITEM(line0, 1)); lr = JM_point_from_py(PyTuple_GET_ITEM(line0, 2)); - + // no need to extract "line1"! line2 = PyList_GET_ITEM(items, len - 1); ur = JM_point_from_py(PyTuple_GET_ITEM(line2, 1)); ul = JM_point_from_py(PyTuple_GET_ITEM(line2, 2)); /* --------------------------------------------------------------------- - Three connected lines: at least a quad! Check whether even a rect. - For this, the lines must be parallel to the axes. Assumption: For decomposing rects, MuPDF always starts with a horizontal line, followed by a vertical line, followed by a horizontal line. @@ -125,34 +124,21 @@ jm_checkrect() as '+1' for anti-clockwise, '-1' for clockwise orientation. --------------------------------------------------------------------- */ - if (ll.y != lr.y) { // not horizontal - goto drop_out; - } - if (lr.x != ur.x) { // not vertical - goto drop_out; - } - if (ur.y != ul.y) { // not horizontal - goto drop_out; + if (ll.y != lr.y || + ll.x != ul.x || + ur.y != ul.y || + ur.x != lr.x) { + goto drop_out; // not a rectangle } - // we have a rect, determine orientation - if (ll.x < lr.x) { // move left to right - if (lr.y > ur.y) { // move upwards - orientation = 1; - } else { - orientation = -1; - } - } else { // move right to left - if (lr.y < ur.y) { // move downwards - orientation = 1; - } else { - orientation = -1; - } + + // we have a rect, replace last 3 "l" items by one "re" item. + if (ul.y < lr.y) { + r = fz_make_rect(ul.x, ul.y, lr.x, lr.y); + orientation = 1; + } else { + r = fz_make_rect(ll.x, ll.y, ur.x, ur.y); + orientation = -1; } - // Replace last 3 "l" items by one "re" item. - fz_rect r = fz_make_rect(ul.x, ul.y, ul.x, ul.y); - r = fz_include_point_in_rect(r, ur); - r = fz_include_point_in_rect(r, ll); - r = fz_include_point_in_rect(r, lr); rect = PyTuple_New(3); PyTuple_SET_ITEM(rect, 0, PyUnicode_FromString("re")); PyTuple_SET_ITEM(rect, 1, JM_py_from_rect(r)); From 3f46d8f9d8de46f9429cdc28fd1e3ec53f5ebbe9 Mon Sep 17 00:00:00 2001 From: "Jorj X. McKie" Date: Sat, 10 Dec 2022 09:04:46 -0400 Subject: [PATCH 4/6] Add new Page utility method Add `Page.replace_image()`, `Page.delete_image()` to globally replace / delete an image given by its xref. --- docs/page.rst | 41 +++++++++++++++++++++++++++ fitz/__init__.py | 16 +++++++---- fitz/utils.py | 73 ++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 113 insertions(+), 17 deletions(-) diff --git a/docs/page.rst b/docs/page.rst index 54936197c..ce17b59b6 100644 --- a/docs/page.rst +++ b/docs/page.rst @@ -62,6 +62,7 @@ In a nutshell, this is what you can do with PyMuPDF: :meth:`Page.apply_redactions` PDF olny: process the redactions of the page :meth:`Page.bound` rectangle of the page :meth:`Page.delete_annot` PDF only: delete an annotation +:meth:`Page.delete_image` PDF only: delete an image :meth:`Page.delete_link` PDF only: delete a link :meth:`Page.delete_widget` PDF only: delete a widget / field :meth:`Page.draw_bezier` PDF only: draw a cubic Bezier curve @@ -100,6 +101,7 @@ In a nutshell, this is what you can do with PyMuPDF: :meth:`Page.load_widget` PDF only: load a specific field :meth:`Page.load_links` return the first link on a page :meth:`Page.new_shape` PDF only: create a new :ref:`Shape` +:meth:`Page.replace_image` PDF only: replace an image :meth:`Page.search_for` search for a string :meth:`Page.set_artbox` PDF only: modify ``/ArtBox`` :meth:`Page.set_bleedbox` PDF only: modify ``/BleedBox`` @@ -949,6 +951,45 @@ In a nutshell, this is what you can do with PyMuPDF: 6. Another efficient way to display the same image on multiple pages is another method: :meth:`show_pdf_page`. Consult :meth:`Document.convert_to_pdf` for how to obtain intermediary PDFs usable for that method. Demo script `fitz-logo.py `_ implements a fairly complete approach. + + .. index:: + pair: filename; replace_image + pair: pixmap; replace_image + pair: stream; replace_image + pair: xref; replace_image + + .. method:: replace_image(xref, filename=None, pixmap=None, stream=None) + + * New in v1.21.0 + + Replace the image at xref with another one. + + :arg int xref: the :data:`xref` of the image. + :arg filename: the filename of the new image. + :arg pixmap: the :ref:`Pixmap` of the new image. + :arg stream: the memory area containing the new image. + + Arguments ``filename``, ``pixmap``, ``stream`` have the same meaning as in :meth:`Page.insert_image`, especially exactly one of these must be provided. + + This is a **global replacement:** the new image will also be shown wherever the old one has been displayed throughout the file. + + This method mainly exists for technical purposes. Typical uses include replacing large images by smaller versions, like a lower resolution, graylevel instead of colored, etc., or changing transparency. + + + .. index:: + pair: xref; delete_image + + .. method:: delete_image(xref) + + * New in v1.21.0 + + Delete the image at xref. This is slightly misleading: actually the image is being replaced with a small transparent :ref:`Pixmap` using above :meth:`Page.replace_image`. The visible effect however is equivalent. + + :arg int xref: the :data:`xref` of the image. + + This is a **global replacement:** the image will disappear wherever the old one has been displayed throughout the file. + + .. index:: pair: blocks; Page.get_text pair: dict; Page.get_text diff --git a/fitz/__init__.py b/fitz/__init__.py index eca50f8fb..0c6f24b49 100644 --- a/fitz/__init__.py +++ b/fitz/__init__.py @@ -7,6 +7,7 @@ # maintained and developed by Artifex Software, Inc. https://artifex.com. # ------------------------------------------------------------------------ import sys + from fitz.fitz import * # define the supported colorspaces for convenience @@ -31,12 +32,16 @@ # This atexit handler runs, but doesn't cause ~Tools() to be run. # import atexit -def cleanup_tools( TOOLS): - #print(f'cleanup_tools: TOOLS={TOOLS} id(TOOLS)={id(TOOLS)}') - #print(f'TOOLS.thisown={TOOLS.thisown}') + + +def cleanup_tools(TOOLS): + # print(f'cleanup_tools: TOOLS={TOOLS} id(TOOLS)={id(TOOLS)}') + # print(f'TOOLS.thisown={TOOLS.thisown}') del TOOLS del fitz.TOOLS -atexit.register( cleanup_tools, TOOLS) + + +atexit.register(cleanup_tools, TOOLS) if fitz.VersionFitz != fitz.TOOLS.mupdf_version(): v1 = fitz.VersionFitz.split(".") @@ -50,7 +55,6 @@ def cleanup_tools( TOOLS): # copy functions in 'utils' to their respective fitz classes import fitz.utils - # ------------------------------------------------------------------------------ # General # ------------------------------------------------------------------------------ @@ -127,6 +131,8 @@ def cleanup_tools( TOOLS): fitz.Page.get_label = fitz.utils.get_label fitz.Page.get_image_rects = fitz.utils.get_image_rects fitz.Page.get_textpage_ocr = fitz.utils.get_textpage_ocr +fitz.Page.delete_image = fitz.utils.delete_image +fitz.Page.replace_image = fitz.utils.replace_image # ------------------------------------------------------------------------ # Annot diff --git a/fitz/utils.py b/fitz/utils.py index 154ca9e33..4cfc66df0 100644 --- a/fitz/utils.py +++ b/fitz/utils.py @@ -12,13 +12,12 @@ import os import random import string +import tempfile import typing import warnings -import tempfile from fitz import * - TESSDATA_PREFIX = os.environ.get("TESSDATA_PREFIX") point_like = "point_like" rect_like = "rect_like" @@ -236,6 +235,51 @@ def calc_matrix(sr, tr, keep=True, rotate=0): return xref +def replace_image(page: Page, xref: int, *, filename=None, pixmap=None, stream=None): + """Replace the image referred to by xref. + + Replace the image by changing the object definition stored under xref. This + will leave the pages appearance instructions intact, so the new image is + being displayed with the same bbox, rotation etc. + By providing a small fully transparent image, an effect as if the image had + been deleted can be achieved. + A typical use may include replacing large images by a smaller version, + e.g. with a lower resolution or graylevel instead of colored. + + Args: + xref: the xref of the image to replace. + filename, pixmap, stream: exactly one of these must be provided. The + meaning being the same as in Page.insert_image. + """ + doc = page.parent # the owning document + if not doc.is_image(xref): + raise ValueError("xref not an image") # insert new image anywhere in page + if bool(filename) + bool(stream) + bool(pixmap) != 1: + raise ValueError("Exactly one of filename/stream/pixmap must be given") + new_xref = page.insert_image( + page.rect, filename=filename, stream=stream, pixmap=pixmap + ) + doc.xref_copy(new_xref, xref) # copy over new to old + last_contents_xref = page.get_contents()[-1] + # new image insertion has created a new /Contents source, + # which we will set to spaces now + doc.update_stream(last_contents_xref, b" ") + + +def delete_image(page: Page, xref: int): + """Delete the image referred to by xef. + + Actually replaces by a small transparent Pixmap using method Page.replace_image. + + Args: + xref: xref of the image to delete. + """ + # make a small 100% transparent pixmap (of just any dimension) + pix = fitz.Pixmap(fitz.csGRAY, (0, 0, 1, 1), 1) + pix.clear_with() # clear all samples bytes to 0x00 + page.replace_image(xref, pixmap=pix) + + def insert_image(page, rect, **kwargs): """Insert an image for display in a rectangle. @@ -810,15 +854,15 @@ def get_page_text( def get_pixmap( - page: Page, - *, - matrix: matrix_like=Identity, - dpi=None, - colorspace: Colorspace=csRGB, - clip: rect_like=None, - alpha: bool=False, - annots: bool=True, - ) -> Pixmap: + page: Page, + *, + matrix: matrix_like = Identity, + dpi=None, + colorspace: Colorspace = csRGB, + clip: rect_like = None, + alpha: bool = False, + annots: bool = True, +) -> Pixmap: """Create pixmap of page. Keyword args: @@ -876,7 +920,12 @@ def get_page_pixmap( annots: (bool) also render annotations """ return doc[pno].get_pixmap( - matrix=matrix, dpi=dpi, colorspace=colorspace, clip=clip, alpha=alpha, annots=annots + matrix=matrix, + dpi=dpi, + colorspace=colorspace, + clip=clip, + alpha=alpha, + annots=annots, ) From 558a3a203a4f82be9d61f92181d1cc2f327d9055 Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Mon, 12 Dec 2022 13:05:45 +0000 Subject: [PATCH 5/6] fitz/fitz.i: fixed potentially unsafe call of fz_warn(). --- fitz/fitz.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fitz/fitz.i b/fitz/fitz.i index c2a21f2fd..11f3568ea 100644 --- a/fitz/fitz.i +++ b/fitz/fitz.i @@ -2838,7 +2838,7 @@ if len(pyliste) == 0 or min(pyliste) not in range(len(self)) or max(pyliste) not fz_catch(gctx) { Py_CLEAR(rc); - fz_warn(gctx, fz_caught_message(gctx)); + fz_warn(gctx, "%s", fz_caught_message(gctx)); Py_RETURN_FALSE; } if (!rc) From a16f0aacd0340ac5dd9197c88993418ecfaa55b8 Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Mon, 12 Dec 2022 12:53:57 +0000 Subject: [PATCH 6/6] Updated version numbers and dates for 1.21.1rc1 release. --- README.md | 5 +++-- changes.txt | 35 ++++++++++++++++++++++++++++++++++- docs/changes.rst | 35 ++++++++++++++++++++++++++++++++++- docs/conf.py | 2 +- docs/version.rst | 2 +- fitz/version.i | 8 ++++---- setup.py | 4 ++-- 7 files changed, 79 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6ee2befa5..d92e3b1c5 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ -# PyMuPDF 1.21.0 +# PyMuPDF 1.21.1rc1 ![logo](https://artifex.com/images/logos/py-mupdf-github-icon.png) -Release date: November 8, 2022 + +Release date: December 12, 2022 On **[PyPI](https://pypi.org/project/PyMuPDF)** since August 2016: [![Downloads](https://static.pepy.tech/personalized-badge/pymupdf?period=total&units=international_system&left_color=black&right_color=orange&left_text=Downloads)](https://pepy.tech/project/pymupdf) diff --git a/changes.txt b/changes.txt index 6ff1ee32d..2d9a6de45 100644 --- a/changes.txt +++ b/changes.txt @@ -1,8 +1,41 @@ Change Log ========== +**Changes in Version 1.21.1rc1 (2022-12-12)** -**Changes in Version 1.21.0** +* This release uses ``MuPDF-1.21.1``. + +* Bug fixes: + + * **Fixed** `#2110 `_: Fully embedded font is extracted only partially if it occupies more than one object + * **Fixed** `#2094 `_: Rectangle Detection Logic + * **Fixed** `#2088 `_: Destination point not set for named links in toc + * **Fixed** `#2087 `_: Image with Filter "[/FlateDecode/JPXDecode]" not extracted + * **Fixed** `#2086 `_: Document.save() owner_pw & user_pw has buffer overflow bug + * **Fixed** `#2076 `_: Segfault in fitz.py + * **Fixed** `#2051 `_: Missing DPI Parameter + * **Fixed** `#2048 `_: Invalid size of TextPage and bbox with newest version 1.21.0 + * **Fixed** `#2045 `_: SystemError: returned a result with an error set + * **Fixed** `#2039 `_: 1.21.0 fails to build against system libmupdf + * **Fixed** `#2036 `_: Archive::Archive defined twice + +* Other + + * Swallow "&zoom=nan" in link uri strings. + * Add new Page utility methods ``Page.replace_image()`` and ``Page.delete_image()``. + +* Documentation: + + * `#2040 `_: Added note about test failure with non-default build of MuPDF, to ``tests/README.md``. + * `#2037 `_: In ``docs/installation.rst``, mention incompatibility with chocolatey.org on Windows. + * `#2061 `_: Fixed description of ``Annot.file_info``. + * `#2065 `_: Show how to insert internal PDF link. + * Improved description of building from source without an sdist. + * Added information about running tests. + * `#2084 `_: Fixed broken link to PyMuPDF-Utilities. + + +**Changes in Version 1.21.0 (2022-11-8)** * This release uses ``MuPDF-1.21.0``. diff --git a/docs/changes.rst b/docs/changes.rst index c6065d078..55fe3fdc7 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -3,8 +3,41 @@ Change Log ========== +**Changes in Version 1.21.1rc1 (2022-12-12)** -**Changes in Version 1.21.0** +* This release uses ``MuPDF-1.21.1``. + +* Bug fixes: + + * **Fixed** `#2110 `_: Fully embedded font is extracted only partially if it occupies more than one objects + * **Fixed** `#2094 `_: Rectangle Detection Logic + * **Fixed** `#2088 `_: Destination point not set for named links in toc + * **Fixed** `#2087 `_: Image with Filter "[/FlateDecode/JPXDecode]" not extracted + * **Fixed** `#2086 `_: Document.save() owner_pw & user_pw has buffer overflow bug + * **Fixed** `#2076 `_: Segfault in fitz.py + * **Fixed** `#2051 `_: Missing DPI Parameter + * **Fixed** `#2048 `_: Invalid size of TextPage and bbox with newest version 1.21.0 + * **Fixed** `#2045 `_: SystemError: returned a result with an error set + * **Fixed** `#2039 `_: 1.21.0 fails to build against system libmupdf + * **Fixed** `#2036 `_: Archive::Archive defined twice + +* Other + + * Swallow "&zoom=nan" in link uri strings. + * Add new Page utility methods ``Page.replace_image()`` and ``Page.delete_image()``. + +* Documentation: + + * `#2040 `_: Added note about test failure with non-default build of MuPDF, to ``tests/README.md``. + * `#2037 `_: In ``docs/installation.rst``, mention incompatibility with chocolatey.org on Windows. + * `#2061 `_: Fixed description of ``Annot.file_info``. + * `#2065 `_: Show how to insert internal PDF link. + * Improved description of building from source without an sdist. + * Added information about running tests. + * `#2084 `_: Fixed broken link to PyMuPDF-Utilities. + + +**Changes in Version 1.21.0 (2022-11-8)** * This release uses ``MuPDF-1.21.0``. diff --git a/docs/conf.py b/docs/conf.py index 7a003e888..001c011c3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -43,7 +43,7 @@ # built documents. # # The full version, including alpha/beta/rc tags. -release = "1.21.0" +release = "1.21.1rc1" # The short X.Y version version = release diff --git a/docs/version.rst b/docs/version.rst index 4ef73312b..c1c0c5d2f 100644 --- a/docs/version.rst +++ b/docs/version.rst @@ -1,6 +1,6 @@ Covered Version -------------------- -This documentation covers PyMuPDF v1.21.0 features as of **2022-11-08 00:00:01**. +This documentation covers PyMuPDF v1.21.1rc1 features as of **2022-12-12 00:00:01**. .. note:: The major and minor versions of **PyMuPDF** and **MuPDF** will always be the same. Only the third qualifier (patch level) may deviate from that of MuPDF. diff --git a/fitz/version.i b/fitz/version.i index 59a160347..7bbbd4312 100644 --- a/fitz/version.i +++ b/fitz/version.i @@ -1,6 +1,6 @@ %pythoncode %{ -VersionFitz = "1.21.0" # MuPDF version. -VersionBind = "1.21.0" # PyMuPDF version. -VersionDate = "2022-11-08 00:00:01" -version = (VersionBind, VersionFitz, "20221108000001") +VersionFitz = "1.21.1" # MuPDF version. +VersionBind = "1.21.1rc1" # PyMuPDF version. +VersionDate = "2022-12-12 00:00:01" +version = (VersionBind, VersionFitz, "20221212000001") %} diff --git a/setup.py b/setup.py index 3a0d4135f..82ce07855 100644 --- a/setup.py +++ b/setup.py @@ -402,7 +402,7 @@ def get_mupdf_tgz(): ''' mupdf_url_or_local = os.environ.get( 'PYMUPDF_SETUP_MUPDF_TGZ', - 'https://mupdf.com/downloads/archive/mupdf-1.21.0-source.tar.gz', + 'https://mupdf.com/downloads/archive/mupdf-1.21.1-source.tar.gz', ) log( f'mupdf_url_or_local={mupdf_url_or_local!r}') if mupdf_url_or_local == '': @@ -788,7 +788,7 @@ def get_mupdf(): setup( name="PyMuPDF", - version="1.21.0", + version="1.21.1rc1", description="Python bindings for the PDF toolkit and renderer MuPDF", long_description=readme, long_description_content_type="text/markdown",