diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 753b98681..a5f11e786 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -807,3 +807,26 @@ class TestImageDraw(PillowTestCase): operation, mode ) self.assert_image_similar(im, Image.open(expected), 1) + + def test_xy(self): + im = hopper() + draw = ImageDraw.Draw(im) + + xys = [ + [X0, Y0, X1, Y1], + [[X0, Y0], [X1, Y1]], + [(X0, Y0), (X1, Y1)], + (X0, Y0, X1, Y1), + ([X0, Y0], [X1, Y1]), + ((X0, Y0), (X1, Y1)), + ] + + for xy in xys: + draw.arc(xy, 0, 90) + draw.chord(xy, 0, 90) + draw.pieslice(xy, 0, 90) + draw.ellipse(xy) + draw.line(xy) + draw.point(xy) + draw.polygon(xy) + draw.rectangle(xy) diff --git a/src/path.c b/src/path.c index 5f0541b0b..42ec0e04e 100644 --- a/src/path.c +++ b/src/path.c @@ -106,6 +106,63 @@ path_dealloc(PyPathObject* path) PyObject_Del(path); } +static int +get_one_item(PyObject *op, double *x) +{ + if (PyFloat_Check(op)) { + *x = PyFloat_AS_DOUBLE(op); + return 1; + } else if (PyInt_Check(op)) { + *x = (float) PyInt_AS_LONG(op); + return 1; + } else if (PyNumber_Check(op)) { + *x = PyFloat_AsDouble(op); + return 1; + } else { + return 0; + } +} + +static int +get_two_item(PyObject *op, double *x, double *y) { + PyObject *o; + int success; + + if (PySequence_Check(op) && PyObject_Length(op) > 1) { + if (PyList_Check(op)) { + o = PyList_GET_ITEM(op, 0); + if (!get_one_item(o, x)) + return 0; + o = PyList_GET_ITEM(op, 1); + if (!get_one_item(o, y)) + return 0; + return 1; + } else if (PyTuple_Check(op)) { + o = PyTuple_GET_ITEM(op, 0); + if (!get_one_item(o, x)) + return 0; + o = PyTuple_GET_ITEM(op, 1); + if (!get_one_item(o, y)) + return 0; + return 1; + } else { + o = PySequence_GetItem(op, 0); + success = get_one_item(o, x); + Py_DECREF(o); + if (!success) + return 0; + o = PySequence_GetItem(op, 1); + success = get_one_item(o, y); + Py_DECREF(o); + if (!success) + return 0; + return 1; + } + } + + return 0; +} + /* -------------------------------------------------------------------- */ /* Helpers */ /* -------------------------------------------------------------------- */ @@ -168,17 +225,14 @@ PyPath_Flatten(PyObject* data, double **pxy) for (i = 0; i < n; i++) { double x, y; PyObject *op = PyList_GET_ITEM(data, i); - if (PyFloat_Check(op)) - xy[j++] = PyFloat_AS_DOUBLE(op); - else if (PyInt_Check(op)) - xy[j++] = (float) PyInt_AS_LONG(op); - else if (PyNumber_Check(op)) - xy[j++] = PyFloat_AsDouble(op); - else if (PyArg_ParseTuple(op, "dd", &x, &y)) { + if (get_one_item(op, &x)) { + xy[j++] = x; + } else if (get_two_item(op, &x, &y)) { xy[j++] = x; xy[j++] = y; } else { free(xy); + PyErr_SetString(PyExc_TypeError, "wrong type of coordinates"); return -1; } } @@ -186,17 +240,14 @@ PyPath_Flatten(PyObject* data, double **pxy) for (i = 0; i < n; i++) { double x, y; PyObject *op = PyTuple_GET_ITEM(data, i); - if (PyFloat_Check(op)) - xy[j++] = PyFloat_AS_DOUBLE(op); - else if (PyInt_Check(op)) - xy[j++] = (float) PyInt_AS_LONG(op); - else if (PyNumber_Check(op)) - xy[j++] = PyFloat_AsDouble(op); - else if (PyArg_ParseTuple(op, "dd", &x, &y)) { + if (get_one_item(op, &x)) { + xy[j++] = x; + } else if (get_two_item(op, &x, &y)) { xy[j++] = x; xy[j++] = y; } else { free(xy); + PyErr_SetString(PyExc_TypeError, "wrong type of coordinates"); return -1; } } @@ -215,18 +266,15 @@ PyPath_Flatten(PyObject* data, double **pxy) return -1; } } - if (PyFloat_Check(op)) - xy[j++] = PyFloat_AS_DOUBLE(op); - else if (PyInt_Check(op)) - xy[j++] = (float) PyInt_AS_LONG(op); - else if (PyNumber_Check(op)) - xy[j++] = PyFloat_AsDouble(op); - else if (PyArg_ParseTuple(op, "dd", &x, &y)) { + if (get_one_item(op, &x)) { + xy[j++] = x; + } else if (get_two_item(op, &x, &y)) { xy[j++] = x; xy[j++] = y; } else { Py_DECREF(op); free(xy); + PyErr_SetString(PyExc_TypeError, "wrong type of coordinates"); return -1; } Py_DECREF(op);