5
5
6
6
Python wrapper for TrueType conversion library in ../ttconv.
7
7
*/
8
- #define PY_SSIZE_T_CLEAN
9
8
#include " mplutils.h"
10
9
11
- #include < Python .h>
10
+ #include < pybind11/pybind11 .h>
12
11
#include " ttconv/pprdrv.h"
13
- #include " py_exceptions.h"
14
12
#include < vector>
15
- #include < cassert>
13
+
14
+ namespace py = pybind11;
16
15
17
16
/* *
18
17
* An implementation of TTStreamWriter that writes to a Python
19
18
* file-like object.
20
19
*/
21
20
class PythonFileWriter : public TTStreamWriter
22
21
{
23
- PyObject * _write_method;
22
+ py::function _write_method;
24
23
25
24
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" )) {}
42
27
43
28
virtual void write (const char *a)
44
29
{
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 ();
58
33
}
34
+ _write_method (py::handle (decoded));
35
+ Py_DECREF (decoded);
59
36
}
60
37
};
61
38
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)
79
44
{
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);
86
46
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 >());
93
51
}
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 ;
121
52
}
122
53
123
54
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)" );
128
57
}
129
58
130
59
try
131
60
{
132
- insert_ttfont (filename, output, ( font_type_enum) fonttype, glyph_ids );
61
+ insert_ttfont (filename, output_, static_cast < font_type_enum>( fonttype), glyph_ids_ );
133
62
}
134
63
catch (TTException &e)
135
64
{
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 ());
142
66
}
143
67
catch (...)
144
68
{
145
- PyErr_SetString (PyExc_RuntimeError, " Unknown C++ exception" );
146
- return NULL ;
69
+ throw std::runtime_error (" Unknown C++ exception" );
147
70
}
148
-
149
- Py_INCREF (Py_None);
150
- return Py_None;
151
71
}
152
72
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" ),
80
+ py::arg (" fonttype" ),
81
+ py::arg (" glyph_ids" ) = py::none (),
159
82
" Converts the Truetype font into a Type 3 or Type 42 Postscript font, "
160
83
" optionally subsetting the font to only the desired set of characters.\n "
161
84
" \n "
@@ -169,29 +92,5 @@ static PyMethodDef ttconv_methods[] =
169
92
" subsetting to a Type 3 font. If glyph_ids is not provided or is None, "
170
93
" then all glyphs will be included. If any of the glyphs specified are "
171
94
" 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
+ );
195
96
}
196
-
197
- #pragma GCC visibility pop
0 commit comments