diff options
author | shumkovnd <shumkovnd@yandex-team.com> | 2023-11-10 14:39:34 +0300 |
---|---|---|
committer | shumkovnd <shumkovnd@yandex-team.com> | 2023-11-10 16:42:24 +0300 |
commit | 77eb2d3fdcec5c978c64e025ced2764c57c00285 (patch) | |
tree | c51edb0748ca8d4a08d7c7323312c27ba1a8b79a /contrib/python/matplotlib/py2/src/_ttconv.cpp | |
parent | dd6d20cadb65582270ac23f4b3b14ae189704b9d (diff) | |
download | ydb-77eb2d3fdcec5c978c64e025ced2764c57c00285.tar.gz |
KIKIMR-19287: add task_stats_drawing script
Diffstat (limited to 'contrib/python/matplotlib/py2/src/_ttconv.cpp')
-rw-r--r-- | contrib/python/matplotlib/py2/src/_ttconv.cpp | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/contrib/python/matplotlib/py2/src/_ttconv.cpp b/contrib/python/matplotlib/py2/src/_ttconv.cpp new file mode 100644 index 0000000000..e0aa4611d2 --- /dev/null +++ b/contrib/python/matplotlib/py2/src/_ttconv.cpp @@ -0,0 +1,307 @@ +/* -*- mode: c++; c-basic-offset: 4 -*- */ + +/* + _ttconv.c + + Python wrapper for TrueType conversion library in ../ttconv. + */ + +#include "mplutils.h" + +#include <Python.h> +#include "ttconv/pprdrv.h" +#include "py_exceptions.h" +#include <vector> +#include <cassert> + +/** + * An implementation of TTStreamWriter that writes to a Python + * file-like object. + */ +class PythonFileWriter : public TTStreamWriter +{ + PyObject *_write_method; + + public: + PythonFileWriter() + { + _write_method = NULL; + } + + ~PythonFileWriter() + { + Py_XDECREF(_write_method); + } + + void set(PyObject *write_method) + { + Py_XDECREF(_write_method); + _write_method = write_method; + Py_XINCREF(_write_method); + } + + virtual void write(const char *a) + { + PyObject *result = NULL; + if (_write_method) { + PyObject *decoded = NULL; + decoded = PyUnicode_DecodeLatin1(a, strlen(a), ""); + if (decoded == NULL) { + throw py::exception(); + } + result = PyObject_CallFunction(_write_method, (char *)"O", decoded); + Py_DECREF(decoded); + if (!result) { + throw py::exception(); + } + Py_DECREF(result); + } + } +}; + +int fileobject_to_PythonFileWriter(PyObject *object, void *address) +{ + PythonFileWriter *file_writer = (PythonFileWriter *)address; + + PyObject *write_method = PyObject_GetAttrString(object, "write"); + if (write_method == NULL || !PyCallable_Check(write_method)) { + PyErr_SetString(PyExc_TypeError, "Expected a file-like object with a write method."); + return 0; + } + + file_writer->set(write_method); + Py_DECREF(write_method); + + return 1; +} + +int pyiterable_to_vector_int(PyObject *object, void *address) +{ + std::vector<int> *result = (std::vector<int> *)address; + + PyObject *iterator = PyObject_GetIter(object); + if (!iterator) { + return 0; + } + + PyObject *item; + while ((item = PyIter_Next(iterator))) { +#if PY3K + long value = PyLong_AsLong(item); +#else + long value = PyInt_AsLong(item); +#endif + Py_DECREF(item); + if (value == -1 && PyErr_Occurred()) { + return 0; + } + result->push_back((int)value); + } + + Py_DECREF(iterator); + + return 1; +} + +static PyObject *convert_ttf_to_ps(PyObject *self, PyObject *args, PyObject *kwds) +{ + const char *filename; + PythonFileWriter output; + int fonttype; + std::vector<int> glyph_ids; + + static const char *kwlist[] = { "filename", "output", "fonttype", "glyph_ids", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, + kwds, +#if PY_MAJOR_VERSION == 3 + "yO&i|O&:convert_ttf_to_ps", +#else + "sO&i|O&:convert_ttf_to_ps", +#endif + (char **)kwlist, + &filename, + fileobject_to_PythonFileWriter, + &output, + &fonttype, + pyiterable_to_vector_int, + &glyph_ids)) { + return NULL; + } + + if (fonttype != 3 && fonttype != 42) { + PyErr_SetString(PyExc_ValueError, + "fonttype must be either 3 (raw Postscript) or 42 " + "(embedded Truetype)"); + return NULL; + } + + try + { + insert_ttfont(filename, output, (font_type_enum)fonttype, glyph_ids); + } + catch (TTException &e) + { + PyErr_SetString(PyExc_RuntimeError, e.getMessage()); + return NULL; + } + catch (const py::exception &) + { + return NULL; + } + catch (...) + { + PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception"); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +class PythonDictionaryCallback : public TTDictionaryCallback +{ + PyObject *_dict; + + public: + PythonDictionaryCallback(PyObject *dict) + { + _dict = dict; + } + + virtual void add_pair(const char *a, const char *b) + { + assert(a != NULL); + assert(b != NULL); + PyObject *value = PyBytes_FromString(b); + if (!value) { + throw py::exception(); + } + if (PyDict_SetItemString(_dict, a, value)) { + Py_DECREF(value); + throw py::exception(); + } + Py_DECREF(value); + } +}; + +static PyObject *py_get_pdf_charprocs(PyObject *self, PyObject *args, PyObject *kwds) +{ + const char *filename; + std::vector<int> glyph_ids; + PyObject *result; + + static const char *kwlist[] = { "filename", "glyph_ids", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, + kwds, +#if PY_MAJOR_VERSION == 3 + "y|O&:get_pdf_charprocs", +#else + "s|O&:get_pdf_charprocs", +#endif + (char **)kwlist, + &filename, + pyiterable_to_vector_int, + &glyph_ids)) { + return NULL; + } + + result = PyDict_New(); + if (!result) { + return NULL; + } + + PythonDictionaryCallback dict(result); + + try + { + ::get_pdf_charprocs(filename, glyph_ids, dict); + } + catch (TTException &e) + { + Py_DECREF(result); + PyErr_SetString(PyExc_RuntimeError, e.getMessage()); + return NULL; + } + catch (const py::exception &) + { + Py_DECREF(result); + return NULL; + } + catch (...) + { + Py_DECREF(result); + PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception"); + return NULL; + } + + return result; +} + +static PyMethodDef ttconv_methods[] = +{ + { + "convert_ttf_to_ps", (PyCFunction)convert_ttf_to_ps, METH_VARARGS | METH_KEYWORDS, + "convert_ttf_to_ps(filename, output, fonttype, glyph_ids)\n" + "\n" + "Converts the Truetype font into a Type 3 or Type 42 Postscript font, " + "optionally subsetting the font to only the desired set of characters.\n" + "\n" + "filename is the path to a TTF font file.\n" + "output is a Python file-like object with a write method that the Postscript " + "font data will be written to.\n" + "fonttype may be either 3 or 42. Type 3 is a \"raw Postscript\" font. " + "Type 42 is an embedded Truetype font. Glyph subsetting is not supported " + "for Type 42 fonts.\n" + "glyph_ids (optional) is a list of glyph ids (integers) to keep when " + "subsetting to a Type 3 font. If glyph_ids is not provided or is None, " + "then all glyphs will be included. If any of the glyphs specified are " + "composite glyphs, then the component glyphs will also be included." + }, + { + "get_pdf_charprocs", (PyCFunction)py_get_pdf_charprocs, METH_VARARGS | METH_KEYWORDS, + "get_pdf_charprocs(filename, glyph_ids)\n" + "\n" + "Given a Truetype font file, returns a dictionary containing the PDF Type 3\n" + "representation of its paths. Useful for subsetting a Truetype font inside\n" + "of a PDF file.\n" + "\n" + "filename is the path to a TTF font file.\n" + "glyph_ids is a list of the numeric glyph ids to include.\n" + "The return value is a dictionary where the keys are glyph names and\n" + "the values are the stream content needed to render that glyph. This\n" + "is useful to generate the CharProcs dictionary in a PDF Type 3 font.\n" + }, + {0, 0, 0, 0} /* Sentinel */ +}; + +static const char *module_docstring = + "Module to handle converting and subsetting TrueType " + "fonts to Postscript Type 3, Postscript Type 42 and " + "Pdf Type 3 fonts."; + +#if PY3K +static PyModuleDef ttconv_module = { + PyModuleDef_HEAD_INIT, + "ttconv", + module_docstring, + -1, + ttconv_methods, + NULL, NULL, NULL, NULL +}; + +PyMODINIT_FUNC +PyInit_ttconv(void) +{ + PyObject* m; + + m = PyModule_Create(&ttconv_module); + + return m; +} +#else +PyMODINIT_FUNC +initttconv(void) +{ + Py_InitModule3("ttconv", ttconv_methods, module_docstring); +} +#endif |