]> granicus.if.org Git - php/commitdiff
Fix #73614: gdImageFilledArc() doesn't properly draw pies
authorChristoph M. Becker <cmbecker69@gmx.de>
Wed, 16 Jan 2019 19:10:04 +0000 (20:10 +0100)
committerChristoph M. Becker <cmbecker69@gmx.de>
Wed, 16 Jan 2019 19:10:04 +0000 (20:10 +0100)
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>

NEWS
ext/gd/libgd/gd.c
ext/gd/tests/bug73614.phpt [new file with mode: 0644]
ext/gd/tests/bug73614.png [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 71f69919abeb20c7e28f2ce58146d1eba059e501..967afa21a0666b7e8bebd775e2821a70b996e9d7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,7 @@ PHP                                                                        NEWS
 - GD:
   . Fixed bug #73281 (imagescale(…, IMG_BILINEAR_FIXED) can cause black border).
     (cmb)
+  . Fixed bug #73614 (gdImageFilledArc() doesn't properly draw pies). (cmb)
   . Fixed bug #77272 (imagescale() may return image resource on failure). (cmb)
   . Fixed bug #77391 (1bpp BMPs may fail to be loaded). (Romain Déoux, cmb)
 
index c96e2085f08d7ce4fe38fff40e18ca7fb4d72a30..6284d091900318971b4d3459e062dbd5ae05218c 100644 (file)
@@ -1593,7 +1593,7 @@ void gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e
        int i, pti;
        int lx = 0, ly = 0;
        int fx = 0, fy = 0;
-
+       int startx, starty, endx, endy;
 
     if ((s % 360)  == (e % 360)) {
                s = 0; e = 360;
@@ -1620,8 +1620,8 @@ void gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e
 
        for (i = s, pti = 1; i <= e; i++, pti++) {
                int x, y;
-               x = ((long) gdCosT[i % 360] * (long) w / (2 * 1024)) + cx;
-               y = ((long) gdSinT[i % 360] * (long) h / (2 * 1024)) + cy;
+               x = endx = ((long) gdCosT[i % 360] * (long) w / (2 * 1024)) + cx;
+               y = endy = ((long) gdSinT[i % 360] * (long) h / (2 * 1024)) + cy;
                if (i != s) {
                        if (!(style & gdChord)) {
                                if (style & gdNoFill) {
@@ -1646,8 +1646,8 @@ void gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e
                        if (!(style & (gdChord | gdNoFill))) {
                                pts[0].x = cx;
                                pts[0].y = cy;
-                               pts[pti].x = x;
-                               pts[pti].y = y;
+                               pts[pti].x = startx = x;
+                               pts[pti].y = starty = y;
                        }
                }
                lx = x;
@@ -1676,6 +1676,24 @@ void gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e
                                gdImageLine(im, cx, cy, fx, fy, color);
                        }
                } else {
+                       if (e - s < 360) {
+                               if (pts[1].x != startx && pts[1].y == starty) {
+                                       /* start point has been removed due to y-coord fix => insert it */
+                                       for (i = pti; i > 1; i--) {
+                                               pts[i].x = pts[i-1].x;
+                                               pts[i].y = pts[i-1].y;
+                                       }
+                                       pts[1].x = startx;
+                                       pts[1].y = starty;
+                                       pti++;
+                               }
+                               if (pts[pti-1].x != endx && pts[pti-1].y == endy) {
+                                       /* end point has been removed due to y-coord fix => insert it */
+                                       pts[pti].x = endx;
+                                       pts[pti].y = endy;
+                                       pti++;
+                               }
+                       }
                        pts[pti].x = cx;
                        pts[pti].y = cy;
                        gdImageFilledPolygon(im, pts, pti+1, color);
diff --git a/ext/gd/tests/bug73614.phpt b/ext/gd/tests/bug73614.phpt
new file mode 100644 (file)
index 0000000..f94881e
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Bug #73614 (gdImageFilledArc() doesn't properly draw pies)
+--SKIPIF--
+<?php
+if (!extension_loaded('gd')) die('skip gd extension not available');
+if (!GD_BUNDLED && version_compare(GD_VERSION, '2.2.5', '<=')) die('skip upstream bugfix not yet released');
+?>
+--FILE--
+<?php
+require_once __DIR__ . '/func.inc';
+
+$image = imagecreatetruecolor(500, 500);
+
+$white    = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
+$navy     = imagecolorallocate($image, 0x00, 0x00, 0x80);
+$red      = imagecolorallocate($image, 0xFF, 0x00, 0x00);
+
+imagefilledarc($image, 250, 250, 500, 250, 0, 88, $white, IMG_ARC_PIE);
+imagefilledarc($image, 250, 250, 500, 250, 88, 91 , $navy, IMG_ARC_PIE);
+imagefilledarc($image, 250, 250, 500, 250, 91, 360 , $red, IMG_ARC_PIE);
+
+test_image_equals_file(__DIR__ . '/bug73614.png', $image);
+?>
+===DONE===
+--EXPECT--
+The images are equal.
+===DONE===
diff --git a/ext/gd/tests/bug73614.png b/ext/gd/tests/bug73614.png
new file mode 100644 (file)
index 0000000..16b2db2
Binary files /dev/null and b/ext/gd/tests/bug73614.png differ