diff --git a/Tests/images/imagedraw_ellipse_L.png b/Tests/images/imagedraw_ellipse_L.png index e47e6e441..d5959cc08 100644 Binary files a/Tests/images/imagedraw_ellipse_L.png and b/Tests/images/imagedraw_ellipse_L.png differ diff --git a/Tests/images/imagedraw_ellipse_RGB.png b/Tests/images/imagedraw_ellipse_RGB.png index b52b12802..1d310ce11 100644 Binary files a/Tests/images/imagedraw_ellipse_RGB.png and b/Tests/images/imagedraw_ellipse_RGB.png differ diff --git a/Tests/images/imagedraw_ellipse_edge.png b/Tests/images/imagedraw_ellipse_edge.png index 25a95a601..a2235115a 100644 Binary files a/Tests/images/imagedraw_ellipse_edge.png and b/Tests/images/imagedraw_ellipse_edge.png differ diff --git a/Tests/images/imagedraw_ellipse_width.png b/Tests/images/imagedraw_ellipse_width.png index ec0ca6731..54cfc291c 100644 Binary files a/Tests/images/imagedraw_ellipse_width.png and b/Tests/images/imagedraw_ellipse_width.png differ diff --git a/Tests/images/imagedraw_ellipse_width_fill.png b/Tests/images/imagedraw_ellipse_width_fill.png index 9b7be6029..4a1edc379 100644 Binary files a/Tests/images/imagedraw_ellipse_width_fill.png and b/Tests/images/imagedraw_ellipse_width_fill.png differ diff --git a/Tests/images/imagedraw_ellipse_width_large.png b/Tests/images/imagedraw_ellipse_width_large.png index 9d3c3326b..e95186019 100644 Binary files a/Tests/images/imagedraw_ellipse_width_large.png and b/Tests/images/imagedraw_ellipse_width_large.png differ diff --git a/Tests/images/imagedraw_ellipse_zero_width.png b/Tests/images/imagedraw_ellipse_zero_width.png index f14a279f2..6661b7d99 100644 Binary files a/Tests/images/imagedraw_ellipse_zero_width.png and b/Tests/images/imagedraw_ellipse_zero_width.png differ diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index f6eabb21a..cc29c097e 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -286,14 +286,14 @@ def test_ellipse_edge(): draw = ImageDraw.Draw(im) # Act - draw.ellipse(((0, 0), (W - 1, H)), fill="white") + draw.ellipse(((0, 0), (W - 1, H - 1)), fill="white") # Assert assert_image_similar(im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1) def test_ellipse_symmetric(): - for bbox in [(25, 25, 76, 76), (25, 25, 75, 75)]: + for bbox in [(24, 25, 76, 75), (25, 25, 75, 75), (25, 24, 75, 76)]: im = Image.new("RGB", (101, 101)) draw = ImageDraw.Draw(im) draw.ellipse(bbox, fill="green", outline="blue") diff --git a/Tests/test_imagedraw2.py b/Tests/test_imagedraw2.py index 72cbb79b8..c26cc0d94 100644 --- a/Tests/test_imagedraw2.py +++ b/Tests/test_imagedraw2.py @@ -79,7 +79,7 @@ def test_ellipse_edge(): brush = ImageDraw2.Brush("white") # Act - draw.ellipse(((0, 0), (W - 1, H)), brush) + draw.ellipse(((0, 0), (W - 1, H - 1)), brush) # Assert assert_image_similar(im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1) diff --git a/src/libImaging/Draw.c b/src/libImaging/Draw.c index ee3a3938e..34d1d4bc5 100644 --- a/src/libImaging/Draw.c +++ b/src/libImaging/Draw.c @@ -1047,78 +1047,76 @@ int8_t quarter_next(quarter_state* s, int32_t* ret_x, int32_t* ret_y) { typedef struct { quarter_state st_o, st_i; int32_t py, pl, pr; - int32_t cy, cl, cr; - // 0 - ready to take next quarter piece, 1, 2, 3 - returned 1, 2, 3 hlines - int8_t state; + int32_t cy[4], cl[4], cr[4]; + int8_t bufcnt; int8_t finished; + int8_t leftmost; } ellipse_state; void ellipse_init(ellipse_state* s, int32_t a, int32_t b, int32_t w) { - s->state = 0; + s->bufcnt = 0; + s->leftmost = a % 2; quarter_init(&s->st_o, a, b); if (w < 1 || quarter_next(&s->st_o, &s->pr, &s->py) == -1) { s->finished = 1; } else { s->finished = 0; quarter_init(&s->st_i, a - 2 * (w - 1), b - 2 * (w - 1)); - s->pl = a % 2; + s->pl = s->leftmost; } } int8_t ellipse_next(ellipse_state* s, int32_t* ret_x0, int32_t* ret_y, int32_t* ret_x1) { - switch (s->state) { - case 0: { - if (s->finished) { - return -1; - } - s->cy = s->py; - s->cl = s->pl; - s->cr = s->pr; - int32_t cx = 0, cy = 0; - int8_t next_ret; - while ((next_ret = quarter_next(&s->st_o, &cx, &cy)) != -1 && cy <= s->cy) { - } - s->pr = cx; - s->py = cy; - if (next_ret == -1) { - s->finished = 1; - } - while ((next_ret = quarter_next(&s->st_i, &cx, &cy)) != -1 && cy <= s->cy) { - s->cl = cx; - } - s->pl = next_ret == -1 ? 0 : cx; - *ret_x0 = -s->cr; - *ret_y = -s->cy; - *ret_x1 = -s->cl; - s->state = 1; - return 0; - } - case 1: { - *ret_x0 = s->cl; - *ret_y = -s->cy; - *ret_x1 = s->cr; - s->state = 2; - return 0; - } - case 2: { - *ret_x0 = -s->cr; - *ret_y = s->cy; - *ret_x1 = -s->cl; - s->state = 3; - return 0; - } - case 3: { - *ret_x0 = s->cl; - *ret_y = s->cy; - *ret_x1 = s->cr; - s->state = 0; - return 0; - } - default: { - assert(0); + if (s->bufcnt == 0) { + if (s->finished) { return -1; } + int32_t y = s->py; + int32_t l = s->pl; + int32_t r = s->pr; + int32_t cx = 0, cy = 0; + int8_t next_ret; + while ((next_ret = quarter_next(&s->st_o, &cx, &cy)) != -1 && cy <= y) { + } + if (next_ret == -1) { + s->finished = 1; + } else { + s->pr = cx; + s->py = cy; + } + while ((next_ret = quarter_next(&s->st_i, &cx, &cy)) != -1 && cy <= y) { + l = cx; + } + s->pl = next_ret == -1 ? s->leftmost : cx; + + if ((l > 0 || l < r) && y > 0) { + s->cl[s->bufcnt] = l == 0 ? 2 : l; + s->cy[s->bufcnt] = y; + s->cr[s->bufcnt] = r; + ++s->bufcnt; + } + if (y > 0) { + s->cl[s->bufcnt] = -r; + s->cy[s->bufcnt] = y; + s->cr[s->bufcnt] = -l; + ++s->bufcnt; + } + if (l > 0 || l < r) { + s->cl[s->bufcnt] = l == 0 ? 2 : l; + s->cy[s->bufcnt] = -y; + s->cr[s->bufcnt] = r; + ++s->bufcnt; + } + s->cl[s->bufcnt] = -r; + s->cy[s->bufcnt] = -y; + s->cr[s->bufcnt] = -l; + ++s->bufcnt; } + --s->bufcnt; + *ret_x0 = s->cl[s->bufcnt]; + *ret_y = s->cy[s->bufcnt]; + *ret_x1 = s->cr[s->bufcnt]; + return 0; } static int