Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f8cadb3

Browse files
authored
Merge pull request #28856 from QuLogic/pybind11-finals
Convert remaining code to pybind11
2 parents 7593423 + 37206c2 commit f8cadb3

9 files changed

+395
-424
lines changed

src/_backend_agg_basic_types.h

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
/* Contains some simple types from the Agg backend that are also used
55
by other modules */
66

7+
#include <pybind11/pybind11.h>
8+
9+
#include <unordered_map>
710
#include <vector>
811

912
#include "agg_color_rgba.h"
@@ -13,6 +16,8 @@
1316

1417
#include "py_adaptors.h"
1518

19+
namespace py = pybind11;
20+
1621
struct ClipPath
1722
{
1823
mpl::PathIterator path;
@@ -121,4 +126,132 @@ class GCAgg
121126
GCAgg &operator=(const GCAgg &);
122127
};
123128

129+
namespace PYBIND11_NAMESPACE { namespace detail {
130+
template <> struct type_caster<agg::line_cap_e> {
131+
public:
132+
PYBIND11_TYPE_CASTER(agg::line_cap_e, const_name("line_cap_e"));
133+
134+
bool load(handle src, bool) {
135+
const std::unordered_map<std::string, agg::line_cap_e> enum_values = {
136+
{"butt", agg::butt_cap},
137+
{"round", agg::round_cap},
138+
{"projecting", agg::square_cap},
139+
};
140+
value = enum_values.at(src.cast<std::string>());
141+
return true;
142+
}
143+
};
144+
145+
template <> struct type_caster<agg::line_join_e> {
146+
public:
147+
PYBIND11_TYPE_CASTER(agg::line_join_e, const_name("line_join_e"));
148+
149+
bool load(handle src, bool) {
150+
const std::unordered_map<std::string, agg::line_join_e> enum_values = {
151+
{"miter", agg::miter_join_revert},
152+
{"round", agg::round_join},
153+
{"bevel", agg::bevel_join},
154+
};
155+
value = enum_values.at(src.cast<std::string>());
156+
return true;
157+
}
158+
};
159+
160+
template <> struct type_caster<ClipPath> {
161+
public:
162+
PYBIND11_TYPE_CASTER(ClipPath, const_name("ClipPath"));
163+
164+
bool load(handle src, bool) {
165+
if (src.is_none()) {
166+
return true;
167+
}
168+
169+
auto [path, trans] =
170+
src.cast<std::pair<std::optional<mpl::PathIterator>, agg::trans_affine>>();
171+
if (path) {
172+
value.path = *path;
173+
}
174+
value.trans = trans;
175+
176+
return true;
177+
}
178+
};
179+
180+
template <> struct type_caster<Dashes> {
181+
public:
182+
PYBIND11_TYPE_CASTER(Dashes, const_name("Dashes"));
183+
184+
bool load(handle src, bool) {
185+
auto [dash_offset, dashes_seq_or_none] =
186+
src.cast<std::pair<double, std::optional<py::sequence>>>();
187+
188+
if (!dashes_seq_or_none) {
189+
return true;
190+
}
191+
192+
auto dashes_seq = *dashes_seq_or_none;
193+
194+
auto nentries = dashes_seq.size();
195+
// If the dashpattern has odd length, iterate through it twice (in
196+
// accordance with the pdf/ps/svg specs).
197+
auto dash_pattern_length = (nentries % 2) ? 2 * nentries : nentries;
198+
199+
for (py::size_t i = 0; i < dash_pattern_length; i += 2) {
200+
auto length = dashes_seq[i % nentries].cast<double>();
201+
auto skip = dashes_seq[(i + 1) % nentries].cast<double>();
202+
203+
value.add_dash_pair(length, skip);
204+
}
205+
206+
value.set_dash_offset(dash_offset);
207+
208+
return true;
209+
}
210+
};
211+
212+
template <> struct type_caster<SketchParams> {
213+
public:
214+
PYBIND11_TYPE_CASTER(SketchParams, const_name("SketchParams"));
215+
216+
bool load(handle src, bool) {
217+
if (src.is_none()) {
218+
value.scale = 0.0;
219+
value.length = 0.0;
220+
value.randomness = 0.0;
221+
return true;
222+
}
223+
224+
auto params = src.cast<std::tuple<double, double, double>>();
225+
std::tie(value.scale, value.length, value.randomness) = params;
226+
227+
return true;
228+
}
229+
};
230+
231+
template <> struct type_caster<GCAgg> {
232+
public:
233+
PYBIND11_TYPE_CASTER(GCAgg, const_name("GCAgg"));
234+
235+
bool load(handle src, bool) {
236+
value.linewidth = src.attr("_linewidth").cast<double>();
237+
value.alpha = src.attr("_alpha").cast<double>();
238+
value.forced_alpha = src.attr("_forced_alpha").cast<bool>();
239+
value.color = src.attr("_rgb").cast<agg::rgba>();
240+
value.isaa = src.attr("_antialiased").cast<bool>();
241+
value.cap = src.attr("_capstyle").cast<agg::line_cap_e>();
242+
value.join = src.attr("_joinstyle").cast<agg::line_join_e>();
243+
value.dashes = src.attr("get_dashes")().cast<Dashes>();
244+
value.cliprect = src.attr("_cliprect").cast<agg::rect_d>();
245+
value.clippath = src.attr("get_clip_path")().cast<ClipPath>();
246+
value.snap_mode = src.attr("get_snap")().cast<e_snap_mode>();
247+
value.hatchpath = src.attr("get_hatch_path")().cast<mpl::PathIterator>();
248+
value.hatch_color = src.attr("get_hatch_color")().cast<agg::rgba>();
249+
value.hatch_linewidth = src.attr("get_hatch_linewidth")().cast<double>();
250+
value.sketch = src.attr("get_sketch_params")().cast<SketchParams>();
251+
252+
return true;
253+
}
254+
};
255+
}} // namespace PYBIND11_NAMESPACE::detail
256+
124257
#endif

src/_backend_agg_wrapper.cpp

Lines changed: 19 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -111,48 +111,25 @@ static void
111111
PyRendererAgg_draw_path_collection(RendererAgg *self,
112112
GCAgg &gc,
113113
agg::trans_affine master_transform,
114-
py::object paths_obj,
115-
py::object transforms_obj,
116-
py::object offsets_obj,
114+
mpl::PathGenerator paths,
115+
py::array_t<double> transforms_obj,
116+
py::array_t<double> offsets_obj,
117117
agg::trans_affine offset_trans,
118-
py::object facecolors_obj,
119-
py::object edgecolors_obj,
120-
py::object linewidths_obj,
118+
py::array_t<double> facecolors_obj,
119+
py::array_t<double> edgecolors_obj,
120+
py::array_t<double> linewidths_obj,
121121
DashesVector dashes,
122-
py::object antialiaseds_obj,
122+
py::array_t<uint8_t> antialiaseds_obj,
123123
py::object Py_UNUSED(ignored_obj),
124124
// offset position is no longer used
125125
py::object Py_UNUSED(offset_position_obj))
126126
{
127-
mpl::PathGenerator paths;
128-
numpy::array_view<const double, 3> transforms;
129-
numpy::array_view<const double, 2> offsets;
130-
numpy::array_view<const double, 2> facecolors;
131-
numpy::array_view<const double, 2> edgecolors;
132-
numpy::array_view<const double, 1> linewidths;
133-
numpy::array_view<const uint8_t, 1> antialiaseds;
134-
135-
if (!convert_pathgen(paths_obj.ptr(), &paths)) {
136-
throw py::error_already_set();
137-
}
138-
if (!convert_transforms(transforms_obj.ptr(), &transforms)) {
139-
throw py::error_already_set();
140-
}
141-
if (!convert_points(offsets_obj.ptr(), &offsets)) {
142-
throw py::error_already_set();
143-
}
144-
if (!convert_colors(facecolors_obj.ptr(), &facecolors)) {
145-
throw py::error_already_set();
146-
}
147-
if (!convert_colors(edgecolors_obj.ptr(), &edgecolors)) {
148-
throw py::error_already_set();
149-
}
150-
if (!linewidths.converter(linewidths_obj.ptr(), &linewidths)) {
151-
throw py::error_already_set();
152-
}
153-
if (!antialiaseds.converter(antialiaseds_obj.ptr(), &antialiaseds)) {
154-
throw py::error_already_set();
155-
}
127+
auto transforms = convert_transforms(transforms_obj);
128+
auto offsets = convert_points(offsets_obj);
129+
auto facecolors = convert_colors(facecolors_obj);
130+
auto edgecolors = convert_colors(edgecolors_obj);
131+
auto linewidths = linewidths_obj.unchecked<1>();
132+
auto antialiaseds = antialiaseds_obj.unchecked<1>();
156133

157134
self->draw_path_collection(gc,
158135
master_transform,
@@ -174,26 +151,16 @@ PyRendererAgg_draw_quad_mesh(RendererAgg *self,
174151
unsigned int mesh_width,
175152
unsigned int mesh_height,
176153
py::array_t<double, py::array::c_style | py::array::forcecast> coordinates_obj,
177-
py::object offsets_obj,
154+
py::array_t<double> offsets_obj,
178155
agg::trans_affine offset_trans,
179-
py::object facecolors_obj,
156+
py::array_t<double> facecolors_obj,
180157
bool antialiased,
181-
py::object edgecolors_obj)
158+
py::array_t<double> edgecolors_obj)
182159
{
183-
numpy::array_view<const double, 2> offsets;
184-
numpy::array_view<const double, 2> facecolors;
185-
numpy::array_view<const double, 2> edgecolors;
186-
187160
auto coordinates = coordinates_obj.mutable_unchecked<3>();
188-
if (!convert_points(offsets_obj.ptr(), &offsets)) {
189-
throw py::error_already_set();
190-
}
191-
if (!convert_colors(facecolors_obj.ptr(), &facecolors)) {
192-
throw py::error_already_set();
193-
}
194-
if (!convert_colors(edgecolors_obj.ptr(), &edgecolors)) {
195-
throw py::error_already_set();
196-
}
161+
auto offsets = convert_points(offsets_obj);
162+
auto facecolors = convert_colors(facecolors_obj);
163+
auto edgecolors = convert_colors(edgecolors_obj);
197164

198165
self->draw_quad_mesh(gc,
199166
master_transform,

src/_path.h

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,7 @@ inline void points_in_path(PointArray &points,
245245
typedef agg::conv_curve<no_nans_t> curve_t;
246246
typedef agg::conv_contour<curve_t> contour_t;
247247

248-
size_t i;
249-
for (i = 0; i < safe_first_shape(points); ++i) {
248+
for (auto i = 0; i < safe_first_shape(points); ++i) {
250249
result[i] = false;
251250
}
252251

@@ -270,10 +269,11 @@ template <class PathIterator>
270269
inline bool point_in_path(
271270
double x, double y, const double r, PathIterator &path, agg::trans_affine &trans)
272271
{
273-
npy_intp shape[] = {1, 2};
274-
numpy::array_view<double, 2> points(shape);
275-
points(0, 0) = x;
276-
points(0, 1) = y;
272+
py::ssize_t shape[] = {1, 2};
273+
py::array_t<double> points_arr(shape);
274+
*points_arr.mutable_data(0, 0) = x;
275+
*points_arr.mutable_data(0, 1) = y;
276+
auto points = points_arr.mutable_unchecked<2>();
277277

278278
int result[1];
279279
result[0] = 0;
@@ -292,10 +292,11 @@ inline bool point_on_path(
292292
typedef agg::conv_curve<no_nans_t> curve_t;
293293
typedef agg::conv_stroke<curve_t> stroke_t;
294294

295-
npy_intp shape[] = {1, 2};
296-
numpy::array_view<double, 2> points(shape);
297-
points(0, 0) = x;
298-
points(0, 1) = y;
295+
py::ssize_t shape[] = {1, 2};
296+
py::array_t<double> points_arr(shape);
297+
*points_arr.mutable_data(0, 0) = x;
298+
*points_arr.mutable_data(0, 1) = y;
299+
auto points = points_arr.mutable_unchecked<2>();
299300

300301
int result[1];
301302
result[0] = 0;
@@ -382,20 +383,19 @@ void get_path_collection_extents(agg::trans_affine &master_transform,
382383
throw std::runtime_error("Offsets array must have shape (N, 2)");
383384
}
384385

385-
size_t Npaths = paths.size();
386-
size_t Noffsets = safe_first_shape(offsets);
387-
size_t N = std::max(Npaths, Noffsets);
388-
size_t Ntransforms = std::min(safe_first_shape(transforms), N);
389-
size_t i;
386+
auto Npaths = paths.size();
387+
auto Noffsets = safe_first_shape(offsets);
388+
auto N = std::max(Npaths, Noffsets);
389+
auto Ntransforms = std::min(safe_first_shape(transforms), N);
390390

391391
agg::trans_affine trans;
392392

393393
reset_limits(extent);
394394

395-
for (i = 0; i < N; ++i) {
395+
for (auto i = 0; i < N; ++i) {
396396
typename PathGenerator::path_iterator path(paths(i % Npaths));
397397
if (Ntransforms) {
398-
size_t ti = i % Ntransforms;
398+
py::ssize_t ti = i % Ntransforms;
399399
trans = agg::trans_affine(transforms(ti, 0, 0),
400400
transforms(ti, 1, 0),
401401
transforms(ti, 0, 1),
@@ -429,24 +429,23 @@ void point_in_path_collection(double x,
429429
bool filled,
430430
std::vector<int> &result)
431431
{
432-
size_t Npaths = paths.size();
432+
auto Npaths = paths.size();
433433

434434
if (Npaths == 0) {
435435
return;
436436
}
437437

438-
size_t Noffsets = safe_first_shape(offsets);
439-
size_t N = std::max(Npaths, Noffsets);
440-
size_t Ntransforms = std::min(safe_first_shape(transforms), N);
441-
size_t i;
438+
auto Noffsets = safe_first_shape(offsets);
439+
auto N = std::max(Npaths, Noffsets);
440+
auto Ntransforms = std::min(safe_first_shape(transforms), N);
442441

443442
agg::trans_affine trans;
444443

445-
for (i = 0; i < N; ++i) {
444+
for (auto i = 0; i < N; ++i) {
446445
typename PathGenerator::path_iterator path = paths(i % Npaths);
447446

448447
if (Ntransforms) {
449-
size_t ti = i % Ntransforms;
448+
auto ti = i % Ntransforms;
450449
trans = agg::trans_affine(transforms(ti, 0, 0),
451450
transforms(ti, 1, 0),
452451
transforms(ti, 0, 1),
@@ -1224,17 +1223,15 @@ bool convert_to_string(PathIterator &path,
12241223
}
12251224

12261225
template<class T>
1227-
bool is_sorted_and_has_non_nan(PyArrayObject *array)
1226+
bool is_sorted_and_has_non_nan(py::array_t<T> array)
12281227
{
1229-
char* ptr = PyArray_BYTES(array);
1230-
npy_intp size = PyArray_DIM(array, 0),
1231-
stride = PyArray_STRIDE(array, 0);
1228+
auto size = array.shape(0);
12321229
using limits = std::numeric_limits<T>;
12331230
T last = limits::has_infinity ? -limits::infinity() : limits::min();
12341231
bool found_non_nan = false;
12351232

1236-
for (npy_intp i = 0; i < size; ++i, ptr += stride) {
1237-
T current = *(T*)ptr;
1233+
for (auto i = 0; i < size; ++i) {
1234+
T current = *array.data(i);
12381235
// The following tests !isnan(current), but also works for integral
12391236
// types. (The isnan(IntegralType) overload is absent on MSVC.)
12401237
if (current == current) {

0 commit comments

Comments
 (0)