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

Skip to content

Commit f14a566

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

File tree

2 files changed

+36
-140
lines changed

2 files changed

+36
-140
lines changed

setupext.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,14 +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"])
478+
include_dirs=["extern"],
479+
cxx_std=11)
479480
add_numpy_flags(ext)
480481
yield ext
481482

src/_ttconv.cpp

Lines changed: 33 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -5,157 +5,76 @@
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
*/
2118
class 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)
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-
}
F438
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)
37+
static void convert_ttf_to_ps(
38+
const char *filename,
39+
pybind11::object &output,
40+
int fonttype,
41+
pybind11::iterable glyph_ids)
7942
{
80-
std::vector<int> *result = (std::vector<int> *)address;
43+
PythonFileWriter output_(output);
44+
std::vector<int> glyph_ids_;
8145

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;
93-
}
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;
46+
for (pybind11::handle glyph_id: glyph_ids) {
47+
glyph_ids_.push_back(glyph_id.cast<int>());
12148
}
12249

12350
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;
51+
throw pybind11::value_error(
52+
"fonttype must be either 3 (raw Postscript) or 42 (embedded Truetype)");
12853
}
12954

13055
try
13156
{
132-
insert_ttfont(filename, output, (font_type_enum)fonttype, glyph_ids);
57+
insert_ttfont(filename, output_, static_cast<font_type_enum>(fonttype), glyph_ids_);
13358
}
13459
catch (TTException &e)
13560
{
136-
PyErr_SetString(PyExc_RuntimeError, e.getMessage());
137-
return NULL;
138-
}
139-
catch (const py::exception &)
140-
{
141-
return NULL;
61+
throw std::runtime_error(e.getMessage());
14262
}
14363
catch (...)
14464
{
145-
PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception");
146-
return NULL;
65+
throw std::runtime_error("Unknown C++ exception");
14766
}
148-
149-
Py_INCREF(Py_None);
150-
return Py_None;
15167
}
15268

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"
69+
PYBIND11_MODULE(_ttconv, m) {
70+
m.doc() = "Module to handle converting and subsetting TrueType "
71+
"fonts to Postscript Type 3, Postscript Type 42 and "
72+
"Pdf Type 3 fonts.";
73+
m.def("convert_ttf_to_ps", &convert_ttf_to_ps,
74+
pybind11::arg("filename"),
75+
pybind11::arg("output"),
76+
pybind11::arg("fonttype"),
77+
pybind11::arg("glyph_ids"),
15978
"Converts the Truetype font into a Type 3 or Type 42 Postscript font, "
16079
"optionally subsetting the font to only the desired set of characters.\n"
16180
"\n"
@@ -169,29 +88,5 @@ static PyMethodDef ttconv_methods[] =
16988
"subsetting to a Type 3 font. If glyph_ids is not provided or is None, "
17089
"then all glyphs will be included. If any of the glyphs specified are "
17190
"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);
91+
);
19592
}
196-
197-
#pragma GCC visibility pop

0 commit comments

Comments
 (0)
0