summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H25
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx364
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);
}