diff --git a/PKG-INFO b/PKG-INFO index 0ded8473d..9facfcbd1 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -9,7 +9,7 @@ Home-page: https://github.com/pymupdf/PyMuPDF Download-url: https://github.com/pymupdf/PyMuPDF Summary: PyMuPDF is a Python binding for the PDF rendering library MuPDF Description: - Release date: March 05, 2020 + Release date: March 10, 2020 Authors ======= diff --git a/docs/changes.rst b/docs/changes.rst index c24455357..6e055a620 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -6,10 +6,11 @@ Changes in Version 1.16.12 * **Fixed** issue `#447 `_ * **Fixed** issue `#461 `_. * **Fixed** issue `#397 `_. -* **Added** JavaScript support to PDF form fields, thereby addressing `#454 `_. -* **Added** a new annotation method :meth:`Annot.delete_responses`, which removes 'Popup' and response annotations referring to the current one. +* **Fixed** issue `#463 `_. +* **Added** JavaScript support to PDF form fields, thereby fixing `#454 `_. +* **Added** a new annotation method :meth:`Annot.delete_responses`, which removes 'Popup' and response annotations referring to the current one. Mainly serves data protection purposes. * **Added** a new form field method :meth:`Widget.reset`, which resets the field value to its default. -* **Changed** and extended handling of redactions: images and XObjects are removed if *contained* in a redaction rectangle. Any partial overlaps will just be covered by the redaction background color. Now a text can be specified to be inserted in the rectangle area to **replace the deleted original** text. This resolves `#434 `_. +* **Changed** and extended handling of redactions: images and XObjects are removed if *contained* in a redaction rectangle. Any partial only overlaps will just be covered by the redaction background color. Now an *overlay* text can be specified to be inserted in the rectangle area to **take the place the deleted original** text. This resolves `#434 `_. Changes in Version 1.16.11 --------------------------- diff --git a/docs/installation.rst b/docs/installation.rst index cd5f716fa..8b0668ad7 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -55,27 +55,7 @@ Windows binaries are provided for Python **32-bit and 64-bit** versions. **Overview of wheel names (PyMuPDF version is x.xx.xx):** -* ``PyMuPDF-x.xx.xx-cp27-cp27m-macosx_10_6_intel.whl`` -* ``PyMuPDF-x.xx.xx-cp27-cp27m-manylinux2010_x86_64.whl`` -* ``PyMuPDF-x.xx.xx-cp27-cp27m-win32.whl`` -* ``PyMuPDF-x.xx.xx-cp27-cp27m-win_amd64.whl`` -* ``PyMuPDF-x.xx.xx-cp27-cp27mu-manylinux2010_x86_64.whl`` -* ``PyMuPDF-x.xx.xx-cp35-cp35m-macosx_10_6_intel.whl`` -* ``PyMuPDF-x.xx.xx-cp35-cp35m-manylinux2010_x86_64.whl`` -* ``PyMuPDF-x.xx.xx-cp35-cp35m-win32.whl`` -* ``PyMuPDF-x.xx.xx-cp35-cp35m-win_amd64.whl`` -* ``PyMuPDF-x.xx.xx-cp36-cp36m-macosx_10_6_intel.whl`` -* ``PyMuPDF-x.xx.xx-cp36-cp36m-manylinux2010_x86_64.whl`` -* ``PyMuPDF-x.xx.xx-cp36-cp36m-win32.whl`` -* ``PyMuPDF-x.xx.xx-cp36-cp36m-win_amd64.whl`` -* ``PyMuPDF-x.xx.xx-cp37-cp37m-macosx_10_6_intel.whl`` -* ``PyMuPDF-x.xx.xx-cp37-cp37m-manylinux2010_x86_64.whl`` -* ``PyMuPDF-x.xx.xx-cp37-cp37m-win32.whl`` -* ``PyMuPDF-x.xx.xx-cp37-cp37m-win_amd64.whl`` -* ``PyMuPDF-x.xx.xx-cp38-cp38-macosx_10_9_x86_64.whl`` -* ``PyMuPDF-x.xx.xx-cp38-cp38-manylinux2010_x86_64.whl`` -* ``PyMuPDF-x.xx.xx-cp38-cp38-win32.whl`` -* ``PyMuPDF-x.xx.xx-cp38-cp38-win_amd64.whl`` +.. literalinclude:: wheelnames.txt Older versions can be found in the releases directory of our home page https://github.com/pymupdf/PyMuPDF/releases. diff --git a/docs/page.rst b/docs/page.rst index 8663843a6..cfacd7865 100644 --- a/docs/page.rst +++ b/docs/page.rst @@ -984,13 +984,13 @@ This is available for PDF documents only. There are basically two groups of meth .. attribute:: CropBoxPosition - Contains the displacement of the page's */CropBox* for a PDF, otherwise the top-left coordinates of :attr:`Page.rect`. + Contains the top-left point of the page's */CropBox* for a PDF, otherwise *Point(0, 0)*. :type: :ref:`Point` .. attribute:: CropBox - The page's */CropBox* for a PDF, else :attr:`Page.rect`. + The page's */CropBox* for a PDF. Always the **unrotated** page rectangle is returned. For a non-PDF this will always equal the page rectangle. :type: :ref:`Rect` @@ -1006,7 +1006,7 @@ This is available for PDF documents only. There are basically two groups of meth :type: :ref:`Rect` - .. note:: For most PDF documents and for all other types, *page.rect == page.CropBox == page.MediaBox* is true. However, for some PDFs the visible page is a true subset of */MediaBox*. In this case the above attributes help to correctly locate page elements. + .. note:: For most PDF documents and for all other types, *page.rect == page.CropBox == page.MediaBox* is true. However, for some PDFs the visible page is a true subset of */MediaBox*. Also, if the page is rotated, its ``Page.rect`` may not equal ``Page.CropBox``. In these cases the above attributes help to correctly locate page elements. .. attribute:: firstLink diff --git a/docs/wheelnames.txt b/docs/wheelnames.txt new file mode 100644 index 000000000..a3744da3a --- /dev/null +++ b/docs/wheelnames.txt @@ -0,0 +1,21 @@ +PyMuPDF-x.xx.xx-cp27-cp27m-macosx_10_9_x86_64.whl +PyMuPDF-x.xx.xx-cp27-cp27m-manylinux2010_x86_64.whl +PyMuPDF-x.xx.xx-cp27-cp27m-win32.whl +PyMuPDF-x.xx.xx-cp27-cp27m-win_amd64.whl +PyMuPDF-x.xx.xx-cp27-cp27mu-manylinux2010_x86_64.whl +PyMuPDF-x.xx.xx-cp35-cp35m-macosx_10_9_x86_64.whl +PyMuPDF-x.xx.xx-cp35-cp35m-manylinux2010_x86_64.whl +PyMuPDF-x.xx.xx-cp35-cp35m-win32.whl +PyMuPDF-x.xx.xx-cp35-cp35m-win_amd64.whl +PyMuPDF-x.xx.xx-cp36-cp36m-macosx_10_9_x86_64.whl +PyMuPDF-x.xx.xx-cp36-cp36m-manylinux2010_x86_64.whl +PyMuPDF-x.xx.xx-cp36-cp36m-win32.whl +PyMuPDF-x.xx.xx-cp36-cp36m-win_amd64.whl +PyMuPDF-x.xx.xx-cp37-cp37m-macosx_10_9_x86_64.whl +PyMuPDF-x.xx.xx-cp37-cp37m-manylinux2010_x86_64.whl +PyMuPDF-x.xx.xx-cp37-cp37m-win32.whl +PyMuPDF-x.xx.xx-cp37-cp37m-win_amd64.whl +PyMuPDF-x.xx.xx-cp38-cp38-macosx_10_9_x86_64.whl +PyMuPDF-x.xx.xx-cp38-cp38-manylinux2010_x86_64.whl +PyMuPDF-x.xx.xx-cp38-cp38-win32.whl +PyMuPDF-x.xx.xx-cp38-cp38-win_amd64.whl diff --git a/fitz/fitz.i b/fitz/fitz.i index 91adc5276..2c023e283 100644 --- a/fitz/fitz.i +++ b/fitz/fitz.i @@ -2592,8 +2592,6 @@ if len(pyliste) == 0 or min(pyliste) not in range(len(self)) or max(pyliste) not xrefObject = get_pdf_object - xref_object = get_pdf_object - xref_stream = xrefStream def __repr__(self): @@ -3673,28 +3671,56 @@ annot._erase() } //--------------------------------------------------------------------- - // MediaBox size: width, height of /MediaBox (PDF only) + // MediaBox: get the /MediaBox (PDF only) //--------------------------------------------------------------------- - PARENTCHECK(MediaBoxSize) + PARENTCHECK(MediaBox) %pythoncode %{@property%} - %feature("autodoc","Retrieve width, height of /MediaBox.") MediaBoxSize; - %pythonappend MediaBoxSize %{ - val = Point(val) - if not bool(val): - r = self.rect - val = Point(r.width, r.height) + %feature("autodoc","Retrieve the /MediaBox.") MediaBox; + %pythonappend MediaBox %{ + val = Rect(val) %} - PyObject *MediaBoxSize() + PyObject *MediaBox() { - PyObject *p = JM_py_from_point(fz_make_point(0, 0)); pdf_page *page = pdf_page_from_fz_page(gctx, $self); - if (!page) return p; - fz_rect r = fz_empty_rect; - pdf_obj *o = pdf_dict_get_inheritable(gctx, page->obj, PDF_NAME(MediaBox)); - if (!o) return p; + if (!page) return JM_py_from_rect(fz_bound_page(gctx, $self)); + + fz_rect mediabox, cropbox, page_mediabox; + PyObject *rect = NULL; + pdf_obj *obj; + float userunit = 1; + + obj = pdf_dict_get(gctx, page->obj, PDF_NAME(UserUnit)); + if (pdf_is_real(gctx, obj)) + { + userunit = pdf_to_real(gctx, obj); + } + + mediabox = pdf_to_rect(gctx, pdf_dict_get_inheritable(gctx, page->obj, PDF_NAME(MediaBox))); + if (fz_is_empty_rect(mediabox)) + { + mediabox.x0 = 0; + mediabox.y0 = 0; + mediabox.x1 = 612; + mediabox.y1 = 792; + } + + cropbox = pdf_to_rect(gctx, + pdf_dict_get_inheritable(gctx, page->obj, PDF_NAME(CropBox))); + if (!fz_is_empty_rect(cropbox)) + { + mediabox = fz_intersect_rect(mediabox, cropbox); + } + page_mediabox.x0 = fz_min(mediabox.x0, mediabox.x1); + page_mediabox.y0 = fz_min(mediabox.y0, mediabox.y1); + page_mediabox.x1 = fz_max(mediabox.x0, mediabox.x1); + page_mediabox.y1 = fz_max(mediabox.y0, mediabox.y1); + + if (page_mediabox.x1 - page_mediabox.x0 < 1 || + page_mediabox.y1 - page_mediabox.y0 < 1) + page_mediabox = fz_unit_rect; + + return JM_py_from_rect(page_mediabox); - r = pdf_to_rect(gctx, o); - return JM_py_from_point(fz_make_point(r.x1 - r.x0, r.y1 - r.y0)); } //--------------------------------------------------------------------- @@ -3712,6 +3738,7 @@ annot._erase() pdf_obj *o = pdf_dict_get_inheritable(gctx, page->obj, PDF_NAME(CropBox)); if (!o) return p; // no CropBox specified fz_rect cbox = pdf_to_rect(gctx, o); + Py_DECREF(p); return JM_py_from_point(fz_make_point(cbox.x0, cbox.y0));; } @@ -4253,7 +4280,12 @@ def insertFont(self, fontname="helv", fontfile=None, fontbuffer=None, //--------------------------------------------------------------------- PARENTCHECK(_getTransformation) %feature("autodoc","Return page transformation matrix.") _getTransformation; - %pythonappend _getTransformation %{val = Matrix(val)%} + %pythonappend _getTransformation %{ + if self.rotation % 360 == 0: + val = Matrix(val) + else: + val = Matrix(1, 0, 0, -1, 0, self.CropBox.height) + %} PyObject *_getTransformation() { fz_matrix ctm = fz_identity; @@ -4454,18 +4486,25 @@ def insertFont(self, fontname="helv", fontfile=None, fontbuffer=None, @property def CropBox(self): + """Rectangle /CropBox IGNORING any page rotation.""" + rotation = self.rotation # page rotation + width = self.rect.width # page width + height = self.rect.height # page height + if rotation % 180 != 0: # rotation by odd number of 90 + width, height = height, width # so revert width and height x0 = self.CropBoxPosition.x - y0 = self.MediaBoxSize.y - self.CropBoxPosition.y - self.rect.height - x1 = x0 + self.rect.width - y1 = y0 + self.rect.height + y0 = self.MediaBox.height - self.CropBoxPosition.y - height + x1 = x0 + width + y1 = y0 + height return Rect(x0, y0, x1, y1) @property - def MediaBox(self): - return Rect(0, 0, self.MediaBoxSize) - - clean_contents = _cleanContents - get_contents = _getContents + def MediaBoxSize(self): + return Point(self.MediaBox.width, self.MediaBox.height) + + cleanContents = _cleanContents + getContents = _getContents + getTransformation = _getTransformation %} } diff --git a/fitz/utils.py b/fitz/utils.py index f8ffe1bc2..dd83ef733 100644 --- a/fitz/utils.py +++ b/fitz/utils.py @@ -2419,8 +2419,10 @@ def __init__(self, page): self.width = page.MediaBoxSize.x self.x = page.CropBoxPosition.x self.y = page.CropBoxPosition.y + self.pctm = page._getTransformation() # page transf. matrix self.ipctm = ~self.pctm # inverted transf. matrix + self.draw_cont = "" self.text_cont = "" self.totalcont = ""