Fixed X11 line implementation - clip lines that are going to go outside the window.
authorSam Lantinga <slouken@libsdl.org>
Fri, 11 Dec 2009 09:59:36 +0000
changeset 3543c2154674c0c1
parent 3542 97eae5a705f9
child 3544 71189305cd33
Fixed X11 line implementation - clip lines that are going to go outside the window.
src/video/x11/SDL_x11render.c
src/video/x11/SDL_x11sym.h
     1.1 --- a/src/video/x11/SDL_x11render.c	Fri Dec 11 09:57:54 2009 +0000
     1.2 +++ b/src/video/x11/SDL_x11render.c	Fri Dec 11 09:59:36 2009 +0000
     1.3 @@ -23,6 +23,8 @@
     1.4  
     1.5  #if SDL_VIDEO_RENDER_X11
     1.6  
     1.7 +#include <limits.h> /* For INT_MIN and INT_MAX */
     1.8 +
     1.9  #include "SDL_x11video.h"
    1.10  #include "../SDL_rect_c.h"
    1.11  #include "../SDL_pixels_c.h"
    1.12 @@ -647,26 +649,134 @@
    1.13      SDL_Window *window = SDL_GetWindowFromID(renderer->window);
    1.14      SDL_Rect clip, rect;
    1.15      unsigned long foreground;
    1.16 +    XPoint *xpoints, *xpoint;
    1.17 +    int i, xcount;
    1.18 +    int minx, miny;
    1.19 +    int maxx, maxy;
    1.20  
    1.21      clip.x = 0;
    1.22      clip.y = 0;
    1.23      clip.w = window->w;
    1.24      clip.h = window->h;
    1.25  
    1.26 -    if (data->makedirty) {
    1.27 -        /* Get the smallest rectangle that contains everything */
    1.28 -        SDL_EnclosePoints(points, count, NULL, &rect);
    1.29 -        if (!SDL_IntersectRect(&rect, &clip, &rect)) {
    1.30 -            /* Nothing to draw */
    1.31 -            return 0;
    1.32 -        }
    1.33 -        SDL_AddDirtyRect(&data->dirty, &rect);
    1.34 -    }
    1.35 -
    1.36      foreground = renderdrawcolor(renderer, 1);
    1.37      XSetForeground(data->display, data->gc, foreground);
    1.38 -    /* FIXME: Can we properly handle lines that extend beyond visible space? */
    1.39 -    //XDrawLine(data->display, data->drawable, data->gc, x1, y1, x2, y2);
    1.40 +
    1.41 +    xpoint = xpoints = SDL_stack_alloc(XPoint, count);
    1.42 +    xcount = 0;
    1.43 +    minx = INT_MAX;
    1.44 +    miny = INT_MAX;
    1.45 +    maxx = INT_MIN;
    1.46 +    maxy = INT_MIN;
    1.47 +    for (i = 0; i < count; ++i) {
    1.48 +        int x = points[i].x;
    1.49 +        int y = points[i].y;
    1.50 +
    1.51 +        /* If the point is inside the window, add it to the list */
    1.52 +        if (x >= 0 && x < window->w && y >= 0 && y < window->h) {
    1.53 +            if (x < minx) {
    1.54 +                minx = x;
    1.55 +            } else if (x > maxx) {
    1.56 +                maxx = x;
    1.57 +            }
    1.58 +            if (y < miny) {
    1.59 +                miny = y;
    1.60 +            } else if (y > maxy) {
    1.61 +                maxy = y;
    1.62 +            }
    1.63 +            xpoint->x = (short)x;
    1.64 +            xpoint->y = (short)y;
    1.65 +            ++xpoint;
    1.66 +            ++xcount;
    1.67 +            continue;
    1.68 +        }
    1.69 +
    1.70 +        /* We need to clip the line segments joined by this point */
    1.71 +        if (xcount > 0) {
    1.72 +            int x1 = xpoint[-1].x;
    1.73 +            int y1 = xpoint[-1].y;
    1.74 +            int x2 = x;
    1.75 +            int y2 = y;
    1.76 +            if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
    1.77 +                if (x2 < minx) {
    1.78 +                    minx = x2;
    1.79 +                } else if (x2 > maxx) {
    1.80 +                    maxx = x2;
    1.81 +                }
    1.82 +                if (y2 < miny) {
    1.83 +                    miny = y2;
    1.84 +                } else if (y2 > maxy) {
    1.85 +                    maxy = y2;
    1.86 +                }
    1.87 +                xpoint->x = (short)x2;
    1.88 +                xpoint->y = (short)y2;
    1.89 +                ++xpoint;
    1.90 +                ++xcount;
    1.91 +            }
    1.92 +            XDrawLines(data->display, data->drawable, data->gc,
    1.93 +                       xpoints, xcount, CoordModeOrigin);
    1.94 +            if (xpoints[0].x != x2 || xpoints[0].y != y2) {
    1.95 +                XDrawPoint(data->display, data->drawable, data->gc, x2, y2);
    1.96 +            }
    1.97 +            if (data->makedirty) {
    1.98 +                SDL_Rect rect;
    1.99 +
   1.100 +                rect.x = minx;
   1.101 +                rect.y = miny;
   1.102 +                rect.w = (maxx - minx) + 1;
   1.103 +                rect.h = (maxy - miny) + 1;
   1.104 +                SDL_AddDirtyRect(&data->dirty, &rect);
   1.105 +            }
   1.106 +            xpoint = xpoints;
   1.107 +            xcount = 0;
   1.108 +            minx = INT_MAX;
   1.109 +            miny = INT_MAX;
   1.110 +            maxx = INT_MIN;
   1.111 +            maxy = INT_MIN;
   1.112 +        }
   1.113 +        if (i < (count-1)) {
   1.114 +            int x1 = x;
   1.115 +            int y1 = y;
   1.116 +            int x2 = points[i+1].x;
   1.117 +            int y2 = points[i+1].y;
   1.118 +            if (SDL_IntersectRectAndLine(&clip, &x1, &y1, &x2, &y2)) {
   1.119 +                if (x1 < minx) {
   1.120 +                    minx = x1;
   1.121 +                } else if (x1 > maxx) {
   1.122 +                    maxx = x1;
   1.123 +                }
   1.124 +                if (y1 < miny) {
   1.125 +                    miny = y1;
   1.126 +                } else if (y1 > maxy) {
   1.127 +                    maxy = y1;
   1.128 +                }
   1.129 +                xpoint->x = (short)x1;
   1.130 +                xpoint->y = (short)y1;
   1.131 +                ++xpoint;
   1.132 +                ++xcount;
   1.133 +            }
   1.134 +        }
   1.135 +    }
   1.136 +    if (xcount > 1) {
   1.137 +        int x2 = xpoint[-1].x;
   1.138 +        int y2 = xpoint[-1].y;
   1.139 +        XDrawLines(data->display, data->drawable, data->gc, xpoints, xcount,
   1.140 +                   CoordModeOrigin);
   1.141 +        if (xpoints[0].x != x2 || xpoints[0].y != y2) {
   1.142 +            XDrawPoint(data->display, data->drawable, data->gc, x2, y2);
   1.143 +        }
   1.144 +        if (data->makedirty) {
   1.145 +            SDL_Rect rect;
   1.146 +
   1.147 +            rect.x = minx;
   1.148 +            rect.y = miny;
   1.149 +            rect.w = (maxx - minx) + 1;
   1.150 +            rect.h = (maxy - miny) + 1;
   1.151 +            SDL_AddDirtyRect(&data->dirty, &rect);
   1.152 +        }
   1.153 +    }
   1.154 +    SDL_stack_free(xpoints);
   1.155 +
   1.156      return 0;
   1.157  }
   1.158  
     2.1 --- a/src/video/x11/SDL_x11sym.h	Fri Dec 11 09:57:54 2009 +0000
     2.2 +++ b/src/video/x11/SDL_x11sym.h	Fri Dec 11 09:59:36 2009 +0000
     2.3 @@ -95,6 +95,7 @@
     2.4  SDL_X11_SYM(int,XPending,(Display* a),(a),return)
     2.5  SDL_X11_SYM(int,XPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j),(a,b,c,d,e,f,g,h,i,j),return)
     2.6  SDL_X11_SYM(int,XDrawLines,(Display* a, Drawable b, GC c, XPoint* d, int e, int f),(a,b,c,d,e,f),return)
     2.7 +SDL_X11_SYM(int,XDrawPoint,(Display* a, Drawable b, GC c, int d, int e),(a,b,c,d,e),return)
     2.8  SDL_X11_SYM(int,XDrawPoints,(Display* a, Drawable b, GC c, XPoint* d, int e, int f),(a,b,c,d,e,f),return)
     2.9  SDL_X11_SYM(int,XQueryColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return)
    2.10  SDL_X11_SYM(int,XQueryKeymap,(Display* a,char *b),(a,b),return)