Skip to content

Commit f04475b

Browse files
committed
Add a pybind11 type caster for GCAgg and its requirements
1 parent c23f1b2 commit f04475b

File tree

3 files changed

+119
-46
lines changed

3 files changed

+119
-46
lines changed

src/_backend_agg_wrapper.cpp

Lines changed: 8 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,11 @@ PyBufferRegion_get_extents(BufferRegion *self)
4040

4141
static void
4242
PyRendererAgg_draw_path(RendererAgg *self,
43-
pybind11::object gc_obj,
43+
GCAgg &gc,
4444
mpl::PathIterator path,
4545
agg::trans_affine trans,
4646
agg::rgba face)
4747
{
48-
GCAgg gc;
49-
50-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
51-
throw pybind11::error_already_set();
52-
}
53-
5448
self->draw_path(gc, path, trans, face);
5549
}
5650

@@ -60,52 +54,38 @@ PyRendererAgg_draw_text_image(RendererAgg *self,
6054
double x,
6155
double y,
6256
double angle,
63-
pybind11::object gc_obj)
57+
GCAgg &gc)
6458
{
6559
numpy::array_view<agg::int8u, 2> image;
66-
GCAgg gc;
6760

6861
if (!image.converter_contiguous(image_obj.ptr(), &image)) {
6962
throw pybind11::error_already_set();
7063
}
71-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
72-
throw pybind11::error_already_set();
73-
}
7464

7565
self->draw_text_image(gc, image, x, y, angle);
7666
}
7767

7868
static void
7969
PyRendererAgg_draw_markers(RendererAgg *self,
80-
pybind11::object gc_obj,
70+
GCAgg &gc,
8171
mpl::PathIterator marker_path,
8272
agg::trans_affine marker_path_trans,
8373
mpl::PathIterator path,
8474
agg::trans_affine trans,
8575
agg::rgba face)
8676
{
87-
GCAgg gc;
88-
89-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
90-
throw pybind11::error_already_set();
91-
}
92-
9377
self->draw_markers(gc, marker_path, marker_path_trans, path, trans, face);
9478
}
9579

9680
static void
9781
PyRendererAgg_draw_image(RendererAgg *self,
98-
pybind11::object gc_obj,
82+
GCAgg &gc,
9983
double x,
10084
double y,
10185
pybind11::array_t<agg::int8u, pybind11::array::c_style> image_obj)
10286
{
103-
GCAgg gc;
10487
numpy::array_view<agg::int8u, 3> image;
10588

106-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
107-
throw pybind11::error_already_set();
108-
}
10989
if (!image.set(image_obj.ptr())) {
11090
throw pybind11::error_already_set();
11191
}
@@ -119,7 +99,7 @@ PyRendererAgg_draw_image(RendererAgg *self,
11999

120100
static void
121101
PyRendererAgg_draw_path_collection(RendererAgg *self,
122-
pybind11::object gc_obj,
102+
GCAgg &gc,
123103
agg::trans_affine master_transform,
124104
pybind11::object paths_obj,
125105
pybind11::object transforms_obj,
@@ -128,25 +108,20 @@ PyRendererAgg_draw_path_collection(RendererAgg *self,
128108
pybind11::object facecolors_obj,
129109
pybind11::object edgecolors_obj,
130110
pybind11::object linewidths_obj,
131-
pybind11::object dashes_obj,
111+
DashesVector dashes,
132112
pybind11::object antialiaseds_obj,
133113
pybind11::object Py_UNUSED(ignored_obj),
134114
// offset position is no longer used
135115
pybind11::object Py_UNUSED(offset_position_obj))
136116
{
137-
GCAgg gc;
138117
mpl::PathGenerator paths;
139118
numpy::array_view<const double, 3> transforms;
140119
numpy::array_view<const double, 2> offsets;
141120
numpy::array_view<const double, 2> facecolors;
142121
numpy::array_view<const double, 2> edgecolors;
143122
numpy::array_view<const double, 1> linewidths;
144-
DashesVector dashes;
145123
numpy::array_view<const uint8_t, 1> antialiaseds;
146124

147-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
148-
throw pybind11::error_already_set();
149-
}
150125
if (!convert_pathgen(paths_obj.ptr(), &paths)) {
151126
throw pybind11::error_already_set();
152127
}
@@ -165,9 +140,6 @@ PyRendererAgg_draw_path_collection(RendererAgg *self,
165140
if (!linewidths.converter(linewidths_obj.ptr(), &linewidths)) {
166141
throw pybind11::error_already_set();
167142
}
168-
if (!convert_dashes_vector(dashes_obj.ptr(), &dashes)) {
169-
throw pybind11::error_already_set();
170-
}
171143
if (!antialiaseds.converter(antialiaseds_obj.ptr(), &antialiaseds)) {
172144
throw pybind11::error_already_set();
173145
}
@@ -187,7 +159,7 @@ PyRendererAgg_draw_path_collection(RendererAgg *self,
187159

188160
static void
189161
PyRendererAgg_draw_quad_mesh(RendererAgg *self,
190-
pybind11::object gc_obj,
162+
GCAgg &gc,
191163
agg::trans_affine master_transform,
192164
unsigned int mesh_width,
193165
unsigned int mesh_height,
@@ -198,15 +170,11 @@ PyRendererAgg_draw_quad_mesh(RendererAgg *self,
198170
bool antialiased,
199171
pybind11::object edgecolors_obj)
200172
{
201-
GCAgg gc;
202173
numpy::array_view<const double, 3> coordinates;
203174
numpy::array_view<const double, 2> offsets;
204175
numpy::array_view<const double, 2> facecolors;
205176
numpy::array_view<const double, 2> edgecolors;
206177

207-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
208-
throw pybind11::error_already_set();
209-
}
210178
if (!coordinates.converter(coordinates_obj.ptr(), &coordinates)) {
211179
throw pybind11::error_already_set();
212180
}
@@ -234,18 +202,14 @@ PyRendererAgg_draw_quad_mesh(RendererAgg *self,
234202

235203
static void
236204
PyRendererAgg_draw_gouraud_triangles(RendererAgg *self,
237-
pybind11::object gc_obj,
205+
GCAgg &gc,
238206
pybind11::object points_obj,
239207
pybind11::object colors_obj,
240208
agg::trans_affine trans)
241209
{
242-
GCAgg gc;
243210
numpy::array_view<const double, 3> points;
244211
numpy::array_view<const double, 3> colors;
245212

246-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
247-
throw pybind11::error_already_set();
248-
}
249213
if (!points.converter(points_obj.ptr(), &points)) {
250214
throw pybind11::error_already_set();
251215
}

src/py_converters.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,6 @@ int convert_pathgen(PyObject *obj, void *pathgenp)
415415
int convert_clippath(PyObject *clippath_tuple, void *clippathp)
416416
{
417417
ClipPath *clippath = (ClipPath *)clippathp;
418-
mpl::PathIterator path;
419-
agg::trans_affine trans;
420418

421419
if (clippath_tuple != NULL && clippath_tuple != Py_None) {
422420
if (!PyArg_ParseTuple(clippath_tuple,

src/py_converters_11.h

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
// pybind11 equivalent of py_converters.h
55

6+
#include <map>
7+
68
#include <pybind11/pybind11.h>
79
#include <pybind11/numpy.h>
810

@@ -135,6 +137,37 @@ namespace PYBIND11_NAMESPACE { namespace detail {
135137

136138
/* Remove all this macro magic after dropping NumPy usage and just include `py_adaptors.h`. */
137139
#ifdef MPL_PY_ADAPTORS_H
140+
template <> struct type_caster<agg::line_cap_e> {
141+
public:
142+
PYBIND11_TYPE_CASTER(agg::line_cap_e, const_name("line_cap_e"));
143+
144+
bool load(handle src, bool) {
145+
const std::map<std::string, agg::line_cap_e> enum_values = {
146+
{"butt", agg::butt_cap},
147+
{"round", agg::round_cap},
148+
{"projecting", agg::square_cap},
149+
};
150+
value = enum_values.at(src.cast<std::string>());
151+
return true;
152+
}
153+
};
154+
155+
template <> struct type_caster<agg::line_join_e> {
156+
public:
157+
PYBIND11_TYPE_CASTER(agg::line_join_e, const_name("line_join_e"));
158+
159+
bool load(handle src, bool) {
160+
const std::map<std::string, agg::line_join_e> enum_values = {
161+
{"miter", agg::miter_join_revert},
162+
{"round", agg::round_join},
163+
{"bevel", agg::bevel_join},
164+
};
165+
value = agg::miter_join_revert;
166+
value = enum_values.at(src.cast<std::string>());
167+
return true;
168+
}
169+
};
170+
138171
template <> struct type_caster<mpl::PathIterator> {
139172
public:
140173
PYBIND11_TYPE_CASTER(mpl::PathIterator, const_name("PathIterator"));
@@ -161,6 +194,59 @@ namespace PYBIND11_NAMESPACE { namespace detail {
161194

162195
/* Remove all this macro magic after dropping NumPy usage and just include `_backend_agg_basic_types.h`. */
163196
#ifdef MPL_BACKEND_AGG_BASIC_TYPES_H
197+
template <> struct type_caster<ClipPath> {
198+
public:
199+
PYBIND11_TYPE_CASTER(ClipPath, const_name("ClipPath"));
200+
201+
bool load(handle src, bool) {
202+
if (src.is_none()) {
203+
return true;
204+
}
205+
206+
auto clippath_tuple = src.cast<std::tuple<pybind11::object, agg::trans_affine>>();
207+
208+
if (!convert_path(std::get<0>(clippath_tuple).ptr(), &value.path)) {
209+
throw pybind11::error_already_set();
210+
}
211+
value.trans = std::get<1>(clippath_tuple);
212+
213+
return true;
214+
}
215+
};
216+
217+
template <> struct type_caster<Dashes> {
218+
public:
219+
PYBIND11_TYPE_CASTER(Dashes, const_name("Dashes"));
220+
221+
bool load(handle src, bool) {
222+
auto dash_tuple = src.cast<std::tuple<double, pybind11::object>>();
223+
auto dash_offset = std::get<0>(dash_tuple);
224+
auto dashes_seq_or_none = std::get<1>(dash_tuple);
225+
226+
if (dashes_seq_or_none.is_none()) {
227+
return true;
228+
}
229+
230+
auto dashes_seq = dashes_seq_or_none.cast<pybind11::sequence>();
231+
232+
auto nentries = dashes_seq.size();
233+
// If the dashpattern has odd length, iterate through it twice (in
234+
// accordance with the pdf/ps/svg specs).
235+
auto dash_pattern_length = (nentries % 2) ? 2 * nentries : nentries;
236+
237+
for (pybind11::size_t i = 0; i < dash_pattern_length; i += 2) {
238+
auto length = dashes_seq[i % nentries].cast<double>();
239+
auto skip = dashes_seq[(i + 1) % nentries].cast<double>();
240+
241+
value.add_dash_pair(length, skip);
242+
}
243+
244+
value.set_dash_offset(dash_offset);
245+
246+
return true;
247+
}
248+
};
249+
164250
template <> struct type_caster<SketchParams> {
165251
public:
166252
PYBIND11_TYPE_CASTER(SketchParams, const_name("SketchParams"));
@@ -177,6 +263,31 @@ namespace PYBIND11_NAMESPACE { namespace detail {
177263
return true;
178264
}
179265
};
266+
267+
template <> struct type_caster<GCAgg> {
268+
public:
269+
PYBIND11_TYPE_CASTER(GCAgg, const_name("GCAgg"));
270+
271+
bool load(handle src, bool) {
272+
value.linewidth = src.attr("_linewidth").cast<double>();
273+
value.alpha = src.attr("_alpha").cast<double>();
274+
value.forced_alpha = src.attr("_forced_alpha").cast<bool>();
275+
value.color = src.attr("_rgb").cast<agg::rgba>();
276+
value.isaa = src.attr("_antialiased").cast<bool>();
277+
value.cap = src.attr("_capstyle").cast<agg::line_cap_e>();
278+
value.join = src.attr("_joinstyle").cast<agg::line_join_e>();
279+
value.dashes = src.attr("get_dashes")().cast<Dashes>();
280+
value.cliprect = src.attr("_cliprect").cast<agg::rect_d>();
281+
value.clippath = src.attr("get_clip_path")().cast<ClipPath>();
282+
value.snap_mode = src.attr("get_snap")().cast<e_snap_mode>();
283+
value.hatchpath = src.attr("get_hatch_path")().cast<mpl::PathIterator>();
284+
value.hatch_color = src.attr("get_hatch_color")().cast<agg::rgba>();
285+
value.hatch_linewidth = src.attr("get_hatch_linewidth")().cast<double>();
286+
value.sketch = src.attr("get_sketch_params")().cast<SketchParams>();
287+
288+
return true;
289+
}
290+
};
180291
#endif
181292
}} // namespace PYBIND11_NAMESPACE::detail
182293

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy