diff options
| author | Manolo Gouy <Manolo> | 2014-08-27 11:55:57 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2014-08-27 11:55:57 +0000 |
| commit | 8997131377a02004503c40ba2a96e6937bfd39c1 (patch) | |
| tree | 666c4f7d681f1a47f4f3d8372b20d6fc96d2b582 | |
| parent | 22beee52afd4e06e0f7fa2e19ce86e132b75730b (diff) | |
Added the Fl_Shaped_Window class to support windows of arbitrary shapes.
The new class is fully Doxygen-documented.
Added an example program (example/shapedwindow.cxx) that exercises the new class.
Modified all IDE-supporting files accordingly.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10255 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | FL/Fl_Shaped_Window.H | 78 | ||||
| -rw-r--r-- | FL/Fl_Window.H | 3 | ||||
| -rw-r--r-- | examples/shapedwindow.cxx | 125 | ||||
| -rw-r--r-- | ide/VisualC2008/fltk.lib.vcproj | 52 | ||||
| -rw-r--r-- | ide/VisualC2008/fltkdll.vcproj | 42 | ||||
| -rw-r--r-- | ide/VisualC2010/fltk.lib.vcxproj | 19 | ||||
| -rw-r--r-- | ide/VisualC2010/fltk.lib.vcxproj.filters | 4 | ||||
| -rw-r--r-- | ide/VisualC2010/fltkdll.vcxproj | 12 | ||||
| -rw-r--r-- | ide/VisualC6/fltk.dsp | 4 | ||||
| -rw-r--r-- | ide/VisualC6/fltkdll.dsp | 4 | ||||
| -rw-r--r-- | ide/Xcode3/FLTK.xcodeproj/project.pbxproj | 6 | ||||
| -rw-r--r-- | ide/Xcode4/FLTK.xcodeproj/project.pbxproj | 6 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/Fl_Shaped_Window.cxx | 369 | ||||
| -rw-r--r-- | src/Fl_cocoa.mm | 7 | ||||
| -rw-r--r-- | src/Fl_x.cxx | 6 | ||||
| -rw-r--r-- | src/Makefile | 1 |
17 files changed, 734 insertions, 5 deletions
diff --git a/FL/Fl_Shaped_Window.H b/FL/Fl_Shaped_Window.H new file mode 100644 index 000000000..af2cefc5a --- /dev/null +++ b/FL/Fl_Shaped_Window.H @@ -0,0 +1,78 @@ +// +// "$Id" +// +// Fl_Shaped_Window header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2014 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#ifndef Fl_Shaped_Window_H +#define Fl_Shaped_Window_H + +#include <FL/Fl_Window.H> +#if defined(__APPLE__) +#include <FL/x.H> +#endif + + +class Fl_Bitmap; +class Fl_Pixmap; + +/** + The Fl_Shaped_Window is an Fl_Window that can take an arbitrary shape (not just a rectangular region). + The window shape is determined by the argument of the Fl_Shaped_Window::shape(const Fl_Image*) + member function. + 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. + + On the Mac platform, OS version 10.4 or above is required. + On the unix/linux platform, the SHAPE extension of the X server is required. + + 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. + */ +class FL_EXPORT Fl_Shaped_Window : public Fl_Window { +private: + int lw_, lh_; + Fl_Image* shape_; +#if defined(__APPLE__) + CGImageRef mask; +#endif + Fl_Bitmap *todelete_; + void shape_bitmap_(Fl_Bitmap*); + void shape_pixmap_(Fl_Pixmap*); + void shape_alpha_(Fl_RGB_Image* img, int offset); +protected: + virtual void draw(); +public: + Fl_Shaped_Window(int w, int h, const char* l = 0); + Fl_Shaped_Window(int x, int y, int w, int h, const char* l = 0); + ~Fl_Shaped_Window(); + void shape(const Fl_Image*); + /** Set the window's shape with an Fl_Image */ + inline void shape(const Fl_Image& b) { shape(&b); } +#if ! (defined(WIN32) || defined(__APPLE__) || defined(FL_DOXYGEN)) + void combine_mask(void); +#endif +}; + +#endif // Fl_Shaped_Window_H + +// +// End of "$Id". +// diff --git a/FL/Fl_Window.H b/FL/Fl_Window.H index 92e76676f..03c82789e 100644 --- a/FL/Fl_Window.H +++ b/FL/Fl_Window.H @@ -16,7 +16,7 @@ // http://www.fltk.org/str.php // -/* \file +/** \file Fl_Window widget . */ #ifndef Fl_Window_H @@ -30,6 +30,7 @@ #define FL_WINDOW 0xF0 ///< window type id all subclasses have type() >= this #define FL_DOUBLE_WINDOW 0xF1 ///< double window type id +#define FL_SHAPED_WINDOW 0xF2 ///< shaped window type id class Fl_X; class Fl_RGB_Image; diff --git a/examples/shapedwindow.cxx b/examples/shapedwindow.cxx new file mode 100644 index 000000000..9426c5d7b --- /dev/null +++ b/examples/shapedwindow.cxx @@ -0,0 +1,125 @@ +// +// "$Id" +// +// shapedwindow example source file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2014 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl_Window.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Box.H> +#include <FL/Fl.H> +#include <FL/Fl_Shaped_Window.H> +#include <FL/Fl_Image.H> +#include <FL/Fl_Tiled_Image.H> +#include <FL/Fl_Image_Surface.H> +#include "test/pixmaps/tile.xpm" + + +void cb(Fl_Widget *w, void *) { + w->window()->hide(); +} + +class dragbox : public Fl_Box { +public: + dragbox(int x, int y, int w, int h, const char *t=0) : Fl_Box(x,y,w,h,t) {}; + int handle(int event) { + static int fromx, fromy, winx, winy; + if (event == FL_PUSH) { + fromx = Fl::event_x_root(); + fromy = Fl::event_y_root(); + winx = window()->x_root(); + winy = window()->y_root(); + return 1; + } + else if (event == FL_DRAG) { + int deltax = Fl::event_x_root() - fromx; + int deltay = Fl::event_y_root() - fromy; + window()->resize(winx + deltax, winy + deltay, window()->w(), window()->h()); + return 1; + } + return Fl_Box::handle(event); + } +}; + +const float factor = 1.3; + +void shrink(Fl_Widget *wdgt, void *data) +{ + Fl_Window *win = wdgt->window(); + int old = win->w(); + win->size(old/factor, old/factor); + if (win->w() <= *(int*)data) wdgt->deactivate(); +} + +void enlarge(Fl_Widget *wdgt, void *data) +{ + Fl_Window *win = wdgt->window(); + int old = win->w(); + win->size(old*factor, old*factor); + ((Fl_Widget*)data)->activate(); +} + +Fl_RGB_Image* prepare_shape(int w) +{ + // draw a white circle with a hole in it on black background + Fl_Image_Surface *surf = new Fl_Image_Surface(w, w); + Fl_Surface_Device* current = Fl_Surface_Device::surface(); + surf->set_current(); + fl_color(FL_BLACK); + fl_rectf(-1, -1, w+2, w+2); + fl_color(FL_WHITE); + fl_pie(2,2,w-4,w-4,0,360); + fl_color(FL_BLACK); + fl_pie(0.7*w,w/2,w/4,w/4,0,360); + Fl_RGB_Image* img = surf->image(); + delete surf; + current->set_current(); + return img; // return depth-3 white image on black background +} + +int main(int argc, char **argv) { + int dim = 200; + Fl_Shaped_Window *win = new Fl_Shaped_Window(100, 100, dim, dim, "Testing1"); + Fl_RGB_Image *img = prepare_shape(dim); + win->shape(img); + dragbox *box = new dragbox(0, 0, win->w(), win->h()); + box->image(new Fl_Tiled_Image(new Fl_Pixmap((const char * const *)tile_xpm))); + Fl_Group *g = new Fl_Group(10, 20, 80, 20); + g->box(FL_NO_BOX); + Fl_Button *b = new Fl_Button(10, 20, 80, 20, "Close"); + b->callback(cb); + g->end(); + g->resizable(NULL); + g = new Fl_Group(60, 70, 80, 40, "Drag me"); + g->box(FL_NO_BOX); + g->align(FL_ALIGN_TOP); + Fl_Button *bs = new Fl_Button(60, 70, 80, 20, "Shrink"); + bs->callback(shrink, &dim); + bs->deactivate(); + Fl_Button *be = new Fl_Button(60, 90, 80, 20, "Enlarge"); + be->callback(enlarge, bs); + g->end(); + g->resizable(NULL); + win->end(); + win->resizable(win); + win->show(argc, argv); + Fl::run(); + delete win; + return 0; +} + +// +// End of "$Id". +// diff --git a/ide/VisualC2008/fltk.lib.vcproj b/ide/VisualC2008/fltk.lib.vcproj index 484e61d8f..af7eaef9a 100644 --- a/ide/VisualC2008/fltk.lib.vcproj +++ b/ide/VisualC2008/fltk.lib.vcproj @@ -656,6 +656,10 @@ >
</File>
<File
+ RelativePath="..\..\FL\Fl_Shaped_Window.H"
+ >
+ </File>
+ <File
RelativePath="..\..\FL\Fl_Shared_Image.H"
>
</File>
@@ -5340,7 +5344,53 @@ />
</FileConfiguration>
</File>
- <File
+ <File
+ RelativePath="..\..\src\Fl_Shaped_Window.cxx"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Cairo|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Cairo|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
RelativePath="..\..\src\Fl_Shared_Image.cxx"
>
<FileConfiguration
diff --git a/ide/VisualC2008/fltkdll.vcproj b/ide/VisualC2008/fltkdll.vcproj index 228d1250c..9cf67baaa 100644 --- a/ide/VisualC2008/fltkdll.vcproj +++ b/ide/VisualC2008/fltkdll.vcproj @@ -5006,6 +5006,48 @@ </FileConfiguration>
</File>
<File
+ RelativePath="..\..\src\Fl_Shaped_Window.cxx"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;NDEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;_DEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Cairo|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;_DEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN;$(NoInherit)"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Cairo|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;NDEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN;$(NoInherit)"
+ />
+ </FileConfiguration>
+ </File>
+ <File
RelativePath="..\..\src\Fl_Shared_Image.cxx"
>
<FileConfiguration
diff --git a/ide/VisualC2010/fltk.lib.vcxproj b/ide/VisualC2010/fltk.lib.vcxproj index 3c80ed280..4b5df70f2 100644 --- a/ide/VisualC2010/fltk.lib.vcxproj +++ b/ide/VisualC2010/fltk.lib.vcxproj @@ -256,6 +256,7 @@ <ClInclude Include="..\..\FL\Fl_Scrollbar.H" />
<ClInclude Include="..\..\FL\Fl_Secret_Input.H" />
<ClInclude Include="..\..\FL\Fl_Select_Browser.H" />
+ <ClInclude Include="..\..\FL\Fl_Shaped_Window.H" />
<ClInclude Include="..\..\FL\Fl_Shared_Image.H" />
<ClInclude Include="..\..\FL\fl_show_colormap.H" />
<ClInclude Include="..\..\FL\fl_show_input.H" />
@@ -1855,7 +1856,23 @@ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
- <ClCompile Include="..\..\src\Fl_Shared_Image.cxx">
+ <ClCompile Include="..\..\src\Fl_Shaped_Window.cxx">
+ <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">Disabled</Optimization>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">true</BrowseInformation>
+ <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+ <FavorSizeOrSpeed Condition="'$(Configuration)|$(Platform)'=='Release Cairo|Win32'">Neither</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release Cairo|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FavorSizeOrSpeed Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Neither</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="..\..\src\Fl_Shared_Image.cxx">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
diff --git a/ide/VisualC2010/fltk.lib.vcxproj.filters b/ide/VisualC2010/fltk.lib.vcxproj.filters index 6ada2d1f6..5bf97fdd4 100644 --- a/ide/VisualC2010/fltk.lib.vcxproj.filters +++ b/ide/VisualC2010/fltk.lib.vcxproj.filters @@ -268,6 +268,9 @@ <ClInclude Include="..\..\FL\Fl_Select_Browser.H">
<Filter>Headers</Filter>
</ClInclude>
+ <ClInclude Include="..\..\FL\Fl_Shaped_Window.H">
+ <Filter>Headers</Filter>
+ </ClInclude>
<ClInclude Include="..\..\FL\Fl_Shared_Image.H">
<Filter>Headers</Filter>
</ClInclude>
@@ -481,6 +484,7 @@ <ClCompile Include="..\..\src\fl_set_font.cxx" />
<ClCompile Include="..\..\src\fl_set_fonts.cxx" />
<ClCompile Include="..\..\src\fl_shadow_box.cxx" />
+ <ClCompile Include="..\..\src\Fl_Shaped_Window.cxx" />
<ClCompile Include="..\..\src\Fl_Shared_Image.cxx" />
<ClCompile Include="..\..\src\fl_shortcut.cxx" />
<ClCompile Include="..\..\src\fl_show_colormap.cxx" />
diff --git a/ide/VisualC2010/fltkdll.vcxproj b/ide/VisualC2010/fltkdll.vcxproj index f7314d5d9..048bc49ff 100644 --- a/ide/VisualC2010/fltkdll.vcxproj +++ b/ide/VisualC2010/fltkdll.vcxproj @@ -1552,6 +1552,18 @@ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;NDEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN</PreprocessorDefinitions>
</ClCompile>
+ <ClCompile Include="..\..\src\Fl_Shaped_Window.cxx">
+ <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">Disabled</Optimization>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;_DEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN</PreprocessorDefinitions>
+ <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;_DEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release Cairo|Win32'">_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;NDEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_CRT_SECURE_NO_DEPRECATE;FL_DLL;FL_LIBRARY;WIN32;NDEBUG;_WINDOWS;WIN32_LEAN_AND_MEAN;VC_EXTRA_LEAN;WIN32_EXTRA_LEAN</PreprocessorDefinitions>
+ </ClCompile>
<ClCompile Include="..\..\src\Fl_Shared_Image.cxx">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">Disabled</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug Cairo|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
diff --git a/ide/VisualC6/fltk.dsp b/ide/VisualC6/fltk.dsp index adab15ec7..3c20bad2a 100644 --- a/ide/VisualC6/fltk.dsp +++ b/ide/VisualC6/fltk.dsp @@ -515,6 +515,10 @@ SOURCE=..\..\src\fl_shadow_box.cxx # End Source File
# Begin Source File
+SOURCE=..\..\src\Fl_Shaped_Window.cxx
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Fl_Shared_Image.cxx
# End Source File
# Begin Source File
diff --git a/ide/VisualC6/fltkdll.dsp b/ide/VisualC6/fltkdll.dsp index ac30038d2..311d41c87 100644 --- a/ide/VisualC6/fltkdll.dsp +++ b/ide/VisualC6/fltkdll.dsp @@ -533,6 +533,10 @@ SOURCE=..\..\src\fl_shadow_box.cxx # End Source File
# Begin Source File
+SOURCE=..\..\src\Fl_Shaped_Window.cxx
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Fl_Shared_Image.cxx
# End Source File
# Begin Source File
diff --git a/ide/Xcode3/FLTK.xcodeproj/project.pbxproj b/ide/Xcode3/FLTK.xcodeproj/project.pbxproj index 69b65cbc0..883493a4d 100644 --- a/ide/Xcode3/FLTK.xcodeproj/project.pbxproj +++ b/ide/Xcode3/FLTK.xcodeproj/project.pbxproj @@ -331,6 +331,7 @@ 7F74F393190D7F0500C56950 /* fl_gleam.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 299E717718BC503400FF83F2 /* fl_gleam.cxx */; }; 7F76E016192FAD420071728B /* Fl_Copy_Surface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7F76E015192FAD420071728B /* Fl_Copy_Surface.cxx */; }; 7F76E018192FAD590071728B /* Fl_Image_Surface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7F76E017192FAD590071728B /* Fl_Image_Surface.cxx */; }; + 7FD807F719ADD610007622B2 /* Fl_Shaped_Window.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7FD807F619ADD610007622B2 /* Fl_Shaped_Window.cxx */; }; 7FFDE4AD171D8AA3008753A3 /* Fl_Sys_Menu_Bar.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7FFDE4AC171D8AA3008753A3 /* Fl_Sys_Menu_Bar.mm */; }; 812129561A1981D6DEFBCBFB /* Fl_Positioner.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 05BBBFE4BED0452E5D6A81F7 /* Fl_Positioner.cxx */; }; 812761E94039F13357F56EE6 /* fltk_png.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 98A16A4EC098BA7DB21E13DC /* fltk_png.framework */; }; @@ -4347,6 +4348,8 @@ 7F784151AF1B748D0F3DB1C0 /* forms.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = forms.cxx; path = ../../test/forms.cxx; sourceTree = SOURCE_ROOT; }; 7FAC914955D699539F73B996 /* bitmap.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bitmap.cxx; path = ../../test/bitmap.cxx; sourceTree = SOURCE_ROOT; }; 7FC91721DA7888C8A1FD762E /* input_choice.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = input_choice.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 7FD807F419ADD5F4007622B2 /* Fl_Shaped_Window.H */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Fl_Shaped_Window.H; path = ../../FL/Fl_Shaped_Window.H; sourceTree = SOURCE_ROOT; }; + 7FD807F619ADD610007622B2 /* Fl_Shaped_Window.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Shaped_Window.cxx; path = ../../src/Fl_Shaped_Window.cxx; sourceTree = SOURCE_ROOT; }; 7FFDE4AC171D8AA3008753A3 /* Fl_Sys_Menu_Bar.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Fl_Sys_Menu_Bar.mm; path = ../../src/Fl_Sys_Menu_Bar.mm; sourceTree = SOURCE_ROOT; }; 800E34DEF9E503C5EC6C4FA5 /* Fl_XBM_Image.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_XBM_Image.cxx; path = ../../src/Fl_XBM_Image.cxx; sourceTree = SOURCE_ROOT; }; 806103D71A8CD0075BF8E1DA /* Fl_Group.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Group.cxx; path = ../../src/Fl_Group.cxx; sourceTree = SOURCE_ROOT; }; @@ -5505,6 +5508,7 @@ 13BCF00369D5254F0CE49599 /* Fl_Round_Button.cxx */, 3F60A41762817C834FF38947 /* Fl_Scroll.cxx */, A5B9A5CE605BB8A57F66A2E6 /* Fl_Scrollbar.cxx */, + 7FD807F619ADD610007622B2 /* Fl_Shaped_Window.cxx */, 57639C1D5415FB55436556A2 /* Fl_Shared_Image.cxx */, 9D942824B8FC886F6FCD853D /* Fl_Single_Window.cxx */, 5AF5119D08DFC92EA1032671 /* Fl_Slider.cxx */, @@ -6293,6 +6297,7 @@ 28F3E4EBB6E5F8420624A5DA /* Fl_Scrollbar.H */, 42FEA3A2967D04217C27FA61 /* Fl_Secret_Input.H */, 9DA766AE10DC532F3D0401A2 /* Fl_Select_Browser.H */, + 7FD807F419ADD5F4007622B2 /* Fl_Shaped_Window.H */, A46A39199806D09CE0ABEE59 /* Fl_Shared_Image.H */, 9B57B581401BD8575BFAF2F1 /* Fl_Simple_Counter.H */, 0EC11A5CAD4E3607A72BEF84 /* Fl_Single_Window.H */, @@ -9527,6 +9532,7 @@ 01C68DB0192C6089000BD75C /* Fl_sleep.cxx in Sources */, 7F76E016192FAD420071728B /* Fl_Copy_Surface.cxx in Sources */, 7F76E018192FAD590071728B /* Fl_Image_Surface.cxx in Sources */, + 7FD807F719ADD610007622B2 /* Fl_Shaped_Window.cxx in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ide/Xcode4/FLTK.xcodeproj/project.pbxproj b/ide/Xcode4/FLTK.xcodeproj/project.pbxproj index ce8e93d1b..e9ab50ada 100644 --- a/ide/Xcode4/FLTK.xcodeproj/project.pbxproj +++ b/ide/Xcode4/FLTK.xcodeproj/project.pbxproj @@ -330,6 +330,7 @@ 7F66B1DB12BB924C00C67B59 /* Fl_Quartz_Printer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7F66B1D812BB924C00C67B59 /* Fl_Quartz_Printer.mm */; }; 7FA5C2BE192FAEBB00519823 /* Fl_Copy_Surface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7FA5C2BD192FAEBB00519823 /* Fl_Copy_Surface.cxx */; }; 7FA5C2C0192FAECA00519823 /* Fl_Image_Surface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7FA5C2BF192FAECA00519823 /* Fl_Image_Surface.cxx */; }; + 7FD8085119ADD6F2007622B2 /* Fl_Shaped_Window.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 7FD8085019ADD6F2007622B2 /* Fl_Shaped_Window.cxx */; }; 7FDBB8F416B2D1EA00AE76EF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7F92032516B1A90A000FC50F /* Localizable.strings */; }; 7FDBB8F516B2D1EE00AE76EF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7F92032216B1A909000FC50F /* Localizable.strings */; }; 7FDBB8F616B2D1FA00AE76EF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7F92031F16B1A909000FC50F /* Localizable.strings */; }; @@ -4342,6 +4343,8 @@ 7FA5C2C2192FAEF200519823 /* Fl_Copy_Surface.H */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Fl_Copy_Surface.H; path = ../../FL/Fl_Copy_Surface.H; sourceTree = SOURCE_ROOT; }; 7FAC914955D699539F73B996 /* bitmap.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bitmap.cxx; path = ../../test/bitmap.cxx; sourceTree = SOURCE_ROOT; }; 7FC91721DA7888C8A1FD762E /* input_choice.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = input_choice.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 7FD8084F19ADD6DE007622B2 /* Fl_Shaped_Window.H */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Fl_Shaped_Window.H; path = ../../FL/Fl_Shaped_Window.H; sourceTree = SOURCE_ROOT; }; + 7FD8085019ADD6F2007622B2 /* Fl_Shaped_Window.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Shaped_Window.cxx; path = ../../src/Fl_Shaped_Window.cxx; sourceTree = SOURCE_ROOT; }; 7FFDE551171D8D0D008753A3 /* Fl_Sys_Menu_Bar.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Fl_Sys_Menu_Bar.mm; path = ../../src/Fl_Sys_Menu_Bar.mm; sourceTree = SOURCE_ROOT; }; 800E34DEF9E503C5EC6C4FA5 /* Fl_XBM_Image.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_XBM_Image.cxx; path = ../../src/Fl_XBM_Image.cxx; sourceTree = SOURCE_ROOT; }; 806103D71A8CD0075BF8E1DA /* Fl_Group.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Fl_Group.cxx; path = ../../src/Fl_Group.cxx; sourceTree = SOURCE_ROOT; }; @@ -5499,6 +5502,7 @@ 13BCF00369D5254F0CE49599 /* Fl_Round_Button.cxx */, 3F60A41762817C834FF38947 /* Fl_Scroll.cxx */, A5B9A5CE605BB8A57F66A2E6 /* Fl_Scrollbar.cxx */, + 7FD8085019ADD6F2007622B2 /* Fl_Shaped_Window.cxx */, 57639C1D5415FB55436556A2 /* Fl_Shared_Image.cxx */, 9D942824B8FC886F6FCD853D /* Fl_Single_Window.cxx */, 5AF5119D08DFC92EA1032671 /* Fl_Slider.cxx */, @@ -6332,6 +6336,7 @@ 28F3E4EBB6E5F8420624A5DA /* Fl_Scrollbar.H */, 42FEA3A2967D04217C27FA61 /* Fl_Secret_Input.H */, 9DA766AE10DC532F3D0401A2 /* Fl_Select_Browser.H */, + 7FD8084F19ADD6DE007622B2 /* Fl_Shaped_Window.H */, A46A39199806D09CE0ABEE59 /* Fl_Shared_Image.H */, 9B57B581401BD8575BFAF2F1 /* Fl_Simple_Counter.H */, 0EC11A5CAD4E3607A72BEF84 /* Fl_Single_Window.H */, @@ -9564,6 +9569,7 @@ 299CB8A2848CB844BCEC7829 /* Fl_Paged_Device.cxx in Sources */, 7FA5C2BE192FAEBB00519823 /* Fl_Copy_Surface.cxx in Sources */, 7FA5C2C0192FAECA00519823 /* Fl_Image_Surface.cxx in Sources */, + 7FD8085119ADD6F2007622B2 /* Fl_Shaped_Window.cxx in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index afacb823c..4b8983d46 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,6 +55,7 @@ set(CPPFILES Fl_Round_Button.cxx Fl_Scroll.cxx Fl_Scrollbar.cxx + Fl_Shaped_Window.cxx Fl_Shared_Image.cxx Fl_Single_Window.cxx Fl_Slider.cxx diff --git a/src/Fl_Shaped_Window.cxx b/src/Fl_Shaped_Window.cxx new file mode 100644 index 000000000..e874c7098 --- /dev/null +++ b/src/Fl_Shaped_Window.cxx @@ -0,0 +1,369 @@ +// +// "$Id" +// +// Fl_Shaped_Window source file for the Fast Light Tool Kit (FLTK). +// +// Copyright 2010-2014 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#include <FL/x.H> +#include <FL/Fl_Shaped_Window.H> +#include <FL/Fl_Bitmap.H> +#include <FL/Fl_Pixmap.H> + +#ifdef WIN32 +# include <malloc.h> // needed for VisualC2010 +#elif !defined(__APPLE__) +#include <dlfcn.h> +#define ShapeBounding 0 +#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__) + +static void MyProviderReleaseData (void *info, const void *data, size_t size) { + delete[] (uchar*)data; +} + +// bitwise inversion of all 4-bit quantities +static const unsigned char swapped[16] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}; + +static inline uchar swap_byte(const uchar b) { + // reverse the order of bits of byte b: 1->8 becomes 8->1 + 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)); } + +static HRGN bitmap2region(Fl_Bitmap* image) { + HRGN hRgn = 0; + /* Does this need to be dynamically determined, perhaps? */ + const int ALLOC_UNIT = 100; + DWORD maxRects = ALLOC_UNIT; + + RGNDATA* pData = (RGNDATA*)malloc(sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects)); + pData->rdh.dwSize = sizeof(RGNDATAHEADER); + pData->rdh.iType = RDH_RECTANGLES; + pData->rdh.nCount = pData->rdh.nRgnSize = 0; + SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); + + const int bytesPerLine = (image->w() + 7)/8; + BYTE* p, *data = (BYTE*)image->array; + for (int y = 0; y < image->h(); y++) { + // each row, left to right + for (int x = 0; x < image->w(); x++) { + int x0 = x; + while (x < image->w()) { + p = data + x / 8; + if (!((*p) & bit(x))) break; // transparent pixel + x++; + } + if (x > x0) { + RECT *pr; + /* Add the pixels (x0, y) to (x, y+1) as a new rectangle + * in the region + */ + if (pData->rdh.nCount >= maxRects) { + maxRects += ALLOC_UNIT; + pData = (RGNDATA*)realloc(pData, sizeof(RGNDATAHEADER) + + (sizeof(RECT)*maxRects)); + } + pr = (RECT*)&pData->Buffer; + SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1); + if (x0 < pData->rdh.rcBound.left) + pData->rdh.rcBound.left = x0; + if (y < pData->rdh.rcBound.top) + pData->rdh.rcBound.top = y; + if (x > pData->rdh.rcBound.right) + pData->rdh.rcBound.right = x; + if (y+1 > pData->rdh.rcBound.bottom) + pData->rdh.rcBound.bottom = y+1; + pData->rdh.nCount++; + /* On Windows98, ExtCreateRegion() may fail if the + * number of rectangles is too large (ie: > + * 4000). Therefore, we have to create the region by + * multiple steps. + */ + if (pData->rdh.nCount == 2000) { + HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + + (sizeof(RECT)*maxRects), pData); + if (hRgn) { + CombineRgn(hRgn, hRgn, h, RGN_OR); + DeleteObject(h); + } else + hRgn = h; + pData->rdh.nCount = 0; + SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); + } + } + } + /* Go to next row */ + data += bytesPerLine; + } + /* Create or extend the region with the remaining rectangles*/ + HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + + (sizeof(RECT)*maxRects), pData); + if (hRgn) { + CombineRgn(hRgn, hRgn, h, RGN_OR); + DeleteObject(h); + } else hRgn = h; + free(pData); // I've created the region so I can free this now, right? + 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() +{ + typedef void (*XShapeCombineMask_type)(Display*, int, int, int, int, Pixmap, int); + static XShapeCombineMask_type XShapeCombineMask_f = NULL; + static int beenhere = 0; + typedef Bool (*XShapeQueryExtension_type)(Display*, int*, int*); + int error_base, shapeEventBase; + if (!beenhere) { + beenhere = 1; + fl_open_display(); + void *handle = dlopen(NULL, RTLD_LAZY); // search symbols in executable + XShapeQueryExtension_type XShapeQueryExtension_f = (XShapeQueryExtension_type)dlsym(handle, "XShapeQueryExtension"); + XShapeCombineMask_f = (XShapeCombineMask_type)dlsym(handle, "XShapeCombineMask"); + // make sure that the X server has the SHAPE extension + if ( !( XShapeQueryExtension_f && XShapeCombineMask_f && + 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_); + Pixmap pbitmap = XCreateBitmapFromData(fl_display, fl_xid(this), + (const char*)temp->array, + temp->w(), temp->h()); + XShapeCombineMask_f(fl_display, fl_xid(this), ShapeBounding, 0, 0, pbitmap, ShapeSet); + if (pbitmap != None) XFreePixmap(fl_display, pbitmap); + delete temp; +} +#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 +#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; + uchar *from = new uchar[bytes_per_row * b->h()]; + for (int i = 0; i < b->h(); i++) { + uchar *p = (uchar*)b->array + bytes_per_row * i; + uchar *last = p + bytes_per_row; + uchar *q = from + (b->h() - 1 - i) * bytes_per_row; + while (p < last) { + *q++ = swap_byte(~*p++); + } + } + 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); + CFRelease(provider); + } +#endif +} + + +#if defined(__APPLE__) // on the mac, use an 8-bit mask +/* 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) { + 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_) { + // 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]; + for ( i = 0; i < h; i++) { + uchar *p = (uchar*)img->array + bytes_per_row * i + offset; + uchar *last = p + bytes_per_row; + uchar *q = from + (h - 1 - i) * w; + while (p < last) { + if (d == 3) { + unsigned u = *p++; + u += *p++; + u += *p++; + *q++ = ~(u/3); + } + else { + *q++ = ~(*p); + p += d; + } + } + } + CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, w * h, MyProviderReleaseData); + mask = CGImageMaskCreate(w, h, 8, 8, w, provider, NULL, false); + CFRelease(provider); + } +} + +#else + +/* 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) { + int i, j, d = img->d(), w = img->w(), h = img->h(), bytesperrow = (w+7)/8; + unsigned u; + uchar byte, onebit; + // build an Fl_Bitmap covering the non-fully transparent/black part of the image + const uchar* bits = new uchar[h*bytesperrow]; // to store the bitmap + const uchar* alpha = img->array + offset; // points to alpha value of rgba pixels + for (i = 0; i < h; i++) { + uchar *p = (uchar*)bits + i * bytesperrow; + byte = 0; + onebit = 1; + for (j = 0; j < w; j++) { + if (d == 3) { + u = *alpha; + u += *(alpha+1); + u += *(alpha+2); + } + else u = *alpha; + if (u > 0) { // if the pixel is not fully transparent/black + byte |= onebit; // turn on the corresponding bit of the bitmap + } + onebit = onebit << 1; // move the single set bit one position to the left + if (onebit == 0 || j == w-1) { + onebit = 1; + *p++ = byte; // store in bitmap one pack of bits + byte = 0; + } + alpha += d; // point to alpha value of next pixel + } + } + Fl_Bitmap* bitmap = new Fl_Bitmap(bits, w, h); + bitmap->alloc_array = 1; + shape_bitmap_(bitmap); + todelete_ = bitmap; +} + +#endif + + +void Fl_Shaped_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. + 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. + \li With an Fl_RGB_Image with an alpha channel (depths 2 or 4), the shaped window covers the image part + that is not fully transparent. + \li With an Fl_RGB_Image of depth 1 (gray-scale) or 3 (RGB), the shaped window covers the non-black image part. + + On some platforms, an 8-bit shape-mask is used when \p img is an Fl_RGB_Image: + with depths 2 or 4, the image alpha channel becomes the shape mask such that areas with alpha = 0 + 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. + */ +void Fl_Shaped_Window::shape(const Fl_Image* img) { + 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); +} + +// +// End of "$Id". +// diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index 5de916139..68b21dc43 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -2361,6 +2361,7 @@ void Fl_X::flush() fl_x_to_redraw = NULL; } +//bool Fl_X::make_shaped = false; /* * go ahead, create that (sub)window @@ -2517,6 +2518,10 @@ void Fl_X::make(Fl_Window* w) [cw setFrameOrigin:crect.origin]; [cw setHasShadow:YES]; [cw setAcceptsMouseMovedEvents:YES]; + if (w->type() == FL_SHAPED_WINDOW) { + [cw setOpaque:NO]; // shaped windows must be non opaque + [cw setBackgroundColor:[NSColor clearColor]]; // and with transparent background color + } x->xid = cw; x->w = w; w->i = x; x->wait_for_expose = 1; @@ -2645,7 +2650,7 @@ void Fl_Window::show() { labeltype(FL_NO_LABEL); } Fl_Tooltip::exit(this); - if (!shown() || !i) { + if (!shown()) { Fl_X::make(this); } else { if ( !parent() ) { diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index e071b8d83..b3045c8a6 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -35,6 +35,7 @@ # include <FL/fl_draw.H> # include <FL/Fl_Paged_Device.H> # include <FL/Fl_Shared_Image.H> +# include <FL/Fl_Shaped_Window.H> # include <FL/fl_ask.H> # include <FL/filename.H> # include <stdio.h> @@ -2511,6 +2512,9 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) } #endif + if (win->type() == FL_SHAPED_WINDOW) { + ((Fl_Shaped_Window*)win)->combine_mask(); + } XMapWindow(fl_display, xp->xid); if (showit) { win->set_visible(); @@ -2836,7 +2840,7 @@ void Fl_Window::show() { if (!shown()) { fl_open_display(); // Don't set background pixel for double-buffered windows... - if (type() == FL_WINDOW && can_boxcheat(box())) { + if (type() != FL_DOUBLE_WINDOW && can_boxcheat(box())) { fl_background_pixel = int(fl_xpixel(color())); } Fl_X::make_xid(this); diff --git a/src/Makefile b/src/Makefile index 625e067a7..1376c3595 100644 --- a/src/Makefile +++ b/src/Makefile @@ -71,6 +71,7 @@ CPPFILES = \ Fl_Round_Button.cxx \ Fl_Scroll.cxx \ Fl_Scrollbar.cxx \ + Fl_Shaped_Window.cxx \ Fl_Shared_Image.cxx \ Fl_Single_Window.cxx \ Fl_Slider.cxx \ |
