summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmb@php.net>2016-06-15 20:58:06 +0200
committerChristoph M. Becker <cmb@php.net>2016-06-16 13:59:00 +0200
commit8aa511f1fc8123bba6107fa856b0b6bf298de87c (patch)
treecafc844e4cc1dd45f66c3140b8196b60b34fd209
parent8267a5fba75baf938306d1169807be57d646c6df (diff)
downloadphp-git-8aa511f1fc8123bba6107fa856b0b6bf298de87c.tar.gz
Fix #43475: Styled thick horizontal lines are scrambled
Thick lines are drawn by gdImageFilledRectangle(), which iterates over the x ordinate first (Z order) to apply the style pattern. While this works fine for vertical and diagonal lines, it obviously fails for horizontal lines, which have to be iterated over in N order. To fix this bug, we introduce the helpers gdImageFilled(H|V)Rectangle(), which may be reused for other purposes as well. This is basically the same fix as libgd/libgd/c2b91dbc.
-rw-r--r--ext/gd/libgd/gd.c54
-rw-r--r--ext/gd/tests/bug43475.phpt59
-rw-r--r--ext/gd/tests/bug43475.pngbin0 -> 4697 bytes
3 files changed, 111 insertions, 2 deletions
diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c
index 5170f4f8c0..89c7dbdd58 100644
--- a/ext/gd/libgd/gd.c
+++ b/ext/gd/libgd/gd.c
@@ -1051,11 +1051,13 @@ void gdImageAABlend (gdImagePtr im)
}
}
+static void _gdImageFilledHRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color);
+
static void gdImageHLine(gdImagePtr im, int y, int x1, int x2, int col)
{
if (im->thick > 1) {
int thickhalf = im->thick >> 1;
- gdImageFilledRectangle(im, x1, y - thickhalf, x2, y + im->thick - thickhalf - 1, col);
+ _gdImageFilledHRectangle(im, x1, y - thickhalf, x2, y + im->thick - thickhalf - 1, col);
} else {
if (x2 < x1) {
int t = x2;
@@ -2120,10 +2122,53 @@ void gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
}
}
-void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+static void _gdImageFilledHRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
{
int x, y;
+ if (x1 == x2 && y1 == y2) {
+ gdImageSetPixel(im, x1, y1, color);
+ return;
+ }
+
+ if (x1 > x2) {
+ x = x1;
+ x1 = x2;
+ x2 = x;
+ }
+
+ if (y1 > y2) {
+ y = y1;
+ y1 = y2;
+ y2 = y;
+ }
+
+ if (x1 < 0) {
+ x1 = 0;
+ }
+
+ if (x2 >= gdImageSX(im)) {
+ x2 = gdImageSX(im) - 1;
+ }
+
+ if (y1 < 0) {
+ y1 = 0;
+ }
+
+ if (y2 >= gdImageSY(im)) {
+ y2 = gdImageSY(im) - 1;
+ }
+
+ for (x = x1; (x <= x2); x++) {
+ for (y = y1; (y <= y2); y++) {
+ gdImageSetPixel (im, x, y, color);
+ }
+ }
+}
+
+static void _gdImageFilledVRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+{
+ int x, y;
if (x1 == x2 && y1 == y2) {
gdImageSetPixel(im, x1, y1, color);
@@ -2165,6 +2210,11 @@ void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int
}
}
+void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+{
+ _gdImageFilledVRectangle(im, x1, y1, x2, y2, color);
+}
+
void gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h)
{
int c;
diff --git a/ext/gd/tests/bug43475.phpt b/ext/gd/tests/bug43475.phpt
new file mode 100644
index 0000000000..b29b9800a5
--- /dev/null
+++ b/ext/gd/tests/bug43475.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Bug #43475 (Thick styled lines have scrambled patterns)
+--SKIPIF--
+<?php
+ if (!extension_loaded('gd')) die("skip gd extension not available\n");
+?>
+--FILE--
+<?php
+require_once __DIR__ . '/similarity.inc';
+
+function setStyleAndThickness($im, $color, $thickness)
+{
+ $style = array();
+ $i = 0;
+ while ($i < 16 * $thickness) {
+ $style[$i++] = $color;
+ }
+ while ($i < 20 * $thickness) {
+ $style[$i++] = IMG_COLOR_TRANSPARENT;
+ }
+ while ($i < 28 * $thickness) {
+ $style[$i++] = $color;
+ }
+ while ($i < 32 * $thickness) {
+ $style[$i++] = IMG_COLOR_TRANSPARENT;
+ }
+ imagesetstyle($im, $style);
+ imagesetthickness($im, $thickness);
+}
+
+$im = imagecreate(800, 800);
+imagecolorallocate($im, 255, 255, 255);
+$black = imagecolorallocate($im, 0, 0, 0);
+
+setStyleAndThickness($im, $black, 1);
+imageline($im, 50, 250, 550, 250, IMG_COLOR_STYLED);
+imageline($im, 550, 250, 550, 750, IMG_COLOR_STYLED);
+imageline($im, 550, 750, 50, 250, IMG_COLOR_STYLED);
+
+setStyleAndThickness($im, $black, 2);
+imageline($im, 100, 200, 600, 200, IMG_COLOR_STYLED);
+imageline($im, 600, 200, 600, 700, IMG_COLOR_STYLED);
+imageline($im, 600, 700, 100, 200, IMG_COLOR_STYLED);
+
+setStyleAndThickness($im, $black, 4);
+imageline($im, 150, 150, 650, 150, IMG_COLOR_STYLED);
+imageline($im, 650, 150, 650, 650, IMG_COLOR_STYLED);
+imageline($im, 650, 650, 150, 150, IMG_COLOR_STYLED);
+
+setStyleAndThickness($im, $black, 6);
+imageline($im, 200, 100, 700, 100, IMG_COLOR_STYLED);
+imageline($im, 700, 100, 700, 600, IMG_COLOR_STYLED);
+imageline($im, 700, 600, 200, 100, IMG_COLOR_STYLED);
+
+$ex = imagecreatefrompng(__DIR__ . '/bug43475.png');
+var_dump(calc_image_dissimilarity($ex, $im) < 1e-5);
+?>
+--EXPECT--
+bool(true)
diff --git a/ext/gd/tests/bug43475.png b/ext/gd/tests/bug43475.png
new file mode 100644
index 0000000000..774270f63d
--- /dev/null
+++ b/ext/gd/tests/bug43475.png
Binary files differ