@ -1,7 +1,7 @@
@@ -1,7 +1,7 @@
//
// "$Id$"
//
// Fl_Shaped_Window source file for the Fast Light Tool Kit (FLTK).
// implementation of Fl_Window::shape(Fl_Image*) for the Fast Light Tool Kit (FLTK).
//
// Copyright 2010-2014 by Bill Spitzak and others.
//
@ -16,10 +16,13 @@
@@ -16,10 +16,13 @@
// http://www.fltk.org/str.php
//
# include <FL/Fl.H>
# include <FL/fl_draw.H>
# include <FL/x.H>
# include <FL/Fl_Shaped_Window.H>
# include <FL/Fl_Window.H>
# include <FL/Fl_Bitmap.H>
# include <FL/Fl_Pixmap.H>
# include <string.h>
# ifdef WIN32
# include <malloc.h> // needed for VisualC2010
@ -29,36 +32,6 @@
@@ -29,36 +32,6 @@
# define ShapeSet 0
# endif
/** Create a shaped window with the given size and title */
Fl_Shaped_Window : : Fl_Shaped_Window ( int w , int h , const char * title )
: Fl_Window ( w , h , title ) , lw_ ( 0 ) , lh_ ( 0 ) , shape_ ( 0 ) , todelete_ ( 0 ) {
type ( FL_SHAPED_WINDOW ) ;
border ( false ) ;
# if defined(__APPLE__)
mask = NULL ;
# endif
}
/** Create a shaped window with the given position, size and title */
Fl_Shaped_Window : : Fl_Shaped_Window ( int x , int y , int w , int h , const char * title )
: Fl_Window ( x , y , w , h , title ) , lw_ ( 0 ) , lh_ ( 0 ) , shape_ ( 0 ) , todelete_ ( 0 ) {
type ( FL_SHAPED_WINDOW ) ;
border ( false ) ;
# if defined(__APPLE__)
mask = NULL ;
# endif
}
/** Destroys the shaped window but not its associated Fl_Image */
Fl_Shaped_Window : : ~ Fl_Shaped_Window ( ) {
if ( todelete_ ) delete todelete_ ;
# if defined(__APPLE__)
if ( mask ) {
CGImageRelease ( mask ) ;
}
# endif
}
# if defined(__APPLE__)
@ -74,17 +47,6 @@ static inline uchar swap_byte(const uchar b) {
@@ -74,17 +47,6 @@ static inline uchar swap_byte(const uchar b) {
return ( swapped [ b & 0xF ] < < 4 ) | swapped [ b > > 4 ] ;
}
void Fl_Shaped_Window : : draw ( ) {
# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
if ( mask & & ( CGContextClipToMask ! = NULL ) ) CGContextClipToMask ( fl_gc , CGRectMake ( 0 , 0 , w ( ) , h ( ) ) , mask ) ; // requires Mac OS 10.4
CGContextSaveGState ( fl_gc ) ;
# endif
Fl_Window : : draw ( ) ;
# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
CGContextRestoreGState ( fl_gc ) ;
# endif
}
# elif defined(WIN32)
static inline BYTE bit ( int x ) { return ( BYTE ) ( 1 < < ( x % 8 ) ) ; }
@ -165,24 +127,10 @@ static HRGN bitmap2region(Fl_Bitmap* image) {
@@ -165,24 +127,10 @@ static HRGN bitmap2region(Fl_Bitmap* image) {
return hRgn ;
}
void Fl_Shaped_Window : : draw ( ) {
if ( ( lw_ ! = w ( ) | | lh_ ! = h ( ) ) & & shape_ ) {
// size of window has changed since last time
lw_ = w ( ) ;
lh_ = h ( ) ;
Fl_Bitmap * temp = ( Fl_Bitmap * ) shape_ - > copy ( lw_ , lh_ ) ;
HRGN region = bitmap2region ( temp ) ;
SetWindowRgn ( fl_xid ( this ) , region , TRUE ) ; // the system deletes the region when it's no longer needed
delete temp ;
}
Fl_Window : : draw ( ) ;
}
# else
# ifndef FL_DOXYGEN
void Fl_Shaped_ Window : : combine_mask ( )
void Fl_Window : : combine_mask ( )
{
typedef void ( * XShapeCombineMask_type ) ( Display * , int , int , int , int , Pixmap , int ) ;
static XShapeCombineMask_type XShapeCombineMask_f = NULL ;
@ -200,9 +148,9 @@ void Fl_Shaped_Window::combine_mask()
@@ -200,9 +148,9 @@ void Fl_Shaped_Window::combine_mask()
XShapeQueryExtension_f ( fl_display , & shapeEventBase , & error_base ) ) ) XShapeCombineMask_f = NULL ;
}
if ( ! XShapeCombineMask_f ) return ;
lw_ = w ( ) ;
lh_ = h ( ) ;
Fl_Bitmap * temp = ( Fl_Bitmap * ) shape_ - > copy ( lw_ , lh_ ) ;
shape_data_ - > lw_ = w ( ) ;
shape_data_ - > lh_ = h ( ) ;
Fl_Bitmap * temp = ( Fl_Bitmap * ) shape_data_ - > shape_ - > copy ( shape_data_ - > lw_ , shape_data_ - > lh_ ) ;
Pixmap pbitmap = XCreateBitmapFromData ( fl_display , fl_xid ( this ) ,
( const char * ) temp - > array ,
temp - > w ( ) , temp - > h ( ) ) ;
@ -212,26 +160,12 @@ void Fl_Shaped_Window::combine_mask()
@@ -212,26 +160,12 @@ void Fl_Shaped_Window::combine_mask()
}
# endif // !FL_DOXYGEN
void Fl_Shaped_Window : : draw ( ) {
if ( ( lw_ ! = w ( ) | | lh_ ! = h ( ) ) & & shape_ ) {
// size of window has changed since last time
combine_mask ( ) ;
}
Fl_Window : : draw ( ) ;
}
# endif // __APPLE__
void Fl_Shaped_Window : : shape_bitmap_ ( Fl_Bitmap * b ) {
if ( todelete_ ) { delete todelete_ ; todelete_ = NULL ; }
shape_ = b ;
lw_ = lh_ = 0 ; // so change in mask is detected
void Fl_Window : : shape_bitmap_ ( Fl_Bitmap * b ) {
shape_data_ - > shape_ = b ;
# if defined(__APPLE__)
if ( mask ) {
CGImageRelease ( mask ) ;
mask = NULL ;
}
if ( b ) {
// complement mask bits and perform bitwise inversion of all bytes and also reverse top and bottom
int bytes_per_row = ( b - > w ( ) + 7 ) / 8 ;
@ -245,7 +179,7 @@ void Fl_Shaped_Window::shape_bitmap_(Fl_Bitmap* b) {
@@ -245,7 +179,7 @@ void Fl_Shaped_Window::shape_bitmap_(Fl_Bitmap* b) {
}
}
CGDataProviderRef provider = CGDataProviderCreateWithData ( NULL , from , bytes_per_row * b - > h ( ) , MyProviderReleaseData ) ;
mask = CGImageMaskCreate ( b - > w ( ) , b - > h ( ) , 1 , 1 , bytes_per_row , provider , NULL , false ) ;
shape_data_ - > mask = CGImageMaskCreate ( b - > w ( ) , b - > h ( ) , 1 , 1 , bytes_per_row , provider , NULL , false ) ;
CFRelease ( provider ) ;
}
# endif
@ -256,16 +190,10 @@ void Fl_Shaped_Window::shape_bitmap_(Fl_Bitmap* b) {
@@ -256,16 +190,10 @@ void Fl_Shaped_Window::shape_bitmap_(Fl_Bitmap* b) {
/* the image can be of any depth
offset gives the byte offset from the pixel start to the byte used to construct the shape
*/
void Fl_Shaped_ Window : : shape_alpha_ ( Fl_RGB_Image * img , int offset ) {
void Fl_Window : : shape_alpha_ ( Fl_RGB_Image * img , int offset ) {
int i , d = img - > d ( ) , w = img - > w ( ) , h = img - > h ( ) ;
if ( todelete_ ) { delete todelete_ ; todelete_ = NULL ; }
shape_ = img ;
lw_ = lh_ = 0 ; // so change in mask is detected
if ( mask ) {
CGImageRelease ( mask ) ;
mask = NULL ;
}
if ( shape_ ) {
shape_data_ - > shape_ = img ;
if ( shape_data_ - > shape_ ) {
// reverse top and bottom and convert to gray scale if img->d() == 3 and complement bits
int bytes_per_row = w * d ;
uchar * from = new uchar [ w * h ] ;
@ -287,7 +215,7 @@ void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
@@ -287,7 +215,7 @@ void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
}
}
CGDataProviderRef provider = CGDataProviderCreateWithData ( NULL , from , w * h , MyProviderReleaseData ) ;
mask = CGImageMaskCreate ( w , h , 8 , 8 , w , provider , NULL , false ) ;
shape_data_ - > mask = CGImageMaskCreate ( w , h , 8 , 8 , w , provider , NULL , false ) ;
CFRelease ( provider ) ;
}
}
@ -297,7 +225,7 @@ void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
@@ -297,7 +225,7 @@ void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
/* the img image can be of any depth
offset gives the byte offset from the pixel start to the byte used to construct the shape
*/
void Fl_Shaped_ Window : : shape_alpha_ ( Fl_RGB_Image * img , int offset ) {
void Fl_Window : : shape_alpha_ ( Fl_RGB_Image * img , int offset ) {
int i , j , d = img - > d ( ) , w = img - > w ( ) , h = img - > h ( ) , bytesperrow = ( w + 7 ) / 8 ;
unsigned u ;
uchar byte , onebit ;
@ -330,19 +258,41 @@ void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
@@ -330,19 +258,41 @@ void Fl_Shaped_Window::shape_alpha_(Fl_RGB_Image* img, int offset) {
Fl_Bitmap * bitmap = new Fl_Bitmap ( bits , w , h ) ;
bitmap - > alloc_array = 1 ;
shape_bitmap_ ( bitmap ) ;
todelete_ = bitmap ;
shape_data_ - > todelete_ = bitmap ;
}
# endif
void Fl_Shaped_ Window : : shape_pixmap_ ( Fl_Pixmap * pixmap ) {
void Fl_Window : : shape_pixmap_ ( Fl_Pixmap * pixmap ) {
Fl_RGB_Image * rgba = new Fl_RGB_Image ( pixmap ) ;
shape_alpha_ ( rgba , 3 ) ;
delete rgba ;
}
/** Set the window's shape with an image.
# if FLTK_ABI_VERSION < 10303 && !defined(FL_DOXYGEN)
shape_data_type * Fl_Window : : shape_data_ = NULL ;
# endif
/** Assigns a non-rectangular shape to the window.
This function gives an arbitrary shape ( not just a rectangular region ) to an Fl_Window .
An Fl_Image of any dimension can be used as mask ; it is rescaled to the window ' s dimension as needed .
The layout and widgets inside are unaware of the mask shape , and most will act as though the window ' s
rectangular bounding box is available
to them . It is up to you to make sure they adhere to the bounds of their masking shape .
Platform details :
\ li On the unix / linux platform , the SHAPE extension of the X server is required .
This function does control the shape of Fl_GL_Window instances .
\ li On the MSWindows platform , this function does nothing with class Fl_GL_Window .
\ li On the Mac platform , OS version 10.4 or above is required . This function does nothing with class Fl_GL_Window .
The window borders and caption created by the window system are turned off by default . They
can be re - enabled by calling void Fl_Window : : border ( 1 ) .
A usage example is found at example / shapedwindow . cxx .
The \ p img argument can be an Fl_Bitmap , Fl_Pixmap or Fl_RGB_Image .
\ li With Fl_Bitmap or Fl_Pixmap , the shaped window covers the image part where bitmap bits equal one ,
or where the pixmap is not fully transparent .
@ -355,14 +305,96 @@ void Fl_Shaped_Window::shape_pixmap_(Fl_Pixmap* pixmap) {
@@ -355,14 +305,96 @@ void Fl_Shaped_Window::shape_pixmap_(Fl_Pixmap* pixmap) {
are out of the shaped window ;
with depths 1 or 3 , white and black are in and out of the
shaped window , respectively , and other colors give intermediate masking scores .
\ version 1.3 .3 ( and requires compilation with - DFLTK_ABI_VERSION = 10303 )
*/
void Fl_Shaped_Window : : shape ( const Fl_Image * img ) {
void Fl_Window : : shape ( const Fl_Image * img ) {
# if FLTK_ABI_VERSION >= 10303
if ( shape_data_ ) {
if ( shape_data_ - > todelete_ ) { delete shape_data_ - > todelete_ ; }
# if defined(__APPLE__)
if ( shape_data_ - > mask ) { CGImageRelease ( shape_data_ - > mask ) ; }
# endif
}
else {
shape_data_ = new shape_data_type ;
}
memset ( shape_data_ , 0 , sizeof ( shape_data_type ) ) ;
border ( false ) ;
int d = img - > d ( ) ;
if ( d & & img - > count ( ) > = 2 ) shape_pixmap_ ( ( Fl_Pixmap * ) img ) ;
else if ( d = = 0 ) shape_bitmap_ ( ( Fl_Bitmap * ) img ) ;
else if ( d = = 2 | | d = = 4 ) shape_alpha_ ( ( Fl_RGB_Image * ) img , d - 1 ) ;
else if ( ( d = = 1 | | d = = 3 ) & & img - > count ( ) = = 1 ) shape_alpha_ ( ( Fl_RGB_Image * ) img , 0 ) ;
# endif
}
void Fl_Window : : draw ( ) {
if ( shape_data_ ) {
# if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
if ( shape_data_ - > mask & & ( CGContextClipToMask ! = NULL ) ) {
CGContextClipToMask ( fl_gc , CGRectMake ( 0 , 0 , w ( ) , h ( ) ) , shape_data_ - > mask ) ; // requires Mac OS 10.4
}
CGContextSaveGState ( fl_gc ) ;
# elif defined(WIN32)
if ( ( shape_data_ - > lw_ ! = w ( ) | | shape_data_ - > lh_ ! = h ( ) ) & & shape_data_ - > shape_ ) {
// size of window has changed since last time
shape_data_ - > lw_ = w ( ) ;
shape_data_ - > lh_ = h ( ) ;
Fl_Bitmap * temp = ( Fl_Bitmap * ) shape_data_ - > shape_ - > copy ( shape_data_ - > lw_ , shape_data_ - > lh_ ) ;
HRGN region = bitmap2region ( temp ) ;
SetWindowRgn ( fl_xid ( this ) , region , TRUE ) ; // the system deletes the region when it's no longer needed
delete temp ;
}
# elif !(defined(__APPLE__) || defined(WIN32))
if ( ( shape_data_ - > lw_ ! = w ( ) | | shape_data_ - > lh_ ! = h ( ) ) & & shape_data_ - > shape_ ) {
// size of window has changed since last time
combine_mask ( ) ;
}
# endif
}
// The following is similar to Fl_Group::draw(), but ...
// - we draw the box with x=0 and y=0 instead of x() and y()
// - we don't draw a label
if ( damage ( ) & ~ FL_DAMAGE_CHILD ) { // draw the entire thing
draw_box ( box ( ) , 0 , 0 , w ( ) , h ( ) , color ( ) ) ; // draw box with x/y = 0
}
draw_children ( ) ;
# ifdef __APPLE_QUARTZ__
// on OS X, windows have no frame. Before OS X 10.7, to resize a window, we drag the lower right
// corner. This code draws a little ribbed triangle for dragging.
if ( fl_mac_os_version < 100700 & & fl_gc & & ! parent ( ) & & resizable ( ) & &
( ! size_range_set | | minh ! = maxh | | minw ! = maxw ) ) {
int dx = Fl : : box_dw ( box ( ) ) - Fl : : box_dx ( box ( ) ) ;
int dy = Fl : : box_dh ( box ( ) ) - Fl : : box_dy ( box ( ) ) ;
if ( dx < = 0 ) dx = 1 ;
if ( dy < = 0 ) dy = 1 ;
int x1 = w ( ) - dx - 1 , x2 = x1 , y1 = h ( ) - dx - 1 , y2 = y1 ;
Fl_Color c [ 4 ] = {
color ( ) ,
fl_color_average ( color ( ) , FL_WHITE , 0.7f ) ,
fl_color_average ( color ( ) , FL_BLACK , 0.6f ) ,
fl_color_average ( color ( ) , FL_BLACK , 0.8f ) ,
} ;
int i ;
for ( i = dx ; i < 12 ; i + + ) {
fl_color ( c [ i & 3 ] ) ;
fl_line ( x1 - - , y1 , x2 , y2 - - ) ;
}
}
# endif
# if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
if ( shape_data_ ) CGContextRestoreGState ( fl_gc ) ;
# endif
# if defined(FLTK_USE_CAIRO)
Fl : : cairo_make_current ( this ) ; // checkout if an update is necessary
# endif
}
//
// End of "$Id$".