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