diff options
Diffstat (limited to 'src/drivers/Xlib')
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H | 25 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx | 364 |
2 files changed, 287 insertions, 102 deletions
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 @@ -60,6 +60,8 @@ private: 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); virtual void draw_unscaled(Fl_RGB_Image *img, 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 <config.h> #include "../../config_lib.h" #include <FL/Fl.H> #include <FL/Fl_Widget.H> @@ -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); } |
