Skip to content

Commit 61cfa34

Browse files
committed
Fix #73614: gdImageFilledArc() doesn't properly draw pies
The fix for PHP bug 43828[1] changed the algorithm from drawing filled pies from drawing multiple triangles to drawing a single polygon. Due to quirks of the filled polygon drawing algorithm, we had to filter out extraneous vertices. This lead, however, to a bug regarding displaced starting and ending points near 90° and 270° degrees, which we fix by reinserting these vertices if they had been removed. This fix is a port of libgd/libgd@1406b1a. [1] <https://bugs.php.net/bug.php?id=43828>
1 parent 5ac9990 commit 61cfa34

File tree

4 files changed

+51
-5
lines changed

4 files changed

+51
-5
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ PHP NEWS
88
- GD:
99
. Fixed bug #73281 (imagescale(…, IMG_BILINEAR_FIXED) can cause black border).
1010
(cmb)
11+
. Fixed bug #73614 (gdImageFilledArc() doesn't properly draw pies). (cmb)
1112
. Fixed bug #77272 (imagescale() may return image resource on failure). (cmb)
1213
. Fixed bug #77391 (1bpp BMPs may fail to be loaded). (Romain Déoux, cmb)
1314

ext/gd/libgd/gd.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,7 +1593,7 @@ void gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e
15931593
int i, pti;
15941594
int lx = 0, ly = 0;
15951595
int fx = 0, fy = 0;
1596-
1596+
int startx, starty, endx, endy;
15971597

15981598
if ((s % 360) == (e % 360)) {
15991599
s = 0; e = 360;
@@ -1620,8 +1620,8 @@ void gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e
16201620

16211621
for (i = s, pti = 1; i <= e; i++, pti++) {
16221622
int x, y;
1623-
x = ((long) gdCosT[i % 360] * (long) w / (2 * 1024)) + cx;
1624-
y = ((long) gdSinT[i % 360] * (long) h / (2 * 1024)) + cy;
1623+
x = endx = ((long) gdCosT[i % 360] * (long) w / (2 * 1024)) + cx;
1624+
y = endy = ((long) gdSinT[i % 360] * (long) h / (2 * 1024)) + cy;
16251625
if (i != s) {
16261626
if (!(style & gdChord)) {
16271627
if (style & gdNoFill) {
@@ -1646,8 +1646,8 @@ void gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e
16461646
if (!(style & (gdChord | gdNoFill))) {
16471647
pts[0].x = cx;
16481648
pts[0].y = cy;
1649-
pts[pti].x = x;
1650-
pts[pti].y = y;
1649+
pts[pti].x = startx = x;
1650+
pts[pti].y = starty = y;
16511651
}
16521652
}
16531653
lx = x;
@@ -1676,6 +1676,24 @@ void gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e
16761676
gdImageLine(im, cx, cy, fx, fy, color);
16771677
}
16781678
} else {
1679+
if (e - s < 360) {
1680+
if (pts[1].x != startx && pts[1].y == starty) {
1681+
/* start point has been removed due to y-coord fix => insert it */
1682+
for (i = pti; i > 1; i--) {
1683+
pts[i].x = pts[i-1].x;
1684+
pts[i].y = pts[i-1].y;
1685+
}
1686+
pts[1].x = startx;
1687+
pts[1].y = starty;
1688+
pti++;
1689+
}
1690+
if (pts[pti-1].x != endx && pts[pti-1].y == endy) {
1691+
/* end point has been removed due to y-coord fix => insert it */
1692+
pts[pti].x = endx;
1693+
pts[pti].y = endy;
1694+
pti++;
1695+
}
1696+
}
16791697
pts[pti].x = cx;
16801698
pts[pti].y = cy;
16811699
gdImageFilledPolygon(im, pts, pti+1, color);

ext/gd/tests/bug73614.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Bug #73614 (gdImageFilledArc() doesn't properly draw pies)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('gd')) die('skip gd extension not available');
6+
if (!GD_BUNDLED && version_compare(GD_VERSION, '2.2.5', '<=')) die('skip upstream bugfix not yet released');
7+
?>
8+
--FILE--
9+
<?php
10+
require_once __DIR__ . '/func.inc';
11+
12+
$image = imagecreatetruecolor(500, 500);
13+
14+
$white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
15+
$navy = imagecolorallocate($image, 0x00, 0x00, 0x80);
16+
$red = imagecolorallocate($image, 0xFF, 0x00, 0x00);
17+
18+
imagefilledarc($image, 250, 250, 500, 250, 0, 88, $white, IMG_ARC_PIE);
19+
imagefilledarc($image, 250, 250, 500, 250, 88, 91 , $navy, IMG_ARC_PIE);
20+
imagefilledarc($image, 250, 250, 500, 250, 91, 360 , $red, IMG_ARC_PIE);
21+
22+
test_image_equals_file(__DIR__ . '/bug73614.png', $image);
23+
?>
24+
===DONE===
25+
--EXPECT--
26+
The images are equal.
27+
===DONE===

ext/gd/tests/bug73614.png

2.59 KB
Loading

0 commit comments

Comments
 (0)