Skip to content

Port clip_1d() clipping rectangle improvement of libgd 2.0.26 #17341

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 3, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 30 additions & 22 deletions ext/gd/libgd/gd.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,18 +680,20 @@ void gdImagePaletteCopy (gdImagePtr to, gdImagePtr from)
* the second call!) The code is simplified from that in the article,
* as we know that gd images always start at (0,0)
*/
/* 2.0.26, TBB: we now have to respect a clipping rectangle, it won't
necessarily start at 0. */

static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) {
static int clip_1d(int *x0, int *y0, int *x1, int *y1, int mindim, int maxdim) {
double m; /* gradient of line */

if (*x0 < 0) { /* start of line is left of window */
if(*x1 < 0) { /* as is the end, so the line never cuts the window */
if (*x0 < mindim) { /* start of line is left of window */
if(*x1 < mindim) { /* as is the end, so the line never cuts the window */
return 0;
}
m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */
/* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */
*y0 -= (int)(m * *x0);
*x0 = 0;
*y0 -= (int)(m * (*x0 - mindim));
*x0 = mindim;
/* now, perhaps, adjust the far end of the line as well */
if (*x1 > maxdim) {
*y1 += (int)(m * (maxdim - *x1));
Expand All @@ -707,9 +709,9 @@ static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) {
*y0 += (int)(m * (maxdim - *x0)); /* adjust so point is on the right boundary */
*x0 = maxdim;
/* now, perhaps, adjust the end of the line */
if (*x1 < 0) {
*y1 -= (int)(m * *x1);
*x1 = 0;
if (*x1 < mindim) {
*y1 -= (int)(m * (*x1 - mindim));
*x1 = mindim;
}
return 1;
}
Expand All @@ -720,10 +722,10 @@ static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) {
*x1 = maxdim;
return 1;
}
if (*x1 < 0) { /* other end is outside to the left */
if (*x1 < mindim) { /* other end is outside to the left */
m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */
*y1 -= (int)(m * *x1);
*x1 = 0;
*y1 -= (int)(m * (*x1 - mindim));
*x1 = mindim;
return 1;
}
/* only get here if both points are inside the window */
Expand Down Expand Up @@ -1107,11 +1109,16 @@ void gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
gdImageAALine(im, x1, y1, x2, y2, im->AA_color);
return;
}
/* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no
points need to be drawn. 2.0.26, TBB: clip to edges of clipping
rectangle. We were getting away with this because gdImageSetPixel
is used for actual drawing, but this is still more efficient and opens
the way to skip per-pixel bounds checking in the future. */

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

dx = abs (x2 - x1);
dy = abs (y2 - y1);
Expand Down Expand Up @@ -1299,10 +1306,11 @@ void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col)
return;
}

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

dx = x2 - x1;
dy = y2 - y1;
Expand Down Expand Up @@ -2788,13 +2796,13 @@ void gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
}
pmaxy = maxy;
/* 2.0.16: Optimization by Ilia Chipitsine -- don't waste time offscreen */
if (miny < 0) {
miny = 0;
/* 2.0.26: clipping rectangle is even better */
if (miny < im->cy1) {
miny = im->cy1;
}
if (maxy >= gdImageSY(im)) {
maxy = gdImageSY(im) - 1;
if (maxy > im->cy2) {
maxy = im->cy2;
}

/* Fix in 1.3: count a vertex only once */
for (y = miny; y <= maxy; y++) {
/*1.4 int interLast = 0; */
Expand Down
Loading