@@ -1039,8 +1039,10 @@ public: | |||||
*/ | */ | ||||
public: | public: | ||||
static cairo_surface_t * cairo_create_surface ( Window xid, int W, int H ); | |||||
// Cairo support API | // Cairo support API | ||||
static cairo_t * cairo_make_current(Fl_Window* wi, Window w = 0); | |||||
static cairo_t * cairo_make_current( cairo_surface_t *cs, cairo_t *cc ); | |||||
/** when FLTK_HAVE_CAIRO is defined and cairo_autolink_context() is true, | /** when FLTK_HAVE_CAIRO is defined and cairo_autolink_context() is true, | ||||
any current window dc is linked to a current context. | any current window dc is linked to a current context. | ||||
This is not the default, because it may not be necessary | This is not the default, because it may not be necessary | ||||
@@ -522,9 +522,6 @@ public: | |||||
void line_style(int style, int width=0, char* dashes=0); | void line_style(int style, int width=0, char* dashes=0); | ||||
void restore_clip ( void ); | |||||
void arc( int x, int y, int w, int h, double a1, double a2 ); | void arc( int x, int y, int w, int h, double a1, double a2 ); | ||||
void pie( int x, int y, int w, int h, double a1, double a2 ); | void pie( int x, int y, int w, int h, double a1, double a2 ); | ||||
void arc( double x, double y, double r, double a1, double a2 ); | void arc( double x, double y, double r, double a1, double a2 ); | ||||
@@ -31,7 +31,7 @@ | |||||
#ifndef Fl_Menu_Window_H | #ifndef Fl_Menu_Window_H | ||||
#define Fl_Menu_Window_H | #define Fl_Menu_Window_H | ||||
#include "Fl_Double_Window.H" | |||||
#include "Fl_Single_Window.H" | |||||
/** | /** | ||||
The Fl_Menu_Window widget is a window type used for menus. By | The Fl_Menu_Window widget is a window type used for menus. By | ||||
@@ -39,7 +39,7 @@ | |||||
available so that the menu don't force the rest of the window to | available so that the menu don't force the rest of the window to | ||||
redraw. | redraw. | ||||
*/ | */ | ||||
class FL_EXPORT Fl_Menu_Window : public Fl_Double_Window { | |||||
class FL_EXPORT Fl_Menu_Window : public Fl_Single_Window { | |||||
public: | public: | ||||
void show(); | void show(); | ||||
void erase(); | void erase(); | ||||
@@ -48,10 +48,10 @@ public: | |||||
~Fl_Menu_Window(); | ~Fl_Menu_Window(); | ||||
/** Creates a new Fl_Menu_Window widget using the given size, and label string. */ | /** Creates a new Fl_Menu_Window widget using the given size, and label string. */ | ||||
Fl_Menu_Window(int W, int H, const char *l = 0) | Fl_Menu_Window(int W, int H, const char *l = 0) | ||||
: Fl_Double_Window(W,H,l) { image(0); } | |||||
: Fl_Single_Window(W,H,l) { image(0); } | |||||
/** Creates a new Fl_Menu_Window widget using the given position, size, and label string. */ | /** Creates a new Fl_Menu_Window widget using the given position, size, and label string. */ | ||||
Fl_Menu_Window(int X, int Y, int W, int H, const char *l = 0) | Fl_Menu_Window(int X, int Y, int W, int H, const char *l = 0) | ||||
: Fl_Double_Window(X,Y,W,H,l) { image(0); } | |||||
: Fl_Single_Window(X,Y,W,H,l) { image(0); } | |||||
}; | }; | ||||
#endif | #endif | ||||
@@ -0,0 +1,128 @@ | |||||
// "$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,6 +46,7 @@ | |||||
# 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" | ||||
@@ -64,7 +65,7 @@ | |||||
# 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 Region Fl_Region; | |||||
typedef Fl_Rectangle * Fl_Region; | |||||
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*); | ||||
@@ -158,16 +159,18 @@ extern FL_EXPORT Fl_XFont_On_Demand fl_xfont; | |||||
class FL_EXPORT Fl_X { | class FL_EXPORT Fl_X { | ||||
public: | public: | ||||
Window xid; | Window xid; | ||||
Window other_xid; | |||||
Window other_xid; /* for double buffering */ | |||||
#if FLTK_HAVE_CAIRO | #if FLTK_HAVE_CAIRO | ||||
cairo_t *cc; | cairo_t *cc; | ||||
cairo_surface_t *cs; | cairo_surface_t *cs; | ||||
cairo_t *other_cc; /* for double buffering */ | |||||
cairo_surface_t *other_cs; /* for double buffering */ | |||||
#endif | #endif | ||||
Fl_Window *w; | Fl_Window *w; | ||||
Fl_Region region; | Fl_Region region; | ||||
Fl_X *next; | Fl_X *next; | ||||
char wait_for_expose; | char wait_for_expose; | ||||
char backbuffer_bad; // used for XDBE | |||||
char cairo_surface_invalid; | |||||
static Fl_X* first; | static Fl_X* first; | ||||
static Fl_X* i(const Fl_Window* wi) {return wi->i;} | static Fl_X* i(const Fl_Window* wi) {return wi->i;} | ||||
void setwindow(Fl_Window* wi) {w=wi; wi->i=this;} | void setwindow(Fl_Window* wi) {w=wi; wi->i=this;} | ||||
@@ -750,12 +750,10 @@ void Fl::flush() { | |||||
for (Fl_X* i = Fl_X::first; i; i = i->next) { | for (Fl_X* i = Fl_X::first; i; i = i->next) { | ||||
if (i->wait_for_expose) {damage_ = 1; continue;} | if (i->wait_for_expose) {damage_ = 1; continue;} | ||||
Fl_Window* wi = i->w; | Fl_Window* wi = i->w; | ||||
// Fl::cairo_make_current(wi); | |||||
if (!wi->visible_r()) continue; | if (!wi->visible_r()) continue; | ||||
wi->make_current(); | |||||
if (wi->damage()) {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) {XDestroyRegion(i->region); i->region = 0;} | |||||
if (i->region) {delete i->region; i->region = 0;} | |||||
} | } | ||||
} | } | ||||
#if defined(USE_X11) | #if defined(USE_X11) | ||||
@@ -1436,18 +1434,18 @@ void Fl_Window::hide() { | |||||
fl_window = 0; | fl_window = 0; | ||||
#endif | #endif | ||||
if (ip->region) XDestroyRegion(ip->region); | |||||
if (ip->region) delete ip->region; ip->region = 0; | |||||
#if defined(USE_X11) | #if defined(USE_X11) | ||||
#if FLTK_HAVE_CAIRO | |||||
cairo_destroy( ip->cc ); ip->cc = 0; | |||||
cairo_surface_destroy( ip->cs ); ip->cs = 0; | |||||
#endif | |||||
# if USE_XFT | # if USE_XFT | ||||
fl_destroy_xft_draw(ip->xid); | fl_destroy_xft_draw(ip->xid); | ||||
# endif | # endif | ||||
// this test makes sure ip->xid has not been destroyed already | // this test makes sure ip->xid has not been destroyed already | ||||
if (ip->xid) XDestroyWindow(fl_display, ip->xid); | if (ip->xid) XDestroyWindow(fl_display, ip->xid); | ||||
#if FLTK_HAVE_CAIRO | |||||
cairo_destroy( ip->cc ); ip->cc = NULL; | |||||
cairo_surface_destroy( ip->cs ); ip->cs = NULL; | |||||
#endif | |||||
#elif defined(WIN32) | #elif defined(WIN32) | ||||
// this little trickery seems to avoid the popup window stacking problem | // this little trickery seems to avoid the popup window stacking problem | ||||
HWND p = GetForegroundWindow(); | HWND p = GetForegroundWindow(); | ||||
@@ -1641,7 +1639,7 @@ 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) {XDestroyRegion(i->region); i->region = 0;} | |||||
if (i->region) {delete i->region; i->region = 0;} | |||||
damage_ |= fl; | damage_ |= fl; | ||||
Fl::damage(FL_DAMAGE_CHILD); | Fl::damage(FL_DAMAGE_CHILD); | ||||
} | } | ||||
@@ -1676,9 +1674,7 @@ 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) | ||||
XRectangle R; | |||||
R.x = X; R.y = Y; R.width = W; R.height = H; | |||||
XUnionRectWithRegion(&R, i->region, i->region); | |||||
i->region->merge( Fl_Rectangle( X, Y, W, H ) ); | |||||
#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); | ||||
@@ -1700,25 +1696,26 @@ void Fl_Widget::damage(uchar fl, int X, int Y, int W, int H) { | |||||
wi->damage_ |= fl; | wi->damage_ |= fl; | ||||
} else { | } else { | ||||
// create a new region: | // create a new region: | ||||
if (i->region) XDestroyRegion(i->region); | |||||
i->region = XRectangleRegion(X,Y,W,H); | |||||
if (i->region) delete i->region; | |||||
i->region = new Fl_Rectangle(X,Y,W,H); | |||||
wi->damage_ = fl; | wi->damage_ = fl; | ||||
} | } | ||||
Fl::damage(FL_DAMAGE_CHILD); | Fl::damage(FL_DAMAGE_CHILD); | ||||
} | } | ||||
void Fl_Window::flush() { | void Fl_Window::flush() { | ||||
make_current(); | |||||
//if (damage() == FL_DAMAGE_EXPOSE && can_boxcheat(box())) fl_boxcheat = this; | |||||
/* FIXME: shouldn't this destroy the region? */ | |||||
fl_clip_region(i->region); i->region = 0; | |||||
cairo_surface_flush( i->cs ); | |||||
if ( ! i->cc ) | |||||
{ | |||||
i->cs = Fl::cairo_create_surface( i->xid, w(), h() ); | |||||
i->cc = cairo_create( i->cs ); | |||||
Fl::cairo_make_current( i->cs, i->cc ); | |||||
} | |||||
draw(); | draw(); | ||||
#if FLTK_HAVE_CAIRO | |||||
cairo_surface_flush( i->cs ); | |||||
#endif | |||||
} | } | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
@@ -53,48 +53,20 @@ cairo_surface_t * cairo_create_surface(void * gc, Window w, int W, int H) { | |||||
cairo_surface_t *fl_cairo_surface; | cairo_surface_t *fl_cairo_surface; | ||||
cairo_t *fl_cairo_context; | cairo_t *fl_cairo_context; | ||||
static Window real_xid; | |||||
static int W, H; | |||||
cairo_t * | |||||
Fl::cairo_make_current(Fl_Window* wi, Window w ) { | |||||
if (!wi) return NULL; // Precondition | |||||
if ( ! w ) | |||||
w = wi->i->other_xid ? wi->i->other_xid : wi->i->xid; | |||||
if ( ( fl_cairo_context && fl_cairo_context == wi->i->cc ) && | |||||
w && w == real_xid && | |||||
wi->w() == W && wi->h() == H ) | |||||
/* already current */ | |||||
return wi->i->cc; | |||||
real_xid = w; | |||||
W = wi->w(); | |||||
H = wi->h(); | |||||
if ( wi->i->cs ) | |||||
{ | |||||
cairo_xlib_surface_set_drawable( wi->i->cs, w, wi->w(), wi->h() ); | |||||
cairo_destroy( wi->i->cc ); | |||||
wi->i->cc = 0; | |||||
} | |||||
else | |||||
{ | |||||
wi->i->cs = cairo_create_surface(fl_gc, w, wi->w(), wi->h()); | |||||
} | |||||
cairo_surface_t * | |||||
Fl::cairo_create_surface ( Window xid, int W, int H ) | |||||
{ | |||||
return ::cairo_create_surface( fl_gc, xid, W, H ); | |||||
} | |||||
if ( ! wi->i->cc ) | |||||
{ | |||||
/* set this window's context to be the current one */ | |||||
wi->i->cc = cairo_create( wi->i->cs ); | |||||
} | |||||
cairo_t * | |||||
Fl::cairo_make_current( cairo_surface_t *cs, cairo_t *cc ) { | |||||
fl_cairo_surface = wi->i->cs; | |||||
fl_cairo_context = wi->i->cc; | |||||
fl_cairo_surface = cs; | |||||
fl_cairo_context = cc; | |||||
printf( "NTK: cairo_make_current()\n" ); | |||||
return wi->i->cc; | |||||
return cc; | |||||
} | } | ||||
#endif // FLTK_HAVE_CAIRO | #endif // FLTK_HAVE_CAIRO | ||||
@@ -132,28 +132,6 @@ Fl_Cairo_Graphics_Driver::Fl_Cairo_Graphics_Driver ( ) : Fl_Xlib_Graphics_Driv | |||||
/* fl_cairo_surface = 0; */ | /* fl_cairo_surface = 0; */ | ||||
/* } */ | /* } */ | ||||
void Fl_Cairo_Graphics_Driver::restore_clip ( void ) | |||||
{ | |||||
cairo_t *cr = Fl::cairo_cc(); | |||||
if ( ! cr ) | |||||
return; | |||||
Fl_Xlib_Graphics_Driver::restore_clip(); | |||||
cairo_reset_clip( cr ); | |||||
Fl_Region r = clip_region(); | |||||
if ( r ) | |||||
{ | |||||
XRectangle rect; | |||||
XClipBox(r, &rect); | |||||
cairo_rectangle( cr, rect.x, rect.y, rect.width, rect.height ); | |||||
cairo_clip( cr ); | |||||
} | |||||
} | |||||
void Fl_Cairo_Graphics_Driver::line_style ( int style, int t, char* ) | void Fl_Cairo_Graphics_Driver::line_style ( int style, int t, char* ) | ||||
{ | { | ||||
@@ -32,6 +32,10 @@ | |||||
#include <FL/x.H> | #include <FL/x.H> | ||||
#include <FL/fl_draw.H> | #include <FL/fl_draw.H> | ||||
#include <FL/Fl_Cairo.H> | |||||
//#define DEBUG_EXPOSE | |||||
// On systems that support double buffering "naturally" the base | // On systems that support double buffering "naturally" the base | ||||
// Fl_Window class will probably do double-buffer and this subclass | // Fl_Window class will probably do double-buffer and this subclass | ||||
// does nothing. | // does nothing. | ||||
@@ -305,8 +309,8 @@ void Fl_Double_Window::flush() {flush(0);} | |||||
and leaving the clip region set to the entire window. | and leaving the clip region set to the entire window. | ||||
*/ | */ | ||||
void Fl_Double_Window::flush(int eraseoverlay) { | void Fl_Double_Window::flush(int eraseoverlay) { | ||||
//make_current(); // make sure fl_gc is non-zero | |||||
Fl_X *myi = Fl_X::i(this); | Fl_X *myi = Fl_X::i(this); | ||||
if (!myi->other_xid) { | if (!myi->other_xid) { | ||||
#if defined(USE_X11) || defined(WIN32) | #if defined(USE_X11) || defined(WIN32) | ||||
@@ -318,20 +322,20 @@ void Fl_Double_Window::flush(int eraseoverlay) { | |||||
clear_damage(FL_DAMAGE_ALL); | clear_damage(FL_DAMAGE_ALL); | ||||
} | } | ||||
#else | #else | ||||
# error unsupported platform | # error unsupported platform | ||||
#endif | #endif | ||||
myi->other_cs = Fl::cairo_create_surface( myi->other_xid, w(), h() ); | |||||
myi->other_cc = cairo_create( myi->other_cs ); | |||||
#if FLTK_HAVE_CAIRO | |||||
Fl::cairo_make_current( this ); | |||||
#endif | |||||
} | } | ||||
fl_clip_region(myi->region); | fl_clip_region(myi->region); | ||||
if (damage() & ~FL_DAMAGE_EXPOSE) { | if (damage() & ~FL_DAMAGE_EXPOSE) { | ||||
Fl::cairo_make_current( myi->other_cs, myi->other_cc ); | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
HDC _sgc = fl_gc; | HDC _sgc = fl_gc; | ||||
fl_gc = fl_makeDC(myi->other_xid); | fl_gc = fl_makeDC(myi->other_xid); | ||||
@@ -354,30 +358,46 @@ void Fl_Double_Window::flush(int eraseoverlay) { | |||||
#else // X: | #else // X: | ||||
fl_window = myi->other_xid; | fl_window = myi->other_xid; | ||||
// fl_restore_clip(); | |||||
fl_clip_region(myi->region); | fl_clip_region(myi->region); | ||||
draw(); | draw(); | ||||
#if FLTK_HAVE_CAIRO | #if FLTK_HAVE_CAIRO | ||||
cairo_surface_flush( myi->cs ); | |||||
cairo_surface_flush( myi->other_cs ); | |||||
#endif | #endif | ||||
fl_window = myi->xid; | fl_window = myi->xid; | ||||
#if FLTK_HAVE_CAIRO | |||||
Fl::cairo_make_current( myi->cs, myi->cc ); | |||||
#endif | |||||
// fl_restore_clip(); | |||||
fl_clip_region(myi->region); | fl_clip_region(myi->region); | ||||
#endif | #endif | ||||
} | } | ||||
if (eraseoverlay) fl_clip_region(0); | |||||
// on Irix (at least) it is faster to reduce the area copied to | |||||
// the current clip region: | |||||
if (eraseoverlay) | |||||
{ | { | ||||
int X,Y,W,H; fl_clip_box(0,0,w(),h(),X,Y,W,H); | |||||
if (myi->other_xid) fl_copy_offscreen(X, Y, W, H, myi->other_xid, X, Y); | |||||
fl_clip_region(0); | |||||
} | } | ||||
myi->region = 0; | |||||
// on Irix (at least) it is faster to reduce the area copied to | |||||
// the current clip region: | |||||
int X,Y,W,H; fl_clip_box(0,0,w(),h(),X,Y,W,H); | |||||
if (myi->other_xid) fl_copy_offscreen(X, Y, W, H, myi->other_xid, X, Y); | |||||
#ifdef DEBUG_EXPOSE | |||||
if ( damage() & FL_DAMAGE_EXPOSE ) | |||||
{ | |||||
#if FLTK_HAVE_CAIRO | |||||
fl_rectf( 0,0, w(), h(), fl_color_add_alpha( FL_RED, 50 )); | |||||
#endif | |||||
} | |||||
#endif | |||||
} | } | ||||
void Fl_Double_Window::resize(int X,int Y,int W,int H) { | void Fl_Double_Window::resize(int X,int Y,int W,int H) { | ||||
@@ -386,6 +406,13 @@ void Fl_Double_Window::resize(int X,int Y,int W,int H) { | |||||
Fl_Window::resize(X,Y,W,H); | Fl_Window::resize(X,Y,W,H); | ||||
Fl_X* myi = Fl_X::i(this); | Fl_X* myi = Fl_X::i(this); | ||||
if (myi && myi->other_xid && (ow != w() || oh != h())) { | if (myi && myi->other_xid && (ow != w() || oh != h())) { | ||||
#if FLTK_HAVE_CAIRO | |||||
if ( myi->other_cs ) | |||||
{ | |||||
cairo_destroy( myi->other_cc ); myi->other_cc = 0; | |||||
cairo_surface_destroy( myi->other_cs ); myi->other_cs = 0; | |||||
} | |||||
#endif | |||||
fl_delete_offscreen(myi->other_xid); | fl_delete_offscreen(myi->other_xid); | ||||
myi->other_xid = 0; | myi->other_xid = 0; | ||||
} | } | ||||
@@ -394,6 +421,13 @@ void Fl_Double_Window::resize(int X,int Y,int W,int H) { | |||||
void Fl_Double_Window::hide() { | void Fl_Double_Window::hide() { | ||||
Fl_X* myi = Fl_X::i(this); | Fl_X* myi = Fl_X::i(this); | ||||
if (myi && myi->other_xid) { | if (myi && myi->other_xid) { | ||||
#if FLTK_HAVE_CAIRO | |||||
if ( myi->other_cs ) | |||||
{ | |||||
cairo_destroy( myi->other_cc ); myi->other_cc = 0; | |||||
cairo_surface_destroy( myi->other_cs ); myi->other_cs = 0; | |||||
} | |||||
#endif | |||||
fl_delete_offscreen(myi->other_xid); | fl_delete_offscreen(myi->other_xid); | ||||
myi->other_xid = 0; | myi->other_xid = 0; | ||||
} | } | ||||
@@ -755,8 +755,8 @@ void Fl_Group::draw() { | |||||
\sa Fl_Group::draw_child(Fl_Widget& widget) const | \sa Fl_Group::draw_child(Fl_Widget& widget) const | ||||
*/ | */ | ||||
void Fl_Group::update_child(Fl_Widget& widget) const { | void Fl_Group::update_child(Fl_Widget& widget) const { | ||||
if (widget.damage() && widget.visible() && widget.type() < FL_WINDOW && | |||||
fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) { | |||||
if (widget.damage() && widget.visible() && widget.type() < FL_WINDOW && | |||||
fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) { | |||||
widget.draw(); | widget.draw(); | ||||
widget.clear_damage(); | widget.clear_damage(); | ||||
} | } | ||||
@@ -769,7 +769,7 @@ void Fl_Group::update_child(Fl_Widget& widget) const { | |||||
The damage bits are cleared after drawing. | The damage bits are cleared after drawing. | ||||
*/ | */ | ||||
void Fl_Group::draw_child(Fl_Widget& widget) const { | void Fl_Group::draw_child(Fl_Widget& widget) const { | ||||
if (widget.visible() && widget.type() < FL_WINDOW && | |||||
if (widget.visible() && widget.type() < FL_WINDOW && | |||||
fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) { | fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) { | ||||
widget.clear_damage(FL_DAMAGE_ALL); | widget.clear_damage(FL_DAMAGE_ALL); | ||||
widget.draw(); | widget.draw(); | ||||
@@ -41,18 +41,18 @@ | |||||
#include <stdio.h> | #include <stdio.h> | ||||
void Fl_Menu_Window::show() { | void Fl_Menu_Window::show() { | ||||
Fl_Double_Window::show(); | |||||
Fl_Single_Window::show(); | |||||
} | } | ||||
void Fl_Menu_Window::flush() { | void Fl_Menu_Window::flush() { | ||||
Fl_Double_Window::flush(); | |||||
Fl_Single_Window::flush(); | |||||
} | } | ||||
// Fix the colormap flashing on Maximum Impact Graphics by erasing the | // Fix the colormap flashing on Maximum Impact Graphics by erasing the | ||||
// menu before unmapping it: | // menu before unmapping it: | ||||
void Fl_Menu_Window::hide() { | void Fl_Menu_Window::hide() { | ||||
// erase(); | // erase(); | ||||
Fl_Double_Window::hide(); | |||||
Fl_Single_Window::hide(); | |||||
} | } | ||||
/** Destroys the window and all of its children.*/ | /** Destroys the window and all of its children.*/ | ||||
@@ -56,13 +56,7 @@ void Fl_Overlay_Window::flush() { | |||||
clear_damage((uchar)(damage()&~FL_DAMAGE_OVERLAY)); | clear_damage((uchar)(damage()&~FL_DAMAGE_OVERLAY)); | ||||
Fl_Double_Window::flush(erase_overlay); | Fl_Double_Window::flush(erase_overlay); | ||||
Fl_X* myi = Fl_X::i(this); | Fl_X* myi = Fl_X::i(this); | ||||
#if FLTK_HAVE_CAIRO | |||||
Fl::cairo_make_current( this, myi->xid ); | |||||
#endif | |||||
draw_overlay(); | |||||
#if FLTK_HAVE_CAIRO | |||||
Fl::cairo_make_current( this, myi->other_xid ); | |||||
#endif | |||||
draw_overlay(); | |||||
} | } | ||||
/** | /** | ||||
@@ -0,0 +1,108 @@ | |||||
// "$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()); | |||||
} | |||||
@@ -66,7 +66,7 @@ void Fl_Valuator::precision(int p) { | |||||
for (B = 1; p--;) B *= 10; | for (B = 1; p--;) B *= 10; | ||||
} | } | ||||
/** Asks for partial redraw */ | /** Asks for partial redraw */ | ||||
void Fl_Valuator::value_damage() {damage(FL_DAMAGE_EXPOSE);} // by default do partial-redraw | |||||
void Fl_Valuator::value_damage() {damage(FL_DAMAGE_USER1);} // by default do partial-redraw | |||||
/** | /** | ||||
Sets the current value. The new value is <I>not</I> | Sets the current value. The new value is <I>not</I> | ||||
@@ -38,9 +38,7 @@ | |||||
#include <FL/Fl_Cairo.H> | #include <FL/Fl_Cairo.H> | ||||
#ifdef __APPLE_QUARTZ__ | |||||
#include <FL/fl_draw.H> | #include <FL/fl_draw.H> | ||||
#endif | |||||
char *Fl_Window::default_xclass_ = 0L; | char *Fl_Window::default_xclass_ = 0L; | ||||
@@ -113,14 +111,6 @@ void Fl_Window::draw() { | |||||
} | } | ||||
draw_children(); | draw_children(); | ||||
#if FLTK_HAVE_CAIRO | |||||
cairo_surface_flush( i->cs ); | |||||
#endif | |||||
#ifdef __APPLE_QUARTZ__ | |||||
// on OS X, windows have no frame. To resize a window, we drag the lower right | |||||
// corner. This code draws a little ribbed triangle for dragging. | |||||
extern CGContextRef fl_gc; | |||||
if (fl_gc && !parent() && resizable() && (!size_range_set || minh!=maxh || minw!=maxw)) { | if (fl_gc && !parent() && resizable() && (!size_range_set || minh!=maxh || minw!=maxw)) { | ||||
int dx = Fl::box_dw(box())-Fl::box_dx(box()); | int dx = Fl::box_dw(box())-Fl::box_dx(box()); | ||||
int dy = Fl::box_dh(box())-Fl::box_dy(box()); | int dy = Fl::box_dh(box())-Fl::box_dy(box()); | ||||
@@ -139,7 +129,6 @@ void Fl_Window::draw() { | |||||
fl_line(x1--, y1, x2, y2--); | fl_line(x1--, y1, x2, y2--); | ||||
} | } | ||||
} | } | ||||
#endif | |||||
} | } | ||||
void Fl_Window::label(const char *name) { | void Fl_Window::label(const char *name) { | ||||
@@ -1665,6 +1665,9 @@ void Fl_Window::resize(int X,int Y,int W,int H) { | |||||
} else | } else | ||||
XMoveWindow(fl_display, i->xid, X, Y); | XMoveWindow(fl_display, i->xid, X, Y); | ||||
} | } | ||||
if ( is_a_resize && i ) | |||||
i->cairo_surface_invalid = 1; | |||||
} | } | ||||
//////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////// | ||||
@@ -1679,14 +1682,16 @@ Fl_X* Fl_X::set_xid(Fl_Window* win, Window winxid) { | |||||
xp->xid = winxid; | xp->xid = winxid; | ||||
xp->other_xid = 0; | xp->other_xid = 0; | ||||
#if FLTK_HAVE_CAIRO | #if FLTK_HAVE_CAIRO | ||||
xp->cc = 0; | |||||
xp->cs = 0; | |||||
xp->cs = Fl::cairo_create_surface( winxid, win->w(), win->h() ); | |||||
xp->cc = cairo_create( xp->cs ); | |||||
xp->cairo_surface_invalid = 0; | |||||
xp->other_cc = 0; | |||||
xp->other_cs = 0; | |||||
#endif | #endif | ||||
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 = 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();} | ||||
return xp; | return xp; | ||||
@@ -2038,12 +2043,23 @@ void Fl_Window::make_current() { | |||||
if (!gc) gc = XCreateGC(fl_display, i->xid, 0, 0); | if (!gc) gc = XCreateGC(fl_display, i->xid, 0, 0); | ||||
fl_window = i->xid; | fl_window = i->xid; | ||||
fl_gc = gc; | fl_gc = gc; | ||||
current_ = this; | |||||
fl_clip_region(0); | |||||
#ifdef FLTK_HAVE_CAIRO | #ifdef FLTK_HAVE_CAIRO | ||||
Fl::cairo_make_current(this); | |||||
if ( i->cairo_surface_invalid && i->cc ) | |||||
{ | |||||
cairo_destroy( i->cc ); i->cc = 0; | |||||
cairo_surface_destroy( i->cs ); i->cs = 0; | |||||
} | |||||
if ( ! i->cc ) | |||||
{ | |||||
i->cs = Fl::cairo_create_surface( i->xid, w(), h() ); | |||||
i->cc = cairo_create( i->cs ); | |||||
} | |||||
Fl::cairo_make_current( i->cs, i->cc ); | |||||
#endif | #endif | ||||
current_ = this; | |||||
fl_clip_region(i->region); | |||||
} | } | ||||
Window fl_xid_(const Fl_Window *w) { | Window fl_xid_(const Fl_Window *w) { | ||||
@@ -170,6 +170,7 @@ 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,6 +113,8 @@ 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 ); | |||||
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 | ||||
driver->Fl_Graphics_Driver::font(0, 0); | driver->Fl_Graphics_Driver::font(0, 0); | ||||
@@ -599,8 +601,14 @@ void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) { | |||||
else //if (draw_window != fl_window) | else //if (draw_window != fl_window) | ||||
XftDrawChange(draw_, draw_window = fl_window); | XftDrawChange(draw_, draw_window = fl_window); | ||||
Region region = fl_clip_region(); | |||||
if (region && XEmptyRegion(region)) return; | |||||
Region region = XRegionFromRectangle( fl_clip_region() ); | |||||
if (region && XEmptyRegion(region)) | |||||
{ | |||||
XDestroyRegion( region ); | |||||
return; | |||||
} | |||||
XftDrawSetClip(draw_, region); | XftDrawSetClip(draw_, region); | ||||
// Use fltk's color allocator, copy the results to match what | // Use fltk's color allocator, copy the results to match what | ||||
@@ -619,6 +627,8 @@ void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) { | |||||
#else | #else | ||||
XftDrawString32(draw_, &color, font_descriptor()->font, x, y, (XftChar32 *)buffer, n); | XftDrawString32(draw_, &color, font_descriptor()->font, x, y, (XftChar32 *)buffer, n); | ||||
#endif | #endif | ||||
if ( region ) XDestroyRegion( region ); | |||||
} | } | ||||
void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) { | void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) { | ||||
@@ -644,8 +654,15 @@ static void fl_drawUCS4(Fl_Graphics_Driver *driver, const FcChar32 *str, int n, | |||||
else //if (draw_window != fl_window) | else //if (draw_window != fl_window) | ||||
XftDrawChange(draw_, draw_window = fl_window); | XftDrawChange(draw_, draw_window = fl_window); | ||||
Region region = fl_clip_region(); | |||||
if (region && XEmptyRegion(region)) return; | |||||
Region region = XRegionFromRectangle( fl_clip_region() ); | |||||
if (region && XEmptyRegion(region)) | |||||
{ | |||||
XDestroyRegion( region ); | |||||
return; | |||||
} | |||||
XftDrawSetClip(draw_, region); | XftDrawSetClip(draw_, region); | ||||
// Use fltk's color allocator, copy the results to match what | // Use fltk's color allocator, copy the results to match what | ||||
@@ -659,6 +676,8 @@ static void fl_drawUCS4(Fl_Graphics_Driver *driver, const FcChar32 *str, int n, | |||||
color.color.alpha = 0xffff; | color.color.alpha = 0xffff; | ||||
XftDrawString32(draw_, &color, driver->font_descriptor()->font, x, y, (FcChar32 *)str, n); | XftDrawString32(draw_, &color, driver->font_descriptor()->font, x, y, (FcChar32 *)str, n); | ||||
if ( region ) XDestroyRegion( region ); | |||||
} | } | ||||
@@ -511,18 +511,33 @@ void Fl_Graphics_Driver::point(int x, int y) { | |||||
#endif | #endif | ||||
} | } | ||||
Region XRegionFromRectangle ( Fl_Rectangle *rg ) | |||||
{ | |||||
if ( rg ) | |||||
{ | |||||
Region region = XCreateRegion(); | |||||
XRectangle rr; | |||||
rr.x = rg->x(); | |||||
rr.y = rg->y(); | |||||
rr.width = rg->w(); | |||||
rr.height = rg->h(); | |||||
XUnionRectWithRegion( &rr, region, region ); | |||||
return region; | |||||
} | |||||
return 0; | |||||
} | |||||
//////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////// | ||||
#if !defined(WIN32) && !defined(__APPLE__) | #if !defined(WIN32) && !defined(__APPLE__) | ||||
// 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) { | ||||
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; | |||||
return new Fl_Rectangle( x, y, w, h ); | |||||
} | } | ||||
#endif | #endif | ||||
@@ -530,8 +545,14 @@ 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) XSetRegion(fl_display, fl_gc, r); | |||||
else XSetClipMask(fl_display, fl_gc, 0); | |||||
if (r) | |||||
{ | |||||
Region xr = XRegionFromRectangle( r ); | |||||
XSetRegion(fl_display, fl_gc, xr ); | |||||
XDestroyRegion( xr ); | |||||
} | |||||
else | |||||
XSetClipMask(fl_display, fl_gc, 0); | |||||
#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__) | ||||
@@ -552,12 +573,32 @@ void Fl_Graphics_Driver::restore_clip() { | |||||
#else | #else | ||||
# error unsupported platform | # error unsupported platform | ||||
#endif | #endif | ||||
#if FLTK_HAVE_CAIRO | |||||
cairo_t *cr = fl_cairo_context; | |||||
if ( cr ) | |||||
{ | |||||
cairo_reset_clip( cr ); | |||||
if ( r ) | |||||
{ | |||||
// cairo_set_source_rgb( cr, 0, 1, 0 ); | |||||
cairo_rectangle( cr, r->x(), r->y(), r->w(), r->h() ); | |||||
// cairo_stroke_preserve( cr ); | |||||
cairo_clip( cr ); | |||||
} | |||||
} | |||||
#endif | |||||
} | } | ||||
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 ) XDestroyRegion(oldr); | |||||
rstack[rstackptr] = r; | |||||
if (oldr && r != oldr ) delete oldr; | |||||
rstack[rstackptr] = r ? new Fl_Rectangle( *r ) : 0; | |||||
fl_restore_clip(); | fl_restore_clip(); | ||||
} | } | ||||
@@ -568,14 +609,16 @@ 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 = XRectangleRegion(x,y,w,h); | |||||
r = new Fl_Rectangle( 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) | ||||
Fl_Region temp = XCreateRegion(); | |||||
XIntersectRegion(current, r, temp); | |||||
XDestroyRegion(r); | |||||
r = temp; | |||||
r->intersect( *current ); | |||||
if ( r->empty() ) | |||||
{ | |||||
delete r; | |||||
r = new Fl_Rectangle( 0, 0, 0, 0 ); | |||||
} | |||||
#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__) | ||||
@@ -587,7 +630,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 = XCreateRegion(); | |||||
r = new Fl_Rectangle( 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__) | ||||
@@ -612,7 +655,7 @@ 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) XDestroyRegion(oldr); | |||||
if (oldr) delete oldr; | |||||
} 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(); | ||||
} | } | ||||
@@ -623,8 +666,8 @@ 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 XRectInRegion(r, x, y, w, h); | |||||
// if (clip_to_short(x,y,w,h)) return 0; // clipped | |||||
return r->intersects( Fl_Rectangle( x, y, w, h ) ); | |||||
#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 | ||||
@@ -652,25 +695,32 @@ 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) | |||||
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_Rectangle rec( x, y, w, h ); | |||||
rec.intersect( *r ); | |||||
X = rec.x(); Y = rec.y(); W = rec.w(); H = rec.h(); | |||||
if ( r->contains( x, y ) && r->contains( x + w - 1, y + h - 1 ) ) | |||||
{ | |||||
/* completely inside */ | |||||
return 0; | |||||
} | } | ||||
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); | |||||
if ( rec.empty() ) | |||||
{ | |||||
H = W = 0; | |||||
/* completely outside */ | |||||
return 2; | |||||
} | |||||
/* partial */ | |||||
return 1; | return 1; | ||||
#if defined(USE_X11) | |||||
#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 | ||||
// intersection, so we have to check for partial intersection ourselves. | // intersection, so we have to check for partial intersection ourselves. | ||||