From 12084f73479cac40120abf2152369d67829eeac7 Mon Sep 17 00:00:00 2001 From: "Jorj X. McKie" Date: Wed, 6 Mar 2019 20:05:47 -0400 Subject: [PATCH 1/3] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 456b660a7..c0adf7e83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ matrix: prefix=/usr/local install && cd .." - export CIBW_ENVIRONMENT='CFLAGS=-fPIC' install: -- "$PIP install cibuildwheel==0.10.1" +- "$PIP install --user cibuildwheel" - mkdir mupdf && wget -q $MUPDF -O - | tar zx -C mupdf --strip-components=1 - cp fitz/_mupdf_config.h mupdf/include/mupdf/fitz/config.h - cp fitz/_pdf-device.c mupdf/source/pdf/pdf-device.c From ba5d4a017381a35cb62895ba35e21cc4f42272e9 Mon Sep 17 00:00:00 2001 From: "Jorj X. McKie" Date: Thu, 7 Mar 2019 04:17:23 -0400 Subject: [PATCH 2/3] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c0adf7e83..2501407fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ matrix: prefix=/usr/local install && cd .." - export CIBW_ENVIRONMENT='CFLAGS=-fPIC' install: -- "$PIP install --user cibuildwheel" +- "$PIP install cibuildwheel" - mkdir mupdf && wget -q $MUPDF -O - | tar zx -C mupdf --strip-components=1 - cp fitz/_mupdf_config.h mupdf/include/mupdf/fitz/config.h - cp fitz/_pdf-device.c mupdf/source/pdf/pdf-device.c From 4c4eb76a93cda2e286295af46a930fc4915a547d Mon Sep 17 00:00:00 2001 From: "Jorj X. McKie" Date: Sun, 10 Mar 2019 12:56:56 -0400 Subject: [PATCH 3/3] Upload v1.14.10 --- PKG-INFO | 6 +- README.md | 4 +- fitz/fitz.i | 64 +++++------------- fitz/fitz.py | 37 ++++++----- fitz/fitz_wrap.c | 150 ++++++++++++++++++------------------------ fitz/helper-geo-py.i | 14 ++-- fitz/helper-python.i | 11 ++-- fitz/helper-xobject.i | 21 +++--- fitz/utils.py | 122 ++++++++++++++++++++++++++++++---- fitz/version.i | 6 +- nano_setup.py | 2 +- setup.py | 2 +- 12 files changed, 247 insertions(+), 192 deletions(-) diff --git a/PKG-INFO b/PKG-INFO index e8ea28fc1..ba108da0c 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: PyMuPDF -Version: 1.14.9 +Version: 1.14.10 Author: Ruikai Liu Author-email: lrk700@gmail.com Maintainer: Jorj X. McKie @@ -10,7 +10,7 @@ Download-url: https://github.com/pymupdf/PyMuPDF Summary: PyMuPDF is a Python binding for the PDF rendering library MuPDF Description: - Release date: March 6, 2019 + Release date: March 10, 2019 Authors ======= @@ -21,7 +21,7 @@ Description: Introduction ============ - This is **version 1.14.9 of PyMuPDF**, a Python binding for `MuPDF `_ - "a lightweight PDF and XPS viewer". + This is **version 1.14.10 of PyMuPDF**, a Python binding for `MuPDF `_ - "a lightweight PDF and XPS viewer". MuPDF can access files in PDF, XPS, OpenXPS, epub, comic and fiction book formats, and it is known for both, its top performance and high rendering quality. diff --git a/README.md b/README.md index a7cc8bede..db842ec4d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# PyMuPDF 1.14.9 +# PyMuPDF 1.14.10 ![logo](https://github.com/rk700/PyMuPDF/blob/master/demo/pymupdf.jpg) @@ -14,7 +14,7 @@ On **[PyPI](https://pypi.org/project/PyMuPDF)** since August 2016: [![](https:// # Introduction -This is **version 1.14.9 of PyMuPDF (formerly python-fitz)**, a Python binding with support for [MuPDF 1.14.x](http://mupdf.com/) - "a lightweight PDF, XPS, and E-book viewer". +This is **version 1.14.10 of PyMuPDF (formerly python-fitz)**, a Python binding with support for [MuPDF 1.14.x](http://mupdf.com/) - "a lightweight PDF, XPS, and E-book viewer". MuPDF can access files in PDF, XPS, OpenXPS, CBZ, EPUB and FB2 (e-books) formats, and it is known for its top performance and high rendering quality. diff --git a/fitz/fitz.i b/fitz/fitz.i index 42658dfec..7c1ade7f3 100644 --- a/fitz/fitz.i +++ b/fitz/fitz.i @@ -1418,7 +1418,7 @@ if links: else { // handling JPX - buffer = pdf_load_stream(gctx, obj); + buffer = pdf_load_stream_number(gctx, pdf, xref); freebuf = buffer; // so it will be dropped! type = FZ_IMAGE_JPX; o = pdf_dict_get(gctx, obj, PDF_NAME(ColorSpace)); @@ -1837,7 +1837,8 @@ if links: new_obj = JM_pdf_obj_from_str(gctx, pdf, text); pdf_update_object(gctx, pdf, xref, new_obj); pdf_drop_obj(gctx, new_obj); - if (page) refresh_link_table(gctx, pdf_page_from_fz_page(gctx, page)); + if (page) + refresh_link_table(gctx, pdf_page_from_fz_page(gctx, page)); } fz_catch(gctx) return NULL; pdf->dirty = 1; @@ -2965,75 +2966,41 @@ fannot._erase() // Show a PDF page //--------------------------------------------------------------------- FITZEXCEPTION(_showPDFpage, !result) - PyObject *_showPDFpage(PyObject *rect, struct fz_document_s *docsrc, int pno=0, int overlay=1, int keep_proportion=1, int reuse_xref=0, PyObject *clip = NULL, struct pdf_graft_map_s *graftmap = NULL, char *_imgname = NULL) + PyObject *_showPDFpage(PyObject *rect, struct fz_document_s *docsrc, int pno=0, int overlay=1, int keep_proportion=1, PyObject *matrix=NULL, int reuse_xref=0, PyObject *clip = NULL, struct pdf_graft_map_s *graftmap = NULL, char *_imgname = NULL) { int xref = reuse_xref; pdf_obj *xobj1, *xobj2, *resources, *o; fz_buffer *res, *nres; - fz_rect mediabox; - fz_rect cropbox; + fz_matrix inv_ctm = fz_identity; + fz_rect cropbox = fz_empty_rect; fz_rect rrect = JM_rect_from_py(rect); + fz_matrix mat = JM_matrix_from_py(matrix); fz_try(gctx) { - pdf_page *tpage = pdf_page_from_fz_page(gctx, $self); - assert_PDF(tpage); if (fz_is_infinite_rect(rrect) || fz_is_empty_rect(rrect)) THROWMSG("rect must be finite and not empty"); + + pdf_page *tpage = pdf_page_from_fz_page(gctx, $self); pdf_obj *tpageref = tpage->obj; pdf_document *pdfout = tpage->doc; // target PDF pdf_document *pdfsrc = pdf_specifics(gctx, docsrc); - assert_PDF(pdfsrc); //------------------------------------------------------------- - // make XObject of source page and get its xref + // make XObject out of the source page pno, get its xref, + // mediabox and cropbox. //------------------------------------------------------------- xobj1 = JM_xobject_from_page(gctx, pdfout, pdfsrc, pno, - &mediabox, &cropbox, xref, graftmap); + &inv_ctm, &cropbox, xref, graftmap); xref = pdf_to_num(gctx, xobj1); //------------------------------------------------------------- // Calculate /Matrix and /BBox of the referencing XObject //------------------------------------------------------------- fz_rect rclip = JM_rect_from_py(clip); - if (!fz_is_infinite_rect(rclip)) // set cropbox if clip given - { - cropbox.x0 = rclip.x0; - cropbox.y0 = mediabox.y1 - rclip.y1; - cropbox.x1 = rclip.x1; - cropbox.y1 = mediabox.y1 - rclip.y0; - } - fz_matrix mat = fz_identity; - fz_rect prect = fz_bound_page(gctx, $self); - fz_rect r = fz_empty_rect; - o = pdf_dict_get_inheritable(gctx, tpageref, PDF_NAME(CropBox)); - - if (o) - { - r = pdf_to_rect(gctx, o); - prect.x0 = r.x0; - prect.y0 = r.y0; - } - o = pdf_dict_get_inheritable(gctx, tpageref, PDF_NAME(MediaBox)); - - if (o) + if (!fz_is_infinite_rect(rclip)) // set cropbox = clip { - r = pdf_to_rect(gctx, o); - prect.x1 = r.x1; - prect.y1 = r.y1; + cropbox = fz_transform_rect(rclip, inv_ctm); } - - float W = rrect.x1 - rrect.x0; - float H = rrect.y1 - rrect.y0; - float fw = W / (cropbox.x1 - cropbox.x0); - float fh = H / (cropbox.y1 - cropbox.y0); - if ((fw < fh) && keep_proportion) // zoom factors in matrix - fh = fw; - float X = rrect.x0 + prect.x0 - fw*cropbox.x0; - float Y = prect.y1 - (rrect.y1 + prect.y0 + fh*cropbox.y0); - mat.a = fw; - mat.d = fh; - mat.e = X; - mat.f = Y; //------------------------------------------------------------- // create referencing XObject (controls actual display) @@ -3173,7 +3140,7 @@ fannot._erase() image = fz_new_image_from_file(gctx, filename); else { - imgbuf = fz_new_buffer_from_shared_data(gctx, + imgbuf = fz_new_buffer_from_copied_data(gctx, streamdata, streamlen); image = fz_new_image_from_buffer(gctx, imgbuf); } @@ -3219,6 +3186,7 @@ fannot._erase() fz_drop_image(gctx, mask); fz_drop_pixmap(gctx, pix); fz_drop_pixmap(gctx, pm); + fz_drop_buffer(gctx, imgbuf); } fz_catch(gctx) return NULL; pdf->dirty = 1; diff --git a/fitz/fitz.py b/fitz/fitz.py index 4fc4c62c4..a1107ed4e 100644 --- a/fitz/fitz.py +++ b/fitz/fitz.py @@ -105,9 +105,9 @@ class _object: VersionFitz = "1.14.0" -VersionBind = "1.14.9" -VersionDate = "2019-03-06 14:13:45" -version = (VersionBind, VersionFitz, "20190306141345") +VersionBind = "1.14.10" +VersionDate = "2019-03-10 11:59:51" +version = (VersionBind, VersionFitz, "20190310115951") class Matrix(): @@ -128,9 +128,9 @@ def __init__(self, *args): return None if len(args) == 1: # either an angle or a sequ if hasattr(args[0], "__float__"): - theta = args[0] * math.pi / 180.0 - c = math.cos(theta) - s = math.sin(theta) + theta = math.radians(args[0]) + c = round(math.cos(theta), 8) + s = round(math.sin(theta), 8) self.a = self.d = c self.b = s self.c = -s @@ -221,8 +221,9 @@ def preRotate(self, theta): self.d = b else: - s = math.sin(theta * math.pi / 180.0) - c = math.cos(theta * math.pi / 180.0) + rad = math.radians(theta) + s = round(math.sin(rad), 8) + c = round(math.cos(rad), 8) a = self.a b = self.b self.a = c * a + s * self.c @@ -269,7 +270,8 @@ def __mul__(self, m): if hasattr(m, "__float__"): return Matrix(self.a * m, self.b * m, self.c * m, self.d * m, self.e * m, self.f * m) - return self.concat(self, m) + m1 = Matrix(1,1) + return m1.concat(self, m) def __truediv__(self, m): if hasattr(m, "__float__"): @@ -1238,10 +1240,13 @@ def _check5(self): def getTextlength(text, fontname="helv", fontsize=11, encoding=0): """Calculate length of a string for a given built-in font. - :arg str fontname: name of the font. - :arg float fontsize: size of font in points. - :arg int encoding: encoding to use (0=Latin, 1=Greek, 2=Cyrillic). - :returns: (float) length of text. + + Args: + fontname: name of the font. + fontsize: size of font in points. + encoding: encoding to use (0=Latin, 1=Greek, 2=Cyrillic). + Returns: + (float) length of text. """ fontname = fontname.lower() basename = Base14_fontdict.get(fontname, None) @@ -2922,9 +2927,9 @@ def _cleanContents(self): return _fitz.Page__cleanContents(self) - def _showPDFpage(self, rect, docsrc, pno=0, overlay=1, keep_proportion=1, reuse_xref=0, clip=None, graftmap=None, _imgname=None): - """_showPDFpage(self, rect, docsrc, pno=0, overlay=1, keep_proportion=1, reuse_xref=0, clip=None, graftmap=None, _imgname=None) -> PyObject *""" - return _fitz.Page__showPDFpage(self, rect, docsrc, pno, overlay, keep_proportion, reuse_xref, clip, graftmap, _imgname) + def _showPDFpage(self, rect, docsrc, pno=0, overlay=1, keep_proportion=1, matrix=None, reuse_xref=0, clip=None, graftmap=None, _imgname=None): + """_showPDFpage(self, rect, docsrc, pno=0, overlay=1, keep_proportion=1, matrix=None, reuse_xref=0, clip=None, graftmap=None, _imgname=None) -> PyObject *""" + return _fitz.Page__showPDFpage(self, rect, docsrc, pno, overlay, keep_proportion, matrix, reuse_xref, clip, graftmap, _imgname) def insertImage(self, rect, filename=None, pixmap=None, stream=None, overlay=1, _imgname=None): diff --git a/fitz/fitz_wrap.c b/fitz/fitz_wrap.c index cc367a883..62db260d5 100644 --- a/fitz/fitz_wrap.c +++ b/fitz/fitz_wrap.c @@ -8849,28 +8849,33 @@ void retainpages(fz_context *ctx, globals *glo, PyObject *liste) // Make an XObject from a PDF page // For a positive xref assume that that object can be used instead //----------------------------------------------------------------------------- -pdf_obj *JM_xobject_from_page(fz_context *ctx, pdf_document *pdfout, pdf_document *pdfsrc, int pno, fz_rect *mediabox, fz_rect *cropbox, int xref, pdf_graft_map *gmap) +pdf_obj *JM_xobject_from_page(fz_context *ctx, pdf_document *pdfout, pdf_document *pdfsrc, int pno, fz_matrix *inv_ctm, fz_rect *cropbox, int xref, pdf_graft_map *gmap) { fz_buffer *nres = NULL, *res = NULL; pdf_obj *xobj1, *contents = NULL, *resources = NULL, *o, *spageref; + fz_rect mediabox; + fz_matrix ctm = fz_identity; int i; fz_try(ctx) { if (pno < 0 || pno >= pdf_count_pages(ctx, pdfsrc)) THROWMSG("invalid page number(s)"); spageref = pdf_lookup_page_obj(ctx, pdfsrc, pno); + pdf_page_transform(ctx, pdf_load_page(ctx, pdfsrc, pno), NULL, &ctm); + *inv_ctm = fz_invert_matrix(ctm); pdf_obj *mb = pdf_dict_get_inheritable(ctx, spageref, PDF_NAME(MediaBox)); if (mb) - *mediabox = pdf_to_rect(ctx, mb); + mediabox = pdf_to_rect(ctx, mb); else - *mediabox = pdf_bound_page(ctx, pdf_load_page(ctx, pdfsrc, pno)); + mediabox = pdf_bound_page(ctx, pdf_load_page(ctx, pdfsrc, pno)); + o = pdf_dict_get_inheritable(ctx, spageref, PDF_NAME(CropBox)); if (!o) { - cropbox->x0 = mediabox->x0; - cropbox->y0 = mediabox->y0; - cropbox->x1 = mediabox->x1; - cropbox->y1 = mediabox->y1; + cropbox->x0 = mediabox.x0; + cropbox->y0 = mediabox.y0; + cropbox->x1 = mediabox.x1; + cropbox->y1 = mediabox.y1; } else *cropbox = pdf_to_rect(ctx, o); @@ -8910,7 +8915,7 @@ pdf_obj *JM_xobject_from_page(fz_context *ctx, pdf_document *pdfout, pdf_documen //------------------------------------------------------------- // create XObject representing the source page //------------------------------------------------------------- - xobj1 = pdf_new_xobject(ctx, pdfout, *mediabox, fz_identity, NULL, res); + xobj1 = pdf_new_xobject(ctx, pdfout, mediabox, fz_identity, NULL, res); // store spage contents JM_update_stream(ctx, pdfout, xobj1, res); fz_drop_buffer(ctx, res); @@ -10636,7 +10641,7 @@ SWIGINTERN PyObject *fz_document_s_extractImage(struct fz_document_s *self,int x else { // handling JPX - buffer = pdf_load_stream(gctx, obj); + buffer = pdf_load_stream_number(gctx, pdf, xref); freebuf = buffer; // so it will be dropped! type = FZ_IMAGE_JPX; o = pdf_dict_get(gctx, obj, PDF_NAME(ColorSpace)); @@ -10964,7 +10969,8 @@ SWIGINTERN PyObject *fz_document_s__updateObject(struct fz_document_s *self,int new_obj = JM_pdf_obj_from_str(gctx, pdf, text); pdf_update_object(gctx, pdf, xref, new_obj); pdf_drop_obj(gctx, new_obj); - if (page) refresh_link_table(gctx, pdf_page_from_fz_page(gctx, page)); + if (page) + refresh_link_table(gctx, pdf_page_from_fz_page(gctx, page)); } fz_catch(gctx) return NULL; pdf->dirty = 1; @@ -11624,74 +11630,40 @@ SWIGINTERN PyObject *fz_page_s__cleanContents(struct fz_page_s *self){ page->doc->dirty = 1; return NONE; } -SWIGINTERN PyObject *fz_page_s__showPDFpage(struct fz_page_s *self,PyObject *rect,struct fz_document_s *docsrc,int pno,int overlay,int keep_proportion,int reuse_xref,PyObject *clip,struct pdf_graft_map_s *graftmap,char *_imgname){ +SWIGINTERN PyObject *fz_page_s__showPDFpage(struct fz_page_s *self,PyObject *rect,struct fz_document_s *docsrc,int pno,int overlay,int keep_proportion,PyObject *matrix,int reuse_xref,PyObject *clip,struct pdf_graft_map_s *graftmap,char *_imgname){ int xref = reuse_xref; pdf_obj *xobj1, *xobj2, *resources, *o; fz_buffer *res, *nres; - fz_rect mediabox; - fz_rect cropbox; + fz_matrix inv_ctm = fz_identity; + fz_rect cropbox = fz_empty_rect; fz_rect rrect = JM_rect_from_py(rect); + fz_matrix mat = JM_matrix_from_py(matrix); fz_try(gctx) { - pdf_page *tpage = pdf_page_from_fz_page(gctx, self); - assert_PDF(tpage); if (fz_is_infinite_rect(rrect) || fz_is_empty_rect(rrect)) THROWMSG("rect must be finite and not empty"); + + pdf_page *tpage = pdf_page_from_fz_page(gctx, self); pdf_obj *tpageref = tpage->obj; pdf_document *pdfout = tpage->doc; // target PDF pdf_document *pdfsrc = pdf_specifics(gctx, docsrc); - assert_PDF(pdfsrc); //------------------------------------------------------------- - // make XObject of source page and get its xref + // make XObject out of the source page pno, get its xref, + // mediabox and cropbox. //------------------------------------------------------------- xobj1 = JM_xobject_from_page(gctx, pdfout, pdfsrc, pno, - &mediabox, &cropbox, xref, graftmap); + &inv_ctm, &cropbox, xref, graftmap); xref = pdf_to_num(gctx, xobj1); //------------------------------------------------------------- // Calculate /Matrix and /BBox of the referencing XObject //------------------------------------------------------------- fz_rect rclip = JM_rect_from_py(clip); - if (!fz_is_infinite_rect(rclip)) // set cropbox if clip given - { - cropbox.x0 = rclip.x0; - cropbox.y0 = mediabox.y1 - rclip.y1; - cropbox.x1 = rclip.x1; - cropbox.y1 = mediabox.y1 - rclip.y0; - } - fz_matrix mat = fz_identity; - fz_rect prect = fz_bound_page(gctx, self); - fz_rect r = fz_empty_rect; - o = pdf_dict_get_inheritable(gctx, tpageref, PDF_NAME(CropBox)); - - if (o) - { - r = pdf_to_rect(gctx, o); - prect.x0 = r.x0; - prect.y0 = r.y0; - } - o = pdf_dict_get_inheritable(gctx, tpageref, PDF_NAME(MediaBox)); - - if (o) + if (!fz_is_infinite_rect(rclip)) // set cropbox = clip { - r = pdf_to_rect(gctx, o); - prect.x1 = r.x1; - prect.y1 = r.y1; + cropbox = fz_transform_rect(rclip, inv_ctm); } - - float W = rrect.x1 - rrect.x0; - float H = rrect.y1 - rrect.y0; - float fw = W / (cropbox.x1 - cropbox.x0); - float fh = H / (cropbox.y1 - cropbox.y0); - if ((fw < fh) && keep_proportion) // zoom factors in matrix - fh = fw; - float X = rrect.x0 + prect.x0 - fw*cropbox.x0; - float Y = prect.y1 - (rrect.y1 + prect.y0 + fh*cropbox.y0); - mat.a = fw; - mat.d = fh; - mat.e = X; - mat.f = Y; //------------------------------------------------------------- // create referencing XObject (controls actual display) @@ -11813,7 +11785,7 @@ SWIGINTERN PyObject *fz_page_s_insertImage(struct fz_page_s *self,PyObject *rect image = fz_new_image_from_file(gctx, filename); else { - imgbuf = fz_new_buffer_from_shared_data(gctx, + imgbuf = fz_new_buffer_from_copied_data(gctx, streamdata, streamlen); image = fz_new_image_from_buffer(gctx, imgbuf); } @@ -11859,6 +11831,7 @@ SWIGINTERN PyObject *fz_page_s_insertImage(struct fz_page_s *self,PyObject *rect fz_drop_image(gctx, mask); fz_drop_pixmap(gctx, pix); fz_drop_pixmap(gctx, pm); + fz_drop_buffer(gctx, imgbuf); } fz_catch(gctx) return NULL; pdf->dirty = 1; @@ -17207,10 +17180,11 @@ SWIGINTERN PyObject *_wrap_Page__showPDFpage(PyObject *SWIGUNUSEDPARM(self), PyO int arg4 = (int) 0 ; int arg5 = (int) 1 ; int arg6 = (int) 1 ; - int arg7 = (int) 0 ; - PyObject *arg8 = (PyObject *) NULL ; - struct pdf_graft_map_s *arg9 = (struct pdf_graft_map_s *) NULL ; - char *arg10 = (char *) NULL ; + PyObject *arg7 = (PyObject *) NULL ; + int arg8 = (int) 0 ; + PyObject *arg9 = (PyObject *) NULL ; + struct pdf_graft_map_s *arg10 = (struct pdf_graft_map_s *) NULL ; + char *arg11 = (char *) NULL ; void *argp1 = 0 ; int res1 = 0 ; void *argp3 = 0 ; @@ -17221,13 +17195,13 @@ SWIGINTERN PyObject *_wrap_Page__showPDFpage(PyObject *SWIGUNUSEDPARM(self), PyO int ecode5 = 0 ; int val6 ; int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - void *argp9 = 0 ; - int res9 = 0 ; - int res10 ; - char *buf10 = 0 ; - int alloc10 = 0 ; + int val8 ; + int ecode8 = 0 ; + void *argp10 = 0 ; + int res10 = 0 ; + int res11 ; + char *buf11 = 0 ; + int alloc11 = 0 ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; @@ -17238,9 +17212,10 @@ SWIGINTERN PyObject *_wrap_Page__showPDFpage(PyObject *SWIGUNUSEDPARM(self), PyO PyObject * obj7 = 0 ; PyObject * obj8 = 0 ; PyObject * obj9 = 0 ; + PyObject * obj10 = 0 ; PyObject *result = 0 ; - if (!PyArg_ParseTuple(args,(char *)"OOO|OOOOOOO:Page__showPDFpage",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9)) SWIG_fail; + if (!PyArg_ParseTuple(args,(char *)"OOO|OOOOOOOO:Page__showPDFpage",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9,&obj10)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_page_s, 0 | 0 ); if (!SWIG_IsOK(res1)) { SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Page__showPDFpage" "', argument " "1"" of type '" "struct fz_page_s *""'"); @@ -17274,31 +17249,34 @@ SWIGINTERN PyObject *_wrap_Page__showPDFpage(PyObject *SWIGUNUSEDPARM(self), PyO arg6 = (int)(val6); } if (obj6) { - ecode7 = SWIG_AsVal_int(obj6, &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Page__showPDFpage" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); + arg7 = obj6; } if (obj7) { - arg8 = obj7; + ecode8 = SWIG_AsVal_int(obj7, &val8); + if (!SWIG_IsOK(ecode8)) { + SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Page__showPDFpage" "', argument " "8"" of type '" "int""'"); + } + arg8 = (int)(val8); } if (obj8) { - res9 = SWIG_ConvertPtr(obj8, &argp9,SWIGTYPE_p_pdf_graft_map_s, 0 | 0 ); - if (!SWIG_IsOK(res9)) { - SWIG_exception_fail(SWIG_ArgError(res9), "in method '" "Page__showPDFpage" "', argument " "9"" of type '" "struct pdf_graft_map_s *""'"); - } - arg9 = (struct pdf_graft_map_s *)(argp9); + arg9 = obj8; } if (obj9) { - res10 = SWIG_AsCharPtrAndSize(obj9, &buf10, NULL, &alloc10); + res10 = SWIG_ConvertPtr(obj9, &argp10,SWIGTYPE_p_pdf_graft_map_s, 0 | 0 ); if (!SWIG_IsOK(res10)) { - SWIG_exception_fail(SWIG_ArgError(res10), "in method '" "Page__showPDFpage" "', argument " "10"" of type '" "char *""'"); + SWIG_exception_fail(SWIG_ArgError(res10), "in method '" "Page__showPDFpage" "', argument " "10"" of type '" "struct pdf_graft_map_s *""'"); + } + arg10 = (struct pdf_graft_map_s *)(argp10); + } + if (obj10) { + res11 = SWIG_AsCharPtrAndSize(obj10, &buf11, NULL, &alloc11); + if (!SWIG_IsOK(res11)) { + SWIG_exception_fail(SWIG_ArgError(res11), "in method '" "Page__showPDFpage" "', argument " "11"" of type '" "char *""'"); } - arg10 = (char *)(buf10); + arg11 = (char *)(buf11); } { - result = (PyObject *)fz_page_s__showPDFpage(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10); + result = (PyObject *)fz_page_s__showPDFpage(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11); if(!result) { PyErr_SetString(PyExc_RuntimeError, fz_caught_message(gctx)); @@ -17306,10 +17284,10 @@ SWIGINTERN PyObject *_wrap_Page__showPDFpage(PyObject *SWIGUNUSEDPARM(self), PyO } } resultobj = result; - if (alloc10 == SWIG_NEWOBJ) free((char*)buf10); + if (alloc11 == SWIG_NEWOBJ) free((char*)buf11); return resultobj; fail: - if (alloc10 == SWIG_NEWOBJ) free((char*)buf10); + if (alloc11 == SWIG_NEWOBJ) free((char*)buf11); return NULL; } @@ -22115,7 +22093,7 @@ static PyMethodDef SwigMethods[] = { { (char *)"Page__addAnnot_FromString", _wrap_Page__addAnnot_FromString, METH_VARARGS, (char *)"Page__addAnnot_FromString(self, linklist) -> PyObject *"}, { (char *)"Page__getLinkXrefs", _wrap_Page__getLinkXrefs, METH_VARARGS, (char *)"Page__getLinkXrefs(self) -> PyObject *"}, { (char *)"Page__cleanContents", _wrap_Page__cleanContents, METH_VARARGS, (char *)"Page__cleanContents(self) -> PyObject *"}, - { (char *)"Page__showPDFpage", _wrap_Page__showPDFpage, METH_VARARGS, (char *)"Page__showPDFpage(self, rect, docsrc, pno=0, overlay=1, keep_proportion=1, reuse_xref=0, clip=None, graftmap=None, _imgname=None) -> PyObject *"}, + { (char *)"Page__showPDFpage", _wrap_Page__showPDFpage, METH_VARARGS, (char *)"Page__showPDFpage(self, rect, docsrc, pno=0, overlay=1, keep_proportion=1, matrix=None, reuse_xref=0, clip=None, graftmap=None, _imgname=None) -> PyObject *"}, { (char *)"Page_insertImage", _wrap_Page_insertImage, METH_VARARGS, (char *)"Insert a new image into a rectangle."}, { (char *)"Page__insertFont", _wrap_Page__insertFont, METH_VARARGS, (char *)"Page__insertFont(self, fontname, bfname, fontfile, fontbuffer, set_simple, idx, wmode, serif, encoding, ordering) -> PyObject *"}, { (char *)"Page__getTransformation", _wrap_Page__getTransformation, METH_VARARGS, (char *)"Page__getTransformation(self) -> PyObject *"}, diff --git a/fitz/helper-geo-py.i b/fitz/helper-geo-py.i index 05d83381d..f71c983d5 100644 --- a/fitz/helper-geo-py.i +++ b/fitz/helper-geo-py.i @@ -17,9 +17,9 @@ class Matrix(): return None if len(args) == 1: # either an angle or a sequ if hasattr(args[0], "__float__"): - theta = args[0] * math.pi / 180.0 - c = math.cos(theta) - s = math.sin(theta) + theta = math.radians(args[0]) + c = round(math.cos(theta), 8) + s = round(math.sin(theta), 8) self.a = self.d = c self.b = s self.c = -s @@ -110,8 +110,9 @@ class Matrix(): self.d = b else: - s = math.sin(theta * math.pi / 180.0) - c = math.cos(theta * math.pi / 180.0) + rad = math.radians(theta) + s = round(math.sin(rad), 8) + c = round(math.cos(rad), 8) a = self.a b = self.b self.a = c * a + s * self.c @@ -158,7 +159,8 @@ class Matrix(): if hasattr(m, "__float__"): return Matrix(self.a * m, self.b * m, self.c * m, self.d * m, self.e * m, self.f * m) - return self.concat(self, m) + m1 = Matrix(1,1) + return m1.concat(self, m) def __truediv__(self, m): if hasattr(m, "__float__"): diff --git a/fitz/helper-python.i b/fitz/helper-python.i index 5e9da014a..ed2e1214f 100644 --- a/fitz/helper-python.i +++ b/fitz/helper-python.i @@ -87,10 +87,13 @@ Base14_fontdict["zadb"] = "ZapfDingbats" def getTextlength(text, fontname="helv", fontsize=11, encoding=0): """Calculate length of a string for a given built-in font. - :arg str fontname: name of the font. - :arg float fontsize: size of font in points. - :arg int encoding: encoding to use (0=Latin, 1=Greek, 2=Cyrillic). - :returns: (float) length of text. + + Args: + fontname: name of the font. + fontsize: size of font in points. + encoding: encoding to use (0=Latin, 1=Greek, 2=Cyrillic). + Returns: + (float) length of text. """ fontname = fontname.lower() basename = Base14_fontdict.get(fontname, None) diff --git a/fitz/helper-xobject.i b/fitz/helper-xobject.i index fdd048d27..97c587253 100644 --- a/fitz/helper-xobject.i +++ b/fitz/helper-xobject.i @@ -3,28 +3,33 @@ // Make an XObject from a PDF page // For a positive xref assume that that object can be used instead //----------------------------------------------------------------------------- -pdf_obj *JM_xobject_from_page(fz_context *ctx, pdf_document *pdfout, pdf_document *pdfsrc, int pno, fz_rect *mediabox, fz_rect *cropbox, int xref, pdf_graft_map *gmap) +pdf_obj *JM_xobject_from_page(fz_context *ctx, pdf_document *pdfout, pdf_document *pdfsrc, int pno, fz_matrix *inv_ctm, fz_rect *cropbox, int xref, pdf_graft_map *gmap) { fz_buffer *nres = NULL, *res = NULL; pdf_obj *xobj1, *contents = NULL, *resources = NULL, *o, *spageref; + fz_rect mediabox; + fz_matrix ctm = fz_identity; int i; fz_try(ctx) { if (pno < 0 || pno >= pdf_count_pages(ctx, pdfsrc)) THROWMSG("invalid page number(s)"); spageref = pdf_lookup_page_obj(ctx, pdfsrc, pno); + pdf_page_transform(ctx, pdf_load_page(ctx, pdfsrc, pno), NULL, &ctm); + *inv_ctm = fz_invert_matrix(ctm); pdf_obj *mb = pdf_dict_get_inheritable(ctx, spageref, PDF_NAME(MediaBox)); if (mb) - *mediabox = pdf_to_rect(ctx, mb); + mediabox = pdf_to_rect(ctx, mb); else - *mediabox = pdf_bound_page(ctx, pdf_load_page(ctx, pdfsrc, pno)); + mediabox = pdf_bound_page(ctx, pdf_load_page(ctx, pdfsrc, pno)); + o = pdf_dict_get_inheritable(ctx, spageref, PDF_NAME(CropBox)); if (!o) { - cropbox->x0 = mediabox->x0; - cropbox->y0 = mediabox->y0; - cropbox->x1 = mediabox->x1; - cropbox->y1 = mediabox->y1; + cropbox->x0 = mediabox.x0; + cropbox->y0 = mediabox.y0; + cropbox->x1 = mediabox.x1; + cropbox->y1 = mediabox.y1; } else *cropbox = pdf_to_rect(ctx, o); @@ -64,7 +69,7 @@ pdf_obj *JM_xobject_from_page(fz_context *ctx, pdf_document *pdfout, pdf_documen //------------------------------------------------------------- // create XObject representing the source page //------------------------------------------------------------- - xobj1 = pdf_new_xobject(ctx, pdfout, *mediabox, fz_identity, NULL, res); + xobj1 = pdf_new_xobject(ctx, pdfout, mediabox, fz_identity, NULL, res); // store spage contents JM_update_stream(ctx, pdfout, xobj1, res); fz_drop_buffer(ctx, res); diff --git a/fitz/utils.py b/fitz/utils.py index f768775ee..3990eaaa2 100644 --- a/fitz/utils.py +++ b/fitz/utils.py @@ -1,20 +1,96 @@ from fitz import * import math -''' +""" The following is a collection of functions to extend PyMupdf. -''' +""" #============================================================================== # A function for displaying other PDF pages #============================================================================== -def showPDFpage(page, rect, src, pno, overlay = True, keep_proportion = True, - reuse_xref=0, clip = None): +def showPDFpage(page, + rect, + src, + pno, + overlay=True, + keep_proportion=True, + rotate=0, + reuse_xref=0, + clip = None, + ): """Show page number 'pno' of PDF 'src' in rectangle 'rect'. """ + + def calc_matrix(sr, tr, keep=True, rotate=0): + """ Calculate the transformation matrix between source and target rect. + + Notes: + The result also depends on whether a rotation is requested and the ratio + of the edges should be kept constant. + Args: + sr: source rect in PDF (!) coordinate system + tr: target rect in PDF coordinate system + keep: whether to keep source ratio of width to height + rotate: rotation angle in degrees, one of 0, 90, 180, 270. + Returns: + Transformation matrix. + """ + if rotate in (0, 180): + fw = tr.width / sr.width + fh = tr.height / sr.height + else: + fw = tr.width / sr.height + fh = tr.height / sr.width + + if keep: + fw = fh = min(fw, fh) + msc = Matrix(fw, 0, 0, fh, 0, 0) + + if rotate == 0: + m0 = Matrix(1, 0, 0, 1, -sr.x0, -sr.y0) + m1 = Matrix(1, 0, 0, 1, tr.x0, tr.y0) + rot = Matrix(1, 1) + + if rotate == 180: + m0 = Matrix(1, 0, 0, 1, -sr.x0, -sr.y0) + m1 = Matrix(1, 0, 0, 1, tr.x1, tr.y1) + rot = Matrix(1, 1) + msc.a *= -1 + msc.d *= -1 + + if rotate == 90: + m0 = Matrix(1, 0, 0, 1, -sr.x0, -sr.y0) + m1 = Matrix(1, 0, 0, 1, tr.x1, tr.y0) + rot = Matrix(90) + + if rotate == 270: + m0 = Matrix(1, 0, 0, 1, -sr.x0, -sr.y0) + m1 = Matrix(1, 0, 0, 1, tr.x0, tr.y1) + rot = Matrix(270) + + m = m0 * rot * msc * m1 + return m + CheckParent(page) doc = page.parent + + if not doc.isPDF or not src.isPDF: + raise ValueError("not a PDF") + + while rotate < 0: + rotate += 360 + while rotate > 360: + rotate -= 360 + if rotate not in (0, 90, 180, 270): + raise ValueError("rotate not in (0, 90, 180, 270)") + + tar_rect = rect * ~page._getTransformation() + src_rect = src[pno].rect if not clip else clip + src_rect = src_rect * ~src[pno]._getTransformation() + matrix = calc_matrix(src_rect, tar_rect, keep=keep_proportion, rotate=rotate) + # list of existing /Form /XObjects xobjlist = doc._getPageInfo(page.number, 3) ilst = [i[1] for i in xobjlist] + # create a name that is not in this list n = "fzFrm" i = 0 @@ -34,20 +110,28 @@ def showPDFpage(page, rect, src, pno, overlay = True, keep_proportion = True, gmap = Graftmap(doc) doc.Graftmaps[isrc] = gmap - return page._showPDFpage(rect, src, pno, overlay = overlay, - keep_proportion = keep_proportion, - reuse_xref = reuse_xref, clip = clip, - graftmap = gmap, _imgname = _imgname) + return page._showPDFpage(rect, src, pno, + overlay=overlay, + keep_proportion=keep_proportion, + matrix=matrix, + reuse_xref=reuse_xref, + clip=clip, + graftmap=gmap, + _imgname=_imgname) #============================================================================== # A function for searching string occurrences on a page. #============================================================================== def searchFor(page, text, hit_max = 16, quads = False): - '''Search for a string on a page. Parameters: - text: string to be searched for - hit_max: maximum hits - Returns a list of rectangles, each containing an occurrence. - ''' + """ Search for a string on a page. + + Args: + text: string to be searched for + hit_max: maximum hits + quads: return quads instead of rectangles + Returns: + a list of rectangles or quads, each containing an occurrence. + """ CheckParent(page) dl = page.getDisplayList() # create DisplayList tp = dl.getTextPage() # create TextPage @@ -61,7 +145,17 @@ def searchFor(page, text, hit_max = 16, quads = False): # A function for searching string occurrences on a page. #============================================================================== def searchPageFor(doc, pno, text, hit_max=16, quads=False): - """Search for a string on a page. Parameters:\npno: integer page number\ntext: string to be searched for\nhit_max: maximum hits.\nReturns a list of rectangles or quads, each of which surrounds a found occurrence.""" + """ Search for a string on a page. + + Args: + pno: page number + text: string to be searched for + hit_max: maximum hits + quads: return quads instead of rectangles + Returns: + a list of rectangles or quads, each containing an occurrence. + """ + return doc[pno].searchFor(text, hit_max = hit_max, quads = quads) #============================================================================== diff --git a/fitz/version.i b/fitz/version.i index 2757ecffc..19fa6a25c 100644 --- a/fitz/version.i +++ b/fitz/version.i @@ -1,6 +1,6 @@ %pythoncode %{ VersionFitz = "1.14.0" -VersionBind = "1.14.9" -VersionDate = "2019-03-06 14:13:45" -version = (VersionBind, VersionFitz, "20190306141345") +VersionBind = "1.14.10" +VersionDate = "2019-03-10 11:59:51" +version = (VersionBind, VersionFitz, "20190310115951") %} \ No newline at end of file diff --git a/nano_setup.py b/nano_setup.py index 5337ebd88..ae6dd5e32 100644 --- a/nano_setup.py +++ b/nano_setup.py @@ -60,7 +60,7 @@ setup( name="PyMuPDF", - version="1.14.9", + version="1.14.10", description="Python bindings for the PDF rendering library MuPDF", classifiers=[ "Development Status :: 5 - Production/Stable", diff --git a/setup.py b/setup.py index 25c4690de..9f0624d93 100644 --- a/setup.py +++ b/setup.py @@ -73,7 +73,7 @@ setup( name="PyMuPDF", - version="1.14.9", + version="1.14.10", description="Python bindings for the PDF rendering library MuPDF", long_description=long_desc, classifiers=classifier,