Use cairo_region_t for clipping instead of Fl_Rectangle.tags/v1.3.1000
@@ -1,128 +0,0 @@ | |||
// "$Id: Fl_Rectangle.h 8500 2011-03-03 09:20:46Z bgbnbigben $" | |||
// | |||
// Copyright 1998-2006 by Bill Spitzak and others. | |||
// | |||
// This library is free software; you can redistribute it and/or | |||
// modify it under the terms of the GNU Library General Public | |||
// License as published by the Free Software Foundation; either | |||
// version 2 of the License, or (at your option) any later version. | |||
// | |||
// This library is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
// Library General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Library General Public | |||
// License along with this library; if not, write to the Free Software | |||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |||
// USA. | |||
// | |||
// Please report all bugs and problems on the following page: | |||
// | |||
// http://www.fltk.org/str.php | |||
#ifndef fltk_Fl_Rectangle_h | |||
#define fltk_Fl_Rectangle_h | |||
// rectangle macros that help keeping rectangle predicates as strict as possible | |||
// even when not using rectangles in some situations (as when only using w h scalars) | |||
// so that there is only one strict defintion for common predicates, | |||
// if one change the following, it will be repercuted in all the core lib | |||
#define FLTK_RECT_EMPTY(w,h) (w <= 0 || h <= 0) | |||
// we should always use the same evaluation for center_x, center_y in all corelib code: | |||
//#define FLTK_CENTER_X(coord, length) (coord + (length>>1)) | |||
//#define FLTK_CENTER_Y(coord, length) (coord + (length>>1)) | |||
class Fl_Rectangle { | |||
int x_, y_, w_, h_; | |||
public: | |||
/*! Left edge */ | |||
int x() const {return x_;} | |||
/*! Top edge */ | |||
int y() const {return y_;} | |||
/*! Distance between left and right edges */ | |||
int w() const {return w_;} | |||
/*! Distance between top and bottom edges */ | |||
int h() const {return h_;} | |||
/*! Return x()+w(), the right edge of the rectangle. */ | |||
int r() const {return x_+w_;} | |||
/*! Return y()+h(), the bottom edge of the rectangle. */ | |||
int b() const {return y_+h_;} | |||
/*! Move the rectangle so the left edge is at \a v. */ | |||
void x(int v) {x_ = v;} | |||
/*! Move the rectangle so the top edge is at \a v. */ | |||
void y(int v) {y_ = v;} | |||
/*! Change w() by moving the right edge. x() does not change. */ | |||
void w(int v) {w_ = v;} | |||
/*! Change h() by moving the bottom edge. y() does not change. */ | |||
void h(int v) {h_ = v;} | |||
/*! Change x() without changing r(), by changing the width. */ | |||
void set_x(int v) {w_ -= v-x_; x_ = v;} | |||
/*! Change y() without changing b(), by changing the height. */ | |||
void set_y(int v) {h_ -= v-y_; y_ = v;} | |||
/*! Change r() without changing x(), by changine the width. */ | |||
void set_r(int v) {w_ = v-x_;} | |||
/*! Change b() without changing y(), by changine the height. */ | |||
void set_b(int v) {h_ = v-y_;} | |||
/*! Set x(), y(), w(), and h() all at once. */ | |||
void set(int x, int y, int w, int h) {x_=x; y_=y; w_=w; h_=h;} | |||
/*! Sets x, y, w, h so that's it's centered or aligned (if flags!=0) inside the source r */ | |||
void set (const Fl_Rectangle& r, int w, int h, int flags = 0); | |||
/*! Add \a d to x() without changing r() (it reduces w() by \a d). */ | |||
void move_x(int d) {x_ += d; w_ -= d;} | |||
/*! Add \a d to y() without changing b() (it reduces h() by \a d). */ | |||
void move_y(int d) {y_ += d; h_ -= d;} | |||
/*! Add \a d to r() and w(). */ | |||
void move_r(int d) {w_ += d;} | |||
/*! Add \a d to b() and h(). */ | |||
void move_b(int d) {h_ += d;} | |||
/*! Move all edges in by \a d. See also Symbol::inset() */ | |||
void inset(int d) {x_ += d; y_ += d; w_ -= 2*d; h_ -= 2*d;} | |||
/*! Move entire rectangle by given distance in x and y. */ | |||
void move(int dx, int dy) {x_ += dx; y_ += dy;} | |||
/*! True if w() or h() are less or equal to zero. */ | |||
bool empty() const {return FLTK_RECT_EMPTY(w_, h_);} | |||
/*! Same as !empty(), true if w() and h() are both greater than zero. */ | |||
bool not_empty() const {return !FLTK_RECT_EMPTY(w_, h_);} | |||
/*! Integer center position. Rounded to the left if w() is odd. */ | |||
int center_x() const {return x_+(w_>>1);} | |||
/*! Integer center position. Rounded to lower y if h() is odd. */ | |||
int center_y() const {return y_+(h_>>1);} | |||
/*! Where to put baseline to center current font nicely */ | |||
int baseline_y() const; | |||
Fl_Rectangle() {} | |||
/*! Constructor that sets x(), y(), w(), and h(). */ | |||
Fl_Rectangle(int x, int y, int w, int h) : x_(x), y_(y), w_(w), h_(h) {} | |||
/*! Constructor that sets x() and y() to zero, and sets w() and h(). */ | |||
Fl_Rectangle(int w, int h) : x_(0), y_(0), w_(w), h_(h) {} | |||
/*! Copy constructor. */ | |||
Fl_Rectangle(const Fl_Rectangle& r) : x_(r.x_),y_(r.y_),w_(r.w_),h_(r.h_) {} | |||
/*! Constructor that calls set(). */ | |||
Fl_Rectangle(const Fl_Rectangle& r, int w, int h, int flags = 0) {set(r,w,h,flags);} | |||
/*! True if rectangle contains the pixel who's upper-left corner is at x,y */ | |||
bool contains(int x, int y) const {return x>=x_ && y>=y_ && x<x_+w_ && y<y_+h_;} | |||
/* returns true if the rectangles intersect at all */ | |||
bool intersects ( const Fl_Rectangle &r ) const | |||
{ | |||
Fl_Rectangle r2( r ); | |||
r2.intersect( *this ); | |||
return ! r2.empty(); | |||
} | |||
void merge(const Fl_Rectangle& r); | |||
void intersect(const Fl_Rectangle& r); | |||
}; | |||
#endif |
@@ -46,7 +46,6 @@ | |||
# include "Enumerations.H" | |||
#include <FL/Fl_Cairo.H> | |||
#include <FL/Fl_Rectangle.H> | |||
# ifdef WIN32 | |||
# include "win32.H" | |||
@@ -65,7 +64,11 @@ | |||
# include "Fl_Window.H" | |||
# include "Xutf8.h" | |||
// Mirror X definition of Region to Fl_Region, for portability... | |||
typedef Fl_Rectangle * Fl_Region; | |||
#if FLTK_USE_CAIRO | |||
typedef cairo_region_t * Fl_Region; | |||
#else | |||
typedef Region Fl_Region; | |||
#endif | |||
FL_EXPORT void fl_open_display(); | |||
FL_EXPORT void fl_open_display(Display*); | |||
@@ -753,7 +753,15 @@ void Fl::flush() { | |||
if (!wi->visible_r()) continue; | |||
if (wi->damage()) {wi->make_current(); i->flush(); wi->clear_damage();} | |||
// destroy damage regions for windows that don't use them: | |||
if (i->region) {delete i->region; i->region = 0;} | |||
#if FLTK_USE_CAIRO | |||
if ( i->region ) | |||
{ | |||
cairo_region_destroy( i->region ); | |||
i->region = 0; | |||
} | |||
#else | |||
if (i->region) {XDestroyRegion(i->region); i->region = 0;} | |||
#endif | |||
} | |||
} | |||
#if defined(USE_X11) | |||
@@ -1433,8 +1441,15 @@ void Fl_Window::hide() { | |||
if ( ip->xid == fl_window && !parent() ) | |||
fl_window = 0; | |||
#endif | |||
if (ip->region) delete ip->region; ip->region = 0; | |||
#if FLTK_USE_CAIRO | |||
if (ip->region) | |||
{ | |||
cairo_region_destroy( ip->region ); | |||
ip->region = 0; | |||
} | |||
#else | |||
if (ip->region) XDestroyRegion(ip->region); | |||
#endif | |||
#if defined(USE_X11) | |||
#if FLTK_HAVE_CAIRO | |||
@@ -1639,7 +1654,15 @@ void Fl_Widget::damage(uchar fl) { | |||
// damage entire window by deleting the region: | |||
Fl_X* i = Fl_X::i((Fl_Window*)this); | |||
if (!i) return; // window not mapped, so ignore it | |||
if (i->region) {delete i->region; i->region = 0;} | |||
#if FLTK_USE_CAIRO | |||
if ( i->region ) | |||
{ | |||
cairo_region_destroy( i->region ); | |||
i->region = 0; | |||
} | |||
#else | |||
if (i->region) {XDestroyRegion(i->region); i->region = 0;} | |||
#endif | |||
damage_ |= fl; | |||
Fl::damage(FL_DAMAGE_CHILD); | |||
} | |||
@@ -1674,7 +1697,21 @@ void Fl_Widget::damage(uchar fl, int X, int Y, int W, int H) { | |||
// if we already have damage we must merge with existing region: | |||
if (i->region) { | |||
#if defined(USE_X11) | |||
i->region->merge( Fl_Rectangle( X, Y, W, H ) ); | |||
#if FLTK_USE_CAIRO | |||
cairo_rectangle_int_t rect; | |||
rect.x = X; | |||
rect.y = Y; | |||
rect.width = W; | |||
rect.height = H; | |||
cairo_region_union_rectangle( i->region, &rect ); | |||
#else | |||
XRectangle R; | |||
R.x = X; R.y = Y; R.width = W; R.height = H; | |||
XUnionRectWithRegion(&R, i->region, i->region); | |||
#endif | |||
#elif defined(WIN32) | |||
Fl_Region R = XRectangleRegion(X, Y, W, H); | |||
CombineRgn(i->region, i->region, R, RGN_OR); | |||
@@ -1695,9 +1732,27 @@ void Fl_Widget::damage(uchar fl, int X, int Y, int W, int H) { | |||
} | |||
wi->damage_ |= fl; | |||
} else { | |||
#if FLTK_USE_CAIRO | |||
if ( i->region ) | |||
cairo_region_destroy( i->region ); | |||
i->region = cairo_region_create(); | |||
cairo_rectangle_int_t rect; | |||
rect.x = X; | |||
rect.y = Y; | |||
rect.width = W; | |||
rect.height = H; | |||
cairo_region_union_rectangle( i->region, &rect ); | |||
#else | |||
// create a new region: | |||
if (i->region) delete i->region; | |||
i->region = new Fl_Rectangle(X,Y,W,H); | |||
if (i->region) XDestroyRegion(i->region); | |||
i->region = XRectangleRegion(X,Y,W,H); | |||
#endif | |||
wi->damage_ = fl; | |||
} | |||
Fl::damage(FL_DAMAGE_CHILD); | |||
@@ -1,108 +0,0 @@ | |||
// "$Id: Fl_Rectangle.h 8500 2011-03-03 09:20:46Z bgbnbigben $" | |||
// | |||
// Copyright 1998-2006 by Bill Spitzak and others. | |||
// | |||
// This library is free software; you can redistribute it and/or | |||
// modify it under the terms of the GNU Library General Public | |||
// License as published by the Free Software Foundation; either | |||
// version 2 of the License, or (at your option) any later version. | |||
// | |||
// This library is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
// Library General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Library General Public | |||
// License along with this library; if not, write to the Free Software | |||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |||
// USA. | |||
// | |||
// Please report all bugs and problems on the following page: | |||
// | |||
// http://www.fltk.org/str.php | |||
#include <FL/Fl_Rectangle.H> | |||
#include <FL/fl_draw.H> | |||
/*! \class Fl_Rectangle | |||
Describes an integer-sized rectangle. This is the base class of | |||
Widget, and also used a lot to pass rectangular areas to drawing | |||
functions. Almost all the functions are inline. | |||
Negative w() or h() is supposed to mean an empty and thus | |||
invisible rectangle, but some code will treat the rectangle as | |||
reflected about x or y. Set the size to zero to make sure you | |||
have an empty one. | |||
*/ | |||
/*! \fn Rectangle::Rectangle() | |||
The default constructor does not put anything into the fields! | |||
You can either call set() or just modify the x_, y_, w_, and h_ | |||
variables directly. | |||
*/ | |||
/** Initialize to the size w,h. The rectangle is placed inside the | |||
source rectangle \a r either centered or against an edge depending | |||
on the FL_ALIGN values in \a flags. For centered alignment if the | |||
difference in sizes is odd, it always rounds up and left. | |||
Default value for \a flags is to center in both directions. | |||
*/ | |||
void Fl_Rectangle::set(const Fl_Rectangle& r, int w, int h, int flags) { | |||
if (flags & FL_ALIGN_LEFT) { | |||
if (flags & FL_ALIGN_RIGHT && w > r.w()) x_ = r.r()-w; | |||
else x_ = r.x(); | |||
} else if (flags & FL_ALIGN_RIGHT) { | |||
x_ = r.r()-w; | |||
} else { | |||
x_ = r.x()+((r.w()-w)>>1); | |||
// fabien: shouldn't it consider the case r is smaller to avoid negative values ? | |||
// WAS: no, it is supposed to center at all times. The right-shift | |||
// instead of divide-by-2 is to avoid shifting as it goes negative. | |||
// fabien : well while debugging i observed the shift doesn't avoid | |||
// to get negative value at least on Win32 | |||
// WAS: no, it is *supposed* to return a negative value! I want the | |||
// rectangle "centered" even if it is *bigger*. | |||
// if (x_<0) x_=0; | |||
} | |||
if (flags & FL_ALIGN_TOP) { | |||
if (flags & FL_ALIGN_BOTTOM && h > r.h()) y_ = r.b()-h; | |||
else y_ = r.y(); | |||
} else if (flags & FL_ALIGN_BOTTOM) { | |||
y_ = r.b()-h; | |||
} else { | |||
y_ = r.y()+((r.h()-h)>>1); | |||
// see above | |||
// if (y_<0) y_=0; | |||
} | |||
w_ = w; | |||
h_ = h; | |||
} | |||
/** | |||
Replace the value with the union of this rectangle and \a R | |||
(ie the rectangle that surrounds both of these rectangles). | |||
If one rectangle is empty(), the other is returned unchanged | |||
(ie it does not union in the degenerate point of that rectangle). | |||
*/ | |||
void Fl_Rectangle::merge(const Fl_Rectangle& R) { | |||
if (R.empty()) return; | |||
if (empty()) {*this = R; return;} | |||
if (R.x() < x()) set_x(R.x()); | |||
if (R.r() > r()) set_r(R.r()); | |||
if (R.y() < y()) set_y(R.y()); | |||
if (R.b() > b()) set_b(R.b()); | |||
} | |||
/** | |||
Replace the value with the intersection of this rectangle and \a R. | |||
If the rectangles do not intersect, the result may have negative | |||
width and/or height, this means empty() will return true, but some | |||
code may still draw this rectangle. | |||
*/ | |||
void Fl_Rectangle::intersect(const Fl_Rectangle& R) { | |||
if (R.x() > x()) set_x(R.x()); | |||
if (R.r() < r()) set_r(R.r()); | |||
if (R.y() > y()) set_y(R.y()); | |||
if (R.b() < b()) set_b(R.b()); | |||
} | |||
@@ -1691,7 +1691,7 @@ Fl_X* Fl_X::set_xid(Fl_Window* win, Window winxid) { | |||
xp->setwindow(win); | |||
xp->next = Fl_X::first; | |||
xp->region = 0; | |||
xp->wait_for_expose = 0; | |||
xp->wait_for_expose = 1; | |||
// xp->backbuffer_bad = 1; | |||
Fl_X::first = xp; | |||
if (win->modal()) {Fl::modal_ = win; fl_fix_focus();} | |||
@@ -2014,6 +2014,8 @@ void Fl_Window::show() { | |||
labeltype(FL_NO_LABEL); | |||
} | |||
Fl_Tooltip::exit(this); | |||
if (!shown()) { | |||
fl_open_display(); | |||
@@ -170,7 +170,6 @@ CPPFILES = \ | |||
Clean_Theme.cxx \ | |||
Crystal_Theme.cxx \ | |||
themes.cxx \ | |||
Fl_Rectangle.cxx \ | |||
ps_image.cxx | |||
OBJCPPFILES = \ | |||
@@ -113,7 +113,7 @@ void *fl_xftfont = 0; | |||
//const char* fl_encoding_ = "iso8859-1"; | |||
const char* fl_encoding_ = "iso10646-1"; | |||
extern Region XRegionFromRectangle ( Fl_Rectangle *rg ); | |||
extern Region XRegionFromRectangle ( Fl_Region rg ); | |||
static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle) { | |||
if (fnum==-1) { // special case to stop font caching | |||
@@ -511,10 +511,28 @@ void Fl_Graphics_Driver::point(int x, int y) { | |||
#endif | |||
} | |||
Region XRegionFromRectangle ( Fl_Rectangle *rg ) | |||
Region XRegionFromRectangle ( Fl_Region rg ) | |||
{ | |||
if ( rg ) | |||
{ | |||
#if FLTK_USE_CAIRO | |||
Region region = XCreateRegion(); | |||
XRectangle rr; | |||
cairo_rectangle_int_t rect; | |||
cairo_region_get_extents( rg, &rect ); | |||
rr.x = rect.x; | |||
rr.y = rect.y; | |||
rr.width = rect.width; | |||
rr.height = rect.height; | |||
XUnionRectWithRegion( &rr, region, region ); | |||
return region; | |||
#else | |||
Region region = XCreateRegion(); | |||
XRectangle rr; | |||
@@ -526,6 +544,7 @@ Region XRegionFromRectangle ( Fl_Rectangle *rg ) | |||
XUnionRectWithRegion( &rr, region, region ); | |||
return region; | |||
#endif | |||
} | |||
return 0; | |||
@@ -537,7 +556,27 @@ Region XRegionFromRectangle ( Fl_Rectangle *rg ) | |||
// Missing X call: (is this the fastest way to init a 1-rectangle region?) | |||
// MSWindows equivalent exists, implemented inline in win32.H | |||
Fl_Region XRectangleRegion(int x, int y, int w, int h) { | |||
return new Fl_Rectangle( x, y, w, h ); | |||
#if FLTK_USE_CAIRO | |||
cairo_rectangle_int_t rect; | |||
rect.x = x; | |||
rect.y = y; | |||
rect.width = w; | |||
rect.height = h; | |||
return cairo_region_create_rectangle( &rect ); | |||
#else | |||
XRectangle R; | |||
clip_to_short(x, y, w, h); | |||
R.x = x; R.y = y; R.width = w; R.height = h; | |||
Fl_Region r = XCreateRegion(); | |||
XUnionRectWithRegion(&R, r, r); | |||
return r; | |||
#endif | |||
} | |||
#endif | |||
@@ -545,14 +584,10 @@ void Fl_Graphics_Driver::restore_clip() { | |||
fl_clip_state_number++; | |||
Fl_Region r = rstack[rstackptr]; | |||
#if defined(USE_X11) | |||
if (r) | |||
{ | |||
Region xr = XRegionFromRectangle( r ); | |||
XSetRegion(fl_display, fl_gc, xr ); | |||
XDestroyRegion( xr ); | |||
} | |||
else | |||
XSetClipMask(fl_display, fl_gc, 0); | |||
#if ! FLTK_USE_CAIRO | |||
if (r) XSetRegion(fl_display, fl_gc, r); | |||
else XSetClipMask(fl_display, fl_gc, 0); | |||
#endif | |||
#elif defined(WIN32) | |||
SelectClipRgn(fl_gc, r); //if r is NULL, clip is automatically cleared | |||
#elif defined(__APPLE_QUARTZ__) | |||
@@ -583,8 +618,16 @@ void Fl_Graphics_Driver::restore_clip() { | |||
if ( r ) | |||
{ | |||
cairo_rectangle_int_t rect; | |||
for ( int i = cairo_region_num_rectangles( r ); --i >= 0; ) | |||
{ | |||
cairo_region_get_rectangle( r, i, &rect ); | |||
cairo_rectangle( cr, rect.x, rect.y, rect.width, rect.height ); | |||
} | |||
// cairo_set_source_rgb( cr, 0, 1, 0 ); | |||
cairo_rectangle( cr, r->x(), r->y(), r->w(), r->h() ); | |||
// cairo_rectangle( cr, r->x(), r->y(), r->w(), r->h() ); | |||
// cairo_stroke_preserve( cr ); | |||
cairo_clip( cr ); | |||
@@ -596,9 +639,17 @@ void Fl_Graphics_Driver::restore_clip() { | |||
void Fl_Graphics_Driver::clip_region(Fl_Region r) { | |||
Fl_Region oldr = rstack[rstackptr]; | |||
if (oldr && r != oldr ) delete oldr; | |||
#if FLTK_USE_CAIRO | |||
if (oldr && r != oldr ) | |||
{ | |||
cairo_region_destroy( oldr ); | |||
} | |||
rstack[rstackptr] = r ? new Fl_Rectangle( *r ) : 0; | |||
rstack[rstackptr] = r ? cairo_region_reference( r ) : 0; | |||
#else | |||
if (oldr && r != oldr ) XDestroyRegion(oldr); | |||
rstack[rstackptr] = r; | |||
#endif | |||
fl_restore_clip(); | |||
} | |||
@@ -609,16 +660,18 @@ Fl_Region Fl_Graphics_Driver::clip_region() { | |||
void Fl_Graphics_Driver::push_clip(int x, int y, int w, int h) { | |||
Fl_Region r; | |||
if (w > 0 && h > 0) { | |||
r = new Fl_Rectangle( x, y, w, h ); | |||
r = XRectangleRegion(x,y,w,h); | |||
Fl_Region current = rstack[rstackptr]; | |||
if (current) { | |||
#if defined(USE_X11) | |||
r->intersect( *current ); | |||
if ( r->empty() ) | |||
{ | |||
delete r; | |||
r = new Fl_Rectangle( 0, 0, 0, 0 ); | |||
} | |||
#if FLTK_USE_CAIRO | |||
cairo_region_intersect( r, current ); | |||
#else | |||
Fl_Region temp = XCreateRegion(); | |||
XIntersectRegion(current, r, temp); | |||
XDestroyRegion(r); | |||
r = temp; | |||
#endif | |||
#elif defined(WIN32) | |||
CombineRgn(r,r,current,RGN_AND); | |||
#elif defined(__APPLE_QUARTZ__) | |||
@@ -630,7 +683,7 @@ void Fl_Graphics_Driver::push_clip(int x, int y, int w, int h) { | |||
} | |||
} else { // make empty clip region: | |||
#if defined(USE_X11) | |||
r = new Fl_Rectangle( 0, 0, 0, 0 ); | |||
r = XRectangleRegion( 0, 0, 0, 0 ); | |||
#elif defined(WIN32) | |||
r = CreateRectRgn(0,0,0,0); | |||
#elif defined(__APPLE_QUARTZ__) | |||
@@ -655,7 +708,14 @@ void Fl_Graphics_Driver::push_no_clip() { | |||
void Fl_Graphics_Driver::pop_clip() { | |||
if (rstackptr > 0) { | |||
Fl_Region oldr = rstack[rstackptr--]; | |||
if (oldr) delete oldr; | |||
#if FLTK_USE_CAIRO | |||
if (oldr) | |||
{ | |||
cairo_region_destroy( oldr ); | |||
} | |||
#else | |||
if (oldr) XDestroyRegion(oldr); | |||
#endif | |||
} else Fl::warning("fl_pop_clip: clip stack underflow!\n"); | |||
fl_restore_clip(); | |||
} | |||
@@ -666,8 +726,18 @@ int Fl_Graphics_Driver::not_clipped(int x, int y, int w, int h) { | |||
if (!r) return 1; | |||
#if defined (USE_X11) | |||
// get rid of coordinates outside the 16-bit range the X calls take. | |||
// if (clip_to_short(x,y,w,h)) return 0; // clipped | |||
return r->intersects( Fl_Rectangle( x, y, w, h ) ); | |||
if (clip_to_short(x,y,w,h)) return 0; // clipped | |||
#if FLTK_USE_CAIRO | |||
cairo_rectangle_int_t rect; | |||
rect.x = x; rect.y = y; rect.width = w; rect.height = h; | |||
cairo_region_overlap_t o = cairo_region_contains_rectangle( r, &rect ); | |||
return o != CAIRO_REGION_OVERLAP_OUT; | |||
#else | |||
return XRectInRegion(r, x, y, w, h); | |||
#endif | |||
#elif defined(WIN32) | |||
RECT rect; | |||
if (Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id) { // in case of print context, convert coords from logical to device | |||
@@ -695,31 +765,52 @@ int Fl_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int | |||
X = x; Y = y; W = w; H = h; | |||
Fl_Region r = rstack[rstackptr]; | |||
if (!r) return 0; | |||
#if defined(USE_X11) | |||
#if FLTK_USE_CAIRO | |||
cairo_rectangle_int_t rect; | |||
rect.x = x; rect.y = y; rect.width = w; rect.height = h; | |||
Fl_Rectangle rec( x, y, w, h ); | |||
rec.intersect( *r ); | |||
cairo_region_t *t = cairo_region_copy( r ); | |||
X = rec.x(); Y = rec.y(); W = rec.w(); H = rec.h(); | |||
cairo_region_intersect_rectangle( t, &rect ); | |||
if ( r->contains( x, y ) && r->contains( x + w - 1, y + h - 1 ) ) | |||
{ | |||
/* completely inside */ | |||
return 0; | |||
} | |||
cairo_region_get_extents( t, &rect ); | |||
if ( rec.empty() ) | |||
X = rect.x; Y = rect.y; W = rect.width; H = rect.height; | |||
cairo_region_overlap_t o = cairo_region_contains_rectangle( r, &rect ); | |||
switch ( o ) | |||
{ | |||
H = W = 0; | |||
/* completely outside */ | |||
return 2; | |||
case CAIRO_REGION_OVERLAP_IN: | |||
return 0; | |||
case CAIRO_REGION_OVERLAP_OUT: | |||
return 2; | |||
case CAIRO_REGION_OVERLAP_PART: | |||
return 1; | |||
default: | |||
return 2; | |||
} | |||
/* partial */ | |||
#else | |||
switch (XRectInRegion(r, x, y, w, h)) { | |||
case RectangleOut: // completely outside | |||
W = H = 0; | |||
return 2; | |||
case RectangleIn: // completely inside: | |||
return 0; | |||
default: // partial: | |||
break; | |||
} | |||
Fl_Region rr = XRectangleRegion(x,y,w,h); | |||
Fl_Region temp = XCreateRegion(); | |||
XIntersectRegion(r, rr, temp); | |||
XRectangle rect; | |||
XClipBox(temp, &rect); | |||
X = rect.x; Y = rect.y; W = rect.width; H = rect.height; | |||
XDestroyRegion(temp); | |||
XDestroyRegion(rr); | |||
return 1; | |||
#if defined(USE_X11) | |||
#endif | |||
#elif defined(WIN32) | |||
// The win32 API makes no distinction between partial and complete | |||