diff --git a/README.md b/README.md index afbbea0fc..6e5951c7e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# PyMuPDF 1.14.5 +# PyMuPDF 1.14.6 ![logo](https://github.com/rk700/PyMuPDF/blob/master/demo/pymupdf.jpg) -Release date: January 5, 2018 +Release date: January 15, 2018 **Travis-CI:** [![Build Status](https://travis-ci.org/JorjMcKie/py-mupdf.svg?branch=master)](https://travis-ci.org/JorjMcKie/py-mupdf) @@ -14,7 +14,7 @@ On **[PyPI](https://pypi.org/project/PyMuPDF)** since August 2016: [![](https:// # Introduction -This is **version 1.14.5 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.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". 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. @@ -69,11 +69,11 @@ Other features include embedding vector images (SVG, PDF) such as logos or water You can now also create and update Form PDFs and form fields with support for text, checkbox, listbox and combobox widgets. -To some degree, PyMuPDF can also be used as an [image converter](https://github.com/rk700/PyMuPDF/wiki/How-to-Convert-Images): it supports a broad range of input formats and can produce **PNG**, **Portable Anymap** (PNM, etc.), **Adobe Postscript** and **Adobe Photoshop** documents, making the use of other graphics packages obselete in many cases. Interfacing with PIL/Pillow is easily possible as well. +To some degree, PyMuPDF can also be used as an [image converter](https://github.com/rk700/PyMuPDF/wiki/How-to-Convert-Images): it can read a broad range of input formats and can produce **Portable Network Graphics (PNG)**, **Portable Anymaps** (PNM, etc.), **Portable Arbitrary Maps (PAM)**, **Targa Image Files (TGA)**, **Adobe Postscript** and **Adobe Photoshop** documents, making the use of other graphics packages obselete in many cases. Interfacing with PIL/Pillow is easy as well. Have a look at the basic [demos](https://github.com/rk700/PyMuPDF/tree/master/demo), the [examples](https://github.com/rk700/PyMuPDF/tree/master/examples) (which contain complete, working programs), and the **recipes** section of our [Wiki](https://github.com/rk700/PyMuPDF/wiki) sidebar, which contains more than a dozen of guides in How-To-style. -Our documentation, written using Sphinx, is available in various formats from the following sources. It currently is a combination of a reference guide and a user manual. For a quick start to using PyMuPDF look at the [tutorial](https://pymupdf.readthedocs.io/en/latest/tutorial/) and the [recipes](https://pymupdf.readthedocs.io/en/latest/faq/) chapters. +Our **documentation**, written using Sphinx, is available in various formats from the following sources. It currently is a combination of a reference guide and a user manual. For a quick start to using PyMuPDF look at the [tutorial](https://pymupdf.readthedocs.io/en/latest/tutorial/) and the [recipes](https://pymupdf.readthedocs.io/en/latest/faq/) chapters. * You can view it online at [Read the Docs](https://pymupdf.readthedocs.io/). For **best quality downloads** use the following links. * zipped [HTML](https://github.com/rk700/PyMuPDF/tree/master/doc/html.zip) diff --git a/fitz/__init__.py b/fitz/__init__.py index 557a6b5cf..16c44f83c 100644 --- a/fitz/__init__.py +++ b/fitz/__init__.py @@ -1,9 +1,5 @@ from __future__ import absolute_import from fitz.fitz import * -try: - from fitz import _fitz -except: - pass # define the supported colorspaces for convenience fitz.csRGB = fitz.Colorspace(fitz.CS_RGB) diff --git a/fitz/fitz.i b/fitz/fitz.i index c576745e4..d1678acb4 100644 --- a/fitz/fitz.i +++ b/fitz/fitz.i @@ -134,12 +134,12 @@ char *JM_Python_str_AsChar(PyObject *str); // START redirect stdout/stderr //----------------------------------------------------------------------------- -JM_fitz_stdout = fz_new_output(gctx, 0, JM_fitz_stdout, JM_write_stdout, NULL, NULL); - +JM_output_log = PyByteArray_FromStringAndSize("", 0); +fz_output *JM_fitz_stdout = JM_OutFromBarray(gctx, JM_output_log); fz_set_stdout(gctx, JM_fitz_stdout); -JM_fitz_stderr = fz_new_output(gctx, 0, JM_fitz_stderr, JM_write_stderr, NULL, NULL); - +JM_error_log = PyByteArray_FromStringAndSize("", 0); +fz_output *JM_fitz_stderr = JM_OutFromBarray(gctx, JM_error_log); fz_set_stderr(gctx, JM_fitz_stderr); if (JM_fitz_stderr && JM_fitz_stdout) @@ -147,9 +147,6 @@ if (JM_fitz_stderr && JM_fitz_stdout) else PySys_WriteStderr("error redirecting stdout/stderr!\n"); -JM_error_log = PyByteArray_FromStringAndSize("", 0); -JM_output_log = PyByteArray_FromStringAndSize("", 0); - //----------------------------------------------------------------------------- // STOP redirect stdout/stderr //----------------------------------------------------------------------------- @@ -182,6 +179,7 @@ fitz_py2 = str is bytes # if true, this is Python 2 %include version.i %include helper-geo-c.i %include helper-other.i +%include helper-out-barray.i %include helper-write-c.i %include helper-geo-py.i %include helper-annot.i @@ -957,9 +955,9 @@ struct fz_document_s PyObject *write(int garbage=0, int clean=0, int deflate=0, int ascii=0, int expand=0, int linear=0, int pretty = 0, int decrypt = 1) { - PyObject *r; - struct fz_buffer_s *res = NULL; + PyObject *r = NULL; fz_output *out = NULL; + fz_buffer *res = NULL; int errors = 0; pdf_write_options opts = { 0 }; opts.do_incremental = 0; @@ -977,25 +975,28 @@ struct fz_document_s opts.errors = &errors; pdf_document *pdf = pdf_specifics(gctx, $self); fz_var(out); - fz_var(res); + fz_var(r); fz_try(gctx) { assert_PDF(pdf); if (fz_count_pages(gctx, $self) < 1) THROWMSG("cannot save with zero pages"); JM_embedded_clean(gctx, pdf); - res = fz_new_buffer(gctx, 1024); + res = fz_new_buffer(gctx, 8192); out = fz_new_output_with_buffer(gctx, res); JM_write_document(gctx, pdf, out, &opts, decrypt); - pdf->dirty = 0; r = JM_BinFromBuffer(gctx, res); + pdf->dirty = 0; } fz_always(gctx) + { + fz_drop_buffer(gctx, res); + fz_drop_output(gctx, out); + } + fz_catch(gctx) { - fz_drop_output(gctx, out); - fz_drop_buffer(gctx, res); + return NULL; } - fz_catch(gctx) return NULL; return r; } @@ -3786,52 +3787,6 @@ struct fz_pixmap_s return NONE; } - //---------------------------------------------------------------------- - // get length of one image row - //---------------------------------------------------------------------- - %pythoncode %{@property%} - int stride() - { - return fz_pixmap_stride(gctx, $self); - } - - //---------------------------------------------------------------------- - // check alpha channel - //---------------------------------------------------------------------- - %pythoncode %{@property%} - int alpha() - { - return $self->alpha; - } - - //---------------------------------------------------------------------- - // get colorspace of pixmap - //---------------------------------------------------------------------- - %pythoncode %{@property%} - struct fz_colorspace_s *colorspace() - { - return fz_pixmap_colorspace(gctx, $self); - } - - //---------------------------------------------------------------------- - // return irect of pixmap - //---------------------------------------------------------------------- - %pythoncode %{@property%} - %pythonappend irect %{val = IRect(val)%} - PyObject *irect() - { - return JM_py_from_irect(fz_pixmap_bbox(gctx, $self)); - } - - //---------------------------------------------------------------------- - // return size of pixmap - //---------------------------------------------------------------------- - %pythoncode %{@property%} - int size() - { - return (int) fz_pixmap_size(gctx, $self); - } - //---------------------------------------------------------------------- // set alpha values //---------------------------------------------------------------------- @@ -3870,15 +3825,18 @@ struct fz_pixmap_s // Pixmap._getImageData //---------------------------------------------------------------------- FITZEXCEPTION(_getImageData, !result) - PyObject *_getImageData(int format, int savealpha=-1) + PyObject *_getImageData(int format) { - struct fz_buffer_s *res = NULL; fz_output *out = NULL; - PyObject *r; - if (savealpha != -1) JM_Warning("ignoring savealpha"); - fz_try(gctx) { - res = fz_new_buffer(gctx, 1024); + fz_buffer *res = NULL; + // the following will be returned: + PyObject *barray = NULL; + fz_try(gctx) + { + size_t size = fz_pixmap_stride(gctx, $self) * $self->h; + res = fz_new_buffer(gctx, size); out = fz_new_output_with_buffer(gctx, res); + out->seek = JM_SeekDummy; // ignore seek calls switch(format) { case(1): @@ -3893,34 +3851,47 @@ struct fz_pixmap_s case(4): fz_write_pixmap_as_tga(gctx, out, $self); break; - case(5): + case(5): // Adobe Photoshop Document fz_write_pixmap_as_psd(gctx, out, $self); break; + case(6): // Postscript format + fz_write_pixmap_as_ps(gctx, out, $self); + break; default: fz_write_pixmap_as_png(gctx, out, $self); break; } - r = JM_BinFromBuffer(gctx, res); + barray = JM_BinFromBuffer(gctx, res); } fz_always(gctx) { fz_drop_output(gctx, out); fz_drop_buffer(gctx, res); } - fz_catch(gctx) return NULL; - return r; + + fz_catch(gctx) + { + return NULL; + } + return barray; } %pythoncode %{ def getImageData(self, output="png"): - valid_formats = {"png": 1, "pnm": 2, "pgm": 2, "ppm": 2, "pbm": 2, - "pam": 3, "tga": 4, "psd": 5} + valid_formats = {"png": 1, "pnm": 2, "pgm": 2, "ppm": 2, "pbm": 2, + "pam": 3, "tga": 4, "tpic": 4, + "psd": 5, "ps": 6} idx = valid_formats.get(output.lower(), 1) + if self.alpha and idx in (2, 6): + raise ValueError("'%s' cannot have alpha" % output) + if self.colorspace and self.colorspace.n > 3 and idx in (1, 2, 4): + raise ValueError("unsupported colorspace for '%s'" % output) return self._getImageData(idx) def getPNGdata(self): return self._getImageData(1) -def getPNGData(self, savealpha=-1): + +def getPNGData(self): return self._getImageData(1) %} @@ -3928,9 +3899,8 @@ def getPNGData(self, savealpha=-1): // _writeIMG //---------------------------------------------------------------------- FITZEXCEPTION(_writeIMG, !result) - PyObject *_writeIMG(char *filename, int format, int savealpha=-1) + PyObject *_writeIMG(char *filename, int format) { - if (savealpha != -1) JM_Warning("ignoring savealpha"); fz_try(gctx) { switch(format) { @@ -3946,9 +3916,12 @@ def getPNGData(self, savealpha=-1): case(4): fz_save_pixmap_as_tga(gctx, $self, filename); break; - case(5): + case(5): // Adobe Photoshop Document fz_save_pixmap_as_psd(gctx, $self, filename); break; + case(6): // Postscript + fz_save_pixmap_as_ps(gctx, $self, filename, 0); + break; default: fz_save_pixmap_as_png(gctx, $self, filename); break; @@ -3958,14 +3931,26 @@ def getPNGData(self, savealpha=-1): return NONE; } %pythoncode %{ -def writeImage(self, filename, output="png"): - valid_formats = {"png": 1, "pnm": 2, "pgm": 2, "ppm": 2, "pbm": 2, - "pam": 3, "tga": 4, "psd": 5} +def writeImage(self, filename, output=None): + valid_formats = {"png": 1, "pnm": 2, "pgm": 2, "ppm": 2, "pbm": 2, + "pam": 3, "tga": 4, "tpic": 4, + "psd": 5, "ps": 6} + if output is None: + _, ext = os.path.splitext(filename) + output = ext[1:] + idx = valid_formats.get(output.lower(), 1) + + if self.alpha and idx in (2, 6): + raise ValueError("'%s' cannot have alpha" % output) + if self.colorspace and self.colorspace.n > 3 and idx in (1, 2, 4): + raise ValueError("unsupported colorspace for '%s'" % output) + return self._writeIMG(filename, idx) def writePNG(self, filename, savealpha = -1): - return self._writeIMG(filename, 1, savealpha) + return self._writeIMG(filename, 1) + %} //---------------------------------------------------------------------- // invertIRect @@ -3985,6 +3970,114 @@ def writePNG(self, filename, savealpha = -1): fz_invert_pixmap(gctx, $self); } + //---------------------------------------------------------------------- + // get one pixel as a list + //---------------------------------------------------------------------- + FITZEXCEPTION(pixel, !result) + %feature("autodoc","Return the pixel at (x,y) as a list. Last item is the alpha if Pixmap.alpha is true.") pixel; + PyObject *pixel(int x, int y) + { + PyObject *p = NULL; + fz_try(gctx) + { + if (!INRANGE(x, 0, $self->w - 1) || !INRANGE(y, 0, $self->h - 1)) + THROWMSG("coordinates outside image"); + int n = $self->n; + int stride = fz_pixmap_stride(gctx, $self); + int j, i = stride * y + n * x; + p = PyList_New(n); + for (j=0; j < n; j++) + { + PyList_SetItem(p, j, Py_BuildValue("i", $self->samples[i + j])); + } + } + fz_catch(gctx) return NULL; + return p; + } + + //---------------------------------------------------------------------- + // Set one pixel given as a sequence + //---------------------------------------------------------------------- + FITZEXCEPTION(setPixel, !result) + %feature("autodoc","Set the pixel at (x,y) to the integers in sequence 'value'.") setPixel; + PyObject *setPixel(int x, int y, PyObject *value) + { + fz_try(gctx) + { + if (!INRANGE(x, 0, $self->w - 1) || !INRANGE(y, 0, $self->h - 1)) + THROWMSG("coordinates outside image"); + int n = $self->n; + if (!PySequence_Check(value) || PySequence_Size(value) != n) + THROWMSG("bad pixel value"); + int i, j; + unsigned char c[5]; + for (j = 0; j < n; j++) + { + i = (int) PyInt_AsLong(PySequence_ITEM(value, j)); + if (!INRANGE(i, 0, 255)) THROWMSG("bad pixel component"); + c[j] = (unsigned char) i; + } + int stride = fz_pixmap_stride(gctx, $self); + i = stride * y + n * x; + for (j = 0; j < n; j++) + { + $self->samples[i + j] = c[j]; + } + } + fz_catch(gctx) + { + PyErr_Clear(); + return NULL; + } + return NONE; + } + + //---------------------------------------------------------------------- + // get length of one image row + //---------------------------------------------------------------------- + %pythoncode %{@property%} + int stride() + { + return fz_pixmap_stride(gctx, $self); + } + + //---------------------------------------------------------------------- + // check alpha channel + //---------------------------------------------------------------------- + %pythoncode %{@property%} + int alpha() + { + return $self->alpha; + } + + //---------------------------------------------------------------------- + // get colorspace of pixmap + //---------------------------------------------------------------------- + %pythoncode %{@property%} + struct fz_colorspace_s *colorspace() + { + return fz_pixmap_colorspace(gctx, $self); + } + + //---------------------------------------------------------------------- + // return irect of pixmap + //---------------------------------------------------------------------- + %pythoncode %{@property%} + %pythonappend irect %{val = IRect(val)%} + PyObject *irect() + { + return JM_py_from_irect(fz_pixmap_bbox(gctx, $self)); + } + + //---------------------------------------------------------------------- + // return size of pixmap + //---------------------------------------------------------------------- + %pythoncode %{@property%} + int size() + { + return (int) fz_pixmap_size(gctx, $self); + } + //---------------------------------------------------------------------- // samples //---------------------------------------------------------------------- @@ -3993,19 +4086,11 @@ def writePNG(self, filename, savealpha = -1): { return PyBytes_FromStringAndSize((const char *)$self->samples, (Py_ssize_t) ($self->w)*($self->h)*($self->n)); } + %pythoncode %{ width = w height = h - def pixel(self, x, y): - """Return a tuple representing one pixel. Item values are integers in range - 0 to 255. Last item is the alpha value if Pixmap.alpha is true. - """ - if x not in range(self.width) or y not in range(self.height): - raise IndexError("coordinates outside image") - i = self.stride * y + self.n * x - return tuple(self.samples[i: i + self.n]) - def __len__(self): return self.size @@ -4478,27 +4563,32 @@ struct fz_annot_s // transformed with the page transformation matrix. //---------------------------------------------------------------- o = pdf_dict_get(gctx, annot->obj, PDF_NAME(Vertices)); - if (!o) o = pdf_dict_get(gctx, annot->obj, PDF_NAME(L)); - if (!o) o = pdf_dict_get(gctx, annot->obj, PDF_NAME(QuadPoints)); - if (!o) o = pdf_dict_gets(gctx, annot->obj, "CL"); - if (!o) o = pdf_dict_get(gctx, annot->obj, PDF_NAME(InkList)); - - if (o) // anything found yet? - { - int i, j, n; - fz_point point; // point object to work with - fz_matrix page_ctm; // page transformation matrix - pdf_page_transform(gctx, annot->page, NULL, &page_ctm); - res = PyList_New(0); // create Python list - n = pdf_array_len(gctx, o); - for (i = 0; i < n; i += 2) - { - point.x = pdf_to_real(gctx, pdf_array_get(gctx, o, i)); - point.y = pdf_to_real(gctx, pdf_array_get(gctx, o, i+1)); - point = fz_transform_point(point, page_ctm); - PyList_Append(res, Py_BuildValue("ff", point.x, point.y)); - } + if (o) goto weiter; + o = pdf_dict_get(gctx, annot->obj, PDF_NAME(L)); + if (o) goto weiter; + o = pdf_dict_get(gctx, annot->obj, PDF_NAME(QuadPoints)); + if (o) goto weiter; + o = pdf_dict_gets(gctx, annot->obj, "CL"); + if (o) goto weiter; + o = pdf_dict_get(gctx, annot->obj, PDF_NAME(InkList)); + if (o) goto weiter; + return res; + + weiter:; + int i, n; + fz_point point; // point object to work with + fz_matrix page_ctm; // page transformation matrix + pdf_page_transform(gctx, annot->page, NULL, &page_ctm); + res = PyList_New(0); // create Python list + n = pdf_array_len(gctx, o); + for (i = 0; i < n; i += 2) + { + point.x = pdf_to_real(gctx, pdf_array_get(gctx, o, i)); + point.y = pdf_to_real(gctx, pdf_array_get(gctx, o, i+1)); + point = fz_transform_point(point, page_ctm); + PyList_Append(res, Py_BuildValue("ff", point.x, point.y)); } + return res; } @@ -4583,11 +4673,14 @@ struct fz_annot_s ap_tab = ap.splitlines() # split AP stream into lines idx_BT = ap_tab.index(b"BT") # line no. of text start - # to avoid effort, we rely on a fixed format of this - # annot type: line 0 = fill color, line 5 border color, etc. + # to avoid effort, we rely on a fixed format generated by MuPDF for + # this annot type: line 0 = fill color, line 5 border color, etc. if fill_color is not None: ap_tab[0] = color_string(fill_color, "f") ap_updated = True + else: + ap_tab[0] = ap_tab[1] = ap_tab[2] = b"" + ap_updated = True if idx_BT == 7: if bwidth > 0: @@ -6294,6 +6387,24 @@ struct Tools } return Py_BuildValue("(i, ())", 1); } + + %feature("autodoc","Measure length of a string for a Base14 font.") measure_string; + float measure_string(const char *text, const char *fontname, float fontsize) + { + 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); + if (c < 0) c = 0xB7; + g = fz_encode_character(gctx, font, c); + w += fz_advance_glyph(gctx, font, g, 0); + } + return w * fontsize; + } + %pythoncode %{ def _hor_matrix(self, C, P): diff --git a/fitz/fitz.py b/fitz/fitz.py index 5498a3180..13f354dbd 100644 --- a/fitz/fitz.py +++ b/fitz/fitz.py @@ -105,9 +105,9 @@ class _object: VersionFitz = "1.14.0" -VersionBind = "1.14.5" -VersionDate = "2019-01-04 10:29:25" -version = (VersionBind, VersionFitz, "20190104102925") +VersionBind = "1.14.6" +VersionDate = "2019-01-14 06:46:06" +version = (VersionBind, VersionFitz, "20190114064606") class Matrix(): @@ -117,7 +117,7 @@ def __init__(self, *args): self.a = self.b = self.c = self.d = self.e = self.f = 0.0 return None if len(args) > 6: - raise ValueError("illegal sequ. length") + raise ValueError("bad sequ. length") if len(args) == 6: # 6 numbers self.a = float(args[0]) self.b = float(args[1]) @@ -234,6 +234,8 @@ def preRotate(self, theta): def concat(self, one, two): """Multiply two matrices and replace current one.""" + 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 @@ -283,6 +285,8 @@ def __add__(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) + if len(m) != 6: + raise ValueError("bad sequ. length") return Matrix(self.a + m[0], self.b + m[1], self.c + m[2], self.d + m[3], self.e + m[4], self.f + m[5]) @@ -290,6 +294,8 @@ def __sub__(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) + if len(m) != 6: + raise ValueError("bad sequ. length") return Matrix(self.a - m[0], self.b - m[1], self.c - m[2], self.d - m[3], self.e - m[4], self.f - m[5]) @@ -358,7 +364,7 @@ def __init__(self, *args): return None if len(args) > 2: - raise ValueError("illegal sequ. length") + raise ValueError("bad sequ. length") if len(args) == 2: self.x = float(args[0]) self.y = float(args[1]) @@ -366,16 +372,18 @@ def __init__(self, *args): if len(args) == 1: l = args[0] if hasattr(l, "__getitem__") is False: - raise ValueError("illegal Point constructor") + raise ValueError("bad Point constructor") if len(l) != 2: - raise ValueError("illegal sequ. length") + raise ValueError("bad sequ. length") self.x = float(l[0]) self.y = float(l[1]) return None - raise ValueError("illegal Point constructor") + raise ValueError("bad Point constructor") 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] @@ -478,14 +486,14 @@ def __add__(self, p): if hasattr(p, "__float__"): return Point(self.x + p, self.y + p) if len(p) != 2: - raise ValueError("require point-like object") + raise ValueError("bad sequ. length") return Point(self.x + p[0], self.y + p[1]) def __sub__(self, p): if hasattr(p, "__float__"): return Point(self.x - p, self.y - p) if len(p) != 2: - raise ValueError("require point-like object") + raise ValueError("bad sequ. length") return Point(self.x - p[0], self.y - p[1]) def __mul__(self, m): @@ -516,7 +524,7 @@ def __init__(self, *args): return None if len(args) > 4: - raise ValueError("invalid sequ. length") + raise ValueError("bad sequ. length") if len(args) == 4: self.x0 = float(args[0]) self.y0 = float(args[1]) @@ -526,9 +534,9 @@ def __init__(self, *args): if len(args) == 1: l = args[0] if hasattr(l, "__getitem__") is False: - raise ValueError("invalid Rect constructor") + raise ValueError("bad Rect constructor") if len(l) != 4: - raise ValueError("invalid sequ. length") + raise ValueError("bad sequ. length") self.x0 = float(l[0]) self.y0 = float(l[1]) self.x1 = float(l[2]) @@ -555,7 +563,7 @@ def __init__(self, *args): self.x1 = float(a1) self.y1 = float(a2) return None - raise ValueError("invalid Rect constructor") + raise ValueError("bad Rect constructor") def normalize(self): """Replace rectangle with its finite version.""" @@ -611,21 +619,29 @@ def round(self): def includePoint(self, p): """Extend rectangle to include point p.""" + if not len(p) == 2: + raise ValueError("bad sequ. length") self.x0, self.y0, self.x1, self.y1 = TOOLS._include_point_in_rect(self, p) return self def includeRect(self, r): """Extend rectangle to include rectangle r.""" + if not len(r) == 4: + raise ValueError("bad sequ. length") self.x0, self.y0, self.x1, self.y1 = TOOLS._union_rect(self, r) return self def intersect(self, r): """Restrict self to common area with rectangle r.""" + if not len(r) == 4: + raise ValueError("bad sequ. length") self.x0, self.y0, self.x1, self.y1 = TOOLS._intersect_rect(self, r) return self def transform(self, m): """Replace rectangle with its transformation by matrix m.""" + if not len(m) == 6: + raise ValueError("bad sequ. length") self.x0, self.y0, self.x1, self.y1 = TOOLS._transform_rect(self, m) return self @@ -674,7 +690,7 @@ def __add__(self, p): r = Rect(self.x0 + p, self.y0 + p, self.x1 + p, self.y1 + p) else: if len(p) != 4: - raise ValueError("require rect-like object") + raise ValueError("bad sequ. length") r = Rect(self.x0 + p[0], self.y0 + p[1], self.x1 + p[2], self.y1 + p[3]) return r @@ -682,7 +698,7 @@ def __sub__(self, p): if hasattr(p, "__float__"): return Rect(self.x0 - p, self.y0 - p, self.x1 - p, self.y1 - p) if len(p) != 4: - raise ValueError("require rect-like object") + raise ValueError("bad sequ. length") return Rect(self.x0 - p[0], self.y0 - p[1], self.x1 - p[2], self.y1 - p[3]) def __mul__(self, m): @@ -726,18 +742,18 @@ def __contains__(self, x): def __or__(self, x): if not hasattr(x, "__len__"): - raise ValueError("op2 is an unsupported type") + raise ValueError("bad operand 2") r = Rect(self) if len(x) == 2: return r.includePoint(x) if len(x) == 4: return r.includeRect(x) - raise ValueError("op2 is an unsupported type") + raise ValueError("bad operand 2") def __and__(self, x): if not hasattr(x, "__len__"): - raise ValueError("op2 is an unsupported type") + raise ValueError("bad operand 2") r1 = Rect(x) r = Rect(self) @@ -835,7 +851,7 @@ def __init__(self, *args): return None if len(args) > 4: - raise ValueError("invalid sequ. length") + raise ValueError("bad sequ. length") if len(args) == 4: self.ul = Point(args[0]) self.ur = Point(args[1]) @@ -845,15 +861,15 @@ def __init__(self, *args): if len(args) == 1: l = args[0] if hasattr(l, "__getitem__") is False: - raise ValueError("invalid Quad constructor") + raise ValueError("bad Quad constructor") if len(l) != 4: - raise ValueError("invalid sequ. length") + raise ValueError("bad sequ. length") self.ul = Point(l[0]) self.ur = Point(l[1]) self.ll = Point(l[2]) self.lr = Point(l[3]) return None - raise ValueError("invalid Quad constructor") + raise ValueError("bad Quad constructor") @property def isRectangular(self): @@ -947,6 +963,8 @@ def __abs__(self): def transform(self, m): """Replace quad by its transformation with matrix m.""" + if len(m) != 6: + raise ValueError("bad sequ. length") self.ul *= m self.ur *= m self.ll *= m @@ -1211,6 +1229,31 @@ def _check5(self): Base14_fontdict["symb"] = "Symbol" Base14_fontdict["zadb"] = "ZapfDingbats" +def getTextlen(text, fontname="helv", fontsize=12): + fontname = fontname.lower() + basename = Base14_fontdict.get(fontname, None) + + glyphs = None + if basename == "Symbol": + glyphs = symbol_glyphs + 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]) + return w * fontsize + + if fontname in Base14_fontdict.keys(): + return TOOLS.measure_string(text, Base14_fontdict[fontname], fontsize) + + if fontname in ["china-t", "china-s", + "china-ts", "china-ss", + "japan", "japan-s", + "korea", "korea-s"]: + return len(text) * fontsize + + raise ValueError("Font '%s' is unsupported" % fontname) + + #------------------------------------------------------------------------------ # Glyph list for the built-in font 'ZapfDingbats' #------------------------------------------------------------------------------ @@ -1569,6 +1612,8 @@ def CheckFont(page, fontname): for f in page.getFontList(): if f[4] == fontname: return f + if f[3].lower() == fontname.lower(): + return f return None def CheckFontInfo(doc, xref): @@ -3123,6 +3168,76 @@ def copyPixmap(self, src, bbox): """copyPixmap(self, src, bbox) -> PyObject *""" return _fitz.Pixmap_copyPixmap(self, src, bbox) + + def setAlpha(self, alphavalues=None): + """setAlpha(self, alphavalues=None) -> PyObject *""" + return _fitz.Pixmap_setAlpha(self, alphavalues) + + + def _getImageData(self, format): + """_getImageData(self, format) -> PyObject *""" + return _fitz.Pixmap__getImageData(self, format) + + + def getImageData(self, output="png"): + valid_formats = {"png": 1, "pnm": 2, "pgm": 2, "ppm": 2, "pbm": 2, + "pam": 3, "tga": 4, "tpic": 4, + "psd": 5, "ps": 6} + idx = valid_formats.get(output.lower(), 1) + if self.alpha and idx in (2, 6): + raise ValueError("'%s' cannot have alpha" % output) + if self.colorspace and self.colorspace.n > 3 and idx in (1, 2, 4): + raise ValueError("unsupported colorspace for '%s'" % output) + return self._getImageData(idx) + + def getPNGdata(self): + return self._getImageData(1) + + def getPNGData(self): + return self._getImageData(1) + + + def _writeIMG(self, filename, format): + """_writeIMG(self, filename, format) -> PyObject *""" + return _fitz.Pixmap__writeIMG(self, filename, format) + + + def writeImage(self, filename, output=None): + valid_formats = {"png": 1, "pnm": 2, "pgm": 2, "ppm": 2, "pbm": 2, + "pam": 3, "tga": 4, "tpic": 4, + "psd": 5, "ps": 6} + if output is None: + _, ext = os.path.splitext(filename) + output = ext[1:] + + idx = valid_formats.get(output.lower(), 1) + + if self.alpha and idx in (2, 6): + raise ValueError("'%s' cannot have alpha" % output) + if self.colorspace and self.colorspace.n > 3 and idx in (1, 2, 4): + raise ValueError("unsupported colorspace for '%s'" % output) + + return self._writeIMG(filename, idx) + + def writePNG(self, filename, savealpha = -1): + return self._writeIMG(filename, 1) + + + + def invertIRect(self, irect=None): + """invertIRect(self, irect=None)""" + return _fitz.Pixmap_invertIRect(self, irect) + + + def pixel(self, x, y): + """Return the pixel at (x,y) as a list. Last item is the alpha if Pixmap.alpha is true.""" + return _fitz.Pixmap_pixel(self, x, y) + + + def setPixel(self, x, y, value): + """Set the pixel at (x,y) to the integers in sequence 'value'.""" + return _fitz.Pixmap_setPixel(self, x, y, value) + @property def stride(self): @@ -3156,48 +3271,6 @@ def size(self): """size(self) -> int""" return _fitz.Pixmap_size(self) - - def setAlpha(self, alphavalues=None): - """setAlpha(self, alphavalues=None) -> PyObject *""" - return _fitz.Pixmap_setAlpha(self, alphavalues) - - - def _getImageData(self, format, savealpha=-1): - """_getImageData(self, format, savealpha=-1) -> PyObject *""" - return _fitz.Pixmap__getImageData(self, format, savealpha) - - - def getImageData(self, output="png"): - valid_formats = {"png": 1, "pnm": 2, "pgm": 2, "ppm": 2, "pbm": 2, - "pam": 3, "tga": 4, "psd": 5} - idx = valid_formats.get(output.lower(), 1) - return self._getImageData(idx) - - def getPNGdata(self): - return self._getImageData(1) - def getPNGData(self, savealpha=-1): - return self._getImageData(1) - - - def _writeIMG(self, filename, format, savealpha=-1): - """_writeIMG(self, filename, format, savealpha=-1) -> PyObject *""" - return _fitz.Pixmap__writeIMG(self, filename, format, savealpha) - - - def writeImage(self, filename, output="png"): - valid_formats = {"png": 1, "pnm": 2, "pgm": 2, "ppm": 2, "pbm": 2, - "pam": 3, "tga": 4, "psd": 5} - idx = valid_formats.get(output.lower(), 1) - return self._writeIMG(filename, idx) - - def writePNG(self, filename, savealpha = -1): - return self._writeIMG(filename, 1, savealpha) - - - def invertIRect(self, irect=None): - """invertIRect(self, irect=None)""" - return _fitz.Pixmap_invertIRect(self, irect) - @property def samples(self): @@ -3208,15 +3281,6 @@ def samples(self): width = w height = h - def pixel(self, x, y): - """Return a tuple representing one pixel. Item values are integers in range - 0 to 255. Last item is the alpha value if Pixmap.alpha is true. - """ - if x not in range(self.width) or y not in range(self.height): - raise IndexError("coordinates outside image") - i = self.stride * y + self.n * x - return tuple(self.samples[i: i + self.n]) - def __len__(self): return self.size @@ -3574,11 +3638,14 @@ def color_string(cs, code): ap_tab = ap.splitlines() # split AP stream into lines idx_BT = ap_tab.index(b"BT") # line no. of text start - # to avoid effort, we rely on a fixed format of this - # annot type: line 0 = fill color, line 5 border color, etc. + # to avoid effort, we rely on a fixed format generated by MuPDF for + # this annot type: line 0 = fill color, line 5 border color, etc. if fill_color is not None: ap_tab[0] = color_string(fill_color, "f") ap_updated = True + else: + ap_tab[0] = ap_tab[1] = ap_tab[2] = b"" + ap_updated = True if idx_BT == 7: if bwidth > 0: @@ -4351,6 +4418,11 @@ def _invert_matrix(self, matrix): return _fitz.Tools__invert_matrix(self, matrix) + def measure_string(self, text, fontname, fontsize): + """Measure length of a string for a Base14 font.""" + return _fitz.Tools_measure_string(self, text, fontname, fontsize) + + def _hor_matrix(self, C, P): """Given two points C, P calculate matrix that rotates and translates the vector C -> P such that C is mapped to Point(0, 0), and P to some point on the x axis diff --git a/fitz/fitz_wrap.c b/fitz/fitz_wrap.c index e2c19dc63..487db048f 100644 --- a/fitz/fitz_wrap.c +++ b/fitz/fitz_wrap.c @@ -4083,40 +4083,46 @@ struct fz_store_s int needs_reaping; }; + + //----------------------------------------------------------------------------- -// START redirect stdout/stderr +// Create an fz_output which writes to a Python ByteArray //----------------------------------------------------------------------------- -PyObject *JM_error_log; PyObject *JM_output_log; +PyObject *JM_error_log; static void -JM_write_stdout(fz_context *ctx, void *opaque, const void *buffer, size_t count) +JM_WriteBarray(fz_context *ctx, PyObject *barray, const void *buffer, size_t count) { - if (!buffer || !count) return; + if (!buffer || count < 1) return; PyObject *c = PyByteArray_FromStringAndSize((const char *)buffer, (Py_ssize_t) count); if (!c || c == NONE) return; - JM_output_log = PySequence_InPlaceConcat(JM_output_log, c); - Py_CLEAR(c); + PyObject *old = barray; // save for Py_DECREFing + barray = PySequence_InPlaceConcat(barray, c); + Py_DECREF(c); + Py_DECREF(old); return; } static void -JM_write_stderr(fz_context *ctx, void *opaque, const void *buffer, size_t count) -{ - if (!buffer || !count) return; - PyObject *c = PyByteArray_FromStringAndSize((const char *)buffer, (Py_ssize_t) count); - if (!c || c == NONE) return; - JM_error_log = PySequence_InPlaceConcat(JM_error_log, c); - Py_CLEAR(c); +JM_SeekDummy(fz_context *ctx, void *opaque, int64_t off, int whence) +{ // ignore seeks return; } -fz_output *JM_fitz_stdout; -fz_output *JM_fitz_stderr; -//----------------------------------------------------------------------------- -// STOP redirect stdout/stderr -//----------------------------------------------------------------------------- +static int64_t +JM_TellBarray(fz_context *ctx, PyObject *barray) +{ + return (int64_t) PyByteArray_Size(barray); +} +fz_output *JM_OutFromBarray(fz_context *ctx, PyObject *barray) +{ + fz_output *out = fz_new_output(ctx, 0, barray, JM_WriteBarray, NULL, NULL); + out->seek = JM_SeekDummy; + out->tell = JM_TellBarray; + return out; +} void pdf_dict_put_val_null(fz_context *ctx, pdf_obj *obj, int idx); @@ -9175,9 +9181,8 @@ PyObject *JM_convert_to_pdf(fz_context *ctx, fz_document *doc, int fp, int tp, i fz_rethrow(ctx); } } - // PDF created - now write it to Python bytes - PyObject *r; - fz_buffer *res = NULL; + // PDF created - now write it to Python bytearray + PyObject *r = NULL; fz_output *out = NULL; // prepare write options structure int errors = 0; @@ -9197,17 +9202,16 @@ PyObject *JM_convert_to_pdf(fz_context *ctx, fz_document *doc, int fp, int tp, i opts.errors = &errors; fz_try(ctx) { - res = fz_new_buffer(ctx, 1024); - out = fz_new_output_with_buffer(ctx, res); + r = PyByteArray_FromStringAndSize("", 0); + out = JM_OutFromBarray(gctx, r); pdf_write_document(ctx, pdfout, out, &opts); - r = JM_BinFromBuffer(ctx, res); } - fz_always(ctx) + fz_always(ctx) fz_drop_output(ctx, out); + fz_catch(ctx) { - fz_drop_output(ctx, out); - fz_drop_buffer(ctx, res); + Py_CLEAR(r); + fz_rethrow(ctx); } - fz_catch(ctx) fz_rethrow(ctx); return r; } @@ -10135,9 +10139,9 @@ SWIGINTERN PyObject *fz_document_s_save(struct fz_document_s *self,char *filenam return NONE; } SWIGINTERN PyObject *fz_document_s_write(struct fz_document_s *self,int garbage,int clean,int deflate,int ascii,int expand,int linear,int pretty,int decrypt){ - PyObject *r; - struct fz_buffer_s *res = NULL; + PyObject *r = NULL; fz_output *out = NULL; + fz_buffer *res = NULL; int errors = 0; pdf_write_options opts = { 0 }; opts.do_incremental = 0; @@ -10155,25 +10159,28 @@ SWIGINTERN PyObject *fz_document_s_write(struct fz_document_s *self,int garbage, opts.errors = &errors; pdf_document *pdf = pdf_specifics(gctx, self); fz_var(out); - fz_var(res); + fz_var(r); fz_try(gctx) { assert_PDF(pdf); if (fz_count_pages(gctx, self) < 1) THROWMSG("cannot save with zero pages"); JM_embedded_clean(gctx, pdf); - res = fz_new_buffer(gctx, 1024); + res = fz_new_buffer(gctx, 8192); out = fz_new_output_with_buffer(gctx, res); JM_write_document(gctx, pdf, out, &opts, decrypt); - pdf->dirty = 0; r = JM_BinFromBuffer(gctx, res); + pdf->dirty = 0; } fz_always(gctx) + { + fz_drop_buffer(gctx, res); + fz_drop_output(gctx, out); + } + fz_catch(gctx) { - fz_drop_output(gctx, out); - fz_drop_buffer(gctx, res); + return NULL; } - fz_catch(gctx) return NULL; return r; } SWIGINTERN PyObject *fz_document_s_insertPDF(struct fz_document_s *self,struct fz_document_s *docsrc,int from_page,int to_page,int start_at,int rotate,int links){ @@ -12030,21 +12037,6 @@ SWIGINTERN PyObject *fz_pixmap_s_copyPixmap(struct fz_pixmap_s *self,struct fz_p fz_catch(gctx) return NULL; return NONE; } -SWIGINTERN int fz_pixmap_s_stride(struct fz_pixmap_s *self){ - return fz_pixmap_stride(gctx, self); - } -SWIGINTERN int fz_pixmap_s_alpha(struct fz_pixmap_s *self){ - return self->alpha; - } -SWIGINTERN struct fz_colorspace_s *fz_pixmap_s_colorspace(struct fz_pixmap_s *self){ - return fz_pixmap_colorspace(gctx, self); - } -SWIGINTERN PyObject *fz_pixmap_s_irect(struct fz_pixmap_s *self){ - return JM_py_from_irect(fz_pixmap_bbox(gctx, self)); - } -SWIGINTERN int fz_pixmap_s_size(struct fz_pixmap_s *self){ - return (int) fz_pixmap_size(gctx, self); - } SWIGINTERN PyObject *fz_pixmap_s_setAlpha(struct fz_pixmap_s *self,PyObject *alphavalues){ fz_try(gctx) { @@ -12073,14 +12065,17 @@ SWIGINTERN PyObject *fz_pixmap_s_setAlpha(struct fz_pixmap_s *self,PyObject *alp fz_catch(gctx) return NULL; return NONE; } -SWIGINTERN PyObject *fz_pixmap_s__getImageData(struct fz_pixmap_s *self,int format,int savealpha){ - struct fz_buffer_s *res = NULL; +SWIGINTERN PyObject *fz_pixmap_s__getImageData(struct fz_pixmap_s *self,int format){ fz_output *out = NULL; - PyObject *r; - if (savealpha != -1) JM_Warning("ignoring savealpha"); - fz_try(gctx) { - res = fz_new_buffer(gctx, 1024); + fz_buffer *res = NULL; + // the following will be returned: + PyObject *barray = NULL; + fz_try(gctx) + { + size_t size = fz_pixmap_stride(gctx, self) * self->h; + res = fz_new_buffer(gctx, size); out = fz_new_output_with_buffer(gctx, res); + out->seek = JM_SeekDummy; // ignore seek calls switch(format) { case(1): @@ -12095,25 +12090,31 @@ SWIGINTERN PyObject *fz_pixmap_s__getImageData(struct fz_pixmap_s *self,int form case(4): fz_write_pixmap_as_tga(gctx, out, self); break; - case(5): + case(5): // Adobe Photoshop Document fz_write_pixmap_as_psd(gctx, out, self); break; + case(6): // Postscript format + fz_write_pixmap_as_ps(gctx, out, self); + break; default: fz_write_pixmap_as_png(gctx, out, self); break; } - r = JM_BinFromBuffer(gctx, res); + barray = JM_BinFromBuffer(gctx, res); } fz_always(gctx) { fz_drop_output(gctx, out); fz_drop_buffer(gctx, res); } - fz_catch(gctx) return NULL; - return r; + + fz_catch(gctx) + { + return NULL; + } + return barray; } -SWIGINTERN PyObject *fz_pixmap_s__writeIMG(struct fz_pixmap_s *self,char *filename,int format,int savealpha){ - if (savealpha != -1) JM_Warning("ignoring savealpha"); +SWIGINTERN PyObject *fz_pixmap_s__writeIMG(struct fz_pixmap_s *self,char *filename,int format){ fz_try(gctx) { switch(format) { @@ -12129,9 +12130,12 @@ SWIGINTERN PyObject *fz_pixmap_s__writeIMG(struct fz_pixmap_s *self,char *filena case(4): fz_save_pixmap_as_tga(gctx, self, filename); break; - case(5): + case(5): // Adobe Photoshop Document fz_save_pixmap_as_psd(gctx, self, filename); break; + case(6): // Postscript + fz_save_pixmap_as_ps(gctx, self, filename, 0); + break; default: fz_save_pixmap_as_png(gctx, self, filename); break; @@ -12153,6 +12157,69 @@ SWIGINTERN void fz_pixmap_s_invertIRect(struct fz_pixmap_s *self,PyObject *irect else fz_invert_pixmap(gctx, self); } +SWIGINTERN PyObject *fz_pixmap_s_pixel(struct fz_pixmap_s *self,int x,int y){ + PyObject *p = NULL; + fz_try(gctx) + { + if (!INRANGE(x, 0, self->w - 1) || !INRANGE(y, 0, self->h - 1)) + THROWMSG("coordinates outside image"); + int n = self->n; + int stride = fz_pixmap_stride(gctx, self); + int j, i = stride * y + n * x; + p = PyList_New(n); + for (j=0; j < n; j++) + { + PyList_SetItem(p, j, Py_BuildValue("i", self->samples[i + j])); + } + } + fz_catch(gctx) return NULL; + return p; + } +SWIGINTERN PyObject *fz_pixmap_s_setPixel(struct fz_pixmap_s *self,int x,int y,PyObject *value){ + fz_try(gctx) + { + if (!INRANGE(x, 0, self->w - 1) || !INRANGE(y, 0, self->h - 1)) + THROWMSG("coordinates outside image"); + int n = self->n; + if (!PySequence_Check(value) || PySequence_Size(value) != n) + THROWMSG("bad pixel value"); + int i, j; + unsigned char c[5]; + for (j = 0; j < n; j++) + { + i = (int) PyInt_AsLong(PySequence_ITEM(value, j)); + if (!INRANGE(i, 0, 255)) THROWMSG("bad pixel component"); + c[j] = (unsigned char) i; + } + int stride = fz_pixmap_stride(gctx, self); + i = stride * y + n * x; + for (j = 0; j < n; j++) + { + self->samples[i + j] = c[j]; + } + } + fz_catch(gctx) + { + PyErr_Clear(); + return NULL; + } + return NONE; + } +SWIGINTERN int fz_pixmap_s_stride(struct fz_pixmap_s *self){ + return fz_pixmap_stride(gctx, self); + } +SWIGINTERN int fz_pixmap_s_alpha(struct fz_pixmap_s *self){ + return self->alpha; + } +SWIGINTERN struct fz_colorspace_s *fz_pixmap_s_colorspace(struct fz_pixmap_s *self){ + return fz_pixmap_colorspace(gctx, self); + } +SWIGINTERN PyObject *fz_pixmap_s_irect(struct fz_pixmap_s *self){ + return JM_py_from_irect(fz_pixmap_bbox(gctx, self)); + } +SWIGINTERN int fz_pixmap_s_size(struct fz_pixmap_s *self){ + return (int) fz_pixmap_size(gctx, self); + } SWIGINTERN PyObject *fz_pixmap_s_samples(struct fz_pixmap_s *self){ return PyBytes_FromStringAndSize((const char *)self->samples, (Py_ssize_t) (self->w)*(self->h)*(self->n)); } @@ -12324,27 +12391,32 @@ SWIGINTERN PyObject *fz_annot_s_vertices(struct fz_annot_s *self){ // transformed with the page transformation matrix. //---------------------------------------------------------------- o = pdf_dict_get(gctx, annot->obj, PDF_NAME(Vertices)); - if (!o) o = pdf_dict_get(gctx, annot->obj, PDF_NAME(L)); - if (!o) o = pdf_dict_get(gctx, annot->obj, PDF_NAME(QuadPoints)); - if (!o) o = pdf_dict_gets(gctx, annot->obj, "CL"); - if (!o) o = pdf_dict_get(gctx, annot->obj, PDF_NAME(InkList)); + if (o) goto weiter; + o = pdf_dict_get(gctx, annot->obj, PDF_NAME(L)); + if (o) goto weiter; + o = pdf_dict_get(gctx, annot->obj, PDF_NAME(QuadPoints)); + if (o) goto weiter; + o = pdf_dict_gets(gctx, annot->obj, "CL"); + if (o) goto weiter; + o = pdf_dict_get(gctx, annot->obj, PDF_NAME(InkList)); + if (o) goto weiter; + return res; - if (o) // anything found yet? + weiter:; + int i, n; + fz_point point; // point object to work with + fz_matrix page_ctm; // page transformation matrix + pdf_page_transform(gctx, annot->page, NULL, &page_ctm); + res = PyList_New(0); // create Python list + n = pdf_array_len(gctx, o); + for (i = 0; i < n; i += 2) { - int i, j, n; - fz_point point; // point object to work with - fz_matrix page_ctm; // page transformation matrix - pdf_page_transform(gctx, annot->page, NULL, &page_ctm); - res = PyList_New(0); // create Python list - n = pdf_array_len(gctx, o); - for (i = 0; i < n; i += 2) - { - point.x = pdf_to_real(gctx, pdf_array_get(gctx, o, i)); - point.y = pdf_to_real(gctx, pdf_array_get(gctx, o, i+1)); - point = fz_transform_point(point, page_ctm); - PyList_Append(res, Py_BuildValue("ff", point.x, point.y)); - } + point.x = pdf_to_real(gctx, pdf_array_get(gctx, o, i)); + point.y = pdf_to_real(gctx, pdf_array_get(gctx, o, i+1)); + point = fz_transform_point(point, page_ctm); + PyList_Append(res, Py_BuildValue("ff", point.x, point.y)); } + return res; } SWIGINTERN PyObject *fz_annot_s_colors(struct fz_annot_s *self){ @@ -13393,6 +13465,30 @@ 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){ + 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); + if (c < 0) c = 0xB7; + g = fz_encode_character(gctx, font, c); + w += fz_advance_glyph(gctx, font, g, 0); + } + return w * fontsize; + } + + #define SWIG_From_double PyFloat_FromDouble + + +SWIGINTERNINLINE PyObject * +SWIG_From_float (float value) +{ + return SWIG_From_double (value); +} + #ifdef __cplusplus extern "C" { #endif @@ -18455,137 +18551,188 @@ SWIGINTERN PyObject *_wrap_Pixmap_copyPixmap(PyObject *SWIGUNUSEDPARM(self), PyO } -SWIGINTERN PyObject *_wrap_Pixmap_stride(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_Pixmap_setAlpha(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; + PyObject *arg2 = (PyObject *) NULL ; void *argp1 = 0 ; int res1 = 0 ; PyObject * obj0 = 0 ; - int result; + PyObject * obj1 = 0 ; + PyObject *result = 0 ; - if (!PyArg_ParseTuple(args,(char *)"O:Pixmap_stride",&obj0)) SWIG_fail; + if (!PyArg_ParseTuple(args,(char *)"O|O:Pixmap_setAlpha",&obj0,&obj1)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_stride" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_setAlpha" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); } arg1 = (struct fz_pixmap_s *)(argp1); - result = (int)fz_pixmap_s_stride(arg1); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_Pixmap_alpha(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject * obj0 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"O:Pixmap_alpha",&obj0)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_alpha" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); + if (obj1) { + arg2 = obj1; } - arg1 = (struct fz_pixmap_s *)(argp1); - result = (int)fz_pixmap_s_alpha(arg1); - resultobj = SWIG_From_int((int)(result)); + { + result = (PyObject *)fz_pixmap_s_setAlpha(arg1,arg2); + if(!result) + { + PyErr_SetString(PyExc_RuntimeError, fz_caught_message(gctx)); + return NULL; + } + } + resultobj = result; return resultobj; fail: return NULL; } -SWIGINTERN PyObject *_wrap_Pixmap_colorspace(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_Pixmap__getImageData(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; + int arg2 ; void *argp1 = 0 ; int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; PyObject * obj0 = 0 ; - struct fz_colorspace_s *result = 0 ; + PyObject * obj1 = 0 ; + PyObject *result = 0 ; - if (!PyArg_ParseTuple(args,(char *)"O:Pixmap_colorspace",&obj0)) SWIG_fail; + if (!PyArg_ParseTuple(args,(char *)"OO:Pixmap__getImageData",&obj0,&obj1)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_colorspace" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap__getImageData" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); } arg1 = (struct fz_pixmap_s *)(argp1); - result = (struct fz_colorspace_s *)fz_pixmap_s_colorspace(arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_fz_colorspace_s, 0 | 0 ); + ecode2 = SWIG_AsVal_int(obj1, &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Pixmap__getImageData" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + { + result = (PyObject *)fz_pixmap_s__getImageData(arg1,arg2); + if(!result) + { + PyErr_SetString(PyExc_RuntimeError, fz_caught_message(gctx)); + return NULL; + } + } + resultobj = result; return resultobj; fail: return NULL; } -SWIGINTERN PyObject *_wrap_Pixmap_irect(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_Pixmap__writeIMG(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; + char *arg2 = (char *) 0 ; + int arg3 ; void *argp1 = 0 ; int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + int val3 ; + int ecode3 = 0 ; PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; PyObject *result = 0 ; - if (!PyArg_ParseTuple(args,(char *)"O:Pixmap_irect",&obj0)) SWIG_fail; + if (!PyArg_ParseTuple(args,(char *)"OOO:Pixmap__writeIMG",&obj0,&obj1,&obj2)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_irect" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap__writeIMG" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); } arg1 = (struct fz_pixmap_s *)(argp1); - result = (PyObject *)fz_pixmap_s_irect(arg1); + res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Pixmap__writeIMG" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + ecode3 = SWIG_AsVal_int(obj2, &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Pixmap__writeIMG" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + { + result = (PyObject *)fz_pixmap_s__writeIMG(arg1,arg2,arg3); + if(!result) + { + PyErr_SetString(PyExc_RuntimeError, fz_caught_message(gctx)); + return NULL; + } + } resultobj = result; + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); return resultobj; fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); return NULL; } -SWIGINTERN PyObject *_wrap_Pixmap_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_Pixmap_invertIRect(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; + PyObject *arg2 = (PyObject *) NULL ; void *argp1 = 0 ; int res1 = 0 ; PyObject * obj0 = 0 ; - int result; + PyObject * obj1 = 0 ; - if (!PyArg_ParseTuple(args,(char *)"O:Pixmap_size",&obj0)) SWIG_fail; + if (!PyArg_ParseTuple(args,(char *)"O|O:Pixmap_invertIRect",&obj0,&obj1)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_size" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_invertIRect" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); } arg1 = (struct fz_pixmap_s *)(argp1); - result = (int)fz_pixmap_s_size(arg1); - resultobj = SWIG_From_int((int)(result)); + if (obj1) { + arg2 = obj1; + } + fz_pixmap_s_invertIRect(arg1,arg2); + resultobj = SWIG_Py_Void(); return resultobj; fail: return NULL; } -SWIGINTERN PyObject *_wrap_Pixmap_setAlpha(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_Pixmap_pixel(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; - PyObject *arg2 = (PyObject *) NULL ; + int arg2 ; + int arg3 ; void *argp1 = 0 ; int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + int val3 ; + int ecode3 = 0 ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; PyObject *result = 0 ; - if (!PyArg_ParseTuple(args,(char *)"O|O:Pixmap_setAlpha",&obj0,&obj1)) SWIG_fail; + if (!PyArg_ParseTuple(args,(char *)"OOO:Pixmap_pixel",&obj0,&obj1,&obj2)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_setAlpha" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_pixel" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); } arg1 = (struct fz_pixmap_s *)(argp1); - if (obj1) { - arg2 = obj1; - } + ecode2 = SWIG_AsVal_int(obj1, &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Pixmap_pixel" "', argument " "2"" of type '" "int""'"); + } + arg2 = (int)(val2); + ecode3 = SWIG_AsVal_int(obj2, &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Pixmap_pixel" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); { - result = (PyObject *)fz_pixmap_s_setAlpha(arg1,arg2); + result = (PyObject *)fz_pixmap_s_pixel(arg1,arg2,arg3); if(!result) { PyErr_SetString(PyExc_RuntimeError, fz_caught_message(gctx)); @@ -18599,11 +18746,12 @@ SWIGINTERN PyObject *_wrap_Pixmap_setAlpha(PyObject *SWIGUNUSEDPARM(self), PyObj } -SWIGINTERN PyObject *_wrap_Pixmap__getImageData(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_Pixmap_setPixel(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; int arg2 ; - int arg3 = (int) -1 ; + int arg3 ; + PyObject *arg4 = (PyObject *) 0 ; void *argp1 = 0 ; int res1 = 0 ; int val2 ; @@ -18613,28 +18761,28 @@ SWIGINTERN PyObject *_wrap_Pixmap__getImageData(PyObject *SWIGUNUSEDPARM(self), PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; PyObject *result = 0 ; - if (!PyArg_ParseTuple(args,(char *)"OO|O:Pixmap__getImageData",&obj0,&obj1,&obj2)) SWIG_fail; + if (!PyArg_ParseTuple(args,(char *)"OOOO:Pixmap_setPixel",&obj0,&obj1,&obj2,&obj3)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap__getImageData" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_setPixel" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); } arg1 = (struct fz_pixmap_s *)(argp1); ecode2 = SWIG_AsVal_int(obj1, &val2); if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Pixmap__getImageData" "', argument " "2"" of type '" "int""'"); + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Pixmap_setPixel" "', argument " "2"" of type '" "int""'"); } arg2 = (int)(val2); - if (obj2) { - ecode3 = SWIG_AsVal_int(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Pixmap__getImageData" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - } + ecode3 = SWIG_AsVal_int(obj2, &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Pixmap_setPixel" "', argument " "3"" of type '" "int""'"); + } + arg3 = (int)(val3); + arg4 = obj3; { - result = (PyObject *)fz_pixmap_s__getImageData(arg1,arg2,arg3); + result = (PyObject *)fz_pixmap_s_setPixel(arg1,arg2,arg3,arg4); if(!result) { PyErr_SetString(PyExc_RuntimeError, fz_caught_message(gctx)); @@ -18648,87 +18796,110 @@ SWIGINTERN PyObject *_wrap_Pixmap__getImageData(PyObject *SWIGUNUSEDPARM(self), } -SWIGINTERN PyObject *_wrap_Pixmap__writeIMG(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_Pixmap_stride(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; - char *arg2 = (char *) 0 ; - int arg3 ; - int arg4 = (int) -1 ; void *argp1 = 0 ; int res1 = 0 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - int val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject *result = 0 ; + int result; - if (!PyArg_ParseTuple(args,(char *)"OOO|O:Pixmap__writeIMG",&obj0,&obj1,&obj2,&obj3)) SWIG_fail; + if (!PyArg_ParseTuple(args,(char *)"O:Pixmap_stride",&obj0)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap__writeIMG" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_stride" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); } arg1 = (struct fz_pixmap_s *)(argp1); - res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Pixmap__writeIMG" "', argument " "2"" of type '" "char *""'"); + result = (int)fz_pixmap_s_stride(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Pixmap_alpha(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject * obj0 = 0 ; + int result; + + if (!PyArg_ParseTuple(args,(char *)"O:Pixmap_alpha",&obj0)) SWIG_fail; + res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_alpha" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); } - arg2 = (char *)(buf2); - ecode3 = SWIG_AsVal_int(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Pixmap__writeIMG" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - if (obj3) { - ecode4 = SWIG_AsVal_int(obj3, &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Pixmap__writeIMG" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); + arg1 = (struct fz_pixmap_s *)(argp1); + result = (int)fz_pixmap_s_alpha(arg1); + resultobj = SWIG_From_int((int)(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Pixmap_colorspace(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject * obj0 = 0 ; + struct fz_colorspace_s *result = 0 ; + + if (!PyArg_ParseTuple(args,(char *)"O:Pixmap_colorspace",&obj0)) SWIG_fail; + res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_colorspace" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); } - { - result = (PyObject *)fz_pixmap_s__writeIMG(arg1,arg2,arg3,arg4); - if(!result) - { - PyErr_SetString(PyExc_RuntimeError, fz_caught_message(gctx)); - return NULL; - } + arg1 = (struct fz_pixmap_s *)(argp1); + result = (struct fz_colorspace_s *)fz_pixmap_s_colorspace(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_fz_colorspace_s, 0 | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Pixmap_irect(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject * obj0 = 0 ; + PyObject *result = 0 ; + + if (!PyArg_ParseTuple(args,(char *)"O:Pixmap_irect",&obj0)) SWIG_fail; + res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_irect" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); } + arg1 = (struct fz_pixmap_s *)(argp1); + result = (PyObject *)fz_pixmap_s_irect(arg1); resultobj = result; - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); return resultobj; fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); return NULL; } -SWIGINTERN PyObject *_wrap_Pixmap_invertIRect(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_Pixmap_size(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct fz_pixmap_s *arg1 = (struct fz_pixmap_s *) 0 ; - PyObject *arg2 = (PyObject *) NULL ; void *argp1 = 0 ; int res1 = 0 ; PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; + int result; - if (!PyArg_ParseTuple(args,(char *)"O|O:Pixmap_invertIRect",&obj0,&obj1)) SWIG_fail; + if (!PyArg_ParseTuple(args,(char *)"O:Pixmap_size",&obj0)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_fz_pixmap_s, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_invertIRect" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Pixmap_size" "', argument " "1"" of type '" "struct fz_pixmap_s *""'"); } arg1 = (struct fz_pixmap_s *)(argp1); - if (obj1) { - arg2 = obj1; - } - fz_pixmap_s_invertIRect(arg1,arg2); - resultobj = SWIG_Py_Void(); + result = (int)fz_pixmap_s_size(arg1); + resultobj = SWIG_From_int((int)(result)); return resultobj; fail: return NULL; @@ -21430,6 +21601,61 @@ SWIGINTERN PyObject *_wrap_Tools__invert_matrix(PyObject *SWIGUNUSEDPARM(self), } +SWIGINTERN PyObject *_wrap_Tools_measure_string(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + struct Tools *arg1 = (struct Tools *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + float arg4 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + int res3 ; + char *buf3 = 0 ; + int alloc3 = 0 ; + float val4 ; + int ecode4 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + float result; + + if (!PyArg_ParseTuple(args,(char *)"OOOO:Tools_measure_string",&obj0,&obj1,&obj2,&obj3)) 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 *""'"); + } + arg1 = (struct Tools *)(argp1); + res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Tools_measure_string" "', argument " "2"" of type '" "char const *""'"); + } + arg2 = (char *)(buf2); + res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Tools_measure_string" "', argument " "3"" of type '" "char const *""'"); + } + arg3 = (char *)(buf3); + ecode4 = SWIG_AsVal_float(obj3, &val4); + if (!SWIG_IsOK(ecode4)) { + 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); + resultobj = SWIG_From_float((float)(result)); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); + return NULL; +} + + SWIGINTERN PyObject *_wrap_new_Tools(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct Tools *result = 0 ; @@ -21603,15 +21829,17 @@ static PyMethodDef SwigMethods[] = { "Pixmap_clearWith(self, value, bbox)\n" ""}, { (char *)"Pixmap_copyPixmap", _wrap_Pixmap_copyPixmap, METH_VARARGS, (char *)"Pixmap_copyPixmap(self, src, bbox) -> PyObject *"}, + { (char *)"Pixmap_setAlpha", _wrap_Pixmap_setAlpha, METH_VARARGS, (char *)"Pixmap_setAlpha(self, alphavalues=None) -> PyObject *"}, + { (char *)"Pixmap__getImageData", _wrap_Pixmap__getImageData, METH_VARARGS, (char *)"Pixmap__getImageData(self, format) -> PyObject *"}, + { (char *)"Pixmap__writeIMG", _wrap_Pixmap__writeIMG, METH_VARARGS, (char *)"Pixmap__writeIMG(self, filename, format) -> PyObject *"}, + { (char *)"Pixmap_invertIRect", _wrap_Pixmap_invertIRect, METH_VARARGS, (char *)"Pixmap_invertIRect(self, irect=None)"}, + { (char *)"Pixmap_pixel", _wrap_Pixmap_pixel, METH_VARARGS, (char *)"Return the pixel at (x,y) as a list. Last item is the alpha if Pixmap.alpha is true."}, + { (char *)"Pixmap_setPixel", _wrap_Pixmap_setPixel, METH_VARARGS, (char *)"Set the pixel at (x,y) to the integers in sequence 'value'."}, { (char *)"Pixmap_stride", _wrap_Pixmap_stride, METH_VARARGS, (char *)"Pixmap_stride(self) -> int"}, { (char *)"Pixmap_alpha", _wrap_Pixmap_alpha, METH_VARARGS, (char *)"Pixmap_alpha(self) -> int"}, { (char *)"Pixmap_colorspace", _wrap_Pixmap_colorspace, METH_VARARGS, (char *)"Pixmap_colorspace(self) -> Colorspace"}, { (char *)"Pixmap_irect", _wrap_Pixmap_irect, METH_VARARGS, (char *)"Pixmap_irect(self) -> PyObject *"}, { (char *)"Pixmap_size", _wrap_Pixmap_size, METH_VARARGS, (char *)"Pixmap_size(self) -> int"}, - { (char *)"Pixmap_setAlpha", _wrap_Pixmap_setAlpha, METH_VARARGS, (char *)"Pixmap_setAlpha(self, alphavalues=None) -> PyObject *"}, - { (char *)"Pixmap__getImageData", _wrap_Pixmap__getImageData, METH_VARARGS, (char *)"Pixmap__getImageData(self, format, savealpha=-1) -> PyObject *"}, - { (char *)"Pixmap__writeIMG", _wrap_Pixmap__writeIMG, METH_VARARGS, (char *)"Pixmap__writeIMG(self, filename, format, savealpha=-1) -> PyObject *"}, - { (char *)"Pixmap_invertIRect", _wrap_Pixmap_invertIRect, METH_VARARGS, (char *)"Pixmap_invertIRect(self, irect=None)"}, { (char *)"Pixmap_samples", _wrap_Pixmap_samples, METH_VARARGS, (char *)"Pixmap_samples(self) -> PyObject *"}, { (char *)"Pixmap_swigregister", Pixmap_swigregister, METH_VARARGS, NULL}, { (char *)"delete_Colorspace", _wrap_delete_Colorspace, METH_VARARGS, (char *)"delete_Colorspace(self)"}, @@ -21717,6 +21945,7 @@ static PyMethodDef SwigMethods[] = { { (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."}, + { (char *)"Tools_measure_string", _wrap_Tools_measure_string, METH_VARARGS, (char *)"Measure length of a string for a Base14 font."}, { (char *)"new_Tools", _wrap_new_Tools, METH_VARARGS, (char *)"new_Tools() -> Tools"}, { (char *)"delete_Tools", _wrap_delete_Tools, METH_VARARGS, (char *)"delete_Tools(self)"}, { (char *)"Tools_swigregister", Tools_swigregister, METH_VARARGS, NULL}, @@ -22495,12 +22724,12 @@ SWIG_init(void) { // START redirect stdout/stderr //----------------------------------------------------------------------------- - JM_fitz_stdout = fz_new_output(gctx, 0, JM_fitz_stdout, JM_write_stdout, NULL, NULL); - + JM_output_log = PyByteArray_FromStringAndSize("", 0); + fz_output *JM_fitz_stdout = JM_OutFromBarray(gctx, JM_output_log); fz_set_stdout(gctx, JM_fitz_stdout); - JM_fitz_stderr = fz_new_output(gctx, 0, JM_fitz_stderr, JM_write_stderr, NULL, NULL); - + JM_error_log = PyByteArray_FromStringAndSize("", 0); + fz_output *JM_fitz_stderr = JM_OutFromBarray(gctx, JM_error_log); fz_set_stderr(gctx, JM_fitz_stderr); if (JM_fitz_stderr && JM_fitz_stdout) @@ -22510,9 +22739,6 @@ SWIG_init(void) { else PySys_WriteStderr("error redirecting stdout/stderr!\n"); - JM_error_log = PyByteArray_FromStringAndSize("", 0); - JM_output_log = PyByteArray_FromStringAndSize("", 0); - //----------------------------------------------------------------------------- // STOP redirect stdout/stderr //----------------------------------------------------------------------------- diff --git a/fitz/helper-convert.i b/fitz/helper-convert.i index 17de5ddc0..07efd5d6c 100644 --- a/fitz/helper-convert.i +++ b/fitz/helper-convert.i @@ -49,9 +49,8 @@ PyObject *JM_convert_to_pdf(fz_context *ctx, fz_document *doc, int fp, int tp, i fz_rethrow(ctx); } } - // PDF created - now write it to Python bytes - PyObject *r; - fz_buffer *res = NULL; + // PDF created - now write it to Python bytearray + PyObject *r = NULL; fz_output *out = NULL; // prepare write options structure int errors = 0; @@ -71,17 +70,16 @@ PyObject *JM_convert_to_pdf(fz_context *ctx, fz_document *doc, int fp, int tp, i opts.errors = &errors; fz_try(ctx) { - res = fz_new_buffer(ctx, 1024); - out = fz_new_output_with_buffer(ctx, res); + r = PyByteArray_FromStringAndSize("", 0); + out = JM_OutFromBarray(gctx, r); pdf_write_document(ctx, pdfout, out, &opts); - r = JM_BinFromBuffer(ctx, res); } - fz_always(ctx) + fz_always(ctx) fz_drop_output(ctx, out); + fz_catch(ctx) { - fz_drop_output(ctx, out); - fz_drop_buffer(ctx, res); + Py_CLEAR(r); + fz_rethrow(ctx); } - fz_catch(ctx) fz_rethrow(ctx); return r; } %} \ No newline at end of file diff --git a/fitz/helper-geo-py.i b/fitz/helper-geo-py.i index cedd3a0ba..483be4718 100644 --- a/fitz/helper-geo-py.i +++ b/fitz/helper-geo-py.i @@ -6,7 +6,7 @@ class Matrix(): self.a = self.b = self.c = self.d = self.e = self.f = 0.0 return None if len(args) > 6: - raise ValueError("illegal sequ. length") + raise ValueError("bad sequ. length") if len(args) == 6: # 6 numbers self.a = float(args[0]) self.b = float(args[1]) @@ -123,6 +123,8 @@ class Matrix(): def concat(self, one, two): """Multiply two matrices and replace current one.""" + 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 @@ -172,6 +174,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) + if len(m) != 6: + raise ValueError("bad sequ. length") return Matrix(self.a + m[0], self.b + m[1], self.c + m[2], self.d + m[3], self.e + m[4], self.f + m[5]) @@ -179,6 +183,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) + if len(m) != 6: + raise ValueError("bad sequ. length") return Matrix(self.a - m[0], self.b - m[1], self.c - m[2], self.d - m[3], self.e - m[4], self.f - m[5]) @@ -247,7 +253,7 @@ class Point(): return None if len(args) > 2: - raise ValueError("illegal sequ. length") + raise ValueError("bad sequ. length") if len(args) == 2: self.x = float(args[0]) self.y = float(args[1]) @@ -255,16 +261,18 @@ class Point(): if len(args) == 1: l = args[0] if hasattr(l, "__getitem__") is False: - raise ValueError("illegal Point constructor") + raise ValueError("bad Point constructor") if len(l) != 2: - raise ValueError("illegal sequ. length") + raise ValueError("bad sequ. length") self.x = float(l[0]) self.y = float(l[1]) return None - raise ValueError("illegal Point constructor") + raise ValueError("bad Point constructor") 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] @@ -367,14 +375,14 @@ class Point(): if hasattr(p, "__float__"): return Point(self.x + p, self.y + p) if len(p) != 2: - raise ValueError("require point-like object") + raise ValueError("bad sequ. length") return Point(self.x + p[0], self.y + p[1]) def __sub__(self, p): if hasattr(p, "__float__"): return Point(self.x - p, self.y - p) if len(p) != 2: - raise ValueError("require point-like object") + raise ValueError("bad sequ. length") return Point(self.x - p[0], self.y - p[1]) def __mul__(self, m): @@ -405,7 +413,7 @@ class Rect(): return None if len(args) > 4: - raise ValueError("invalid sequ. length") + raise ValueError("bad sequ. length") if len(args) == 4: self.x0 = float(args[0]) self.y0 = float(args[1]) @@ -415,9 +423,9 @@ class Rect(): if len(args) == 1: l = args[0] if hasattr(l, "__getitem__") is False: - raise ValueError("invalid Rect constructor") + raise ValueError("bad Rect constructor") if len(l) != 4: - raise ValueError("invalid sequ. length") + raise ValueError("bad sequ. length") self.x0 = float(l[0]) self.y0 = float(l[1]) self.x1 = float(l[2]) @@ -444,7 +452,7 @@ class Rect(): self.x1 = float(a1) self.y1 = float(a2) return None - raise ValueError("invalid Rect constructor") + raise ValueError("bad Rect constructor") def normalize(self): """Replace rectangle with its finite version.""" @@ -500,21 +508,29 @@ class Rect(): def includePoint(self, p): """Extend rectangle to include point p.""" + if not len(p) == 2: + raise ValueError("bad sequ. length") self.x0, self.y0, self.x1, self.y1 = TOOLS._include_point_in_rect(self, p) return self def includeRect(self, r): """Extend rectangle to include rectangle r.""" + if not len(r) == 4: + raise ValueError("bad sequ. length") self.x0, self.y0, self.x1, self.y1 = TOOLS._union_rect(self, r) return self def intersect(self, r): """Restrict self to common area with rectangle r.""" + if not len(r) == 4: + raise ValueError("bad sequ. length") self.x0, self.y0, self.x1, self.y1 = TOOLS._intersect_rect(self, r) return self def transform(self, m): """Replace rectangle with its transformation by matrix m.""" + if not len(m) == 6: + raise ValueError("bad sequ. length") self.x0, self.y0, self.x1, self.y1 = TOOLS._transform_rect(self, m) return self @@ -563,7 +579,7 @@ class Rect(): r = Rect(self.x0 + p, self.y0 + p, self.x1 + p, self.y1 + p) else: if len(p) != 4: - raise ValueError("require rect-like object") + raise ValueError("bad sequ. length") r = Rect(self.x0 + p[0], self.y0 + p[1], self.x1 + p[2], self.y1 + p[3]) return r @@ -571,7 +587,7 @@ class Rect(): if hasattr(p, "__float__"): return Rect(self.x0 - p, self.y0 - p, self.x1 - p, self.y1 - p) if len(p) != 4: - raise ValueError("require rect-like object") + raise ValueError("bad sequ. length") return Rect(self.x0 - p[0], self.y0 - p[1], self.x1 - p[2], self.y1 - p[3]) def __mul__(self, m): @@ -615,18 +631,18 @@ class Rect(): def __or__(self, x): if not hasattr(x, "__len__"): - raise ValueError("op2 is an unsupported type") + raise ValueError("bad operand 2") r = Rect(self) if len(x) == 2: return r.includePoint(x) if len(x) == 4: return r.includeRect(x) - raise ValueError("op2 is an unsupported type") + raise ValueError("bad operand 2") def __and__(self, x): if not hasattr(x, "__len__"): - raise ValueError("op2 is an unsupported type") + raise ValueError("bad operand 2") r1 = Rect(x) r = Rect(self) @@ -724,7 +740,7 @@ class Quad(): return None if len(args) > 4: - raise ValueError("invalid sequ. length") + raise ValueError("bad sequ. length") if len(args) == 4: self.ul = Point(args[0]) self.ur = Point(args[1]) @@ -734,15 +750,15 @@ class Quad(): if len(args) == 1: l = args[0] if hasattr(l, "__getitem__") is False: - raise ValueError("invalid Quad constructor") + raise ValueError("bad Quad constructor") if len(l) != 4: - raise ValueError("invalid sequ. length") + raise ValueError("bad sequ. length") self.ul = Point(l[0]) self.ur = Point(l[1]) self.ll = Point(l[2]) self.lr = Point(l[3]) return None - raise ValueError("invalid Quad constructor") + raise ValueError("bad Quad constructor") @property def isRectangular(self): @@ -836,6 +852,8 @@ class Quad(): def transform(self, m): """Replace quad by its transformation with matrix m.""" + if len(m) != 6: + raise ValueError("bad sequ. length") self.ul *= m self.ur *= m self.ll *= m diff --git a/fitz/helper-other.i b/fitz/helper-other.i index 167641842..115581e36 100644 --- a/fitz/helper-other.i +++ b/fitz/helper-other.i @@ -741,38 +741,4 @@ struct fz_store_s int needs_reaping; }; -//----------------------------------------------------------------------------- -// START redirect stdout/stderr -//----------------------------------------------------------------------------- -PyObject *JM_error_log; -PyObject *JM_output_log; - -static void -JM_write_stdout(fz_context *ctx, void *opaque, const void *buffer, size_t count) -{ - if (!buffer || !count) return; - PyObject *c = PyByteArray_FromStringAndSize((const char *)buffer, (Py_ssize_t) count); - if (!c || c == NONE) return; - JM_output_log = PySequence_InPlaceConcat(JM_output_log, c); - Py_CLEAR(c); - return; -} - -static void -JM_write_stderr(fz_context *ctx, void *opaque, const void *buffer, size_t count) -{ - if (!buffer || !count) return; - PyObject *c = PyByteArray_FromStringAndSize((const char *)buffer, (Py_ssize_t) count); - if (!c || c == NONE) return; - JM_error_log = PySequence_InPlaceConcat(JM_error_log, c); - Py_CLEAR(c); - return; -} - -fz_output *JM_fitz_stdout; -fz_output *JM_fitz_stderr; -//----------------------------------------------------------------------------- -// STOP redirect stdout/stderr -//----------------------------------------------------------------------------- - %} \ No newline at end of file diff --git a/fitz/helper-out-barray.i b/fitz/helper-out-barray.i new file mode 100644 index 000000000..6dfd12731 --- /dev/null +++ b/fitz/helper-out-barray.i @@ -0,0 +1,40 @@ +%{ +//----------------------------------------------------------------------------- +// Create an fz_output which writes to a Python ByteArray +//----------------------------------------------------------------------------- +PyObject *JM_output_log; +PyObject *JM_error_log; + +static void +JM_WriteBarray(fz_context *ctx, PyObject *barray, const void *buffer, size_t count) +{ + if (!buffer || count < 1) return; + PyObject *c = PyByteArray_FromStringAndSize((const char *)buffer, (Py_ssize_t) count); + if (!c || c == NONE) return; + PyObject *old = barray; // save for Py_DECREFing + barray = PySequence_InPlaceConcat(barray, c); + Py_DECREF(c); + Py_DECREF(old); + return; +} + +static void +JM_SeekDummy(fz_context *ctx, void *opaque, int64_t off, int whence) +{ // ignore seeks + return; +} + +static int64_t +JM_TellBarray(fz_context *ctx, PyObject *barray) +{ + return (int64_t) PyByteArray_Size(barray); +} + +fz_output *JM_OutFromBarray(fz_context *ctx, PyObject *barray) +{ + fz_output *out = fz_new_output(ctx, 0, barray, JM_WriteBarray, NULL, NULL); + out->seek = JM_SeekDummy; + out->tell = JM_TellBarray; + return out; +} +%} \ No newline at end of file diff --git a/fitz/helper-python.i b/fitz/helper-python.i index 48accb5ed..daa71d08e 100644 --- a/fitz/helper-python.i +++ b/fitz/helper-python.i @@ -79,6 +79,31 @@ Base14_fontdict["tibi"] = "Times-BoldItalic" Base14_fontdict["symb"] = "Symbol" Base14_fontdict["zadb"] = "ZapfDingbats" +def getTextlen(text, fontname="helv", fontsize=12): + fontname = fontname.lower() + basename = Base14_fontdict.get(fontname, None) + + glyphs = None + if basename == "Symbol": + glyphs = symbol_glyphs + 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]) + return w * fontsize + + if fontname in Base14_fontdict.keys(): + return TOOLS.measure_string(text, Base14_fontdict[fontname], fontsize) + + if fontname in ["china-t", "china-s", + "china-ts", "china-ss", + "japan", "japan-s", + "korea", "korea-s"]: + return len(text) * fontsize + + raise ValueError("Font '%s' is unsupported" % fontname) + + #------------------------------------------------------------------------------ # Glyph list for the built-in font 'ZapfDingbats' #------------------------------------------------------------------------------ @@ -437,6 +462,8 @@ def CheckFont(page, fontname): for f in page.getFontList(): if f[4] == fontname: return f + if f[3].lower() == fontname.lower(): + return f return None def CheckFontInfo(doc, xref): diff --git a/fitz/utils.py b/fitz/utils.py index e7dde0359..8d1229899 100644 --- a/fitz/utils.py +++ b/fitz/utils.py @@ -2036,7 +2036,7 @@ def insertText(self, point, buffer, # ensure valid 'fontname' fname = fontname - if fname[0] == "/": + if fname.startswith("/"): fname = fname[1:] xref = self.page.insertFont(fontname = fname, fontfile = fontfile, diff --git a/fitz/version.i b/fitz/version.i index 9350f9170..6edb71315 100644 --- a/fitz/version.i +++ b/fitz/version.i @@ -1,6 +1,6 @@ %pythoncode %{ VersionFitz = "1.14.0" -VersionBind = "1.14.5" -VersionDate = "2019-01-04 10:29:25" -version = (VersionBind, VersionFitz, "20190104102925") +VersionBind = "1.14.6" +VersionDate = "2019-01-14 06:46:06" +version = (VersionBind, VersionFitz, "20190114064606") %} \ No newline at end of file diff --git a/setup.py b/setup.py index 9de937f91..10c70f191 100644 --- a/setup.py +++ b/setup.py @@ -68,7 +68,7 @@ long_desc = "\n".join(long_dtab) setup(name = 'PyMuPDF', - version = "1.14.5", + version = "1.14.6", description = 'Python bindings for the PDF rendering library MuPDF', long_description = long_desc, classifiers = classifier,