From 570eb15ee05924944a4bf38f273815a91672d356 Mon Sep 17 00:00:00 2001 From: gewlitys Date: Wed, 26 Feb 2003 17:05:59 +0000 Subject: [PATCH] Line clipping is now handled correctly; fixes #28 (one pixel corruptions) and #198 (beam weapons changing direction) git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@832 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/ChangeLog | 2 + sc2/src/sc2code/libs/graphics/sdl/canvas.c | 28 ----- .../sc2code/libs/graphics/sdl/primitives.c | 108 ++++++++++++++---- .../sc2code/libs/graphics/sdl/primitives.h | 4 +- 4 files changed, 89 insertions(+), 53 deletions(-) diff --git a/sc2/ChangeLog b/sc2/ChangeLog index 713438899..0fb90c80f 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,6 @@ Changes towards version 0.3: +- Line clipping is now handled correctly; fixes #28 (one pixel corruptions) + and #198 (beam weapons changing direction) - Vux warps in close (fixes bug 93) -from Nic - Fixed lockup on lander-report (Bug #144 annd 187?) - Version # is now printed in the main menu, from Nic diff --git a/sc2/src/sc2code/libs/graphics/sdl/canvas.c b/sc2/src/sc2code/libs/graphics/sdl/canvas.c index 156a51f94..fd3372c3d 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/canvas.c +++ b/sc2/src/sc2code/libs/graphics/sdl/canvas.c @@ -10,38 +10,10 @@ TFB_DrawCanvas_Line (int x1, int y1, int x2, int y2, int r, int g, int b, TFB_Ca { Uint32 color; PutPixelFn screen_plot; - SDL_Rect rect; screen_plot = putpixel_for (target); color = SDL_MapRGB (((NativeCanvas) target)->format, r, g, b); - SDL_GetClipRect((NativeCanvas) target, &rect); - - /* Danger, Will Robinson! This code - looks VERY suspicious. It will end - up changing the slope of the - line! */ - - if (x1 < rect.x) - x1 = rect.x; - else if (x1 > rect.x + rect.w) - x1 = rect.x + rect.w; - - if (x2 < rect.x) - x2 = rect.x; - else if (x2 > rect.x + rect.w) - x2 = rect.x + rect.w; - - if (y1 < rect.y) - y1 = rect.y; - else if (y1 > rect.y + rect.h) - y1 = rect.y + rect.h; - - if (y2 < rect.y) - y2 = rect.y; - else if (y2 > rect.y + rect.h) - y2 = rect.y + rect.h; - SDL_LockSurface ((NativeCanvas) target); line (x1, y1, x2, y2, color, screen_plot, (NativeCanvas) target); SDL_UnlockSurface ((NativeCanvas) target); diff --git a/sc2/src/sc2code/libs/graphics/sdl/primitives.c b/sc2/src/sc2code/libs/graphics/sdl/primitives.c index aa3605d60..a5e2e60de 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/primitives.c +++ b/sc2/src/sc2code/libs/graphics/sdl/primitives.c @@ -153,6 +153,11 @@ PutPixelFn putpixel_for(SDL_Surface *surface) void line(int x1, int y1, int x2, int y2, Uint32 color, PutPixelFn plot, SDL_Surface *surface) { int d, x, y, ax, ay, sx, sy, dx, dy; + SDL_Rect r; + + SDL_GetClipRect (surface, &r); + if (!clip_line (&x1, &y1, &x2, &y2, &r)) + return; // line is completely outside clipping rectangle dx = x2-x1; ax = ((dx < 0) ? -dx : dx) << 1; @@ -192,36 +197,95 @@ void line(int x1, int y1, int x2, int y2, Uint32 color, PutPixelFn plot, SDL_Sur } } -// replaces all non-alpha pixels by color -void replace_color (Uint32 color, SDL_Surface *surface) + +// Clips line against rectangle using Cohen-Sutherland algorithm + +static enum {C_TOP = 0x1, C_BOTTOM = 0x2, C_RIGHT = 0x4, C_LEFT = 0x8}; + +static int +compute_code (float x, float y, float xmin, float ymin, float xmax, float ymax) { - int x,y,w,h; - Uint32 p; - Uint8 r,g,b,a; - GetPixelFn getpix; - PutPixelFn putpix; + int c = 0; + if (y > ymax) + c |= C_TOP; + else if (y < ymin) + c |= C_BOTTOM; + if (x > xmax) + c |= C_RIGHT; + else if (x < xmin) + c |= C_LEFT; + return c; +} - getpix = getpixel_for (surface); - putpix = putpixel_for (surface); +int +clip_line (int *lx1, int *ly1, int *lx2, int *ly2, SDL_Rect *r) +{ + int C0, C1, C; + float x, y, x0, y0, x1, y1, xmin, ymin, xmax, ymax; - SDL_LockSurface(surface); + x0 = (float)*lx1; + y0 = (float)*ly1; + x1 = (float)*lx2; + y1 = (float)*ly2; - w = surface->w; - h = surface->h; + xmin = (float)r->x; + ymin = (float)r->y; + xmax = (float)r->x + r->w - 1; + ymax = (float)r->y + r->h - 1; - for (y=0;yformat, &r, &g, &b, &a); - - if (a) - putpix (surface,x,y,color); + *lx1 = (int)x0; + *ly1 = (int)y0; + *lx2 = (int)x1; + *ly2 = (int)y1; + return 1; + } + + /* trivial reject: both ends on the external side of the rectangle */ + if ((C0 & C1) != 0) + return 0; + + /* normal case: clip end outside rectangle */ + C = C0 ? C0 : C1; + if (C & C_TOP) + { + x = x0 + (x1 - x0) * (ymax - y0) / (y1 - y0); + y = ymax; + } + else if (C & C_BOTTOM) + { + x = x0 + (x1 - x0) * (ymin - y0) / (y1 - y0); + y = ymin; + } + else if (C & C_RIGHT) + { + x = xmax; + y = y0 + (y1 - y0) * (xmax - x0) / (x1 - x0); + } + else + { + x = xmin; + y = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0); + } + + /* set new end point and iterate */ + if (C == C0) + { + x0 = x; y0 = y; + C0 = compute_code (x0, y0, xmin, ymin, xmax, ymax); + } + else + { + x1 = x; y1 = y; + C1 = compute_code (x1, y1, xmin, ymin, xmax, ymax); } } - - SDL_UnlockSurface(surface); } #endif diff --git a/sc2/src/sc2code/libs/graphics/sdl/primitives.h b/sc2/src/sc2code/libs/graphics/sdl/primitives.h index 943bc267c..e74b2acd4 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/primitives.h +++ b/sc2/src/sc2code/libs/graphics/sdl/primitives.h @@ -29,7 +29,5 @@ PutPixelFn putpixel_for(SDL_Surface *surface); void line(int x1, int y1, int x2, int y2, Uint32 color, PutPixelFn plot, SDL_Surface *surface); - -void replace_color (Uint32 color, SDL_Surface *surface); - +int clip_line(int *lx1, int *ly1, int *lx2, int *ly2, SDL_Rect *r); #endif