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 "Enumerations.H" | ||||
#include <FL/Fl_Cairo.H> | #include <FL/Fl_Cairo.H> | ||||
#include <FL/Fl_Rectangle.H> | |||||
# ifdef WIN32 | # ifdef WIN32 | ||||
# include "win32.H" | # include "win32.H" | ||||
@@ -65,7 +64,11 @@ | |||||
# include "Fl_Window.H" | # include "Fl_Window.H" | ||||
# include "Xutf8.h" | # include "Xutf8.h" | ||||
// Mirror X definition of Region to Fl_Region, for portability... | // 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(); | ||||
FL_EXPORT void fl_open_display(Display*); | FL_EXPORT void fl_open_display(Display*); | ||||
@@ -753,7 +753,15 @@ void Fl::flush() { | |||||
if (!wi->visible_r()) continue; | if (!wi->visible_r()) continue; | ||||
if (wi->damage()) {wi->make_current(); i->flush(); wi->clear_damage();} | if (wi->damage()) {wi->make_current(); i->flush(); wi->clear_damage();} | ||||
// destroy damage regions for windows that don't use them: | // 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) | #if defined(USE_X11) | ||||
@@ -1433,8 +1441,15 @@ void Fl_Window::hide() { | |||||
if ( ip->xid == fl_window && !parent() ) | if ( ip->xid == fl_window && !parent() ) | ||||
fl_window = 0; | fl_window = 0; | ||||
#endif | #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 defined(USE_X11) | ||||
#if FLTK_HAVE_CAIRO | #if FLTK_HAVE_CAIRO | ||||
@@ -1639,7 +1654,15 @@ void Fl_Widget::damage(uchar fl) { | |||||
// damage entire window by deleting the region: | // damage entire window by deleting the region: | ||||
Fl_X* i = Fl_X::i((Fl_Window*)this); | Fl_X* i = Fl_X::i((Fl_Window*)this); | ||||
if (!i) return; // window not mapped, so ignore it | 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; | damage_ |= fl; | ||||
Fl::damage(FL_DAMAGE_CHILD); | 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 we already have damage we must merge with existing region: | ||||
if (i->region) { | if (i->region) { | ||||
#if defined(USE_X11) | #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) | #elif defined(WIN32) | ||||
Fl_Region R = XRectangleRegion(X, Y, W, H); | Fl_Region R = XRectangleRegion(X, Y, W, H); | ||||
CombineRgn(i->region, i->region, R, RGN_OR); | 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; | wi->damage_ |= fl; | ||||
} else { | } 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: | // 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; | wi->damage_ = fl; | ||||
} | } | ||||
Fl::damage(FL_DAMAGE_CHILD); | 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->setwindow(win); | ||||
xp->next = Fl_X::first; | xp->next = Fl_X::first; | ||||
xp->region = 0; | xp->region = 0; | ||||
xp->wait_for_expose = 0; | |||||
xp->wait_for_expose = 1; | |||||
// xp->backbuffer_bad = 1; | // xp->backbuffer_bad = 1; | ||||
Fl_X::first = xp; | Fl_X::first = xp; | ||||
if (win->modal()) {Fl::modal_ = win; fl_fix_focus();} | if (win->modal()) {Fl::modal_ = win; fl_fix_focus();} | ||||
@@ -2014,6 +2014,8 @@ void Fl_Window::show() { | |||||
labeltype(FL_NO_LABEL); | labeltype(FL_NO_LABEL); | ||||
} | } | ||||
Fl_Tooltip::exit(this); | Fl_Tooltip::exit(this); | ||||
if (!shown()) { | if (!shown()) { | ||||
fl_open_display(); | fl_open_display(); | ||||
@@ -170,7 +170,6 @@ CPPFILES = \ | |||||
Clean_Theme.cxx \ | Clean_Theme.cxx \ | ||||
Crystal_Theme.cxx \ | Crystal_Theme.cxx \ | ||||
themes.cxx \ | themes.cxx \ | ||||
Fl_Rectangle.cxx \ | |||||
ps_image.cxx | ps_image.cxx | ||||
OBJCPPFILES = \ | OBJCPPFILES = \ | ||||
@@ -113,7 +113,7 @@ void *fl_xftfont = 0; | |||||
//const char* fl_encoding_ = "iso8859-1"; | //const char* fl_encoding_ = "iso8859-1"; | ||||
const char* fl_encoding_ = "iso10646-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) { | 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 | if (fnum==-1) { // special case to stop font caching | ||||
@@ -511,10 +511,28 @@ void Fl_Graphics_Driver::point(int x, int y) { | |||||
#endif | #endif | ||||
} | } | ||||
Region XRegionFromRectangle ( Fl_Rectangle *rg ) | |||||
Region XRegionFromRectangle ( Fl_Region rg ) | |||||
{ | { | ||||
if ( 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(); | Region region = XCreateRegion(); | ||||
XRectangle rr; | XRectangle rr; | ||||
@@ -526,6 +544,7 @@ Region XRegionFromRectangle ( Fl_Rectangle *rg ) | |||||
XUnionRectWithRegion( &rr, region, region ); | XUnionRectWithRegion( &rr, region, region ); | ||||
return region; | return region; | ||||
#endif | |||||
} | } | ||||
return 0; | 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?) | // Missing X call: (is this the fastest way to init a 1-rectangle region?) | ||||
// MSWindows equivalent exists, implemented inline in win32.H | // MSWindows equivalent exists, implemented inline in win32.H | ||||
Fl_Region XRectangleRegion(int x, int y, int w, int 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 | #endif | ||||
@@ -545,14 +584,10 @@ void Fl_Graphics_Driver::restore_clip() { | |||||
fl_clip_state_number++; | fl_clip_state_number++; | ||||
Fl_Region r = rstack[rstackptr]; | Fl_Region r = rstack[rstackptr]; | ||||
#if defined(USE_X11) | #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) | #elif defined(WIN32) | ||||
SelectClipRgn(fl_gc, r); //if r is NULL, clip is automatically cleared | SelectClipRgn(fl_gc, r); //if r is NULL, clip is automatically cleared | ||||
#elif defined(__APPLE_QUARTZ__) | #elif defined(__APPLE_QUARTZ__) | ||||
@@ -583,8 +618,16 @@ void Fl_Graphics_Driver::restore_clip() { | |||||
if ( r ) | 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_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_stroke_preserve( cr ); | ||||
cairo_clip( cr ); | cairo_clip( cr ); | ||||
@@ -596,9 +639,17 @@ void Fl_Graphics_Driver::restore_clip() { | |||||
void Fl_Graphics_Driver::clip_region(Fl_Region r) { | void Fl_Graphics_Driver::clip_region(Fl_Region r) { | ||||
Fl_Region oldr = rstack[rstackptr]; | 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(); | 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) { | void Fl_Graphics_Driver::push_clip(int x, int y, int w, int h) { | ||||
Fl_Region r; | Fl_Region r; | ||||
if (w > 0 && h > 0) { | if (w > 0 && h > 0) { | ||||
r = new Fl_Rectangle( x, y, w, h ); | |||||
r = XRectangleRegion(x,y,w,h); | |||||
Fl_Region current = rstack[rstackptr]; | Fl_Region current = rstack[rstackptr]; | ||||
if (current) { | if (current) { | ||||
#if defined(USE_X11) | #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) | #elif defined(WIN32) | ||||
CombineRgn(r,r,current,RGN_AND); | CombineRgn(r,r,current,RGN_AND); | ||||
#elif defined(__APPLE_QUARTZ__) | #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: | } else { // make empty clip region: | ||||
#if defined(USE_X11) | #if defined(USE_X11) | ||||
r = new Fl_Rectangle( 0, 0, 0, 0 ); | |||||
r = XRectangleRegion( 0, 0, 0, 0 ); | |||||
#elif defined(WIN32) | #elif defined(WIN32) | ||||
r = CreateRectRgn(0,0,0,0); | r = CreateRectRgn(0,0,0,0); | ||||
#elif defined(__APPLE_QUARTZ__) | #elif defined(__APPLE_QUARTZ__) | ||||
@@ -655,7 +708,14 @@ void Fl_Graphics_Driver::push_no_clip() { | |||||
void Fl_Graphics_Driver::pop_clip() { | void Fl_Graphics_Driver::pop_clip() { | ||||
if (rstackptr > 0) { | if (rstackptr > 0) { | ||||
Fl_Region oldr = rstack[rstackptr--]; | 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"); | } else Fl::warning("fl_pop_clip: clip stack underflow!\n"); | ||||
fl_restore_clip(); | 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 (!r) return 1; | ||||
#if defined (USE_X11) | #if defined (USE_X11) | ||||
// get rid of coordinates outside the 16-bit range the X calls take. | // 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) | #elif defined(WIN32) | ||||
RECT rect; | RECT rect; | ||||
if (Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id) { // in case of print context, convert coords from logical to device | 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; | X = x; Y = y; W = w; H = h; | ||||
Fl_Region r = rstack[rstackptr]; | Fl_Region r = rstack[rstackptr]; | ||||
if (!r) return 0; | 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; | return 1; | ||||
#if defined(USE_X11) | |||||
#endif | |||||
#elif defined(WIN32) | #elif defined(WIN32) | ||||
// The win32 API makes no distinction between partial and complete | // The win32 API makes no distinction between partial and complete | ||||