Skip to content

Commit 2d7de1b

Browse files
committed
Add a pybind11 type caster for GCAgg and its requirements
1 parent 3a30cbc commit 2d7de1b

File tree

3 files changed

+120
-46
lines changed

3 files changed

+120
-46
lines changed

src/_backend_agg_wrapper.cpp

Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <pybind11/pybind11.h>
22
#include <pybind11/numpy.h>
3+
#include <pybind11/stl.h>
34
#include "mplutils.h"
45
#include "numpy_cpp.h"
56
#include "py_converters.h"
@@ -40,17 +41,11 @@ PyBufferRegion_get_extents(BufferRegion *self)
4041

4142
static void
4243
PyRendererAgg_draw_path(RendererAgg *self,
43-
pybind11::object gc_obj,
44+
GCAgg &gc,
4445
mpl::PathIterator path,
4546
agg::trans_affine trans,
4647
agg::rgba face)
4748
{
48-
GCAgg gc;
49-
50-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
51-
throw pybind11::error_already_set();
52-
}
53-
5449
self->draw_path(gc, path, trans, face);
5550
}
5651

@@ -60,52 +55,38 @@ PyRendererAgg_draw_text_image(RendererAgg *self,
6055
double x,
6156
double y,
6257
double angle,
63-
pybind11::object gc_obj)
58+
GCAgg &gc)
6459
{
6560
numpy::array_view<agg::int8u, 2> image;
66-
GCAgg gc;
6761

6862
if (!image.converter_contiguous(image_obj.ptr(), &image)) {
6963
throw pybind11::error_already_set();
7064
}
71-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
72-
throw pybind11::error_already_set();
73-
}
7465

7566
self->draw_text_image(gc, image, x, y, angle);
7667
}
7768

7869
static void
7970
PyRendererAgg_draw_markers(RendererAgg *self,
80-
pybind11::object gc_obj,
71+
GCAgg &gc,
8172
mpl::PathIterator marker_path,
8273
agg::trans_affine marker_path_trans,
8374
mpl::PathIterator path,
8475
agg::trans_affine trans,
8576
agg::rgba face)
8677
{
87-
GCAgg gc;
88-
89-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
90-
throw pybind11::error_already_set();
91-
}
92-
9378
self->draw_markers(gc, marker_path, marker_path_trans, path, trans, face);
9479
}
9580

9681
static void
9782
PyRendererAgg_draw_image(RendererAgg *self,
98-
pybind11::object gc_obj,
83+
GCAgg &gc,
9984
double x,
10085
double y,
10186
pybind11::array_t<agg::int8u, pybind11::array::c_style> image_obj)
10287
{
103-
GCAgg gc;
10488
numpy::array_view<agg::int8u, 3> image;
10589

106-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
107-
throw pybind11::error_already_set();
108-
}
10990
if (!image.set(image_obj.ptr())) {
11091
throw pybind11::error_already_set();
11192
}
@@ -119,7 +100,7 @@ PyRendererAgg_draw_image(RendererAgg *self,
119100

120101
static void
121102
PyRendererAgg_draw_path_collection(RendererAgg *self,
122-
pybind11::object gc_obj,
103+
GCAgg &gc,
123104
agg::trans_affine master_transform,
124105
pybind11::object paths_obj,
125106
pybind11::object transforms_obj,
@@ -128,25 +109,20 @@ PyRendererAgg_draw_path_collection(RendererAgg *self,
128109
pybind11::object facecolors_obj,
129110
pybind11::object edgecolors_obj,
130111
pybind11::object linewidths_obj,
131-
pybind11::object dashes_obj,
112+
DashesVector dashes,
132113
pybind11::object antialiaseds_obj,
133114
pybind11::object Py_UNUSED(ignored_obj),
134115
// offset position is no longer used
135116
pybind11::object Py_UNUSED(offset_position_obj))
136117
{
137-
GCAgg gc;
138118
mpl::PathGenerator paths;
139119
numpy::array_view<const double, 3> transforms;
140120
numpy::array_view<const double, 2> offsets;
141121
numpy::array_view<const double, 2> facecolors;
142122
numpy::array_view<const double, 2> edgecolors;
143123
numpy::array_view<const double, 1> linewidths;
144-
DashesVector dashes;
145124
numpy::array_view<const uint8_t, 1> antialiaseds;
146125

147-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
148-
throw pybind11::error_already_set();
149-
}
150126
if (!convert_pathgen(paths_obj.ptr(), &paths)) {
151127
throw pybind11::error_already_set();
152128
}
@@ -165,9 +141,6 @@ PyRendererAgg_draw_path_collection(RendererAgg *self,
165141
if (!linewidths.converter(linewidths_obj.ptr(), &linewidths)) {
166142
throw pybind11::error_already_set();
167143
}
168-
if (!convert_dashes_vector(dashes_obj.ptr(), &dashes)) {
169-
throw pybind11::error_already_set();
170-
}
171144
if (!antialiaseds.converter(antialiaseds_obj.ptr(), &antialiaseds)) {
172145
throw pybind11::error_already_set();
173146
}
@@ -187,7 +160,7 @@ PyRendererAgg_draw_path_collection(RendererAgg *self,
187160

188161
static void
189162
PyRendererAgg_draw_quad_mesh(RendererAgg *self,
190-
pybind11::object gc_obj,
163+
GCAgg &gc,
191164
agg::trans_affine master_transform,
192165
unsigned int mesh_width,
193166
unsigned int mesh_height,
@@ -198,15 +171,11 @@ PyRendererAgg_draw_quad_mesh(RendererAgg *self,
198171
bool antialiased,
199172
pybind11::object edgecolors_obj)
200173
{
201-
GCAgg gc;
202174
numpy::array_view<const double, 3> coordinates;
203175
numpy::array_view<const double, 2> offsets;
204176
numpy::array_view<const double, 2> facecolors;
205177
numpy::array_view<const double, 2> edgecolors;
206178

207-
if (!convert_gcagg(gc_obj.ptr(), &gc)) {
208-
throw pybind11::error_already_set();
209-
}
210179
if (!coordinates.converter(coordinates_obj.ptr(), &coordinates)) {
211180
throw pybind11::error_already_set();
212181
}
@@ -234,18 +203,14 @@ PyRendererAgg_draw_quad_mesh(RendererAgg *self,
234203

235204
static void
236205
PyRendererAgg_draw_gouraud_triangles(RendererAgg *self,
237-
pybind11::object gc_obj,
206+
GCAgg &gc,
238207
pybind11::object points_obj,
239208
pybind11::object colors_obj,
240209
agg::trans_affine trans)
241210
{
242-
GCAgg gc;
243211
numpy::array_view<const double, 3> points;
244212
numpy::array_view<const double, 3> colors;
245213

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

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
@@ -8,6 +8,8 @@
88

99
namespace py = pybind11;
1010

11+
#include <map>
12+
1113
#include "agg_basics.h"
1214
#include "agg_color_rgba.h"
1315
#include "agg_trans_affine.h"
@@ -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