src/video/SDL_rect.c
 changeset 2994 7563b99e9a49 parent 2920 cdb01906cb7e child 2997 e4f025078c1c
```     1.1 --- a/src/video/SDL_rect.c	Sun Jan 04 19:26:50 2009 +0000
1.2 +++ b/src/video/SDL_rect.c	Sun Jan 04 19:33:21 2009 +0000
1.3 @@ -148,13 +148,13 @@
1.4          return SDL_TRUE;
1.5      }
1.6
1.7 -    /* Check to see if entire line is outside rect */
1.8 +    /* Check to see if entire line is to one side of rect */
1.9      if ((x1 < rectx1 && x2 < rectx1) || (x1 > rectx2 && x2 > rectx2) ||
1.10          (y1 < recty1 && y2 < recty2) || (y1 > recty2 && y2 > recty2)) {
1.11          return SDL_FALSE;
1.12      }
1.13
1.14 -    if (y1 = y2) {
1.15 +    if (y1 == y2) {
1.16          /* Horizontal line, easy to clip */
1.17          if (x1 < rectx1) {
1.18              *X1 = rectx1;
1.19 @@ -184,7 +184,92 @@
1.20          return SDL_TRUE;
1.21      }
1.22
1.23 -    /* FIXME: need code to clip diagonal line to rect */
1.24 +    else
1.25 +    {
1.26 +    /* The task of clipping a line with finite slope ratios in a fixed-
1.27 +     * precision coordinate space is not as immediately simple as it is
1.28 +     * with coordinates of arbitrary precision. If the ratio of slopes
1.29 +     * between the input line segment and the result line segment is not
1.30 +     * a whole number, you have in fact *moved* the line segment a bit,
1.31 +     * and there can be no avoiding it without more precision
1.32 +     */
1.33 +        int *x_result_[] = {X1, X2, NULL}, **x_result = x_result_;
1.34 +        int *y_result_[] = {Y1, Y2, NULL}, **y_result = y_result_;
1.35 +        SDL_bool intersection = SDL_FALSE;
1.36 +        double b, m, left, right, bottom, top;
1.37 +        int xl, xh, yl, yh;
1.38 +
1.39 +        /* solve mx+b line formula */
1.40 +        m = (double)(y1-y2) / (double)(x1-x2);
1.41 +        b = y2 - m * (double) x2;
1.42 +
1.43 +        /* find some linear intersections */
1.44 +        left = (m * (double) rectx1) + b;
1.45 +        right = (m * (double) rectx2) + b;
1.46 +        top = (recty1 - b) / m;
1.47 +        bottom = (recty2 - b) / m;
1.48 +
1.49 +        /* sort end-points' x and y components individually */
1.50 +        if (x1 < x2) {
1.51 +            xl = x1;
1.52 +            xh = x2;
1.53 +        } else {
1.54 +            xl = x2;
1.55 +            xh = x1;
1.56 +        }
1.57 +        if (y1 < y2) {
1.58 +            yl = y1;
1.59 +            yh = y2;
1.60 +        } else {
1.61 +            yl = y2;
1.62 +            yh = y1;
1.63 +        }
1.64 +
1.65 +#define RISING(a, b, c) (((a)<=(b))&&((b)<=(c)))
1.66 +
1.67 +        /* check for a point that's entirely inside the rect */
1.68 +        if (RISING(rectx1, x1, rectx2) && RISING(recty1, y1, recty2)) {
1.69 +            x_result++;
1.70 +            y_result++;
1.71 +            intersection = SDL_TRUE;
1.72 +        } else /* it was determined earlier that *both* end-points are not contained */
1.73 +
1.74 +        if (RISING(rectx1, x2, rectx2) && RISING(recty1, y2, recty2)) {
1.75 +            **(x_result++) = x2;
1.76 +            **(y_result++) = y2;
1.77 +            intersection = SDL_TRUE;
1.78 +        }
1.79 +
1.80 +        if (RISING(recty1, left, recty2) && RISING(xl, rectx1, xh)) {
1.81 +            **(x_result++) = rectx1;
1.82 +            **(y_result++) = (int) left;
1.83 +            intersection = SDL_TRUE;
1.84 +        }
1.85 +
1.86 +        if (*x_result == NULL) return intersection;
1.87 +        if (RISING(recty1, right, recty2) && RISING(xl, rectx2, xh)) {
1.88 +            **(x_result++) = rectx2;
1.89 +            **(y_result++) = (int) right;
1.90 +            intersection = SDL_TRUE;
1.91 +        }
1.92 +
1.93 +        if (*x_result == NULL) return intersection;
1.94 +        if (RISING(rectx1, top, rectx2) && RISING(yl, recty1, yh)) {
1.95 +            **(x_result++) = (int) top;
1.96 +            **(y_result++) = recty1;
1.97 +            intersection = SDL_TRUE;
1.98 +        }
1.99 +
1.100 +        if (*x_result == NULL) return intersection;
1.101 +        if (RISING(rectx1, bottom, rectx2) && RISING(yl, recty2, yh)) {
1.102 +            **(x_result++) = (int) bottom;
1.103 +            **(y_result++) = recty2;
1.104 +            intersection = SDL_TRUE;
1.105 +        }
1.106 +
1.107 +        return intersection;
1.108 +    }
1.109 +
1.110      return SDL_FALSE;
1.111  }
1.112
```