Skip to content

Commit

Permalink
Fix #43475: Styled thick horizontal lines are scrambled
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cmb69 committed Jun 16, 2016
1 parent 8267a5f commit 8aa511f
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 2 deletions.
54 changes: 52 additions & 2 deletions ext/gd/libgd/gd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
59 changes: 59 additions & 0 deletions ext/gd/tests/bug43475.phpt
Original file line number Diff line number Diff line change
@@ -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)
Binary file added ext/gd/tests/bug43475.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8aa511f

Please sign in to comment.