8
8
* structures to C++ and Agg-friendly interfaces.
9
9
*/
10
10
11
- #include < Python.h>
12
-
13
- #include " numpy/arrayobject.h"
11
+ #include < pybind11/pybind11.h>
12
+ #include < pybind11/numpy.h>
14
13
15
14
#include " agg_basics.h"
16
- #include " py_exceptions.h"
17
15
18
- extern " C" {
19
- int convert_path (PyObject *obj, void *pathp);
20
- }
16
+ namespace py = pybind11;
21
17
22
18
namespace mpl {
23
19
@@ -35,8 +31,8 @@ class PathIterator
35
31
underlying data arrays, so that Python reference counting
36
32
can work.
37
33
*/
38
- PyArrayObject * m_vertices;
39
- PyArrayObject * m_codes;
34
+ py:: array_t < double > m_vertices;
35
+ py:: array_t < uint8_t > m_codes;
40
36
41
37
unsigned m_iterator;
42
38
unsigned m_total_vertices;
@@ -50,38 +46,29 @@ class PathIterator
50
46
51
47
public:
52
48
inline PathIterator ()
53
- : m_vertices(NULL ),
54
- m_codes(NULL ),
55
- m_iterator(0 ),
49
+ : m_iterator(0 ),
56
50
m_total_vertices(0 ),
57
51
m_should_simplify(false ),
58
52
m_simplify_threshold(1.0 / 9.0 )
59
53
{
60
54
}
61
55
62
- inline PathIterator (PyObject *vertices,
63
- PyObject *codes,
64
- bool should_simplify,
56
+ inline PathIterator (py::object vertices, py::object codes, bool should_simplify,
65
57
double simplify_threshold)
66
- : m_vertices( NULL ), m_codes( NULL ), m_iterator(0 )
58
+ : m_iterator(0 )
67
59
{
68
- if (!set (vertices, codes, should_simplify, simplify_threshold))
69
- throw mpl::exception ();
60
+ set (vertices, codes, should_simplify, simplify_threshold);
70
61
}
71
62
72
- inline PathIterator (PyObject * vertices, PyObject * codes)
73
- : m_vertices( NULL ), m_codes( NULL ), m_iterator(0 )
63
+ inline PathIterator (py::object vertices, py::object codes)
64
+ : m_iterator(0 )
74
65
{
75
- if (!set (vertices, codes))
76
- throw mpl::exception ();
66
+ set (vertices, codes);
77
67
}
78
68
79
69
inline PathIterator (const PathIterator &other)
80
70
{
81
- Py_XINCREF (other.m_vertices );
82
71
m_vertices = other.m_vertices ;
83
-
84
- Py_XINCREF (other.m_codes );
85
72
m_codes = other.m_codes ;
86
73
87
74
m_iterator = 0 ;
@@ -91,47 +78,45 @@ class PathIterator
91
78
m_simplify_threshold = other.m_simplify_threshold ;
92
79
}
93
80
94
- ~PathIterator ()
95
- {
96
- Py_XDECREF (m_vertices);
97
- Py_XDECREF (m_codes);
98
- }
99
-
100
- inline int
101
- set (PyObject *vertices, PyObject *codes, bool should_simplify, double simplify_threshold)
81
+ inline void
82
+ set (py::object vertices, py::object codes, bool should_simplify, double simplify_threshold)
102
83
{
103
84
m_should_simplify = should_simplify;
104
85
m_simplify_threshold = simplify_threshold;
105
86
106
- Py_XDECREF (m_vertices);
107
- m_vertices = (PyArrayObject *)PyArray_FromObject (vertices, NPY_DOUBLE, 2 , 2 );
108
-
109
- if (!m_vertices || PyArray_DIM (m_vertices, 1 ) != 2 ) {
110
- PyErr_SetString (PyExc_ValueError, " Invalid vertices array" );
111
- return 0 ;
87
+ m_vertices = vertices.cast <py::array_t <double >>();
88
+ if (m_vertices.ndim () != 2 || m_vertices.shape (1 ) != 2 ) {
89
+ throw py::value_error (" Invalid vertices array" );
112
90
}
91
+ m_total_vertices = m_vertices.shape (0 );
113
92
114
- Py_XDECREF (m_codes);
115
- m_codes = NULL ;
116
-
117
- if (codes != NULL && codes != Py_None) {
118
- m_codes = (PyArrayObject *)PyArray_FromObject (codes, NPY_UINT8, 1 , 1 );
119
-
120
- if (!m_codes || PyArray_DIM (m_codes, 0 ) != PyArray_DIM (m_vertices, 0 )) {
121
- PyErr_SetString (PyExc_ValueError, " Invalid codes array" );
122
- return 0 ;
93
+ m_codes.release ().dec_ref ();
94
+ if (!codes.is_none ()) {
95
+ m_codes = codes.cast <py::array_t <uint8_t >>();
96
+ if (m_codes.ndim () != 1 || m_codes.shape (0 ) != m_total_vertices) {
97
+ throw py::value_error (" Invalid codes array" );
123
98
}
124
99
}
125
100
126
- m_total_vertices = (unsigned )PyArray_DIM (m_vertices, 0 );
127
101
m_iterator = 0 ;
102
+ }
128
103
104
+ inline int
105
+ set (PyObject *vertices, PyObject *codes, bool should_simplify, double simplify_threshold)
106
+ {
107
+ try {
108
+ set (py::reinterpret_borrow<py::object>(vertices),
109
+ py::reinterpret_borrow<py::object>(codes),
110
+ should_simplify, simplify_threshold);
111
+ } catch (const py::error_already_set &) {
112
+ return 0 ;
113
+ }
129
114
return 1 ;
130
115
}
131
116
132
- inline int set (PyObject * vertices, PyObject * codes)
117
+ inline void set (py::object vertices, py::object codes)
133
118
{
134
- return set (vertices, codes, false , 0.0 );
119
+ set (vertices, codes, false , 0.0 );
135
120
}
136
121
137
122
inline unsigned vertex (double *x, double *y)
@@ -144,12 +129,11 @@ class PathIterator
144
129
145
130
const size_t idx = m_iterator++;
146
131
147
- char *pair = (char *)PyArray_GETPTR2 (m_vertices, idx, 0 );
148
- *x = *(double *)pair;
149
- *y = *(double *)(pair + PyArray_STRIDE (m_vertices, 1 ));
132
+ *x = *m_vertices.data (idx, 0 );
133
+ *y = *m_vertices.data (idx, 1 );
150
134
151
- if (m_codes != NULL ) {
152
- return ( unsigned )(*( char *) PyArray_GETPTR1 ( m_codes, idx) );
135
+ if (m_codes) {
136
+ return * m_codes. data ( idx);
153
137
} else {
154
138
return idx == 0 ? agg::path_cmd_move_to : agg::path_cmd_line_to;
155
139
}
@@ -177,42 +161,38 @@ class PathIterator
177
161
178
162
inline bool has_codes () const
179
163
{
180
- return m_codes != NULL ;
164
+ return bool ( m_codes) ;
181
165
}
182
166
183
167
inline void *get_id ()
184
168
{
185
- return (void *)m_vertices;
169
+ return (void *)m_vertices. ptr () ;
186
170
}
187
171
};
188
172
189
173
class PathGenerator
190
174
{
191
- PyObject * m_paths;
175
+ py::sequence m_paths;
192
176
Py_ssize_t m_npaths;
193
177
194
178
public:
195
179
typedef PathIterator path_iterator;
196
180
197
- PathGenerator () : m_paths( NULL ), m_npaths(0 ) {}
181
+ PathGenerator () : m_npaths(0 ) {}
198
182
199
- ~PathGenerator ( )
183
+ void set (py::object obj )
200
184
{
201
- Py_XDECREF (m_paths);
185
+ m_paths = obj.cast <py::sequence>();
186
+ m_npaths = m_paths.size ();
202
187
}
203
188
204
189
int set (PyObject *obj)
205
190
{
206
- if (!PySequence_Check (obj)) {
191
+ try {
192
+ set (py::reinterpret_borrow<py::object>(obj));
193
+ } catch (const py::error_already_set &) {
207
194
return 0 ;
208
195
}
209
-
210
- Py_XDECREF (m_paths);
211
- m_paths = obj;
212
- Py_INCREF (m_paths);
213
-
214
- m_npaths = PySequence_Size (m_paths);
215
-
216
196
return 1 ;
217
197
}
218
198
@@ -229,20 +209,44 @@ class PathGenerator
229
209
path_iterator operator ()(size_t i)
230
210
{
231
211
path_iterator path;
232
- PyObject *item;
233
212
234
- item = PySequence_GetItem (m_paths, i % m_npaths);
235
- if (item == NULL ) {
236
- throw mpl::exception ();
237
- }
238
- if (!convert_path (item, &path)) {
239
- Py_DECREF (item);
240
- throw mpl::exception ();
241
- }
242
- Py_DECREF (item);
213
+ auto item = m_paths[i % m_npaths];
214
+ path = item.cast <path_iterator>();
243
215
return path;
244
216
}
245
217
};
246
218
}
247
219
220
+ namespace PYBIND11_NAMESPACE { namespace detail {
221
+ template <> struct type_caster <mpl::PathIterator> {
222
+ public:
223
+ PYBIND11_TYPE_CASTER (mpl::PathIterator, const_name(" PathIterator" ));
224
+
225
+ bool load (handle src, bool ) {
226
+ if (src.is_none ()) {
227
+ return true ;
228
+ }
229
+
230
+ py::object vertices = src.attr (" vertices" );
231
+ py::object codes = src.attr (" codes" );
232
+ auto should_simplify = src.attr (" should_simplify" ).cast <bool >();
233
+ auto simplify_threshold = src.attr (" simplify_threshold" ).cast <double >();
234
+
235
+ value.set (vertices, codes, should_simplify, simplify_threshold);
236
+
237
+ return true ;
238
+ }
239
+ };
240
+
241
+ template <> struct type_caster <mpl::PathGenerator> {
242
+ public:
243
+ PYBIND11_TYPE_CASTER (mpl::PathGenerator, const_name(" PathGenerator" ));
244
+
245
+ bool load (handle src, bool ) {
246
+ value.set (py::reinterpret_borrow<py::object>(src));
247
+ return true ;
248
+ }
249
+ };
250
+ }} // namespace PYBIND11_NAMESPACE::detail
251
+
248
252
#endif
0 commit comments