diff --git a/Tests/images/imagedraw/continuous_horizontal_edges_polygon.png b/Tests/images/imagedraw/continuous_horizontal_edges_polygon.png new file mode 100644 index 00000000000..beffed5b918 Binary files /dev/null and b/Tests/images/imagedraw/continuous_horizontal_edges_polygon.png differ diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 7f31e1aaf46..fa1fdddf1b5 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -1349,3 +1349,22 @@ def test_compute_regular_polygon_vertices_input_error_handling( with pytest.raises(expected_error) as e: ImageDraw._compute_regular_polygon_vertices(bounding_circle, n_sides, rotation) assert str(e.value) == error_message + + +def test_continuous_horizontal_edges_polygon(): + xy = [ + (2, 6), + (6, 6), + (12, 6), + (12, 12), + (8, 12), + (8, 8), + (4, 8), + (2, 8), + ] + img, draw = create_base_image_draw((16, 16)) + draw.polygon(xy, BLACK) + expected = os.path.join(IMAGES_PATH, "continuous_horizontal_edges_polygon.png") + assert_image_equal_tofile( + img, expected, "continuous horizontal edges polygon failed" + ) diff --git a/src/libImaging/Draw.c b/src/libImaging/Draw.c index b6f63b7e804..bec8f258249 100644 --- a/src/libImaging/Draw.c +++ b/src/libImaging/Draw.c @@ -734,7 +734,7 @@ ImagingDrawRectangle( int ImagingDrawPolygon(Imaging im, int count, int *xy, const void *ink_, int fill, int op) { - int i, n; + int i, n, x0, y0, x1, y1; DRAW *draw; INT32 ink; @@ -753,10 +753,28 @@ ImagingDrawPolygon(Imaging im, int count, int *xy, const void *ink_, int fill, i return -1; } for (i = n = 0; i < count - 1; i++) { - add_edge(&e[n++], xy[i + i], xy[i + i + 1], xy[i + i + 2], xy[i + i + 3]); + x0 = xy[i * 2]; + y0 = xy[i * 2 + 1]; + x1 = xy[i * 2 + 2]; + y1 = xy[i * 2 + 3]; + if (y0 == y1 && i != 0 && y0 == xy[i * 2 - 1]) { + // This is a horizontal line, + // that immediately follows another horizontal line + Edge *last_e = &e[n-1]; + if (x1 > x0 && x0 > xy[i * 2 - 2]) { + // They are both increasing in x + last_e->xmax = x1; + continue; + } else if (x1 < x0 && x0 < xy[i * 2 - 2]) { + // They are both decreasing in x + last_e->xmin = x1; + continue; + } + } + add_edge(&e[n++], x0, y0, x1, y1); } - if (xy[i + i] != xy[0] || xy[i + i + 1] != xy[1]) { - add_edge(&e[n++], xy[i + i], xy[i + i + 1], xy[0], xy[1]); + if (xy[i * 2] != xy[0] || xy[i * 2 + 1] != xy[1]) { + add_edge(&e[n++], xy[i * 2], xy[i * 2 + 1], xy[0], xy[1]); } draw->polygon(im, n, e, ink, 0); free(e); @@ -764,9 +782,9 @@ ImagingDrawPolygon(Imaging im, int count, int *xy, const void *ink_, int fill, i } else { /* Outline */ for (i = 0; i < count - 1; i++) { - draw->line(im, xy[i + i], xy[i + i + 1], xy[i + i + 2], xy[i + i + 3], ink); + draw->line(im, xy[i * 2], xy[i * 2 + 1], xy[i * 2 + 2], xy[i * 2 + 3], ink); } - draw->line(im, xy[i + i], xy[i + i + 1], xy[0], xy[1], ink); + draw->line(im, xy[i * 2], xy[i * 2 + 1], xy[0], xy[1], ink); } return 0;