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
2.1 --- a/test/Makefile.in Sun Jan 04 19:26:50 2009 +0000
2.2 +++ b/test/Makefile.in Sun Jan 04 19:33:21 2009 +0000
2.3 @@ -7,7 +7,7 @@
2.4 CFLAGS = @CFLAGS@
2.5 LIBS = @LIBS@
2.6
2.7 -TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testdraw2$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) testloadso$(EXE) testhaptic$(EXE) testmmousetablet$(EXE)
2.8 +TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testintersections$(EXE) testdraw2$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) testloadso$(EXE) testhaptic$(EXE) testmmousetablet$(EXE)
2.9
2.10 all: Makefile $(TARGETS)
2.11
2.12 @@ -44,6 +44,9 @@
2.13 testcursor$(EXE): $(srcdir)/testcursor.c
2.14 $(CC) -o $@ $? $(CFLAGS) $(LIBS)
2.15
2.16 +testintersections$(EXE): $(srcdir)/testintersections.c $(srcdir)/common.c
2.17 + $(CC) -o $@ $(srcdir)/testintersections.c $(srcdir)/common.c $(CFLAGS) $(LIBS)
2.18 +
2.19 testdraw2$(EXE): $(srcdir)/testdraw2.c $(srcdir)/common.c
2.20 $(CC) -o $@ $(srcdir)/testdraw2.c $(srcdir)/common.c $(CFLAGS) $(LIBS)
2.21
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/test/testintersections.c Sun Jan 04 19:33:21 2009 +0000
3.3 @@ -0,0 +1,342 @@
3.4 +
3.5 +/* Simple program: draw as many random objects on the screen as possible */
3.6 +
3.7 +#include <stdlib.h>
3.8 +#include <stdio.h>
3.9 +#include <time.h>
3.10 +
3.11 +#include "common.h"
3.12 +
3.13 +#define SWAP(typ,a,b) do{typ t=a;a=b;b=t;}while(0)
3.14 +#define NUM_OBJECTS 100
3.15 +
3.16 +static CommonState *state;
3.17 +static int num_objects;
3.18 +static SDL_bool cycle_color;
3.19 +static SDL_bool cycle_alpha;
3.20 +static int cycle_direction = 1;
3.21 +static int current_alpha = 255;
3.22 +static int current_color = 255;
3.23 +static SDL_BlendMode blendMode = SDL_BLENDMODE_NONE;
3.24 +
3.25 +void
3.26 +DrawPoints(SDL_WindowID window)
3.27 +{
3.28 + int i;
3.29 + int x, y;
3.30 + int window_w, window_h;
3.31 +
3.32 + /* Query the sizes */
3.33 + SDL_GetWindowSize(window, &window_w, &window_h);
3.34 +
3.35 + SDL_SetRenderDrawBlendMode(blendMode);
3.36 + for (i = 0; i < num_objects * 4; ++i) {
3.37 + /* Cycle the color and alpha, if desired */
3.38 + if (cycle_color) {
3.39 + current_color += cycle_direction;
3.40 + if (current_color < 0) {
3.41 + current_color = 0;
3.42 + cycle_direction = -cycle_direction;
3.43 + }
3.44 + if (current_color > 255) {
3.45 + current_color = 255;
3.46 + cycle_direction = -cycle_direction;
3.47 + }
3.48 + }
3.49 + if (cycle_alpha) {
3.50 + current_alpha += cycle_direction;
3.51 + if (current_alpha < 0) {
3.52 + current_alpha = 0;
3.53 + cycle_direction = -cycle_direction;
3.54 + }
3.55 + if (current_alpha > 255) {
3.56 + current_alpha = 255;
3.57 + cycle_direction = -cycle_direction;
3.58 + }
3.59 + }
3.60 + SDL_SetRenderDrawColor(255, (Uint8) current_color,
3.61 + (Uint8) current_color, (Uint8) current_alpha);
3.62 +
3.63 + x = rand() % window_w;
3.64 + y = rand() % window_h;
3.65 + SDL_RenderPoint(x, y);
3.66 + }
3.67 + SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
3.68 +}
3.69 +
3.70 +#define MAX_LINES 16
3.71 +int num_lines = 0;
3.72 +SDL_Rect lines[MAX_LINES];
3.73 +static int add_line(int x1, int y1, int x2, int y2) {
3.74 + if (num_lines >= MAX_LINES) return 0;
3.75 + if ((x1 == x2) && (y1 == y2)) return 0;
3.76 +
3.77 + printf("adding line (%d, %d), (%d, %d)\n", x1, y1, x2, y2);
3.78 + lines[num_lines].x = x1;
3.79 + lines[num_lines].y = y1;
3.80 + lines[num_lines].w = x2;
3.81 + lines[num_lines].h = y2;
3.82 +
3.83 + return ++num_lines;
3.84 +}
3.85 +
3.86 +
3.87 +void
3.88 +DrawLines(SDL_WindowID window)
3.89 +{
3.90 + int i;
3.91 + int x1, y1, x2, y2;
3.92 + int window_w, window_h;
3.93 +
3.94 + /* Query the sizes */
3.95 + SDL_GetWindowSize(window, &window_w, &window_h);
3.96 +
3.97 + SDL_SetRenderDrawBlendMode(blendMode);
3.98 + for (i = 0; i < num_lines; ++i) {
3.99 + SDL_SetRenderDrawColor(255, 255, 255, 255);
3.100 +
3.101 + if (i == -1) {
3.102 + SDL_RenderLine(0, 0, window_w - 1, window_h - 1);
3.103 + SDL_RenderLine(0, window_h - 1, window_w - 1, 0);
3.104 + SDL_RenderLine(0, window_h / 2, window_w - 1, window_h / 2);
3.105 + SDL_RenderLine(window_w / 2, 0, window_w / 2, window_h - 1);
3.106 + } else {
3.107 + SDL_RenderLine(lines[i].x, lines[i].y, lines[i].w, lines[i].h);
3.108 + }
3.109 + }
3.110 + SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
3.111 +}
3.112 +
3.113 +#define MAX_RECTS 16
3.114 +int num_rects = 0;
3.115 +SDL_Rect rects[MAX_RECTS];
3.116 +static int add_rect(int x1, int y1, int x2, int y2) {
3.117 + if (num_rects >= MAX_RECTS) return 0;
3.118 + if ((x1 == x2) || (y1 == y2)) return 0;
3.119 +
3.120 + if (x1 > x2) SWAP(int, x1, x2);
3.121 + if (y1 > y2) SWAP(int, y1, y2);
3.122 +
3.123 + printf("adding rect (%d, %d), (%d, %d) [%dx%d]\n", x1, y1, x2, y2, x2-x1, y2-y1);
3.124 +
3.125 + rects[num_rects].x = x1;
3.126 + rects[num_rects].y = y1;
3.127 + rects[num_rects].w = x2 - x1;
3.128 + rects[num_rects].h = y2 - y1;
3.129 +
3.130 + return ++num_rects;
3.131 +}
3.132 +
3.133 +static void
3.134 +DrawRects(SDL_WindowID window)
3.135 +{
3.136 + int i;
3.137 + int window_w, window_h;
3.138 +
3.139 + /* Query the sizes */
3.140 + SDL_GetWindowSize(window, &window_w, &window_h);
3.141 +
3.142 + SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
3.143 + for (i = 0; i < num_rects; ++i) {
3.144 + SDL_SetRenderDrawColor(255, 127, 0, 255);
3.145 + SDL_RenderFill(&rects[i]);
3.146 + }
3.147 + SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
3.148 +}
3.149 +
3.150 +static void
3.151 +DrawRectLineIntersections(SDL_WindowID window)
3.152 +{
3.153 + int i, j, window_w, window_h;
3.154 +
3.155 + /* Query the sizes */
3.156 + SDL_GetWindowSize(window, &window_w, &window_h);
3.157 +
3.158 + SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
3.159 +
3.160 + for (i = 0; i < num_rects; i++)
3.161 + for (j = 0; j < num_lines; j++) {
3.162 + int x1, y1, x2, y2;
3.163 + SDL_Rect r;
3.164 +
3.165 + r = rects[i];
3.166 + x1 = lines[j].x;
3.167 + y1 = lines[j].y;
3.168 + x2 = lines[j].w;
3.169 + y2 = lines[j].h;
3.170 +
3.171 + if (SDL_IntersectRectAndLine(&r, &x1, &y1, &x2, &y2)) {
3.172 + SDL_SetRenderDrawColor(0, 255, 55, 255);
3.173 + SDL_RenderLine(x1, y1, x2, y2);
3.174 + }
3.175 + }
3.176 +
3.177 + SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
3.178 +}
3.179 +
3.180 +static void
3.181 +DrawRectRectIntersections(SDL_WindowID window)
3.182 +{
3.183 + int i, j;
3.184 +
3.185 + SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
3.186 +
3.187 + for (i = 0; i < num_rects; i++)
3.188 + for (j = i+1; j < num_rects; j++) {
3.189 + SDL_Rect r;
3.190 + if (SDL_IntersectRect(&rects[i], &rects[j], &r)) {
3.191 + SDL_SetRenderDrawColor(255, 200, 0, 255);
3.192 + SDL_RenderFill(&r);
3.193 + }
3.194 + }
3.195 +
3.196 + SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
3.197 +}
3.198 +
3.199 +int
3.200 +main(int argc, char *argv[])
3.201 +{
3.202 + int mouse_begin_x = -1, mouse_begin_y = -1;
3.203 + int i, done;
3.204 + SDL_Event event;
3.205 + Uint32 then, now, frames;
3.206 +
3.207 + /* Initialize parameters */
3.208 + num_objects = NUM_OBJECTS;
3.209 +
3.210 + /* Initialize test framework */
3.211 + state = CommonCreateState(argv, SDL_INIT_VIDEO);
3.212 + if (!state) {
3.213 + return 1;
3.214 + }
3.215 + for (i = 1; i < argc;) {
3.216 + int consumed;
3.217 +
3.218 + consumed = CommonArg(state, i);
3.219 + if (consumed == 0) {
3.220 + consumed = -1;
3.221 + if (SDL_strcasecmp(argv[i], "--blend") == 0) {
3.222 + if (argv[i + 1]) {
3.223 + if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
3.224 + blendMode = SDL_BLENDMODE_NONE;
3.225 + consumed = 2;
3.226 + } else if (SDL_strcasecmp(argv[i + 1], "mask") == 0) {
3.227 + blendMode = SDL_BLENDMODE_MASK;
3.228 + consumed = 2;
3.229 + } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
3.230 + blendMode = SDL_BLENDMODE_BLEND;
3.231 + consumed = 2;
3.232 + } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
3.233 + blendMode = SDL_BLENDMODE_ADD;
3.234 + consumed = 2;
3.235 + } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
3.236 + blendMode = SDL_BLENDMODE_MOD;
3.237 + consumed = 2;
3.238 + }
3.239 + }
3.240 + } else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) {
3.241 + cycle_color = SDL_TRUE;
3.242 + consumed = 1;
3.243 + } else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) {
3.244 + cycle_alpha = SDL_TRUE;
3.245 + consumed = 1;
3.246 + } else if (SDL_isdigit(*argv[i])) {
3.247 + num_objects = SDL_atoi(argv[i]);
3.248 + consumed = 1;
3.249 + }
3.250 + }
3.251 + if (consumed < 0) {
3.252 + fprintf(stderr,
3.253 + "Usage: %s %s [--blend none|mask|blend|add|mod] [--cyclecolor] [--cyclealpha]\n",
3.254 + argv[0], CommonUsage(state));
3.255 + return 1;
3.256 + }
3.257 + i += consumed;
3.258 + }
3.259 + if (!CommonInit(state)) {
3.260 + return 2;
3.261 + }
3.262 +
3.263 + /* Create the windows and initialize the renderers */
3.264 + for (i = 0; i < state->num_windows; ++i) {
3.265 + SDL_SelectRenderer(state->windows[i]);
3.266 + SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
3.267 + SDL_RenderFill(NULL);
3.268 + }
3.269 +
3.270 + srand(time(NULL));
3.271 +
3.272 + /* Main render loop */
3.273 + frames = 0;
3.274 + then = SDL_GetTicks();
3.275 + done = 0;
3.276 + while (!done) {
3.277 + /* Check for events */
3.278 + ++frames;
3.279 + while (SDL_PollEvent(&event)) {
3.280 + CommonEvent(state, &event, &done);
3.281 + switch (event.type) {
3.282 + case SDL_MOUSEBUTTONDOWN:
3.283 + if (event.button.which == 0) {
3.284 + mouse_begin_x = event.button.x;
3.285 + mouse_begin_y = event.button.y;
3.286 + }
3.287 + break;
3.288 + case SDL_MOUSEBUTTONUP:
3.289 + if (event.button.which == 0) {
3.290 + if (event.button.button == 3)
3.291 + add_line(mouse_begin_x, mouse_begin_y, event.button.x, event.button.y);
3.292 + if (event.button.button == 1)
3.293 + add_rect(mouse_begin_x, mouse_begin_y, event.button.x, event.button.y);
3.294 + }
3.295 + break;
3.296 + case SDL_KEYDOWN:
3.297 + switch (event.key.keysym.sym) {
3.298 + case 'l':
3.299 + if (event.key.keysym.mod & KMOD_SHIFT) num_lines = 0;
3.300 + else add_line(rand()%640, rand()%480, rand()%640, rand()%480);
3.301 + break;
3.302 + case 'r':
3.303 + if (event.key.keysym.mod & KMOD_SHIFT) num_rects = 0;
3.304 + else add_rect(rand()%640, rand()%480, rand()%640, rand()%480);
3.305 + break;
3.306 + }
3.307 + break;
3.308 + case SDL_WINDOWEVENT:
3.309 + switch (event.window.event) {
3.310 + case SDL_WINDOWEVENT_EXPOSED:
3.311 + SDL_SelectRenderer(event.window.windowID);
3.312 + SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
3.313 + SDL_RenderFill(NULL);
3.314 + break;
3.315 + }
3.316 + break;
3.317 + default:
3.318 + break;
3.319 + }
3.320 + }
3.321 + for (i = 0; i < state->num_windows; ++i) {
3.322 + SDL_SelectRenderer(state->windows[i]);
3.323 + SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
3.324 + SDL_RenderFill(NULL);
3.325 +
3.326 + DrawRects(state->windows[i]);
3.327 + DrawPoints(state->windows[i]);
3.328 + DrawRectRectIntersections(state->windows[i]);
3.329 + DrawLines(state->windows[i]);
3.330 + DrawRectLineIntersections(state->windows[i]);
3.331 +
3.332 + SDL_RenderPresent();
3.333 + }
3.334 + }
3.335 +
3.336 + /* Print out some timing information */
3.337 + now = SDL_GetTicks();
3.338 + if (now > then) {
3.339 + double fps = ((double) frames * 1000) / (now - then);
3.340 + printf("%2.2f frames per second\n", fps);
3.341 + }
3.342 + return 0;
3.343 +}
3.344 +
3.345 +/* vi: set ts=4 sw=4 expandtab: */