mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +03:00
Fixed arc gaps
This commit is contained in:
parent
53433419e9
commit
21c7fd251c
BIN
Tests/images/imagedraw_arc_width_pieslice.png
Normal file
BIN
Tests/images/imagedraw_arc_width_pieslice.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 402 B |
BIN
Tests/images/imagedraw_ellipse_width_large.png
Normal file
BIN
Tests/images/imagedraw_ellipse_width_large.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
|
@ -114,6 +114,19 @@ class TestImageDraw(PillowTestCase):
|
|||
# Assert
|
||||
self.assert_image_similar(im, Image.open(expected), 1)
|
||||
|
||||
def test_arc_width_pieslice_large(self):
|
||||
# Tests an arc with a large enough width that it is a pieslice
|
||||
# Arrange
|
||||
im = Image.new("RGB", (W, H))
|
||||
draw = ImageDraw.Draw(im)
|
||||
expected = "Tests/images/imagedraw_arc_width_pieslice.png"
|
||||
|
||||
# Act
|
||||
draw.arc(BBOX1, 10, 260, fill="yellow", width=100)
|
||||
|
||||
# Assert
|
||||
self.assert_image_similar(im, Image.open(expected), 1)
|
||||
|
||||
def test_arc_width_fill(self):
|
||||
# Arrange
|
||||
im = Image.new("RGB", (W, H))
|
||||
|
@ -239,6 +252,18 @@ class TestImageDraw(PillowTestCase):
|
|||
# Assert
|
||||
self.assert_image_similar(im, Image.open(expected), 1)
|
||||
|
||||
def test_ellipse_width_large(self):
|
||||
# Arrange
|
||||
im = Image.new("RGB", (500, 500))
|
||||
draw = ImageDraw.Draw(im)
|
||||
expected = "Tests/images/imagedraw_ellipse_width_large.png"
|
||||
|
||||
# Act
|
||||
draw.ellipse((25, 25, 475, 475), outline="blue", width=75)
|
||||
|
||||
# Assert
|
||||
self.assert_image_similar(im, Image.open(expected), 1)
|
||||
|
||||
def test_ellipse_width_fill(self):
|
||||
# Arrange
|
||||
im = Image.new("RGB", (W, H))
|
||||
|
|
|
@ -765,115 +765,150 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1,
|
|||
int width, int mode, int op)
|
||||
{
|
||||
float i;
|
||||
int j;
|
||||
int inner;
|
||||
int n;
|
||||
int cx, cy;
|
||||
int maxEdgeCount;
|
||||
int w, h;
|
||||
int x = 0, y = 0;
|
||||
int lx = 0, ly = 0;
|
||||
int sx = 0, sy = 0;
|
||||
int x, y;
|
||||
int cx, cy;
|
||||
int lx, ly;
|
||||
int sx, sy;
|
||||
int lx_inner, ly_inner;
|
||||
int sx_inner, sy_inner;
|
||||
DRAW* draw;
|
||||
INT32 ink;
|
||||
Edge* e;
|
||||
|
||||
DRAWINIT();
|
||||
|
||||
if (width == 0) {
|
||||
width = 1;
|
||||
while (end < start)
|
||||
end += 360;
|
||||
|
||||
if (end - start > 360) {
|
||||
// no need to go in loops
|
||||
end = start + 361;
|
||||
}
|
||||
|
||||
for (j = 0; j < width; j++) {
|
||||
w = x1 - x0;
|
||||
h = y1 - y0;
|
||||
if (w <= 0 || h <= 0)
|
||||
return 0;
|
||||
|
||||
w = x1 - x0;
|
||||
h = y1 - y0;
|
||||
if (w < 0 || h < 0)
|
||||
cx = (x0 + x1) / 2;
|
||||
cy = (y0 + y1) / 2;
|
||||
|
||||
if (!fill && width <= 1) {
|
||||
for (i = start; i < end+1; i++) {
|
||||
if (i > end) {
|
||||
i = end;
|
||||
}
|
||||
ellipsePoint(cx, cy, w, h, i, &x, &y);
|
||||
if (i != start)
|
||||
draw->line(im, lx, ly, x, y, ink);
|
||||
else
|
||||
sx = x, sy = y;
|
||||
lx = x, ly = y;
|
||||
}
|
||||
|
||||
if (i != start) {
|
||||
if (mode == PIESLICE) {
|
||||
if (x != cx || y != cy) {
|
||||
draw->line(im, x, y, cx, cy, ink);
|
||||
draw->line(im, cx, cy, sx, sy, ink);
|
||||
}
|
||||
} else if (mode == CHORD) {
|
||||
if (x != sx || y != sy)
|
||||
draw->line(im, x, y, sx, sy, ink);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inner = (mode == ARC || !fill) ? 1 : 0;
|
||||
|
||||
// Build edge list
|
||||
// malloc check UNDONE, FLOAT?
|
||||
maxEdgeCount = end - start;
|
||||
if (inner) {
|
||||
maxEdgeCount *= 2;
|
||||
}
|
||||
maxEdgeCount += 3;
|
||||
e = calloc(maxEdgeCount, sizeof(Edge));
|
||||
if (!e) {
|
||||
ImagingError_MemoryError();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Outer circle
|
||||
n = 0;
|
||||
for (i = start; i < end+1; i++) {
|
||||
if (i > end) {
|
||||
i = end;
|
||||
}
|
||||
ellipsePoint(cx, cy, w, h, i, &x, &y);
|
||||
if (i == start) {
|
||||
sx = x, sy = y;
|
||||
} else {
|
||||
add_edge(&e[n++], lx, ly, x, y);
|
||||
}
|
||||
lx = x, ly = y;
|
||||
}
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
cx = (x0 + x1) / 2;
|
||||
cy = (y0 + y1) / 2;
|
||||
if (inner) {
|
||||
// Inner circle
|
||||
x0 += width - 1;
|
||||
y0 += width - 1;
|
||||
x1 -= width - 1;
|
||||
y1 -= width - 1;
|
||||
|
||||
while (end < start)
|
||||
end += 360;
|
||||
|
||||
if (end - start > 360) {
|
||||
/* no need to go in loops */
|
||||
end = start + 361;
|
||||
}
|
||||
|
||||
if (mode != ARC && fill) {
|
||||
|
||||
/* Build edge list */
|
||||
/* malloc check UNDONE, FLOAT? */
|
||||
Edge* e = calloc((end - start + 3), sizeof(Edge));
|
||||
if (!e) {
|
||||
ImagingError_MemoryError();
|
||||
return -1;
|
||||
}
|
||||
n = 0;
|
||||
|
||||
for (i = start; i < end+1; i++) {
|
||||
if (i > end) {
|
||||
i = end;
|
||||
}
|
||||
ellipsePoint(cx, cy, w, h, i, &x, &y);
|
||||
if (i != start)
|
||||
add_edge(&e[n++], lx, ly, x, y);
|
||||
else
|
||||
sx = x, sy = y;
|
||||
lx = x, ly = y;
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
/* close and draw polygon */
|
||||
if (mode == PIESLICE) {
|
||||
if (x != cx || y != cy) {
|
||||
add_edge(&e[n++], x, y, cx, cy);
|
||||
add_edge(&e[n++], cx, cy, sx, sy);
|
||||
w = x1 - x0;
|
||||
h = y1 - y0;
|
||||
if (w <= 0 || h <= 0) {
|
||||
// ARC with no gap in the middle is a PIESLICE
|
||||
mode = PIESLICE;
|
||||
inner = 0;
|
||||
} else {
|
||||
for (i = start; i < end+1; i++) {
|
||||
if (i > end) {
|
||||
i = end;
|
||||
}
|
||||
} else {
|
||||
if (x != sx || y != sy)
|
||||
add_edge(&e[n++], x, y, sx, sy);
|
||||
}
|
||||
draw->polygon(im, n, e, ink, 0);
|
||||
}
|
||||
|
||||
free(e);
|
||||
|
||||
} else {
|
||||
|
||||
for (i = start; i < end+1; i++) {
|
||||
if (i > end) {
|
||||
i = end;
|
||||
}
|
||||
ellipsePoint(cx, cy, w, h, i, &x, &y);
|
||||
if (i != start)
|
||||
draw->line(im, lx, ly, x, y, ink);
|
||||
else
|
||||
sx = x, sy = y;
|
||||
lx = x, ly = y;
|
||||
}
|
||||
|
||||
if (i != start) {
|
||||
if (mode == PIESLICE) {
|
||||
if (j == 0 && (x != cx || y != cy)) {
|
||||
if (width == 1) {
|
||||
draw->line(im, x, y, cx, cy, ink);
|
||||
draw->line(im, cx, cy, sx, sy, ink);
|
||||
} else {
|
||||
ImagingDrawWideLine(im, x, y, cx, cy, &ink, width, op);
|
||||
ImagingDrawWideLine(im, cx, cy, sx, sy, &ink, width, op);
|
||||
}
|
||||
}
|
||||
} else if (mode == CHORD) {
|
||||
if (x != sx || y != sy)
|
||||
draw->line(im, x, y, sx, sy, ink);
|
||||
ellipsePoint(cx, cy, w, h, i, &x, &y);
|
||||
if (i == start)
|
||||
sx_inner = x, sy_inner = y;
|
||||
else
|
||||
add_edge(&e[n++], lx_inner, ly_inner, x, y);
|
||||
lx_inner = x, ly_inner = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
x0++;
|
||||
y0++;
|
||||
x1--;
|
||||
y1--;
|
||||
|
||||
if (end - start < 360) {
|
||||
// Close polygon
|
||||
if (mode == PIESLICE) {
|
||||
if (x != cx || y != cy) {
|
||||
add_edge(&e[n++], sx, sy, cx, cy);
|
||||
add_edge(&e[n++], cx, cy, lx, ly);
|
||||
if (inner) {
|
||||
ImagingDrawWideLine(im, sx, sy, cx, cy, &ink, width, op);
|
||||
ImagingDrawWideLine(im, cx, cy, lx, ly, &ink, width, op);
|
||||
}
|
||||
}
|
||||
} else if (mode == CHORD) {
|
||||
add_edge(&e[n++], sx, sy, lx, ly);
|
||||
if (inner) {
|
||||
add_edge(&e[n++], sx_inner, sy_inner, lx_inner, ly_inner);
|
||||
}
|
||||
} else if (mode == ARC) {
|
||||
add_edge(&e[n++], sx, sy, sx_inner, sy_inner);
|
||||
add_edge(&e[n++], lx, ly, lx_inner, ly_inner);
|
||||
}
|
||||
}
|
||||
|
||||
draw->polygon(im, n, e, ink, 0);
|
||||
|
||||
free(e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user