Skip to content

Commit 8a0b617

Browse files
authored
Port clip_1d() clipping rectangle improvement of libgd 2.0.26 (GH-17341)
This is not a functional change, but rather a performance improvement, to avoid unnecessary calls of `gdImageSetPixel()` which would be no-ops due to positions outside of the clipping bounds.
1 parent 21f4211 commit 8a0b617

File tree

1 file changed

+30
-22
lines changed

1 file changed

+30
-22
lines changed

ext/gd/libgd/gd.c

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -680,18 +680,20 @@ void gdImagePaletteCopy (gdImagePtr to, gdImagePtr from)
680680
* the second call!) The code is simplified from that in the article,
681681
* as we know that gd images always start at (0,0)
682682
*/
683+
/* 2.0.26, TBB: we now have to respect a clipping rectangle, it won't
684+
necessarily start at 0. */
683685

684-
static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) {
686+
static int clip_1d(int *x0, int *y0, int *x1, int *y1, int mindim, int maxdim) {
685687
double m; /* gradient of line */
686688

687-
if (*x0 < 0) { /* start of line is left of window */
688-
if(*x1 < 0) { /* as is the end, so the line never cuts the window */
689+
if (*x0 < mindim) { /* start of line is left of window */
690+
if(*x1 < mindim) { /* as is the end, so the line never cuts the window */
689691
return 0;
690692
}
691693
m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */
692694
/* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */
693-
*y0 -= (int)(m * *x0);
694-
*x0 = 0;
695+
*y0 -= (int)(m * (*x0 - mindim));
696+
*x0 = mindim;
695697
/* now, perhaps, adjust the far end of the line as well */
696698
if (*x1 > maxdim) {
697699
*y1 += (int)(m * (maxdim - *x1));
@@ -707,9 +709,9 @@ static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) {
707709
*y0 += (int)(m * (maxdim - *x0)); /* adjust so point is on the right boundary */
708710
*x0 = maxdim;
709711
/* now, perhaps, adjust the end of the line */
710-
if (*x1 < 0) {
711-
*y1 -= (int)(m * *x1);
712-
*x1 = 0;
712+
if (*x1 < mindim) {
713+
*y1 -= (int)(m * (*x1 - mindim));
714+
*x1 = mindim;
713715
}
714716
return 1;
715717
}
@@ -720,10 +722,10 @@ static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) {
720722
*x1 = maxdim;
721723
return 1;
722724
}
723-
if (*x1 < 0) { /* other end is outside to the left */
725+
if (*x1 < mindim) { /* other end is outside to the left */
724726
m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */
725-
*y1 -= (int)(m * *x1);
726-
*x1 = 0;
727+
*y1 -= (int)(m * (*x1 - mindim));
728+
*x1 = mindim;
727729
return 1;
728730
}
729731
/* only get here if both points are inside the window */
@@ -1107,11 +1109,16 @@ void gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
11071109
gdImageAALine(im, x1, y1, x2, y2, im->AA_color);
11081110
return;
11091111
}
1112+
/* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no
1113+
points need to be drawn. 2.0.26, TBB: clip to edges of clipping
1114+
rectangle. We were getting away with this because gdImageSetPixel
1115+
is used for actual drawing, but this is still more efficient and opens
1116+
the way to skip per-pixel bounds checking in the future. */
11101117

1111-
/* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no points need to be drawn */
1112-
if (!clip_1d(&x1,&y1,&x2,&y2,gdImageSX(im)-1) || !clip_1d(&y1,&x1,&y2,&x2,gdImageSY(im)-1)) {
1118+
if (clip_1d (&x1, &y1, &x2, &y2, im->cx1, im->cx2) == 0)
1119+
return;
1120+
if (clip_1d (&y1, &x1, &y2, &x2, im->cy1, im->cy2) == 0)
11131121
return;
1114-
}
11151122

11161123
dx = abs (x2 - x1);
11171124
dy = abs (y2 - y1);
@@ -1299,10 +1306,11 @@ void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col)
12991306
return;
13001307
}
13011308

1302-
/* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no points need to be drawn */
1303-
if (!clip_1d(&x1,&y1,&x2,&y2,gdImageSX(im)-1) || !clip_1d(&y1,&x1,&y2,&x2,gdImageSY(im)-1)) {
1309+
/* TBB: use the clipping rectangle */
1310+
if (clip_1d (&x1, &y1, &x2, &y2, im->cx1, im->cx2) == 0)
1311+
return;
1312+
if (clip_1d (&y1, &x1, &y2, &x2, im->cy1, im->cy2) == 0)
13041313
return;
1305-
}
13061314

13071315
dx = x2 - x1;
13081316
dy = y2 - y1;
@@ -2788,13 +2796,13 @@ void gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
27882796
}
27892797
pmaxy = maxy;
27902798
/* 2.0.16: Optimization by Ilia Chipitsine -- don't waste time offscreen */
2791-
if (miny < 0) {
2792-
miny = 0;
2799+
/* 2.0.26: clipping rectangle is even better */
2800+
if (miny < im->cy1) {
2801+
miny = im->cy1;
27932802
}
2794-
if (maxy >= gdImageSY(im)) {
2795-
maxy = gdImageSY(im) - 1;
2803+
if (maxy > im->cy2) {
2804+
maxy = im->cy2;
27962805
}
2797-
27982806
/* Fix in 1.3: count a vertex only once */
27992807
for (y = miny; y <= maxy; y++) {
28002808
/*1.4 int interLast = 0; */

0 commit comments

Comments
 (0)