From b7feda63647a877e4d94eff283717b303cb855b1 Mon Sep 17 00:00:00 2001 From: "Jorj X. McKie" Date: Wed, 16 Jan 2019 04:36:52 -0400 Subject: [PATCH 1/2] Fix a type typo --- fitz/fitz.py | 8 ++++---- fitz/helper-geo-py.i | 2 +- fitz/helper-python.i | 2 +- fitz/version.i | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fitz/fitz.py b/fitz/fitz.py index 13f354dbd..d71b44dff 100644 --- a/fitz/fitz.py +++ b/fitz/fitz.py @@ -106,8 +106,8 @@ class _object: VersionFitz = "1.14.0" VersionBind = "1.14.6" -VersionDate = "2019-01-14 06:46:06" -version = (VersionBind, VersionFitz, "20190114064606") +VersionDate = "2019-01-16 04:32:29" +version = (VersionBind, VersionFitz, "20190116043229") class Matrix(): @@ -234,7 +234,7 @@ def preRotate(self, theta): def concat(self, one, two): """Multiply two matrices and replace current one.""" - if not len(one) == len(Two) == 6: + if not len(one) == len(two) == 6: raise ValueError("bad sequ. length") self.a, self.b, self.c, self.d, self.e, self.f = TOOLS._concat_matrix(one, two) return self @@ -1502,7 +1502,7 @@ def getTJstr(text, glyphs, simple, ordering): if glyphs is None: # simple and not Symbol / ZapfDingbats otxt = "".join([hex(ord(c))[2:].rjust(2, "0") if ord(c)<256 else "3f" for c in text]) else: # Symbol or ZapfDingbats - otxt = "".join([hex(glyphs[ord(c)][0])[2:].rjust(2, "0") for c in text]) + otxt = "".join([hex(glyphs[ord(c)][0])[2:].rjust(2, "0") if ord(c)<256 else "20" for c in text]) return "[<" + otxt + ">]" if ordering < 0: # not a CJK font: use the glyphs diff --git a/fitz/helper-geo-py.i b/fitz/helper-geo-py.i index 483be4718..200f1d2a5 100644 --- a/fitz/helper-geo-py.i +++ b/fitz/helper-geo-py.i @@ -123,7 +123,7 @@ class Matrix(): def concat(self, one, two): """Multiply two matrices and replace current one.""" - if not len(one) == len(Two) == 6: + if not len(one) == len(two) == 6: raise ValueError("bad sequ. length") self.a, self.b, self.c, self.d, self.e, self.f = TOOLS._concat_matrix(one, two) return self diff --git a/fitz/helper-python.i b/fitz/helper-python.i index daa71d08e..892dfd609 100644 --- a/fitz/helper-python.i +++ b/fitz/helper-python.i @@ -352,7 +352,7 @@ def getTJstr(text, glyphs, simple, ordering): if glyphs is None: # simple and not Symbol / ZapfDingbats otxt = "".join([hex(ord(c))[2:].rjust(2, "0") if ord(c)<256 else "3f" for c in text]) else: # Symbol or ZapfDingbats - otxt = "".join([hex(glyphs[ord(c)][0])[2:].rjust(2, "0") for c in text]) + otxt = "".join([hex(glyphs[ord(c)][0])[2:].rjust(2, "0") if ord(c)<256 else "20" for c in text]) return "[<" + otxt + ">]" if ordering < 0: # not a CJK font: use the glyphs diff --git a/fitz/version.i b/fitz/version.i index 6edb71315..f8ba79e14 100644 --- a/fitz/version.i +++ b/fitz/version.i @@ -1,6 +1,6 @@ %pythoncode %{ VersionFitz = "1.14.0" VersionBind = "1.14.6" -VersionDate = "2019-01-14 06:46:06" -version = (VersionBind, VersionFitz, "20190114064606") +VersionDate = "2019-01-16 04:32:29" +version = (VersionBind, VersionFitz, "20190116043229") %} \ No newline at end of file From 0b6c02ebed952899c191379deef7828a019b74c0 Mon Sep 17 00:00:00 2001 From: "Jorj X. McKie" Date: Thu, 17 Jan 2019 16:59:40 -0400 Subject: [PATCH 2/2] Upload v1.14.7 --- PKG-INFO | 78 +++++++++++++++++++++ README.md | 4 +- fitz/fitz.i | 71 +++++++++++-------- fitz/fitz.py | 159 +++++++++++++++++++++++-------------------- fitz/fitz_wrap.c | 59 ++++++++++++++-- fitz/helper-geo-py.i | 8 +-- fitz/helper-python.i | 84 +++++++++++++---------- fitz/utils.py | 152 +++++++++++++++++++++++------------------ fitz/version.i | 6 +- nano_setup.py | 2 +- setup.py | 11 ++- 11 files changed, 410 insertions(+), 224 deletions(-) create mode 100644 PKG-INFO diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 000000000..28dca9496 --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,78 @@ +Metadata-Version: 1.1 +Name: PyMuPDF +Version: 1.14.7 +Author: Ruikai Liu +Author-email: lrk700@gmail.com +Maintainer: Ruikai Liu +Maintainer-email: lrk700@gmail.com +Home-page: https://github.com/rk700/PyMuPDF +Download-url: https://github.com/rk700/PyMuPDF +Summary: PyMuPDF is a Python binding for the PDF rendering library MuPDF +Description: + + Release date: January 15, 2019 + + Authors + ======= + + * Ruikai Liu + * Jorj X. McKie + + Introduction + ============ + + This is **version 1.14.7 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. + + With PyMuPDF you therefore can access files with extensions ``*.pdf``, ``*.xps``, ``*.oxps``, ``*.epub``, ``*.cbz`` or ``*.fb2`` from your Python scripts. A number of popular image formats is supported as well, including multi-page TIFF images. + + PyMuPDF should run on all platforms that are supported by both, MuPDF and Python. These include, but are not limited to, Windows (XP/SP2 and up), Mac OS and Linux, 32-bit or 64-bit. If you can generate MuPDF on a Python supported platform, then also PyMuPDF can be used there. + + PyMuPDF is hosted on `GitHub `_ where you find up-to-date information of its features, our `issue tracker `_, `Wikis `_ and much more. + + Installation + ============ + + For all MS Windows versions as well as popular Max OS and Linux versions, we are providing Python wheels - see the download section of this site and the current `release directory `_ of our home page. For Windows users, `zip-based installation `_ options are also available. Other platforms need to download and generate the MuPDF library first and then set up PyMuPDF. Do visit our GitHub home, which has more details on this, including latest bugfixes, pre-releases, etc. + + Usage and Documentation + ======================== + + For all document types you can render pages in raster (PNG) or vector (SVG) formats, extract text and access meta information, links, annotations and bookmarks, as well as decrypt the document. For PDF files, most of these objects can also be created, modified or deleted. Plus you can rotate, re-arrange, duplicate, create, or delete pages and join or split documents. + + Specifically for PDF files, PyMuPDF provides update access to low-level structure information, supports handling of embedded files and modification of page contents (like inserting images, fonts, text, annotations and drawings). When saving changes to password protected PDFs you can now choose, whether to keep or remove encryption. + + Other features include embedding vector images (SVG, PDF) such as logos or watermarks, joining or splitting single PDF pages (including things like posterizing and 2-up / 4-up processing). + + You can now also create **PDF Form fields** with support for text, checkbox, listbox and combobox widgets. + + Our home page provides many examples and How-Tos for all of this. At a minimum, read the tutorial and the the recipes sections of our documentation. + + Written using **Sphinx**, documentation is available here: + + * View it online at `Read The Docs `_. For **best quality downloads**, use the following links. + + * `HTML `_ + + * `Windows CHM `_ + + * `PDF `_ + + +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+) +Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) +Classifier: Operating System :: MacOS +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: POSIX :: Linux +Classifier: Programming Language :: C +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Topic :: Utilities diff --git a/README.md b/README.md index 6e5951c7e..15efd2e4f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# PyMuPDF 1.14.6 +# PyMuPDF 1.14.7 ![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.6 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.7 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 d1678acb4..4d37d4513 100644 --- a/fitz/fitz.i +++ b/fitz/fitz.i @@ -6352,6 +6352,12 @@ struct Tools JM_point_from_py(p))); } + %feature("autodoc","Transform point with matrix.") _transform_point; + PyObject *_transform_point(PyObject *point, PyObject *matrix) + { + return JM_py_from_point(fz_transform_point(JM_point_from_py(point), JM_matrix_from_py(matrix))); + } + %feature("autodoc","Replace r1 with smallest rect containing both.") _union_rect; PyObject *_union_rect(PyObject *r1, PyObject *r2) { @@ -6389,7 +6395,8 @@ struct Tools } %feature("autodoc","Measure length of a string for a Base14 font.") measure_string; - float measure_string(const char *text, const char *fontname, float fontsize) + float measure_string(const char *text, const char *fontname, float fontsize, + int encoding = 0) { fz_font *font = fz_new_base14_font(gctx, fontname); float w = 0; @@ -6397,7 +6404,15 @@ struct Tools { int c, g; text += fz_chartorune(&c, text); - c = pdf_winansi_from_unicode(c); + switch (encoding) + { + case PDF_SIMPLE_ENCODING_GREEK: + c = pdf_greek_from_unicode(c); break; + case PDF_SIMPLE_ENCODING_CYRILLIC: + c = pdf_cyrillic_from_unicode(c); break; + default: + c = pdf_winansi_from_unicode(c); break; + } if (c < 0) c = 0xB7; g = fz_encode_character(gctx, font, c); w += fz_advance_glyph(gctx, font, g, 0); @@ -6440,7 +6455,7 @@ def _oval_string(self, p1, p2, p3, p4): """Return /AP string defining an oval within a 4-polygon provided as points """ def bezier(p, q, r): - f = "%g %g %g %g %g %g c\n" + f = "%f %f %f %f %f %f c\n" return f % (p.x, p.y, q.x, q.y, r.x, r.y) kappa = 0.55228474983 # magic number @@ -6457,7 +6472,7 @@ def _oval_string(self, p1, p2, p3, p4): ul1 = mu + (p4 - mu) * kappa ul2 = ml + (p4 - ml) * kappa # now draw, starting from middle point of left side - ap = "%g %g m\n" % (ml.x, ml.y) + ap = "%f %f m\n" % (ml.x, ml.y) ap += bezier(ol1, ol2, mo) ap += bezier(or1, or2, mr) ap += bezier(ur1, ur2, mu) @@ -6474,13 +6489,13 @@ def _le_diamond(self, annot, p1, p2, lr): r = Rect(M, M) + (-d, -d, d, d) # the square # the square makes line longer by (2*shift - 1)*width p = (r.tl + (r.bl - r.tl) * 0.5) * im - ap = "q\n%s%g %g m\n" % (opacity, p.x, p.y) + ap = "q\n%s%f %f m\n" % (opacity, p.x, p.y) p = (r.tl + (r.tr - r.tl) * 0.5) * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) p = (r.tr + (r.br - r.tr) * 0.5) * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) p = (r.br + (r.bl - r.br) * 0.5) * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) ap += "%g w\n" % w ap += scol + fcol + "b\nQ\n" return ap @@ -6495,13 +6510,13 @@ def _le_square(self, annot, p1, p2, lr): r = Rect(M, M) + (-d, -d, d, d) # the square # the square makes line longer by (2*shift - 1)*width p = r.tl * im - ap = "q\n%s%g %g m\n" % (opacity, p.x, p.y) + ap = "q\n%s%f %f m\n" % (opacity, p.x, p.y) p = r.tr * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) p = r.br * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) p = r.bl * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) ap += "%g w\n" % w ap += scol + fcol + "b\nQ\n" return ap @@ -6528,8 +6543,8 @@ def _le_butt(self, annot, p1, p2, lr): M = R if lr else L top = (M + (0, -d/2.)) * im bot = (M + (0, d/2.)) * im - ap = "\nq\n%s%g %g m\n" % (opacity, top.x, top.y) - ap += "%g %g l\n" % (bot.x, bot.y) + ap = "\nq\n%s%f %f m\n" % (opacity, top.x, top.y) + ap += "%f %f l\n" % (bot.x, bot.y) ap += "%g w\n" % w ap += scol + "s\nQ\n" return ap @@ -6543,8 +6558,8 @@ def _le_slash(self, annot, p1, p2, lr): r = Rect(M.x - rw, M.y - 2 * w, M.x + rw, M.y + 2 * w) top = r.tl * im bot = r.br * im - ap = "\nq\n%s%g %g m\n" % (opacity, top.x, top.y) - ap += "%g %g l\n" % (bot.x, bot.y) + ap = "\nq\n%s%f %f m\n" % (opacity, top.x, top.y) + ap += "%f %f l\n" % (bot.x, bot.y) ap += "%g w\n" % w ap += scol + "s\nQ\n" return ap @@ -6561,9 +6576,9 @@ def _le_openarrow(self, annot, p1, p2, lr): p1 *= im p2 *= im p3 *= im - ap = "\nq\n%s%g %g m\n" % (opacity, p1.x, p1.y) - ap += "%g %g l\n" % (p2.x, p2.y) - ap += "%g %g l\n" % (p3.x, p3.y) + ap = "\nq\n%s%f %f m\n" % (opacity, p1.x, p1.y) + ap += "%f %f l\n" % (p2.x, p2.y) + ap += "%f %f l\n" % (p3.x, p3.y) ap += "%g w\n" % w ap += scol + "S\nQ\n" return ap @@ -6580,9 +6595,9 @@ def _le_closedarrow(self, annot, p1, p2, lr): p1 *= im p2 *= im p3 *= im - ap = "\nq\n%s%g %g m\n" % (opacity, p1.x, p1.y) - ap += "%g %g l\n" % (p2.x, p2.y) - ap += "%g %g l\n" % (p3.x, p3.y) + ap = "\nq\n%s%f %f m\n" % (opacity, p1.x, p1.y) + ap += "%f %f l\n" % (p2.x, p2.y) + ap += "%f %f l\n" % (p3.x, p3.y) ap += "%g w\n" % w ap += scol + fcol + "b\nQ\n" return ap @@ -6599,9 +6614,9 @@ def _le_ropenarrow(self, annot, p1, p2, lr): p1 *= im p2 *= im p3 *= im - ap = "\nq\n%s%g %g m\n" % (opacity, p1.x, p1.y) - ap += "%g %g l\n" % (p2.x, p2.y) - ap += "%g %g l\n" % (p3.x, p3.y) + ap = "\nq\n%s%f %f m\n" % (opacity, p1.x, p1.y) + ap += "%f %f l\n" % (p2.x, p2.y) + ap += "%f %f l\n" % (p3.x, p3.y) ap += "%g w\n" % w ap += scol + fcol + "S\nQ\n" return ap @@ -6618,9 +6633,9 @@ def _le_rclosedarrow(self, annot, p1, p2, lr): p1 *= im p2 *= im p3 *= im - ap = "\nq\n%s%g %g m\n" % (opacity, p1.x, p1.y) - ap += "%g %g l\n" % (p2.x, p2.y) - ap += "%g %g l\n" % (p3.x, p3.y) + ap = "\nq\n%s%f %f m\n" % (opacity, p1.x, p1.y) + ap += "%f %f l\n" % (p2.x, p2.y) + ap += "%f %f l\n" % (p3.x, p3.y) ap += "%g w\n" % w ap += scol + fcol + "b\nQ\n" return ap diff --git a/fitz/fitz.py b/fitz/fitz.py index d71b44dff..b22231d6d 100644 --- a/fitz/fitz.py +++ b/fitz/fitz.py @@ -105,9 +105,9 @@ class _object: VersionFitz = "1.14.0" -VersionBind = "1.14.6" -VersionDate = "2019-01-16 04:32:29" -version = (VersionBind, VersionFitz, "20190116043229") +VersionBind = "1.14.7" +VersionDate = "2019-01-17 16:53:54" +version = (VersionBind, VersionFitz, "20190117165354") class Matrix(): @@ -129,8 +129,8 @@ def __init__(self, *args): if len(args) == 1: # either an angle or a sequ if hasattr(args[0], "__float__"): theta = args[0] * math.pi / 180.0 - c = round(math.cos(theta), 10) - s = round(math.sin(theta), 10) + c = math.cos(theta) + s = math.sin(theta) self.a = self.d = c self.b = s self.c = -s @@ -384,9 +384,7 @@ def transform(self, m): """Replace point by its transformation with matrix-like m.""" if len(m) != 6: raise ValueError("bad sequ. length") - x = self.x - self.x = x * m[0] + self.y * m[2] + m[4] - self.y = x * m[1] + self.y * m[3] + m[5] + self.x, self.y = TOOLS._transform_point(self, m) return self @property @@ -1184,6 +1182,12 @@ def _check5(self): TEXT_PRESERVE_WHITESPACE = 2 TEXT_PRESERVE_IMAGES = 4 +#------------------------------------------------------------------------------ +# Simple text encoding options +#------------------------------------------------------------------------------ +TEXT_ENCODING_LATIN = 0 +TEXT_ENCODING_GREEK = 1 +TEXT_ENCODING_CYRILLIC = 2 #------------------------------------------------------------------------------ # Stamp annotation icon numbers #------------------------------------------------------------------------------ @@ -1229,7 +1233,13 @@ def _check5(self): Base14_fontdict["symb"] = "Symbol" Base14_fontdict["zadb"] = "ZapfDingbats" -def getTextlen(text, fontname="helv", fontsize=12): +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. + """ fontname = fontname.lower() basename = Base14_fontdict.get(fontname, None) @@ -1239,11 +1249,11 @@ def getTextlen(text, fontname="helv", fontsize=12): if basename == "ZapfDingbats": glyphs = zapf_glyphs if glyphs is not None: - w = sum([glyphs[ord(c)][1] for c in text if ord(c) < 256]) + w = sum([glyphs[ord(c)][1] if ord(c)<256 else glyphs[183][1] for c in text]) return w * fontsize if fontname in Base14_fontdict.keys(): - return TOOLS.measure_string(text, Base14_fontdict[fontname], fontsize) + return TOOLS.measure_string(text, Base14_fontdict[fontname], fontsize, encoding) if fontname in ["china-t", "china-s", "china-ts", "china-ss", @@ -1258,12 +1268,12 @@ def getTextlen(text, fontname="helv", fontsize=12): # Glyph list for the built-in font 'ZapfDingbats' #------------------------------------------------------------------------------ zapf_glyphs = ( - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (33, 0.974), (34, 0.961), (35, 0.974), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (32, 0.278), (33, 0.974), (34, 0.961), (35, 0.974), (36, 0.98), (37, 0.719), (38, 0.789), (39, 0.79), (40, 0.791), (41, 0.69), (42, 0.96), (43, 0.939), (44, 0.549), (45, 0.855), (46, 0.911), (47, 0.933), (48, 0.911), (49, 0.945), (50, 0.974), (51, 0.755), (52, 0.846), (53, 0.762), @@ -1280,12 +1290,12 @@ def getTextlen(text, fontname="helv", fontsize=12): (112, 0.762), (113, 0.759), (114, 0.759), (115, 0.892), (116, 0.892), (117, 0.788), (118, 0.784), (119, 0.438), (120, 0.138), (121, 0.277), (122, 0.415), (123, 0.392), (124, 0.392), (125, 0.668), (126, 0.668), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (161, 0.732), (162, 0.544), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (161, 0.732), (162, 0.544), (163, 0.544), (164, 0.91), (165, 0.667), (166, 0.76), (167, 0.76), (168, 0.776), (169, 0.595), (170, 0.694), (171, 0.626), (172, 0.788), (173, 0.788), (174, 0.788), (175, 0.788), (176, 0.788), (177, 0.788), @@ -1301,23 +1311,23 @@ def getTextlen(text, fontname="helv", fontsize=12): (223, 0.834), (224, 0.873), (225, 0.828), (226, 0.924), (227, 0.924), (228, 0.917), (229, 0.93), (230, 0.931), (231, 0.463), (232, 0.883), (233, 0.836), (234, 0.836), (235, 0.867), (236, 0.867), (237, 0.696), - (238, 0.696), (239, 0.874), (32, 0.278), (241, 0.874), (242, 0.76), + (238, 0.696), (239, 0.874), (183, 0.788), (241, 0.874), (242, 0.76), (243, 0.946), (244, 0.771), (245, 0.865), (246, 0.771), (247, 0.888), (248, 0.967), (249, 0.888), (250, 0.831), (251, 0.873), (252, 0.927), - (253, 0.97), (32, 0.278), (32, 0.278) + (253, 0.97), (183, 0.788), (183, 0.788) ) #------------------------------------------------------------------------------ # Glyph list for the built-in font 'Symbol' #------------------------------------------------------------------------------ symbol_glyphs = ( - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (32, 0.25), (33, 0.333), (34, 0.713), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (32, 0.25), (33, 0.333), (34, 0.713), (35, 0.5), (36, 0.549), (37, 0.833), (38, 0.778), (39, 0.439), (40, 0.333), (41, 0.333), (42, 0.5), (43, 0.549), (44, 0.25), (45, 0.549), (46, 0.25), (47, 0.278), (48, 0.5), (49, 0.5), (50, 0.5), (51, 0.5), @@ -1335,14 +1345,14 @@ def getTextlen(text, fontname="helv", fontsize=12): (109, 0.576), (110, 0.521), (111, 0.549), (112, 0.549), (113, 0.521), (114, 0.549), (115, 0.603), (116, 0.439), (117, 0.576), (118, 0.713), (119, 0.686), (120, 0.493), (121, 0.686), (122, 0.494), (123, 0.48), - (124, 0.2), (125, 0.48), (126, 0.549), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (160, 0.25), (161, 0.62), (162, 0.247), (163, 0.549), + (124, 0.2), (125, 0.48), (126, 0.549), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (160, 0.25), (161, 0.62), (162, 0.247), (163, 0.549), (164, 0.167), (165, 0.713), (166, 0.5), (167, 0.753), (168, 0.753), (169, 0.753), (170, 0.753), (171, 1.042), (172, 0.713), (173, 0.603), (174, 0.987), (175, 0.603), (176, 0.4), (177, 0.549), (178, 0.411), @@ -1358,10 +1368,10 @@ def getTextlen(text, fontname="helv", fontsize=12): (224, 0.494), (225, 0.329), (226, 0.79), (227, 0.79), (228, 0.786), (229, 0.713), (230, 0.384), (231, 0.384), (232, 0.384), (233, 0.384), (234, 0.384), (235, 0.384), (236, 0.494), (237, 0.494), (238, 0.494), - (239, 0.494), (63, 0.444), (241, 0.329), (242, 0.274), (243, 0.686), + (239, 0.494), (183, 0.46), (241, 0.329), (242, 0.274), (243, 0.686), (244, 0.686), (245, 0.686), (246, 0.384), (247, 0.549), (248, 0.384), (249, 0.384), (250, 0.384), (251, 0.384), (252, 0.494), (253, 0.494), - (254, 0.494), (63, 0.444) + (254, 0.494), (183, 0.46) ) class linkDest(): @@ -1500,9 +1510,9 @@ def getTJstr(text, glyphs, simple, ordering): if simple: if glyphs is None: # simple and not Symbol / ZapfDingbats - otxt = "".join([hex(ord(c))[2:].rjust(2, "0") if ord(c)<256 else "3f" for c in text]) + otxt = "".join([hex(ord(c))[2:].rjust(2, "0") if ord(c)<256 else "b7" for c in text]) else: # Symbol or ZapfDingbats - otxt = "".join([hex(glyphs[ord(c)][0])[2:].rjust(2, "0") if ord(c)<256 else "20" for c in text]) + otxt = "".join([hex(glyphs[ord(c)][0])[2:].rjust(2, "0") if ord(c)<256 else "b7" for c in text]) return "[<" + otxt + ">]" if ordering < 0: # not a CJK font: use the glyphs @@ -4403,6 +4413,11 @@ def _include_point_in_rect(self, r, p): return _fitz.Tools__include_point_in_rect(self, r, p) + def _transform_point(self, point, matrix): + """Transform point with matrix.""" + return _fitz.Tools__transform_point(self, point, matrix) + + def _union_rect(self, r1, r2): """Replace r1 with smallest rect containing both.""" return _fitz.Tools__union_rect(self, r1, r2) @@ -4418,9 +4433,9 @@ def _invert_matrix(self, matrix): return _fitz.Tools__invert_matrix(self, matrix) - def measure_string(self, text, fontname, fontsize): + def measure_string(self, text, fontname, fontsize, encoding=0): """Measure length of a string for a Base14 font.""" - return _fitz.Tools_measure_string(self, text, fontname, fontsize) + return _fitz.Tools_measure_string(self, text, fontname, fontsize, encoding) @@ -4457,7 +4472,7 @@ def _oval_string(self, p1, p2, p3, p4): """Return /AP string defining an oval within a 4-polygon provided as points """ def bezier(p, q, r): - f = "%g %g %g %g %g %g c\n" + f = "%f %f %f %f %f %f c\n" return f % (p.x, p.y, q.x, q.y, r.x, r.y) kappa = 0.55228474983 # magic number @@ -4474,7 +4489,7 @@ def bezier(p, q, r): ul1 = mu + (p4 - mu) * kappa ul2 = ml + (p4 - ml) * kappa # now draw, starting from middle point of left side - ap = "%g %g m\n" % (ml.x, ml.y) + ap = "%f %f m\n" % (ml.x, ml.y) ap += bezier(ol1, ol2, mo) ap += bezier(or1, or2, mr) ap += bezier(ur1, ur2, mu) @@ -4491,13 +4506,13 @@ def _le_diamond(self, annot, p1, p2, lr): r = Rect(M, M) + (-d, -d, d, d) # the square # the square makes line longer by (2*shift - 1)*width p = (r.tl + (r.bl - r.tl) * 0.5) * im - ap = "q\n%s%g %g m\n" % (opacity, p.x, p.y) + ap = "q\n%s%f %f m\n" % (opacity, p.x, p.y) p = (r.tl + (r.tr - r.tl) * 0.5) * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) p = (r.tr + (r.br - r.tr) * 0.5) * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) p = (r.br + (r.bl - r.br) * 0.5) * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) ap += "%g w\n" % w ap += scol + fcol + "b\nQ\n" return ap @@ -4512,13 +4527,13 @@ def _le_square(self, annot, p1, p2, lr): r = Rect(M, M) + (-d, -d, d, d) # the square # the square makes line longer by (2*shift - 1)*width p = r.tl * im - ap = "q\n%s%g %g m\n" % (opacity, p.x, p.y) + ap = "q\n%s%f %f m\n" % (opacity, p.x, p.y) p = r.tr * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) p = r.br * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) p = r.bl * im - ap += "%g %g l\n" % (p.x, p.y) + ap += "%f %f l\n" % (p.x, p.y) ap += "%g w\n" % w ap += scol + fcol + "b\nQ\n" return ap @@ -4545,8 +4560,8 @@ def _le_butt(self, annot, p1, p2, lr): M = R if lr else L top = (M + (0, -d/2.)) * im bot = (M + (0, d/2.)) * im - ap = "\nq\n%s%g %g m\n" % (opacity, top.x, top.y) - ap += "%g %g l\n" % (bot.x, bot.y) + ap = "\nq\n%s%f %f m\n" % (opacity, top.x, top.y) + ap += "%f %f l\n" % (bot.x, bot.y) ap += "%g w\n" % w ap += scol + "s\nQ\n" return ap @@ -4560,8 +4575,8 @@ def _le_slash(self, annot, p1, p2, lr): r = Rect(M.x - rw, M.y - 2 * w, M.x + rw, M.y + 2 * w) top = r.tl * im bot = r.br * im - ap = "\nq\n%s%g %g m\n" % (opacity, top.x, top.y) - ap += "%g %g l\n" % (bot.x, bot.y) + ap = "\nq\n%s%f %f m\n" % (opacity, top.x, top.y) + ap += "%f %f l\n" % (bot.x, bot.y) ap += "%g w\n" % w ap += scol + "s\nQ\n" return ap @@ -4578,9 +4593,9 @@ def _le_openarrow(self, annot, p1, p2, lr): p1 *= im p2 *= im p3 *= im - ap = "\nq\n%s%g %g m\n" % (opacity, p1.x, p1.y) - ap += "%g %g l\n" % (p2.x, p2.y) - ap += "%g %g l\n" % (p3.x, p3.y) + ap = "\nq\n%s%f %f m\n" % (opacity, p1.x, p1.y) + ap += "%f %f l\n" % (p2.x, p2.y) + ap += "%f %f l\n" % (p3.x, p3.y) ap += "%g w\n" % w ap += scol + "S\nQ\n" return ap @@ -4597,9 +4612,9 @@ def _le_closedarrow(self, annot, p1, p2, lr): p1 *= im p2 *= im p3 *= im - ap = "\nq\n%s%g %g m\n" % (opacity, p1.x, p1.y) - ap += "%g %g l\n" % (p2.x, p2.y) - ap += "%g %g l\n" % (p3.x, p3.y) + ap = "\nq\n%s%f %f m\n" % (opacity, p1.x, p1.y) + ap += "%f %f l\n" % (p2.x, p2.y) + ap += "%f %f l\n" % (p3.x, p3.y) ap += "%g w\n" % w ap += scol + fcol + "b\nQ\n" return ap @@ -4616,9 +4631,9 @@ def _le_ropenarrow(self, annot, p1, p2, lr): p1 *= im p2 *= im p3 *= im - ap = "\nq\n%s%g %g m\n" % (opacity, p1.x, p1.y) - ap += "%g %g l\n" % (p2.x, p2.y) - ap += "%g %g l\n" % (p3.x, p3.y) + ap = "\nq\n%s%f %f m\n" % (opacity, p1.x, p1.y) + ap += "%f %f l\n" % (p2.x, p2.y) + ap += "%f %f l\n" % (p3.x, p3.y) ap += "%g w\n" % w ap += scol + fcol + "S\nQ\n" return ap @@ -4635,9 +4650,9 @@ def _le_rclosedarrow(self, annot, p1, p2, lr): p1 *= im p2 *= im p3 *= im - ap = "\nq\n%s%g %g m\n" % (opacity, p1.x, p1.y) - ap += "%g %g l\n" % (p2.x, p2.y) - ap += "%g %g l\n" % (p3.x, p3.y) + ap = "\nq\n%s%f %f m\n" % (opacity, p1.x, p1.y) + ap += "%f %f l\n" % (p2.x, p2.y) + ap += "%f %f l\n" % (p3.x, p3.y) ap += "%g w\n" % w ap += scol + fcol + "b\nQ\n" return ap diff --git a/fitz/fitz_wrap.c b/fitz/fitz_wrap.c index 487db048f..8e6ba28b3 100644 --- a/fitz/fitz_wrap.c +++ b/fitz/fitz_wrap.c @@ -13438,6 +13438,9 @@ SWIGINTERN PyObject *Tools__include_point_in_rect(struct Tools *self,PyObject *r return JM_py_from_rect(fz_include_point_in_rect(JM_rect_from_py(r), JM_point_from_py(p))); } +SWIGINTERN PyObject *Tools__transform_point(struct Tools *self,PyObject *point,PyObject *matrix){ + return JM_py_from_point(fz_transform_point(JM_point_from_py(point), JM_matrix_from_py(matrix))); + } SWIGINTERN PyObject *Tools__union_rect(struct Tools *self,PyObject *r1,PyObject *r2){ return JM_py_from_rect(fz_union_rect(JM_rect_from_py(r1), JM_rect_from_py(r2))); @@ -13465,14 +13468,22 @@ SWIGINTERN PyObject *Tools__invert_matrix(struct Tools *self,PyObject *matrix){ } return Py_BuildValue("(i, ())", 1); } -SWIGINTERN float Tools_measure_string(struct Tools *self,char const *text,char const *fontname,float fontsize){ +SWIGINTERN float Tools_measure_string(struct Tools *self,char const *text,char const *fontname,float fontsize,int encoding){ fz_font *font = fz_new_base14_font(gctx, fontname); float w = 0; while (*text) { int c, g; text += fz_chartorune(&c, text); - c = pdf_winansi_from_unicode(c); + switch (encoding) + { + case PDF_SIMPLE_ENCODING_GREEK: + c = pdf_greek_from_unicode(c); break; + case PDF_SIMPLE_ENCODING_CYRILLIC: + c = pdf_cyrillic_from_unicode(c); break; + default: + c = pdf_winansi_from_unicode(c); break; + } if (c < 0) c = 0xB7; g = fz_encode_character(gctx, font, c); w += fz_advance_glyph(gctx, font, g, 0); @@ -21520,6 +21531,34 @@ SWIGINTERN PyObject *_wrap_Tools__include_point_in_rect(PyObject *SWIGUNUSEDPARM } +SWIGINTERN PyObject *_wrap_Tools__transform_point(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct Tools *arg1 = (struct Tools *) 0 ; + PyObject *arg2 = (PyObject *) 0 ; + PyObject *arg3 = (PyObject *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject *result = 0 ; + + if (!PyArg_ParseTuple(args,(char *)"OOO:Tools__transform_point",&obj0,&obj1,&obj2)) SWIG_fail; + res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Tools, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tools__transform_point" "', argument " "1"" of type '" "struct Tools *""'"); + } + arg1 = (struct Tools *)(argp1); + arg2 = obj1; + arg3 = obj2; + result = (PyObject *)Tools__transform_point(arg1,arg2,arg3); + resultobj = result; + return resultobj; +fail: + return NULL; +} + + SWIGINTERN PyObject *_wrap_Tools__union_rect(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct Tools *arg1 = (struct Tools *) 0 ; @@ -21607,6 +21646,7 @@ SWIGINTERN PyObject *_wrap_Tools_measure_string(PyObject *SWIGUNUSEDPARM(self), char *arg2 = (char *) 0 ; char *arg3 = (char *) 0 ; float arg4 ; + int arg5 = (int) 0 ; void *argp1 = 0 ; int res1 = 0 ; int res2 ; @@ -21617,13 +21657,16 @@ SWIGINTERN PyObject *_wrap_Tools_measure_string(PyObject *SWIGUNUSEDPARM(self), int alloc3 = 0 ; float val4 ; int ecode4 = 0 ; + int val5 ; + int ecode5 = 0 ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; float result; - if (!PyArg_ParseTuple(args,(char *)"OOOO:Tools_measure_string",&obj0,&obj1,&obj2,&obj3)) SWIG_fail; + if (!PyArg_ParseTuple(args,(char *)"OOOO|O:Tools_measure_string",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Tools, 0 | 0 ); if (!SWIG_IsOK(res1)) { SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Tools_measure_string" "', argument " "1"" of type '" "struct Tools *""'"); @@ -21644,7 +21687,14 @@ SWIGINTERN PyObject *_wrap_Tools_measure_string(PyObject *SWIGUNUSEDPARM(self), SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Tools_measure_string" "', argument " "4"" of type '" "float""'"); } arg4 = (float)(val4); - result = (float)Tools_measure_string(arg1,(char const *)arg2,(char const *)arg3,arg4); + if (obj4) { + ecode5 = SWIG_AsVal_int(obj4, &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Tools_measure_string" "', argument " "5"" of type '" "int""'"); + } + arg5 = (int)(val5); + } + result = (float)Tools_measure_string(arg1,(char const *)arg2,(char const *)arg3,arg4,arg5); resultobj = SWIG_From_float((float)(result)); if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); @@ -21942,6 +21992,7 @@ static PyMethodDef SwigMethods[] = { { (char *)"Tools__transform_rect", _wrap_Tools__transform_rect, METH_VARARGS, (char *)"Transform rectangle with matrix."}, { (char *)"Tools__intersect_rect", _wrap_Tools__intersect_rect, METH_VARARGS, (char *)"Intersect two rectangles."}, { (char *)"Tools__include_point_in_rect", _wrap_Tools__include_point_in_rect, METH_VARARGS, (char *)"Include point in a rect."}, + { (char *)"Tools__transform_point", _wrap_Tools__transform_point, METH_VARARGS, (char *)"Transform point with matrix."}, { (char *)"Tools__union_rect", _wrap_Tools__union_rect, METH_VARARGS, (char *)"Replace r1 with smallest rect containing both."}, { (char *)"Tools__concat_matrix", _wrap_Tools__concat_matrix, METH_VARARGS, (char *)"Concatenate matrices m1, m2."}, { (char *)"Tools__invert_matrix", _wrap_Tools__invert_matrix, METH_VARARGS, (char *)"Invert a matrix."}, diff --git a/fitz/helper-geo-py.i b/fitz/helper-geo-py.i index 200f1d2a5..3b6e2c29a 100644 --- a/fitz/helper-geo-py.i +++ b/fitz/helper-geo-py.i @@ -18,8 +18,8 @@ class Matrix(): if len(args) == 1: # either an angle or a sequ if hasattr(args[0], "__float__"): theta = args[0] * math.pi / 180.0 - c = round(math.cos(theta), 10) - s = round(math.sin(theta), 10) + c = math.cos(theta) + s = math.sin(theta) self.a = self.d = c self.b = s self.c = -s @@ -273,9 +273,7 @@ class Point(): """Replace point by its transformation with matrix-like m.""" if len(m) != 6: raise ValueError("bad sequ. length") - x = self.x - self.x = x * m[0] + self.y * m[2] + m[4] - self.y = x * m[1] + self.y * m[3] + m[5] + self.x, self.y = TOOLS._transform_point(self, m) return self @property diff --git a/fitz/helper-python.i b/fitz/helper-python.i index 892dfd609..a97055982 100644 --- a/fitz/helper-python.i +++ b/fitz/helper-python.i @@ -34,6 +34,12 @@ TEXT_PRESERVE_LIGATURES = 1 TEXT_PRESERVE_WHITESPACE = 2 TEXT_PRESERVE_IMAGES = 4 +#------------------------------------------------------------------------------ +# Simple text encoding options +#------------------------------------------------------------------------------ +TEXT_ENCODING_LATIN = 0 +TEXT_ENCODING_GREEK = 1 +TEXT_ENCODING_CYRILLIC = 2 #------------------------------------------------------------------------------ # Stamp annotation icon numbers #------------------------------------------------------------------------------ @@ -79,7 +85,13 @@ Base14_fontdict["tibi"] = "Times-BoldItalic" Base14_fontdict["symb"] = "Symbol" Base14_fontdict["zadb"] = "ZapfDingbats" -def getTextlen(text, fontname="helv", fontsize=12): +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. + """ fontname = fontname.lower() basename = Base14_fontdict.get(fontname, None) @@ -89,11 +101,11 @@ def getTextlen(text, fontname="helv", fontsize=12): if basename == "ZapfDingbats": glyphs = zapf_glyphs if glyphs is not None: - w = sum([glyphs[ord(c)][1] for c in text if ord(c) < 256]) + w = sum([glyphs[ord(c)][1] if ord(c)<256 else glyphs[183][1] for c in text]) return w * fontsize if fontname in Base14_fontdict.keys(): - return TOOLS.measure_string(text, Base14_fontdict[fontname], fontsize) + return TOOLS.measure_string(text, Base14_fontdict[fontname], fontsize, encoding) if fontname in ["china-t", "china-s", "china-ts", "china-ss", @@ -108,12 +120,12 @@ def getTextlen(text, fontname="helv", fontsize=12): # Glyph list for the built-in font 'ZapfDingbats' #------------------------------------------------------------------------------ zapf_glyphs = ( - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (33, 0.974), (34, 0.961), (35, 0.974), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (32, 0.278), (33, 0.974), (34, 0.961), (35, 0.974), (36, 0.98), (37, 0.719), (38, 0.789), (39, 0.79), (40, 0.791), (41, 0.69), (42, 0.96), (43, 0.939), (44, 0.549), (45, 0.855), (46, 0.911), (47, 0.933), (48, 0.911), (49, 0.945), (50, 0.974), (51, 0.755), (52, 0.846), (53, 0.762), @@ -130,12 +142,12 @@ zapf_glyphs = ( (112, 0.762), (113, 0.759), (114, 0.759), (115, 0.892), (116, 0.892), (117, 0.788), (118, 0.784), (119, 0.438), (120, 0.138), (121, 0.277), (122, 0.415), (123, 0.392), (124, 0.392), (125, 0.668), (126, 0.668), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), - (32, 0.278), (32, 0.278), (32, 0.278), (32, 0.278), (161, 0.732), (162, 0.544), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), + (183, 0.788), (183, 0.788), (183, 0.788), (183, 0.788), (161, 0.732), (162, 0.544), (163, 0.544), (164, 0.91), (165, 0.667), (166, 0.76), (167, 0.76), (168, 0.776), (169, 0.595), (170, 0.694), (171, 0.626), (172, 0.788), (173, 0.788), (174, 0.788), (175, 0.788), (176, 0.788), (177, 0.788), @@ -151,23 +163,23 @@ zapf_glyphs = ( (223, 0.834), (224, 0.873), (225, 0.828), (226, 0.924), (227, 0.924), (228, 0.917), (229, 0.93), (230, 0.931), (231, 0.463), (232, 0.883), (233, 0.836), (234, 0.836), (235, 0.867), (236, 0.867), (237, 0.696), - (238, 0.696), (239, 0.874), (32, 0.278), (241, 0.874), (242, 0.76), + (238, 0.696), (239, 0.874), (183, 0.788), (241, 0.874), (242, 0.76), (243, 0.946), (244, 0.771), (245, 0.865), (246, 0.771), (247, 0.888), (248, 0.967), (249, 0.888), (250, 0.831), (251, 0.873), (252, 0.927), - (253, 0.97), (32, 0.278), (32, 0.278) + (253, 0.97), (183, 0.788), (183, 0.788) ) #------------------------------------------------------------------------------ # Glyph list for the built-in font 'Symbol' #------------------------------------------------------------------------------ symbol_glyphs = ( - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (32, 0.25), (33, 0.333), (34, 0.713), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (32, 0.25), (33, 0.333), (34, 0.713), (35, 0.5), (36, 0.549), (37, 0.833), (38, 0.778), (39, 0.439), (40, 0.333), (41, 0.333), (42, 0.5), (43, 0.549), (44, 0.25), (45, 0.549), (46, 0.25), (47, 0.278), (48, 0.5), (49, 0.5), (50, 0.5), (51, 0.5), @@ -185,14 +197,14 @@ symbol_glyphs = ( (109, 0.576), (110, 0.521), (111, 0.549), (112, 0.549), (113, 0.521), (114, 0.549), (115, 0.603), (116, 0.439), (117, 0.576), (118, 0.713), (119, 0.686), (120, 0.493), (121, 0.686), (122, 0.494), (123, 0.48), - (124, 0.2), (125, 0.48), (126, 0.549), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), (63, 0.444), - (63, 0.444), (160, 0.25), (161, 0.62), (162, 0.247), (163, 0.549), + (124, 0.2), (125, 0.48), (126, 0.549), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), (183, 0.46), + (183, 0.46), (160, 0.25), (161, 0.62), (162, 0.247), (163, 0.549), (164, 0.167), (165, 0.713), (166, 0.5), (167, 0.753), (168, 0.753), (169, 0.753), (170, 0.753), (171, 1.042), (172, 0.713), (173, 0.603), (174, 0.987), (175, 0.603), (176, 0.4), (177, 0.549), (178, 0.411), @@ -208,10 +220,10 @@ symbol_glyphs = ( (224, 0.494), (225, 0.329), (226, 0.79), (227, 0.79), (228, 0.786), (229, 0.713), (230, 0.384), (231, 0.384), (232, 0.384), (233, 0.384), (234, 0.384), (235, 0.384), (236, 0.494), (237, 0.494), (238, 0.494), - (239, 0.494), (63, 0.444), (241, 0.329), (242, 0.274), (243, 0.686), + (239, 0.494), (183, 0.46), (241, 0.329), (242, 0.274), (243, 0.686), (244, 0.686), (245, 0.686), (246, 0.384), (247, 0.549), (248, 0.384), (249, 0.384), (250, 0.384), (251, 0.384), (252, 0.494), (253, 0.494), - (254, 0.494), (63, 0.444) + (254, 0.494), (183, 0.46) ) class linkDest(): @@ -350,9 +362,9 @@ def getTJstr(text, glyphs, simple, ordering): if simple: if glyphs is None: # simple and not Symbol / ZapfDingbats - otxt = "".join([hex(ord(c))[2:].rjust(2, "0") if ord(c)<256 else "3f" for c in text]) + otxt = "".join([hex(ord(c))[2:].rjust(2, "0") if ord(c)<256 else "b7" for c in text]) else: # Symbol or ZapfDingbats - otxt = "".join([hex(glyphs[ord(c)][0])[2:].rjust(2, "0") if ord(c)<256 else "20" for c in text]) + otxt = "".join([hex(glyphs[ord(c)][0])[2:].rjust(2, "0") if ord(c)<256 else "b7" for c in text]) return "[<" + otxt + ">]" if ordering < 0: # not a CJK font: use the glyphs diff --git a/fitz/utils.py b/fitz/utils.py index 8d1229899..3b7c6114e 100644 --- a/fitz/utils.py +++ b/fitz/utils.py @@ -747,16 +747,17 @@ def insertLink(page, lnk, mark = True): # Page.insertTextbox #------------------------------------------------------------------------------- def insertTextbox(page, rect, buffer, - fontname = "helv", - fontfile = None, - set_simple = 0, - fontsize = 11, - color = (0,0,0), - expandtabs = 1, - align = 0, - rotate = 0, - morph = None, - overlay = True): + fontname="helv", + fontfile=None, + set_simple=0, + encoding=0, + fontsize=11, + color=(0,0,0), + expandtabs=1, + align=0, + rotate=0, + morph=None, + overlay=True): """Insert text into a given rectangle. Parameters: rect - the textbox to fill @@ -774,15 +775,16 @@ def insertTextbox(page, rect, buffer, """ img = page.newShape() rc = img.insertTextbox(rect, buffer, - fontsize = fontsize, - fontname = fontname, - fontfile = fontfile, - set_simple = set_simple, - color = color, - expandtabs = expandtabs, - align = align, - rotate = rotate, - morph = morph) + fontsize=fontsize, + fontname=fontname, + fontfile=fontfile, + set_simple=set_simple, + encoding=encoding, + color=color, + expandtabs=expandtabs, + align=align, + rotate=rotate, + morph=morph) if rc >= 0: img.commit(overlay) return rc @@ -791,24 +793,26 @@ def insertTextbox(page, rect, buffer, # Page.insertText #------------------------------------------------------------------------------ def insertText(page, point, text, - fontsize = 11, - fontname = "helv", - fontfile = None, - set_simple = 0, - color = (0,0,0), - rotate = 0, - morph = None, - overlay = True): + fontsize=11, + fontname="helv", + fontfile=None, + set_simple=0, + encoding=0, + color=(0,0,0), + rotate=0, + morph=None, + overlay=True): img = page.newShape() rc = img.insertText(point, text, - fontsize = fontsize, - fontname = fontname, - fontfile = fontfile, - set_simple = set_simple, - color = color, - rotate = rotate, - morph = morph) + fontsize=fontsize, + fontname=fontname, + fontfile=fontfile, + set_simple=set_simple, + encoding=encoding, + color=color, + rotate=rotate, + morph=morph) if rc >= 0: img.commit(overlay) return rc @@ -1774,11 +1778,11 @@ def drawLine(self, p1, p2): p1 = Point(p1) p2 = Point(p2) if not (self.lastPoint == p1): - self.draw_cont += "%g %g m\n" % tuple(p1 * self.ipctm) + self.draw_cont += "%f %f m\n" % tuple(p1 * self.ipctm) self.lastPoint = p1 self.updateRect(p1) - self.draw_cont += "%g %g l\n" % tuple(p2 * self.ipctm) + self.draw_cont += "%f %f l\n" % tuple(p2 * self.ipctm) self.updateRect(p2) self.lastPoint = p2 return self.lastPoint @@ -1789,10 +1793,10 @@ def drawPolyline(self, points): for i, p in enumerate(points): if i == 0: if not (self.lastPoint == Point(p)): - self.draw_cont += "%g %g m\n" % tuple(Point(p) * self.ipctm) + self.draw_cont += "%f %f m\n" % tuple(Point(p) * self.ipctm) self.lastPoint = Point(p) else: - self.draw_cont += "%g %g l\n" % tuple(Point(p) * self.ipctm) + self.draw_cont += "%f %f l\n" % tuple(Point(p) * self.ipctm) self.updateRect(p) self.lastPoint = Point(points[-1]) @@ -1806,8 +1810,8 @@ def drawBezier(self, p1, p2, p3, p4): p3 = Point(p3) p4 = Point(p4) if not (self.lastPoint == p1): - self.draw_cont += "%g %g m\n" % tuple(p1 * self.ipctm) - self.draw_cont += "%g %g %g %g %g %g c\n" % tuple(list(p2 * self.ipctm) + \ + self.draw_cont += "%f %f m\n" % tuple(p1 * self.ipctm) + self.draw_cont += "%f %f %f %f %f %f c\n" % tuple(list(p2 * self.ipctm) + \ list(p3 * self.ipctm) + \ list(p4 * self.ipctm)) self.updateRect(p1) @@ -1832,7 +1836,7 @@ def drawOval(self, tetra): mb = q.ll + (q.lr - q.ll) * 0.5 ml = q.ul + (q.ll - q.ul) * 0.5 if not (self.lastPoint == ml): - self.draw_cont += "%g %g m\n" % tuple(ml * self.ipctm) + self.draw_cont += "%f %f m\n" % tuple(ml * self.ipctm) self.lastPoint = ml self.drawCurve(ml, q.ll, mb) self.drawCurve(mb, q.lr, mr) @@ -1845,7 +1849,8 @@ def drawOval(self, tetra): def drawCircle(self, center, radius): """Draw a circle given its center and radius. """ - assert radius > 1e-5, "radius must be postive" + if not radius > 1e-5: + raise ValueError("radius must be postive") center = Point(center) p1 = center - (radius, 0) return self.drawSector(center, p1, 360, fullSector = False) @@ -1866,10 +1871,9 @@ def drawSector(self, center, point, beta, fullSector = True): """ center = Point(center) point = Point(point) - h = self.height - l3 = "%g %g m\n" - l4 = "%g %g %g %g %g %g c\n" - l5 = "%g %g l\n" + l3 = "%f %f m\n" + l4 = "%f %f %f %f %f %f c\n" + l5 = "%f %f l\n" betar = math.radians(-beta) w360 = math.radians(math.copysign(360, betar)) * (-1) w90 = math.radians(math.copysign(90, betar)) @@ -1935,7 +1939,7 @@ def drawRect(self, rect): """Draw a rectangle. """ r = Rect(rect) - self.draw_cont += "%g %g %g %g re\n" % tuple(list(r.bl * self.ipctm) + \ + self.draw_cont += "%f %f %f %f re\n" % tuple(list(r.bl * self.ipctm) + \ [r.width, r.height]) self.updateRect(r) self.lastPoint = r.tl @@ -2009,13 +2013,14 @@ def drawSquiggle(self, p1, p2, breadth = 2): # Shape.insertText #============================================================================== def insertText(self, point, buffer, - fontsize = 11, - fontname = "helv", - fontfile = None, - set_simple = 0, - color = (0,0,0), - rotate = 0, - morph = None): + fontsize=11, + fontname="helv", + fontfile=None, + set_simple=0, + encoding=0, + color=(0,0,0), + rotate=0, + morph=None): # ensure 'text' is a list of strings, worth dealing with if not bool(buffer): return 0 @@ -2039,8 +2044,11 @@ def insertText(self, point, buffer, if fname.startswith("/"): fname = fname[1:] - xref = self.page.insertFont(fontname = fname, fontfile = fontfile, - set_simple = set_simple) + xref = self.page.insertFont(fontname=fname, + fontfile=fontfile, + encoding=encoding, + set_simple=set_simple, + ) fontinfo = CheckFontInfo(self.doc, xref) fontdict = fontinfo[1] @@ -2065,7 +2073,7 @@ def insertText(self, point, buffer, while rot < 0: rot += 360 rot = rot % 360 # text rotate = 0, 90, 270, 180 red, green, blue = color if color else (0,0,0) - templ1 = "\nq BT\n%s1 0 0 1 %g %g Tm /%s %g Tf %g %g %g rg " + templ1 = "\nq BT\n%s1 0 0 1 %f %f Tm /%s %g Tf %g %g %g rg " templ2 = "TJ\n0 -%g TD\n" cmp90 = "0 1 -1 0 0 0 cm\n" # rotates 90 deg counter-clockwise cmm90 = "0 -1 1 0 0 0 cm\n" # rotates 90 deg clockwise @@ -2079,7 +2087,7 @@ def insertText(self, point, buffer, m1 = Matrix(1, 0, 0, 1, morph[0].x + self.x, height - morph[0].y - self.y) mat = ~m1 * morph[1] * m1 - cm = "%g %g %g %g %g %g cm\n" % tuple(map(lambda x: round(x, 5), mat)) + cm = "%f %f %f %f %f %f cm\n" % tuple(mat) else: cm = "" top = height - point.y - self.y # start of 1st char @@ -2139,10 +2147,17 @@ def insertText(self, point, buffer, #============================================================================== # Shape.insertTextbox #============================================================================== - def insertTextbox(self, rect, buffer, fontname = "helv", fontfile = None, - fontsize = 11, set_simple = 0, - color = (0,0,0), expandtabs = 1, - align = 0, rotate = 0, morph = None): + def insertTextbox(self, rect, buffer, + fontname="helv", + fontfile=None, + fontsize=11, + set_simple=0, + encoding=0, + color=(0,0,0), + expandtabs=1, + align=0, + rotate=0, + morph=None): """Insert text into a given rectangle. Arguments: rect - the textbox to fill buffer - text to be inserted @@ -2179,8 +2194,11 @@ def insertTextbox(self, rect, buffer, fontname = "helv", fontfile = None, if fname.startswith("/"): fname = fname[1:] - xref = self.page.insertFont(fontname = fname, fontfile = fontfile, - set_simple = set_simple) + xref = self.page.insertFont(fontname=fname, + fontfile=fontfile, + encoding=encoding, + set_simple=set_simple, + ) fontinfo = CheckFontInfo(self.doc, xref) fontdict = fontinfo[1] @@ -2231,7 +2249,7 @@ def pixlen(x): m1 = Matrix(1, 0, 0, 1, morph[0].x + self.x, self.height - morph[0].y - self.y) mat = ~m1 * morph[1] * m1 - cm = "%g %g %g %g %g %g cm\n" % tuple(map(lambda x: round(x, 5), mat)) + cm = "%f %f %f %f %f %f cm\n" % tuple(mat) else: cm = "" @@ -2331,7 +2349,7 @@ def pixlen(x): if more < 1e-5: more = 0 # don't bother with epsilons nres = "\nq BT\n" + cm # initialize output buffer - templ = "1 0 0 1 %g %g Tm /%s %g Tf %g Tw %g %g %g rg %sTJ\n" + templ = "1 0 0 1 %f %f Tm /%s %g Tf %g Tw %g %g %g rg %sTJ\n" # center, right, justify: output each line with its own specifics spacing = 0 text_t = text.splitlines() # split text in lines again @@ -2414,7 +2432,7 @@ def finish(self, width = 1, m1 = Matrix(1, 0, 0, 1, morph[0].x + self.x, self.height - morph[0].y - self.y) mat = ~m1 * morph[1] * m1 - self.draw_cont = "%g %g %g %g %g %g cm\n" % tuple(map(lambda x: round(x, 5), mat)) + self.draw_cont + self.draw_cont = "%f %f %f %f %f %f cm\n" % tuple(mat) + self.draw_cont self.totalcont += "\nq\n" + self.draw_cont + "Q\n" self.draw_cont = "" diff --git a/fitz/version.i b/fitz/version.i index f8ba79e14..b5e1bcf0c 100644 --- a/fitz/version.i +++ b/fitz/version.i @@ -1,6 +1,6 @@ %pythoncode %{ VersionFitz = "1.14.0" -VersionBind = "1.14.6" -VersionDate = "2019-01-16 04:32:29" -version = (VersionBind, VersionFitz, "20190116043229") +VersionBind = "1.14.7" +VersionDate = "2019-01-17 16:53:54" +version = (VersionBind, VersionFitz, "20190117165354") %} \ No newline at end of file diff --git a/nano_setup.py b/nano_setup.py index fa1cf58e3..98edfbab3 100644 --- a/nano_setup.py +++ b/nano_setup.py @@ -52,7 +52,7 @@ sources=['./fitz/fitz_wrap.c',]) setup(name = 'PyMuPDF', - version = "1.14.3", + version = "1.14.7", description = 'Python bindings for the PDF rendering library MuPDF', classifiers = ['Development Status :: 5 - Production/Stable', 'Environment :: Console', diff --git a/setup.py b/setup.py index 10c70f191..86b9e5c88 100644 --- a/setup.py +++ b/setup.py @@ -13,15 +13,15 @@ #library_dirs=[''], libraries=[ 'mupdf', + #'crypto', #openssl is required by mupdf on archlinux + #'jbig2dec', 'openjp2', 'jpeg', 'freetype', 'mupdf-third', - # 'jbig2dec', 'openjp2', 'jpeg', 'freetype', - # 'crypto', #openssl is required by mupdf on archlinux ], # the libraries to link with ) elif sys.platform.startswith(('darwin', 'freebsd')): module = Extension('fitz._fitz', # name of the module ['fitz/fitz_wrap.c'], # C source file - # this are directories containing mupdf's and zlib's header files + # directories containing mupdf's and zlib's header files include_dirs=['/usr/local/include/mupdf', '/usr/local/include'], # libraries should already be linked here by brew library_dirs=['/usr/local/lib'], @@ -36,8 +36,7 @@ else: #=============================================================================== -# This will build / set up PyMuPDF under Windows. -# For details consult the documentation. +# Build / set up PyMuPDF under Windows #=============================================================================== module = Extension('fitz._fitz', include_dirs=[ # we need the path of the MuPDF's headers @@ -68,7 +67,7 @@ long_desc = "\n".join(long_dtab) setup(name = 'PyMuPDF', - version = "1.14.6", + version = "1.14.7", description = 'Python bindings for the PDF rendering library MuPDF', long_description = long_desc, classifiers = classifier,