55
66 Python wrapper for TrueType conversion library in ../ttconv.
77 */
8- #define PY_SSIZE_T_CLEAN
98#include " mplutils.h"
109
11- #include < Python .h>
10+ #include < pybind11/pybind11 .h>
1211#include " ttconv/pprdrv.h"
13- #include " py_exceptions.h"
1412#include < vector>
15- #include < cassert>
1613
1714/* *
1815 * An implementation of TTStreamWriter that writes to a Python
1916 * file-like object.
2017 */
2118class PythonFileWriter : public TTStreamWriter
2219{
23- PyObject * _write_method;
20+ pybind11::function _write_method;
2421
2522 public:
26- PythonFileWriter ()
27- {
28- _write_method = NULL ;
29- }
30-
31- ~PythonFileWriter ()
32- {
33- Py_XDECREF (_write_method);
34- }
35-
36- void set (PyObject *write_method)
37- {
38- Py_XDECREF (_write_method);
39- _write_method = write_method;
40- Py_XINCREF (_write_method);
41- }
23+ PythonFileWriter (pybind11::object& file_object)
24+ : _write_method(file_object.attr(" write" )) {}
4225
4326 virtual void write (const char *a)
4427 {
45- PyObject *result = NULL ;
46- if (_write_method) {
47- PyObject *decoded = NULL ;
48- decoded = PyUnicode_DecodeLatin1 (a, strlen (a), " " );
49- if (decoded == NULL ) {
50- throw py::exception ();
51- }
52- result = PyObject_CallFunctionObjArgs (_write_method, decoded, NULL );
53- Py_DECREF (decoded);
54- if (!result) {
55- throw py::exception ();
56- }
57- Py_DECREF (result);
28+ PyObject* decoded = PyUnicode_DecodeLatin1 (a, strlen (a), " " );
29+ if (decoded == NULL ) {
30+ throw pybind11::error_already_set ();
5831 }
32+ _write_method (pybind11::handle (decoded));
33+ Py_DECREF (decoded);
5934 }
6035};
6136
62- int fileobject_to_PythonFileWriter (PyObject *object, void *address)
37+ static void convert_ttf_to_ps (
38+ const char *filename,
39+ pybind11::object &output,
40+ int fonttype,
41+ pybind11::iterable* glyph_ids)
6342{
64- PythonFileWriter *file_writer = (PythonFileWriter *)address;
65-
66- PyObject *write_method = PyObject_GetAttrString (object, " write" );
67- if (write_method == NULL || !PyCallable_Check (write_method)) {
68- PyErr_SetString (PyExc_TypeError, " Expected a file-like object with a write method." );
69- return 0 ;
70- }
43+ PythonFileWriter output_ (output);
7144
72- file_writer->set (write_method);
73- Py_DECREF (write_method);
74-
75- return 1 ;
76- }
77-
78- int pyiterable_to_vector_int (PyObject *object, void *address)
79- {
80- std::vector<int > *result = (std::vector<int > *)address;
81-
82- PyObject *iterator = PyObject_GetIter (object);
83- if (!iterator) {
84- return 0 ;
85- }
86-
87- PyObject *item;
88- while ((item = PyIter_Next (iterator))) {
89- long value = PyLong_AsLong (item);
90- Py_DECREF (item);
91- if (value == -1 && PyErr_Occurred ()) {
92- return 0 ;
45+ std::vector<int > glyph_ids_;
46+ if (glyph_ids) {
47+ for (pybind11::handle glyph_id: *glyph_ids) {
48+ glyph_ids_.push_back (glyph_id.cast <int >());
9349 }
94- result->push_back ((int )value);
9550 }
9651
97- Py_DECREF (iterator);
98-
99- return 1 ;
100- }
101-
102- static PyObject *convert_ttf_to_ps (PyObject *self, PyObject *args, PyObject *kwds)
103- {
104- const char *filename;
105- PythonFileWriter output;
106- int fonttype;
107- std::vector<int > glyph_ids;
108-
109- static const char *kwlist[] = { " filename" , " output" , " fonttype" , " glyph_ids" , NULL };
110- if (!PyArg_ParseTupleAndKeywords (args,
111- kwds,
112- " yO&i|O&:convert_ttf_to_ps" ,
113- (char **)kwlist,
114- &filename,
115- fileobject_to_PythonFileWriter,
116- &output,
117- &fonttype,
118- pyiterable_to_vector_int,
119- &glyph_ids)) {
120- return NULL ;
121- }
12252
12353 if (fonttype != 3 && fonttype != 42 ) {
124- PyErr_SetString (PyExc_ValueError,
125- " fonttype must be either 3 (raw Postscript) or 42 "
126- " (embedded Truetype)" );
127- return NULL ;
54+ throw pybind11::value_error (
55+ " fonttype must be either 3 (raw Postscript) or 42 (embedded Truetype)" );
12856 }
12957
13058 try
13159 {
132- insert_ttfont (filename, output, ( font_type_enum) fonttype, glyph_ids );
60+ insert_ttfont (filename, output_, static_cast < font_type_enum>( fonttype), glyph_ids_ );
13361 }
13462 catch (TTException &e)
13563 {
136- PyErr_SetString (PyExc_RuntimeError, e.getMessage ());
137- return NULL ;
138- }
139- catch (const py::exception &)
140- {
141- return NULL ;
64+ throw std::runtime_error (e.getMessage ());
14265 }
14366 catch (...)
14467 {
145- PyErr_SetString (PyExc_RuntimeError, " Unknown C++ exception" );
146- return NULL ;
68+ throw std::runtime_error (" Unknown C++ exception" );
14769 }
148-
149- Py_INCREF (Py_None);
150- return Py_None;
15170}
15271
153- static PyMethodDef ttconv_methods[] =
154- {
155- {
156- " convert_ttf_to_ps" , (PyCFunction)convert_ttf_to_ps, METH_VARARGS | METH_KEYWORDS,
157- " convert_ttf_to_ps(filename, output, fonttype, glyph_ids)\n "
158- " \n "
72+ PYBIND11_MODULE (_ttconv, m) {
73+ m.doc () = " Module to handle converting and subsetting TrueType "
74+ " fonts to Postscript Type 3, Postscript Type 42 and "
75+ " Pdf Type 3 fonts." ;
76+ m.def (" convert_ttf_to_ps" , &convert_ttf_to_ps,
77+ pybind11::arg (" filename" ),
78+ pybind11::arg (" output" ),
79+ pybind11::arg (" fonttype" ),
80+ pybind11::arg (" glyph_ids" ) = pybind11::none (),
15981 " Converts the Truetype font into a Type 3 or Type 42 Postscript font, "
16082 " optionally subsetting the font to only the desired set of characters.\n "
16183 " \n "
@@ -169,29 +91,5 @@ static PyMethodDef ttconv_methods[] =
16991 " subsetting to a Type 3 font. If glyph_ids is not provided or is None, "
17092 " then all glyphs will be included. If any of the glyphs specified are "
17193 " composite glyphs, then the component glyphs will also be included."
172- },
173- {0 , 0 , 0 , 0 } /* Sentinel */
174- };
175-
176- static const char *module_docstring =
177- " Module to handle converting and subsetting TrueType "
178- " fonts to Postscript Type 3, Postscript Type 42 and "
179- " Pdf Type 3 fonts." ;
180-
181- static PyModuleDef ttconv_module = {
182- PyModuleDef_HEAD_INIT,
183- " ttconv" ,
184- module_docstring,
185- -1 ,
186- ttconv_methods,
187- };
188-
189- #pragma GCC visibility push(default)
190-
191- PyMODINIT_FUNC
192- PyInit__ttconv (void )
193- {
194- return PyModule_Create (&ttconv_module);
94+ );
19595}
196-
197- #pragma GCC visibility pop
0 commit comments