mirror of
https://github.com/fltk/fltk.git
synced 2026-06-01 06:14:28 +08:00
More clipping fixes for X11 with coordinates > 32767 (STR #2304).
The following functions are fixed now: fl_rect(x,y,w,h), fl_rectf(x,y,w,h), fl_not_clipped(x,y,w,h), fl_xyline(x, y, x1), and fl_yxline(x, y, y1). These functions are sufficient for basic box and frame drawing functions, but maybe there are other functions left. Note that fl_xyline() and fl_yxline() are fixed only for one line segment. Those with more line segments need still to be fixed. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7884 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
+85
-25
@@ -47,11 +47,62 @@ extern float fl_quartz_line_width_;
|
|||||||
#define USINGQUARTZPRINTER (Fl_Surface_Device::surface()->type() == Fl_Printer::device_type)
|
#define USINGQUARTZPRINTER (Fl_Surface_Device::surface()->type() == Fl_Printer::device_type)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_X11
|
||||||
|
|
||||||
|
#ifndef SHRT_MAX
|
||||||
|
#define SHRT_MAX (32767)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
We need to check some coordinates for areas for clipping before we
|
||||||
|
use X calls, because X can't handle coordinates outside the 16-bit
|
||||||
|
range. Since windows use relative coordinates > 0, we do also check
|
||||||
|
for negative values. X11 only, see also STR #2304.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
We could use max. screen coordinates instead of SHRT_MAX, but that
|
||||||
|
would need more work and would probably be slower.
|
||||||
|
|
||||||
|
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 < 0 i.e. left of or above visible area
|
||||||
|
(c) x or y are > SHRT_MAX i.e. right of or below visible area
|
||||||
|
|
||||||
|
returns 0, if the area is potentially visible and X can handle the
|
||||||
|
clipping. x, y, w, and h may have been adjusted to fit into the
|
||||||
|
X coordinate space.
|
||||||
|
*/
|
||||||
|
static int clip_to_short(int &x, int &y, int &w, int &h) {
|
||||||
|
|
||||||
|
if (w <= 0 || h <= 0) return 1; // (a)
|
||||||
|
if (x+w < 0 || y+h < 0) return 1; // (b)
|
||||||
|
if (x > SHRT_MAX || y > SHRT_MAX) return 1; // (c)
|
||||||
|
|
||||||
|
if (x < 0) { w += x; x = 0; }
|
||||||
|
if (y < 0) { h += y; y = 0; }
|
||||||
|
if (x+w > SHRT_MAX) w = SHRT_MAX - x;
|
||||||
|
if (y+h > SHRT_MAX) h = SHRT_MAX - y;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_X11
|
||||||
|
|
||||||
|
|
||||||
void Fl_Graphics_Driver::rect(int x, int y, int w, int h) {
|
void Fl_Graphics_Driver::rect(int x, int y, int w, int h) {
|
||||||
|
|
||||||
if (w<=0 || h<=0) return;
|
if (w<=0 || h<=0) return;
|
||||||
#if defined(USE_X11)
|
#if defined(USE_X11)
|
||||||
XDrawRectangle(fl_display, fl_window, fl_gc, x, y, w-1, h-1);
|
if (x+w < 0 || y+h < 0 || x > SHRT_MAX || y > SHRT_MAX ) return;
|
||||||
|
|
||||||
|
if (x+w > SHRT_MAX || y+h > SHRT_MAX ||
|
||||||
|
w > SHRT_MAX || h > SHRT_MAX) { // X can't handle clipping
|
||||||
|
xyline(x, y, x+w-1);
|
||||||
|
yxline(x+w-1, y, y+h-1);
|
||||||
|
xyline(x+w-1, y+h-1, x);
|
||||||
|
yxline(x, y+h-1, y);
|
||||||
|
} else
|
||||||
|
XDrawRectangle(fl_display, fl_window, fl_gc, x, y, w-1, h-1);
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
MoveToEx(fl_gc, x, y, 0L);
|
MoveToEx(fl_gc, x, y, 0L);
|
||||||
LineTo(fl_gc, x+w-1, y);
|
LineTo(fl_gc, x+w-1, y);
|
||||||
@@ -71,7 +122,10 @@ void Fl_Graphics_Driver::rect(int x, int y, int w, int h) {
|
|||||||
void Fl_Graphics_Driver::rectf(int x, int y, int w, int h) {
|
void Fl_Graphics_Driver::rectf(int x, int y, int w, int h) {
|
||||||
if (w<=0 || h<=0) return;
|
if (w<=0 || h<=0) return;
|
||||||
#if defined(USE_X11)
|
#if defined(USE_X11)
|
||||||
if (w && h) XFillRectangle(fl_display, fl_window, fl_gc, x, y, w, h);
|
if (w && h) {
|
||||||
|
if (!clip_to_short(x,y,w,h))
|
||||||
|
XFillRectangle(fl_display, fl_window, fl_gc, x, y, w, h);
|
||||||
|
}
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
RECT rect;
|
RECT rect;
|
||||||
rect.left = x; rect.top = y;
|
rect.left = x; rect.top = y;
|
||||||
@@ -89,6 +143,17 @@ void Fl_Graphics_Driver::rectf(int x, int y, int w, int h) {
|
|||||||
|
|
||||||
void Fl_Graphics_Driver::xyline(int x, int y, int x1) {
|
void Fl_Graphics_Driver::xyline(int x, int y, int x1) {
|
||||||
#if defined(USE_X11)
|
#if defined(USE_X11)
|
||||||
|
// get rid of coordinates outside the 16-bit range
|
||||||
|
if (y < 0 || y > SHRT_MAX) return;
|
||||||
|
if (x <= x1) {
|
||||||
|
if (x1 < 0 || x > SHRT_MAX) return;
|
||||||
|
if (x < 0) x = 0;
|
||||||
|
if (x1 > SHRT_MAX) x1 = SHRT_MAX;
|
||||||
|
} else { // x1 < x
|
||||||
|
if (x < 0 || x1 > SHRT_MAX) return;
|
||||||
|
if (x1 < 0) x1 = 0;
|
||||||
|
if (x > SHRT_MAX) x = SHRT_MAX;
|
||||||
|
}
|
||||||
XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y);
|
XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y);
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x1+1, y);
|
MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x1+1, y);
|
||||||
@@ -156,6 +221,17 @@ void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
|
|||||||
|
|
||||||
void Fl_Graphics_Driver::yxline(int x, int y, int y1) {
|
void Fl_Graphics_Driver::yxline(int x, int y, int y1) {
|
||||||
#if defined(USE_X11)
|
#if defined(USE_X11)
|
||||||
|
// get rid of coordinates outside the 16-bit range
|
||||||
|
if (x < 0 || x > SHRT_MAX) return;
|
||||||
|
if (y <= y1) {
|
||||||
|
if (y1 < 0 || y > SHRT_MAX) return;
|
||||||
|
if (y < 0) y = 0;
|
||||||
|
if (y1 > SHRT_MAX) y1 = SHRT_MAX;
|
||||||
|
} else { // y1 < y
|
||||||
|
if (y < 0 || y1 > SHRT_MAX) return;
|
||||||
|
if (y1 < 0) y1 = 0;
|
||||||
|
if (y > SHRT_MAX) y = SHRT_MAX;
|
||||||
|
}
|
||||||
XDrawLine(fl_display, fl_window, fl_gc, x, y, x, y1);
|
XDrawLine(fl_display, fl_window, fl_gc, x, y, x, y1);
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
if (y1 < y) y1--;
|
if (y1 < y) y1--;
|
||||||
@@ -508,24 +584,9 @@ int Fl_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
|
|||||||
Fl_Region r = rstack[rstackptr];
|
Fl_Region r = rstack[rstackptr];
|
||||||
#if defined (USE_X11)
|
#if defined (USE_X11)
|
||||||
if (!r) return 1;
|
if (!r) return 1;
|
||||||
|
// get rid of coordinates outside the 16-bit range the X calls take.
|
||||||
// First get rid of coordinates outside the 16-bit range the X calls take.
|
if (clip_to_short(x,y,w,h)) return 0; // clipped
|
||||||
// We could probably also use max. screen coordinates instead of SHRT_MAX
|
return XRectInRegion(r, x, y, w, h);
|
||||||
|
|
||||||
#ifndef SHRT_MAX
|
|
||||||
#define SHRT_MAX (32767)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (x>SHRT_MAX || y > SHRT_MAX) return 0;
|
|
||||||
int tx = x, ty = y, tw = w, th = h;
|
|
||||||
if (x < 0) { tx = 0; tw += x; }
|
|
||||||
if (y < 0) { ty = 0; th += y; }
|
|
||||||
if (tx+tw > SHRT_MAX) tw = SHRT_MAX - tx;
|
|
||||||
if (ty+th > SHRT_MAX) th = SHRT_MAX - ty;
|
|
||||||
|
|
||||||
// now all coordinates to test are in the range [0,32767]
|
|
||||||
|
|
||||||
return XRectInRegion(r, tx, ty, tw, th);
|
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
if (!r) return 1;
|
if (!r) return 1;
|
||||||
RECT rect;
|
RECT rect;
|
||||||
@@ -533,17 +594,16 @@ int Fl_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
|
|||||||
POINT pt[2] = { {x, y}, {x + w, y + h} };
|
POINT pt[2] = { {x, y}, {x + w, y + h} };
|
||||||
LPtoDP(fl_gc, pt, 2);
|
LPtoDP(fl_gc, pt, 2);
|
||||||
rect.left = pt[0].x; rect.top = pt[0].y; rect.right = pt[1].x; rect.bottom = pt[1].y;
|
rect.left = pt[0].x; rect.top = pt[0].y; rect.right = pt[1].x; rect.bottom = pt[1].y;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
|
rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
|
||||||
}
|
}
|
||||||
return RectInRegion(r,&rect);
|
return RectInRegion(r,&rect);
|
||||||
#elif defined(__APPLE_QUARTZ__)
|
#elif defined(__APPLE_QUARTZ__)
|
||||||
if (!r) return 1;
|
if (!r) return 1;
|
||||||
CGRect arg = fl_cgrectmake_cocoa(x, y, w, h);
|
CGRect arg = fl_cgrectmake_cocoa(x, y, w, h);
|
||||||
for(int i = 0; i < r->count; i++) {
|
for (int i = 0; i < r->count; i++) {
|
||||||
CGRect test = CGRectIntersection(r->rects[i], arg);
|
CGRect test = CGRectIntersection(r->rects[i], arg);
|
||||||
if( ! CGRectIsEmpty(test)) return 1;
|
if (!CGRectIsEmpty(test)) return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
|
|||||||
Reference in New Issue
Block a user