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
This commit is contained in:
Albrecht Schlosser 2018-03-09 22:30:07 +00:00
parent 7b3e9347ba
commit dc2fb581b7
2 changed files with 281 additions and 96 deletions

View File

@ -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);

View File

@ -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.
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.
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):
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
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.
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.
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)...
*/
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.
int lw = (line_width > 0) ? line_width : 1;
int kmin = -lw;
int kmax = SHRT_MAX - lw;
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:
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);
}