Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f529327

Browse filesBrowse files
committed
Merge pull request #5274 from mdboom/uninited-data2
Check dimensions of arrays passed to C++, handle 0 dimensions
1 parent d114237 commit f529327
Copy full SHA for f529327

File tree

Expand file treeCollapse file tree

7 files changed

+177
-60
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+177
-60
lines changed

‎src/_backend_agg.h

Copy file name to clipboardExpand all lines: src/_backend_agg.h
-36Lines 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

Copy file name to clipboardExpand all lines: src/_backend_agg_wrapper.cpp
+43-7Lines 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

Copy file name to clipboardExpand all lines: src/_path.h
+4-4Lines 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

Copy file name to clipboardExpand all lines: src/_path_wrapper.cpp
+15-12Lines 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

Copy file name to clipboardExpand all lines: src/numpy_cpp.h
+15-1Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.