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>
13+
14+ namespace py = pybind11;
1615
1716/* *
1817 * An implementation of TTStreamWriter that writes to a Python
1918 * file-like object.
2019 */
2120class PythonFileWriter : public TTStreamWriter
2221{
23- PyObject * _write_method;
22+ py::function _write_method;
2423
2524 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- }
25+ PythonFileWriter (py::object& file_object)
26+ : _write_method(file_object.attr(" write" )) {}
4227
4328 virtual void write (const char *a)
4429 {
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);
30+ PyObject* decoded = PyUnicode_DecodeLatin1 (a, strlen (a), " " );
31+ if (decoded == NULL ) {
32+ throw py::error_already_set ();
5833 }
34+ _write_method (py::handle (decoded));
35+ Py_DECREF (decoded);
5936 }
6037};
6138
62- int fileobject_to_PythonFileWriter (PyObject *object, void *address)
63- {
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- }
71-
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)
39+ static void convert_ttf_to_ps (
40+ const char *filename,
41+ py::object &output,
42+ int fonttype,
43+ py::iterable* glyph_ids)
7944{
80- std::vector<int > *result = (std::vector<int > *)address;
81-
82- PyObject *iterator = PyObject_GetIter (object);
83- if (!iterator) {
84- return 0 ;
85- }
45+ PythonFileWriter output_ (output);
8646
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 ;
47+ std::vector<int > glyph_ids_;
48+ if (glyph_ids) {
49+ for (py::handle glyph_id: *glyph_ids) {
50+ glyph_ids_.push_back (glyph_id.cast <int >());
9351 }
94- result->push_back ((int )value);
95- }
96-
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 ;
12152 }
12253
12354 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 ;
55+ throw py::value_error (
56+ " fonttype must be either 3 (raw Postscript) or 42 (embedded Truetype)" );
12857 }
12958
13059 try
13160 {
132- insert_ttfont (filename, output, ( font_type_enum) fonttype, glyph_ids );
61+ insert_ttfont (filename, output_, static_cast < font_type_enum>( fonttype), glyph_ids_ );
13362 }
13463 catch (TTException &e)
13564 {
136- PyErr_SetString (PyExc_RuntimeError, e.getMessage ());
137- return NULL ;
138- }
139- catch (const py::exception &)
140- {
141- return NULL ;
65+ throw std::runtime_error (e.getMessage ());
14266 }
14367 catch (...)
14468 {
145- PyErr_SetString (PyExc_RuntimeError, " Unknown C++ exception" );
146- return NULL ;
69+ throw std::runtime_error (" Unknown C++ exception" );
14770 }
148-
149- Py_INCREF (Py_None);
150- return Py_None;
15171}
15272
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 "
73+ PYBIND11_MODULE (_ttconv, m) {
74+ m.doc () = " Module to handle converting and subsetting TrueType "
75+ " fonts to Postscript Type 3, Postscript Type 42 and "
76+ " Pdf Type 3 fonts." ;
77+ m.def (" convert_ttf_to_ps" , &convert_ttf_to_ps,
78+ py::arg (" filename" ),
79+ py::arg (" output"
4B92
span> ),
80+ py::arg (" fonttype" ),
81+ py::arg (" glyph_ids" ) = py::none (),
15982 " Converts the Truetype font into a Type 3 or Type 42 Postscript font, "
16083 " optionally subsetting the font to only the desired set of characters.\n "
16184 " \n "
@@ -169,29 +92,5 @@ static PyMethodDef ttconv_methods[] =
16992 " subsetting to a Type 3 font. If glyph_ids is not provided or is None, "
17093 " then all glyphs will be included. If any of the glyphs specified are "
17194 " 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);
95+ );
19596}
196-
197- #pragma GCC visibility pop
0 commit comments