8000 Use pybind11 in ttconv module · matplotlib/matplotlib@c38348b · GitHub
[go: up one dir, main page]

Skip to content

Commit c38348b

Browse files
committed
Use pybind11 in ttconv module
1 parent 238e275 commit c38348b

File tree

2 files changed

+39
-140
lines changed

2 files changed

+39
-140
lines changed

setupext.py

Lines changed: 3 additions & 3 deletions
10000
Original file line numberDiff line numberDiff line change
@@ -468,15 +468,15 @@ def get_extensions(self):
468468
cxx_std=11)
469469
yield ext
470470
# ttconv
471-
ext = Extension(
471+
ext = Pybind11Extension(
472472
"matplotlib._ttconv", [
473473
"src/_ttconv.cpp",
474474
"extern/ttconv/pprdrv_tt.cpp",
475475
"extern/ttconv/pprdrv_tt2.cpp",
476476
"extern/ttconv/ttutil.cpp",
477477
],
478-
include_dirs=["extern"])
479-
add_numpy_flags(ext)
478+
include_dirs=["extern"],
479+
cxx_std=11)
480480
yield ext
481481

482482

src/_ttconv.cpp

Lines changed: 36 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -5,157 +5,80 @@
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
*/
2120
class 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"),
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

Comments
 (0)
0