From dc2fb581b76ea84ebd70a7ced1291dd26b40fc71 Mon Sep 17 00:00:00 2001 From: Albrecht Schlosser Date: Fri, 9 Mar 2018 22:30:07 +0000 Subject: Improve X11 (16-bit) clipping of lines and rectangles. In FLTK 1.3.x only horizontal and vertical long lines with endpoints outside the 16-bit coordinate space could be drawn with proper X11 coordinate clipping. Now arbitrary lines are clipped so they can be drawn with X11 functions. All rectangles are clipped as well (as in 1.3). Todo: The code needs better documentation and clipping of polygons, circles, curves etc. is still missing. The next step should be the clipping of polygons... git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12725 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H | 25 +- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx | 364 ++++++++++++++++------ 2 files changed, 287 insertions(+), 102 deletions(-) (limited to 'src/drivers/Xlib') diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H index 8e44e2371..0870ebb2f 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H @@ -59,6 +59,8 @@ private: int stack_x_[20], stack_y_[20]; // translation stack allowing cumulative translations int line_delta_; virtual void set_current_(); +protected: + int xmin, ymin, xmax, ymax; // ranges of valid x/y coordinates, see set_clip_range() protected: virtual void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy); virtual void draw_unscaled(Fl_Bitmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy); @@ -94,7 +96,6 @@ protected: int p_size; typedef struct {short x, y;} XPOINT; XPOINT *p; - int clip_x(int x); #if USE_XFT static Window draw_window; static struct _XftDraw* draw_; @@ -112,7 +113,7 @@ public: #if USE_XFT static void destroy_xft_draw(Window id); #endif - + // --- bitmap stuff Fl_Bitmask create_bitmask(int w, int h, const uchar *array); void delete_bitmask(Fl_Bitmask bm); @@ -150,6 +151,26 @@ protected: virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3); virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2); virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3); + + // --- clipped drawing (after scaling, with real screen coordinates) + // --- currently specific to Fl_Xlib_Graphics_Driver (16-bit coordinate clipping) + + // clip one coordinate (x or y) --- correct axis (x/y) is important ! + virtual int clip_x(int x); + virtual int clip_y(int y); + + // clip one line + virtual int clip_line(int &x1, int &y1, int &x2, int &y2); + + // clip one rectangle + virtual int clip_rect(int &x, int &y, int &w, int &h); + + // draw a line after clipping (if visible) + virtual void draw_clipped_line(int x1, int y1, int x2, int y2); + + // set_clip_range() - set valid coordinate range (16-bit or current window) + virtual void set_clip_range(); + // --- clipping void push_clip(int x, int y, int w, int h); int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H); diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx index bf1edd3ac..a01c4042a 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx @@ -21,7 +21,6 @@ \brief X11 Xlib specific line and polygon drawing with integer coordinates. */ -#include #include "../../config_lib.h" #include #include @@ -31,116 +30,262 @@ #include "Fl_Xlib_Graphics_Driver.H" +// Arbitrary line clipping: clip line end points to 16-bit coordinate range. -#ifndef SHRT_MAX -#define SHRT_MAX (32767) -#endif +// We clip at +/- 16-bit boundaries (+/- (2**15-K)) where K currently is 8 +// to account for line width. We could also clip at lower bound 0 but that +// would make lines less accurate (rounding effects < 1 pixel, but anyway). +// Note that we're only clipping the line end points so we can send true +// 16-bit coordinates to X functions. Actual clipping to window borders +// and clip regions will be done by X. +// Note: the current (default) approach is to clip to the current window +// boundaries instead. This can avoid drawing unecessary (invisible) objects. + +#define MAXK (32760) // 2 ** 15 - K (8) + +#define CLIP_TO_WINDOW (0) // Default: 1 (clip to window), see below + +/* + Sets the coordinate space limits for clipping. + + We have two choices: + + - the entire 16-bit coordinate space (CLIP_TO_WINDOW = 0) + - the current window (Default: CLIP_TO_WINDOW != 0) + + The current approach is to use window coordinates. The macro CLIP_TO_WINDOW + (above) can be set to 0 to clip to the entire 16-bit coordinate space + instead. This can be done for testing purposes or if it turns out that + window clipping doesn't work as expected. + AlbrechtS, 09 Mar 2018 + + Implementation note: to optimize setting the clip area this could be done + when drawing starts, maybe in make_current() or something like that. + This is left for a later step. +*/ +void Fl_Xlib_Graphics_Driver::set_clip_range() { + +#if (CLIP_TO_WINDOW) // should be true (the default) + + Fl_Window *win = Fl_Window::current(); // get current window + + xmax = win->w() * scale_ + line_width_ + 1; + ymax = win->h() * scale_ + line_width_ + 1; + xmin = 0 - line_width_ - 1; + ymin = 0 - line_width_ - 1; + + // the following checks are likely unnecessary, but with large scaling + // factors ... (a little paranoid) + + if (xmax > MAXK) xmax = MAXK; + if (ymax > MAXK) ymax = MAXK; + if (xmin < -MAXK) xmin = -MAXK; + if (ymin < -MAXK) ymin = -MAXK; + +#else // use full X (16-bit) coordinate space + + xmax = MAXK; + ymax = xmax; + xmin = -xmax; + ymin = -xmax; + +#endif // CLIP_TO_WINDOW + +} // set_clip_range() + +/* + Liang-Barsky line clipping algorithm. For documentation see: + https://en.wikipedia.org/wiki/Liang-Barsky_algorithm . + Modified by AlbrechtS for FLTK. +*/ +/* + Returns new coordinates in function arguments x1, y1, x2, y2 if the line + is within or intersects the valid coordinate space so it is potentially + visible. Arguments are not changed if the entire line is outside the + valid coordinate space. + + If the return value is non-zero (true) the line is entirely *clipped* + and must not be drawn with X functions because the coordinates could be + outside the valid coordinate space and the result would be undefined. + + Returns 1 (true) if line is clipped, i.e. *not* visible. + Returns 0 (false) if line is not clipped, i.e. potentially visible. +*/ + +int Fl_Xlib_Graphics_Driver::clip_line(int &x1, int &y1, int &x2, int &y2) { + + set_clip_range(); + + // define variables + float p1 = float(-(x2 - x1)); + float p2 = float(-p1); + float p3 = float(-(y2 - y1)); + float p4 = float(-p3); + + float q1 = float(x1 - xmin); + float q2 = float(xmax - x1); + float q3 = float(y1 - ymin); + float q4 = float(ymax - y1); + + float posmin = 1; // positive minimum + float negmax = 0; // negative maximum + + if ((p1 == 0 && q1 < 0) || (p3 == 0 && q3 < 0)) { + return 1; // Line is parallel to clipping window (not visible) + } + if (p1 != 0) { + float r1 = q1 / p1; + float r2 = q2 / p2; + if (p1 < 0) { + if (r1 > negmax) negmax = r1; + if (r2 < posmin) posmin = r2; + } else { + if (r2 > negmax) negmax = r2; + if (r1 < posmin) posmin = r1; + } + } + if (p3 != 0) { + float r3 = q3 / p3; + float r4 = q4 / p4; + if (p3 < 0) { + if (r3 > negmax) negmax = r3; + if (r4 < posmin) posmin = r4; + } else { + if (r4 > negmax) negmax = r4; + if (r3 < posmin) posmin = r3; + } + } + + // compute new points (note: order is important!) + + x2 = int(x1 + p2 * posmin); + y2 = int(y1 + p4 * posmin); + + x1 = int(x1 + p2 * negmax); + y1 = int(y1 + p4 * negmax); + + return 0; // not clipped + +} // clip_line() + +// "Old" line clipping: only horizontal and vertical lines and rectangles // line_width_ must contain the absolute value of the current // line width to be used for X11 clipping (see below). /* - We need to check some coordinates for areas for clipping before we - use X functions, because X can't handle coordinates outside the 16-bit - range. Since all windows use relative coordinates > 0, we do also - check for negative values. X11 only, see also STR #2304. - - Note that this is only necessary for large objects, where only a - part of the object is visible. The draw() functions (e.g. box - drawing) must be clipped correctly. This is usually only a matter - for large container widgets. The individual child widgets will be - clipped completely. - - We define the usable X coordinate space as [ -LW : SHRT_MAX - LW ] - where LW = current line width for drawing. This is done so that - horizontal and vertical line drawing works correctly, even in real - border cases, e.g. drawing a rectangle slightly outside the top left - window corner, but with a line width so that a part of the line should - be visible (in this case 2 of 5 pixels): - - fl_line_style (FL_SOLID,5); // line width = 5 - fl_rect (-1,-1,100,100); // top/left: 2 pixels visible - - In this example case, no clipping would be done, because X can - handle it and clip unneeded pixels. - - Note that we must also take care of the case where line_width_ - is zero (maybe unitialized). If this is the case, we assume a line - width of 1. - - Todo: Arbitrary line drawings (e.g. polygons) and clip regions - are not yet done. - - Note: - - We could use max. screen coordinates instead of SHRT_MAX, but that - would need more work and would probably be slower. We assume that - all window coordinates are >= 0 and that no window extends up to - 32767 - LW (where LW = current line width). Thus it is safe to clip - all coordinates to this range before calling X functions. If this - is not true, then clip_to_short() and clip_x() must be redefined. - - It would be somewhat easier if we had fl_clip_w and fl_clip_h, as - defined in FLTK 2.0 (for the upper clipping bounds)... - */ + We need to check some coordinates for areas for clipping before we + use X functions, because X can't handle coordinates outside the 16-bit + range. Since all windows use relative coordinates > 0, we do also + check for negative values. X11 only, see also STR #2304. + + Note that this is only necessary for large objects, where only a + part of the object is visible. The draw() functions (e.g. box + drawing) must be clipped correctly. This is usually only a matter + for large container widgets. The individual child widgets will be + clipped completely. + + We define the usable X coordinate space as [ -LW : SHRT_MAX - LW ] + where LW = current line width for drawing. This is done so that + horizontal and vertical line drawing works correctly, even in real + border cases, e.g. drawing a rectangle slightly outside the top left + window corner, but with a line width so that a part of the line should + be visible (in this case 2 of 5 pixels): + + fl_line_style (FL_SOLID,5); // line width = 5 + fl_rect (-1,-1,100,100); // top/left: 2 pixels visible + + In this example case, no clipping would be done, because X can + handle it and clip unneeded pixels. + + Note that we must also take care of the case where line_width_ + is zero (maybe unitialized). If this is the case, we assume a line + width of 1. + + Todo: Arbitrary line drawings (e.g. polygons), circles and curves. +*/ /* - clip_to_short() returns 1, if the area is invisible (clipped), - because ... + clip_rect() returns 1 if the area is invisible (clipped) because ... - (a) w or h are <= 0 i.e. nothing is visible - (b) x+w or y+h are < kmin i.e. left of or above visible area - (c) x or y are > kmax i.e. right of or below visible area + (a) w <= 0 or h <= 0 i.e. nothing is visible + (b) x+w < xmin or y+h < ymin i.e. left of or above visible area + (c) x > xmax or y > ymax i.e. right of or below visible area - kmin and kmax are the minimal and maximal X coordinate values, - as defined above. In this case x, y, w, and h are not changed. + xmin, ymin, xmax, and ymax are the minimal and maximal X coordinate + values or the window bounds as defined above. + In the above cases x, y, w, and h are not changed and the return + value is 1 (clipped). - It returns 0, if the area is potentially visible and X can handle - clipping. x, y, w, and h may have been adjusted to fit into the - X coordinate space. + clip_rect() returns 0 if the area is potentially visible and X can + handle clipping. x, y, w, and h may have been adjusted to fit into the + valid coordinate space. - Use this for clipping rectangles, as used in fl_rect() and - fl_rectf(). - */ -static int clip_to_short(int &x, int &y, int &w, int &h, int line_width) { + Use this for clipping rectangles as in fl_rect() and fl_rectf(). + It is fast and convenient. + + Todo: Test for exact (filled) rectangle and border limits. If coordinates + are modified (clipped) borders should not be visible if they would be + outside the window, for instance: - int lw = (line_width > 0) ? line_width : 1; - int kmin = -lw; - int kmax = SHRT_MAX - lw; + fl_line_style(FL_SOLID, 5); // line width = 5 + fl_rect(-6, 0, 100, 100); // left border should not be visible + fl_rect(-1, 0, 100, 100); // left border should be partially visible + + This is no problem with 16-bit clipping but might be relevant with + window clipping. The same applies to the bottom and right borders, resp.. +*/ + +int Fl_Xlib_Graphics_Driver::clip_rect(int &x, int &y, int &w, int &h) { + + set_clip_range(); if (w <= 0 || h <= 0) return 1; // (a) - if (x+w < kmin || y+h < kmin) return 1; // (b) - if (x > kmax || y > kmax) return 1; // (c) + if (x+w < xmin || y+h < ymin) return 1; // (b) + if (x > xmax || y > ymax) return 1; // (c) - if (x < kmin) { w -= (kmin-x); x = kmin; } - if (y < kmin) { h -= (kmin-y); y = kmin; } - if (x+w > kmax) w = kmax - x; - if (y+h > kmax) h = kmax - y; + if (x < xmin) { w -= (xmin-x); x = xmin; } + if (y < ymin) { h -= (ymin-y); y = ymin; } + if (x+w > xmax) w = xmax - x; + if (y+h > ymax) h = ymax - y; return 0; } /* - clip_x() returns a coordinate value clipped to the 16-bit coordinate - space (see above). This can be used to draw horizontal and vertical - lines that can be handled by X11. Each single coordinate value can - be clipped individually, and the result can be used directly, e.g. - in fl_xyline() and fl_yxline(). Note that this can't be used for - arbitrary lines (not horizontal or vertical). - */ -int Fl_Xlib_Graphics_Driver::clip_x (int x) { + clip_x() and clip_y() return a coordinate value clipped to the 16-bit + coordinate space or the current window (see above). - int lw = (line_width_ > 0) ? line_width_ : 1; - int kmin = -lw; - int kmax = SHRT_MAX - lw; + This can be used to draw horizontal and vertical lines that can be + handled by X11. Each single coordinate value can be clipped individually + and the result can be used directly, e.g. in fl_xyline() and fl_yxline(). - if (x < kmin) - x = kmin; - else if (x > kmax) - x = kmax; + Note 1: this can't be used for arbitrary lines (neither horizontal nor vertical). + Note 2: may be changed since Fl_Xlib_Graphics_Driver::clip_line() exists. +*/ + +int Fl_Xlib_Graphics_Driver::clip_x(int x) { + + set_clip_range(); + + if (x < xmin) + x = xmin; + else if (x > xmax) + x = xmax; return x; } +int Fl_Xlib_Graphics_Driver::clip_y(int y) { + + set_clip_range(); + + if (y < ymin) + y = ymin; + else if (y > ymax) + y = ymax; + return y; +} + // Missing X call: (is this the fastest way to init a 1-rectangle region?) // Windows equivalent exists, implemented inline in win32.H @@ -150,8 +295,8 @@ int Fl_Xlib_Graphics_Driver::clip_x (int x) { Fl_Region Fl_Xlib_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) { XRectangle R; Fl_Region r = XCreateRegion(); // create an empty region - if (clip_to_short(x, y, w, h, line_width_)) // outside X coordinate space - return r; + if (clip_rect(x, y, w, h)) // outside valid coordinate space + return r; // empty region R.x = x; R.y = y; R.width = w; R.height = h; XUnionRectWithRegion(&R, r, r); return r; @@ -171,7 +316,7 @@ void Fl_Xlib_Graphics_Driver::rect_unscaled(float fx, float fy, float fw, float int x = fx; int y = fy; int w = int(fw) - 1 - deltaf; int h = int(fh) - 1 - deltaf; - if (!clip_to_short(x, y, w, h, line_width_)) + if (!clip_rect(x, y, w, h)) XDrawRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, w, h); } @@ -183,21 +328,23 @@ void Fl_Xlib_Graphics_Driver::rectf_unscaled(float fx, float fy, float fw, float // make sure no unfilled area lies between rectf(x,y,w,h) and rectf(x+w,y,1,h) or rectf(x,y+w,w,1) int w = int(int(fx/scale_+fw/scale_+0.5)*scale_) - int(fx); int h = int(int(fy/scale_+fh/scale_+0.5)*scale_) - int(fy); - if (!clip_to_short(x, y, w, h, line_width_)) + if (!clip_rect(x, y, w, h)) XFillRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, w, h); } void Fl_Xlib_Graphics_Driver::point_unscaled(float fx, float fy) { int deltaf = scale_ >= 2 ? scale_/2 : 0; - int x = fx+offset_x_*scale_-deltaf; int y = fy+offset_y_*scale_-deltaf; + int x = fx+offset_x_*scale_-deltaf; + int y = fy+offset_y_*scale_-deltaf; int width = scale_ >= 1 ? scale_ : 1; + // *FIXME* This needs X coordinate clipping: XFillRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, width, width); } void Fl_Xlib_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1) { if (x == x1) yxline_unscaled(x, y, y1); else if (y == y1) xyline_unscaled(x, y, x1); - else XDrawLine(fl_display, fl_window, gc_, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, x1+offset_x_*scale_+line_delta_, y1+offset_y_*scale_+line_delta_); + else draw_clipped_line(x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, x1+offset_x_*scale_+line_delta_, y1+offset_y_*scale_+line_delta_); } void Fl_Xlib_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1, float x2, float y2) { @@ -205,6 +352,7 @@ void Fl_Xlib_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1 p[0].x = x+offset_x_*scale_+line_delta_; p[0].y = y+offset_y_*scale_+line_delta_; p[1].x = x1+offset_x_*scale_+line_delta_; p[1].y = y1+offset_y_*scale_+line_delta_; p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_; + // *FIXME* This needs X coordinate clipping! XDrawLines(fl_display, fl_window, gc_, p, 3, 0); } @@ -213,13 +361,14 @@ void Fl_Xlib_Graphics_Driver::xyline_unscaled(float x, float y, float x1) { int tw = line_width_ ? line_width_ : 1; // true line width if (x > x1) { float exch = x; x = x1; x1 = exch; } int ix = clip_x(x+line_delta_); if (scale_ >= 2) ix -= int(scale_/2); - int iy = clip_x(y+line_delta_); + int iy = clip_y(y+line_delta_); // make sure that line output by xyline(a,b,c) extends to pixel just at left of where xyline(c+1,b,d) begins int ix1 = int(x1/scale_+1.5)*scale_-1; ix1 += line_delta_; if (scale_ >= 4) ix1 -= 1; - XDrawLine(fl_display, fl_window, gc_, ix, iy, ix1, iy); + draw_clipped_line(ix, iy, ix1, iy); // make sure no unfilled area lies between xyline(x,y,x1) and xyline(x,y+1,x1) - if (y+line_delta_ + scale_ >= iy + tw+1 - 0.001 ) XDrawLine(fl_display, fl_window, gc_, ix, iy+1, ix1, iy+1); + if (y+line_delta_ + scale_ >= iy + tw+1 - 0.001 ) + draw_clipped_line(ix, iy+1, ix1, iy+1); } void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1) { @@ -227,13 +376,14 @@ void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1) { int tw = line_width_ ? line_width_ : 1; // true line width if (y > y1) { float exch = y; y = y1; y1 = exch; } int ix = clip_x(x+line_delta_); - int iy = clip_x(y+line_delta_); if (scale_ >= 2) iy -= int(scale_/2); + int iy = clip_y(y+line_delta_); if (scale_ >= 2) iy -= int(scale_/2); int iy1 = int(y1/scale_+1.5)*scale_-1; // make sure that line output by yxline(a,b,c) extends to pixel just above where yxline(a,c+1,d) begins iy1 += line_delta_; if (scale_ >= 4) iy1 -= 1; - XDrawLine(fl_display, fl_window, gc_, ix, iy, ix, iy1); + draw_clipped_line(ix, iy, ix, iy1); // make sure no unfilled area lies between yxline(x,y,y1) and yxline(x+1,y,y1) - if (x+line_delta_+scale_ >= ix + tw+1 -0.001) XDrawLine(fl_display, fl_window, gc_, ix+1, iy, ix+1, iy1); + if (x+line_delta_+scale_ >= ix + tw+1 -0.001) + draw_clipped_line(ix+1, iy, ix+1, iy1); } void Fl_Xlib_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2) { @@ -242,6 +392,7 @@ void Fl_Xlib_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1 p[1].x = x1 +offset_x_*scale_+line_delta_; p[1].y = y1 +offset_y_*scale_+line_delta_; p[2].x = x2 +offset_x_*scale_+line_delta_; p[2].y = y2 +offset_y_*scale_+line_delta_; p[3].x = x +offset_x_*scale_+line_delta_; p[3].y = y +offset_y_*scale_+line_delta_; + // *FIXME* This needs X coordinate clipping! XDrawLines(fl_display, fl_window, gc_, p, 4, 0); } @@ -252,6 +403,7 @@ void Fl_Xlib_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1 p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_; p[3].x = x3+offset_x_*scale_+line_delta_; p[3].y = y3+offset_y_*scale_+line_delta_; p[4].x = x+offset_x_*scale_+line_delta_; p[4].y = y+offset_y_*scale_+line_delta_; + // *FIXME* This needs X coordinate clipping! XDrawLines(fl_display, fl_window, gc_, p, 5, 0); } @@ -261,6 +413,7 @@ void Fl_Xlib_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float p[1].x = x1+offset_x_*scale_+line_delta_; p[1].y = y1+offset_y_*scale_+line_delta_; p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_; p[3].x = x+offset_x_*scale_+line_delta_; p[3].y = y+offset_y_*scale_+line_delta_; + // *FIXME* This needs X coordinate clipping! XFillPolygon(fl_display, fl_window, gc_, p, 3, Convex, 0); XDrawLines(fl_display, fl_window, gc_, p, 4, 0); } @@ -272,16 +425,27 @@ void Fl_Xlib_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_; p[3].x = x3+offset_x_*scale_+line_delta_; p[3].y = y3+offset_y_*scale_+line_delta_; p[4].x = x+offset_x_*scale_+line_delta_; p[4].y = y+offset_y_*scale_+line_delta_; + // *FIXME* This needs X coordinate clipping! XFillPolygon(fl_display, fl_window, gc_, p, 4, Convex, 0); XDrawLines(fl_display, fl_window, gc_, p, 5, 0); } +// --- clipped line drawing in X coordinate space (16-bit) + +// Draw an arbitrary line with coordinates clipped to the X coordinate space. +// This draws nothing if the line is entirely outside the X coordinate space. + +void Fl_Xlib_Graphics_Driver::draw_clipped_line(int x1, int y1, int x2, int y2) { + if (!clip_line(x1, y1, x2, y2)) + XDrawLine(fl_display, fl_window, gc_, x1, y1, x2, y2); +} + // --- clipping void Fl_Xlib_Graphics_Driver::push_clip(int x, int y, int w, int h) { Fl_Region r; if (w > 0 && h > 0) { - r = XRectangleRegion(x,y,w,h); + r = XRectangleRegion(x, y, w, h); // does X coordinate clipping Fl_Region current = rstack[rstackptr]; if (current) { Fl_Region temp = XCreateRegion(); @@ -297,7 +461,7 @@ void Fl_Xlib_Graphics_Driver::push_clip(int x, int y, int w, int h) { restore_clip(); } -int Fl_Xlib_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){ +int Fl_Xlib_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H) { X = x; Y = y; W = w; H = h; Fl_Region r = rstack[rstackptr]; if (!r) return 0; @@ -326,7 +490,7 @@ int Fl_Xlib_Graphics_Driver::not_clipped(int x, int y, int w, int h) { Fl_Region r = rstack[rstackptr]; if (!r) return 1; // get rid of coordinates outside the 16-bit range the X calls take. - if (clip_to_short(x,y,w,h, line_width_)) return 0; // clipped + if (clip_rect(x,y,w,h)) return 0; // clipped return XRectInRegion(r, x, y, w, h); } -- cgit v1.2.3