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

Skip to content

Commit 8990d11

Browse files
committed
Merge pull request #5274 from mdboom/uninited-data2
Check dimensions of arrays passed to C++, handle 0 dimensions
2 parents b6f78ce + a291e98 commit 8990d11

7 files changed

+177
-60
lines changed

src/_backend_agg.h

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -922,22 +922,6 @@ inline void RendererAgg::_draw_path_collection_generic(GCAgg &gc,
922922
typedef agg::conv_curve<snapped_t> snapped_curve_t;
923923
typedef agg::conv_curve<clipped_t> curve_t;
924924

925-
if (offsets.dim(0) != 0 && offsets.dim(1) != 2) {
926-
throw "Offsets array must be Nx2 or empty";
927-
}
928-
929-
if (facecolors.dim(0) != 0 && facecolors.dim(1) != 4) {
930-
throw "Facecolors array must be a Nx4 array or empty";
931-
}
932-
933-
if (edgecolors.dim(0) != 0 && edgecolors.dim(1) != 4) {
934-
throw "Edgecolors array must by Nx4 or empty";
935-
}
936-
937-
if (transforms.dim(0) != 0 && (transforms.dim(1) != 3 || transforms.dim(2) != 3)) {
938-
throw "Transforms array must by Nx3x3 or empty";
939-
}
940-
941925
size_t Npaths = path_generator.num_paths();
942926
size_t Noffsets = offsets.size();
943927
size_t N = std::max(Npaths, Noffsets);
@@ -1266,14 +1250,6 @@ inline void RendererAgg::draw_gouraud_triangle(GCAgg &gc,
12661250
set_clipbox(gc.cliprect, theRasterizer);
12671251
bool has_clippath = render_clippath(gc.clippath.path, gc.clippath.trans);
12681252

1269-
if (points.dim(0) != 3 || points.dim(1) != 2) {
1270-
throw "points must be a 3x2 array";
1271-
}
1272-
1273-
if (colors.dim(0) != 3 || colors.dim(1) != 4) {
1274-
throw "colors must be a 3x4 array";
1275-
}
1276-
12771253
_draw_gouraud_triangle(points, colors, trans, has_clippath);
12781254
}
12791255

@@ -1288,18 +1264,6 @@ inline void RendererAgg::draw_gouraud_triangles(GCAgg &gc,
12881264
set_clipbox(gc.cliprect, theRasterizer);
12891265
bool has_clippath = render_clippath(gc.clippath.path, gc.clippath.trans);
12901266

1291-
if (points.dim(1) != 3 || points.dim(2) != 2) {
1292-
throw "points must be a Nx3x2 array";
1293-
}
1294-
1295-
if (colors.dim(1) != 3 || colors.dim(2) != 4) {
1296-
throw "colors must be a Nx3x4 array";
1297-
}
1298-
1299-
if (points.dim(0) != colors.dim(0)) {
1300-
throw "points and colors arrays must be the same length";
1301-
}
1302-
13031267
for (int i = 0; i < points.dim(0); ++i) {
13041268
typename PointArray::sub_t point = points[i];
13051269
typename ColorArray::sub_t color = colors[i];

src/_backend_agg_wrapper.cpp

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -340,15 +340,15 @@ PyRendererAgg_draw_path_collection(PyRendererAgg *self, PyObject *args, PyObject
340340
&convert_trans_affine,
341341
&master_transform,
342342
&pathobj,
343-
&transforms.converter,
343+
&convert_transforms,
344344
&transforms,
345-
&offsets.converter,
345+
&convert_points,
346346
&offsets,
347347
&convert_trans_affine,
348348
&offset_trans,
349-
&facecolors.converter,
349+
&convert_colors,
350350
&facecolors,
351-
&edgecolors.converter,
351+
&convert_colors,
352352
&edgecolors,
353353
&linewidths.converter,
354354
&linewidths,
@@ -411,14 +411,14 @@ static PyObject *PyRendererAgg_draw_quad_mesh(PyRendererAgg *self, PyObject *arg
411411
&mesh_height,
412412
&coordinates.converter,
413413
&coordinates,
414-
&offsets.converter,
414+
&convert_points,
415415
&offsets,
416416
&convert_trans_affine,
417417
&offset_trans,
418-
&facecolors.converter,
418+
&convert_colors,
419419
&facecolors,
420420
&antialiased,
421-
&edgecolors.converter,
421+
&convert_colors,
422422
&edgecolors)) {
423423
return NULL;
424424
}
@@ -459,6 +459,21 @@ PyRendererAgg_draw_gouraud_triangle(PyRendererAgg *self, PyObject *args, PyObjec
459459
return NULL;
460460
}
461461

462+
if (points.dim(0) != 3 || points.dim(1) != 2) {
463+
PyErr_Format(PyExc_ValueError,
464+
"points must be a 3x2 array, got %dx%d",
465+
points.dim(0), points.dim(1));
466+
return NULL;
467+
}
468+
469+
if (colors.dim(0) != 3 || colors.dim(1) != 4) {
470+
PyErr_Format(PyExc_ValueError,
471+
"colors must be a 3x4 array, got %dx%d",
472+
colors.dim(0), colors.dim(1));
473+
return NULL;
474+
}
475+
476+
462477
CALL_CPP("draw_gouraud_triangle", (self->x->draw_gouraud_triangle(gc, points, colors, trans)));
463478

464479
Py_RETURN_NONE;
@@ -485,6 +500,27 @@ PyRendererAgg_draw_gouraud_triangles(PyRendererAgg *self, PyObject *args, PyObje
485500
return NULL;
486501
}
487502

503+
if (points.size() != 0 && (points.dim(1) != 3 || points.dim(2) != 2)) {
504+
PyErr_Format(PyExc_ValueError,
505+
"points must be a Nx3x2 array, got %dx%dx%d",
506+
points.dim(0), points.dim(1), points.dim(2));
507+
return NULL;
508+
}
509+
510+
if (colors.size() != 0 && (colors.dim(1) != 3 || colors.dim(2) != 4)) {
511+
PyErr_Format(PyExc_ValueError,
512+
"colors must be a Nx3x4 array, got %dx%dx%d",
513+
colors.dim(0), colors.dim(1), colors.dim(2));
514+
return NULL;
515+
}
516+
517+
if (points.size() != colors.size()) {
518+
PyErr_Format(PyExc_ValueError,
519+
"points and colors arrays must be the same length, got %d and %d",
520+
points.dim(0), colors.dim(0));
521+
return NULL;
522+
}
523+
488524
CALL_CPP("draw_gouraud_triangles", self->x->draw_gouraud_triangles(gc, points, colors, trans));
489525

490526
Py_RETURN_NONE;

src/_path.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ void get_path_collection_extents(agg::trans_affine &master_transform,
358358
agg::trans_affine &offset_trans,
359359
extent_limits &extent)
360360
{
361-
if (offsets.dim(0) != 0 && offsets.dim(1) != 2) {
361+
if (offsets.size() != 0 && offsets.dim(1) != 2) {
362362
throw "Offsets array must be Nx2";
363363
}
364364

@@ -416,7 +416,7 @@ void point_in_path_collection(double x,
416416
return;
417417
}
418418

419-
size_t Noffsets = offsets.dim(0);
419+
size_t Noffsets = offsets.size();
420420
size_t N = std::max(Npaths, Noffsets);
421421
size_t Ntransforms = std::min(transforms.size(), N);
422422
size_t i;
@@ -692,11 +692,11 @@ clip_path_to_rect(PathIterator &path, agg::rect_d &rect, bool inside, std::vecto
692692
template <class VerticesArray, class ResultArray>
693693
void affine_transform_2d(VerticesArray &vertices, agg::trans_affine &trans, ResultArray &result)
694694
{
695-
if (vertices.dim(0) != 0 && vertices.dim(1) != 2) {
695+
if (vertices.size() != 0 && vertices.dim(1) != 2) {
696696
throw "Invalid vertices array.";
697697
}
698698

699-
size_t n = vertices.dim(0);
699+
size_t n = vertices.size();
700700
double x;
701701
double y;
702702
double t0;

src/_path_wrapper.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static PyObject *Py_points_in_path(PyObject *self, PyObject *args, PyObject *kwd
6969

7070
if (!PyArg_ParseTuple(args,
7171
"O&dO&O&:points_in_path",
72-
&points.converter,
72+
&convert_points,
7373
&points,
7474
&r,
7575
&convert_path,
@@ -79,7 +79,7 @@ static PyObject *Py_points_in_path(PyObject *self, PyObject *args, PyObject *kwd
7979
return NULL;
8080
}
8181

82-
npy_intp dims[] = { points.dim(0) };
82+
npy_intp dims[] = { points.size() };
8383
numpy::array_view<bool, 1> results(dims);
8484

8585
CALL_CPP("points_in_path", (points_in_path(points, r, path, trans, results)));
@@ -128,7 +128,7 @@ static PyObject *Py_points_on_path(PyObject *self, PyObject *args, PyObject *kwd
128128

129129
if (!PyArg_ParseTuple(args,
130130
"O&dO&O&:points_on_path",
131-
&points.converter,
131+
&convert_points,
132132
&points,
133133
&r,
134134
&convert_path,
@@ -138,7 +138,7 @@ static PyObject *Py_points_on_path(PyObject *self, PyObject *args, PyObject *kwd
138138
return NULL;
139139
}
140140

141-
npy_intp dims[] = { points.dim(0) };
141+
npy_intp dims[] = { points.size() };
142142
numpy::array_view<bool, 1> results(dims);
143143

144144
CALL_CPP("points_on_path", (points_on_path(points, r, path, trans, results)));
@@ -200,7 +200,10 @@ static PyObject *Py_update_path_extents(PyObject *self, PyObject *args, PyObject
200200
}
201201

202202
if (minpos.dim(0) != 2) {
203-
PyErr_SetString(PyExc_ValueError, "minpos must be of length 2");
203+
PyErr_Format(PyExc_ValueError,
204+
"minpos must be of length 2, got %d",
205+
minpos.dim(0));
206+
return NULL;
204207
}
205208

206209
extent_limits e;
@@ -263,9 +266,9 @@ static PyObject *Py_get_path_collection_extents(PyObject *self, PyObject *args,
263266
&convert_trans_affine,
264267
&master_transform,
265268
&pathsobj,
266-
&transforms.converter,
269+
&convert_transforms,
267270
&transforms,
268-
&offsets.converter,
271+
&convert_points,
269272
&offsets,
270273
&convert_trans_affine,
271274
&offset_trans)) {
@@ -319,9 +322,9 @@ static PyObject *Py_point_in_path_collection(PyObject *self, PyObject *args, PyO
319322
&convert_trans_affine,
320323
&master_transform,
321324
&pathsobj,
322-
&transforms.converter,
325+
&convert_transforms,
323326
&transforms,
324-
&offsets.converter,
327+
&convert_points,
325328
&offsets,
326329
&convert_trans_affine,
327330
&offset_trans,
@@ -434,15 +437,15 @@ static PyObject *Py_affine_transform(PyObject *self, PyObject *args, PyObject *k
434437

435438
try {
436439
numpy::array_view<double, 2> vertices(vertices_obj);
437-
npy_intp dims[] = { vertices.dim(0), 2 };
440+
npy_intp dims[] = { vertices.size(), 2 };
438441
numpy::array_view<double, 2> result(dims);
439442
CALL_CPP("affine_transform", (affine_transform_2d(vertices, trans, result)));
440443
return result.pyobj();
441444
} catch (py::exception) {
442445
PyErr_Clear();
443446
try {
444447
numpy::array_view<double, 1> vertices(vertices_obj);
445-
npy_intp dims[] = { vertices.dim(0) };
448+
npy_intp dims[] = { vertices.size() };
446449
numpy::array_view<double, 1> result(dims);
447450
CALL_CPP("affine_transform", (affine_transform_1d(vertices, trans, result)));
448451
return result.pyobj();
@@ -464,7 +467,7 @@ static PyObject *Py_count_bboxes_overlapping_bbox(PyObject *self, PyObject *args
464467
"O&O&:count_bboxes_overlapping_bbox",
465468
&convert_rect,
466469
&bbox,
467-
&bboxes.converter,
470+
&convert_bboxes,
468471
&bboxes)) {
469472
return NULL;
470473
}

src/numpy_cpp.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,9 +479,23 @@ class array_view : public detail::array_view_accessors<array_view, T, ND>
479479
return m_shape[i];
480480
}
481481

482+
/*
483+
In most cases, code should use size() instead of dim(0), since
484+
size() == 0 when any dimension is 0.
485+
*/
482486
size_t size() const
483487
{
484-
return (size_t)dim(0);
488+
bool empty = (ND == 0);
489+
for (size_t i = 0; i < ND; i++) {
490+
if (m_shape[i] == 0) {
491+
empty = true;
492+
}
493+
}
494+
if (empty) {
495+
return 0;
496+
} else {
497+
return (size_t)dim(0);
498+
}
485499
}
486500

487501
bool empty() const

0 commit comments

Comments
 (0)