Author: manolo
Date: 2012-09-29 07:39:41 -0700 (Sat, 29 Sep 2012)
New Revision: 9689
Log:
Added the Mac OS implementation of the fltk3::ShapedWindow class.

Modified:
   branches/branch-3.0/include/fltk3/ShapedWindow.h
   branches/branch-3.0/include/fltk3/Widget.h
   branches/branch-3.0/src/fltk3/ShapedWindow.cxx
   branches/branch-3.0/src/fltk3/cocoa.mm
   branches/branch-3.0/test/shapedwindow.cxx

Modified: branches/branch-3.0/include/fltk3/ShapedWindow.h
===================================================================
--- branches/branch-3.0/include/fltk3/ShapedWindow.h    2012-09-28 08:07:47 UTC 
(rev 9688)
+++ branches/branch-3.0/include/fltk3/ShapedWindow.h    2012-09-29 14:39:41 UTC 
(rev 9689)
@@ -29,6 +29,7 @@
 #define fltk3_ShapedWindow_H
 
 #include "Window.h"
+#include "fltk3/x.h"
 
 namespace fltk3 {
 
@@ -40,6 +41,8 @@
 
   The layout and widgets inside are unaware of the mask shape, and most will 
act as though the 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.
 
   The window borders and caption created by the window system are turned off 
by default for a ShapedWindow object.  They 
   can be re-enabled by calling void Window::border(bool set).
@@ -55,12 +58,17 @@
 
 
 class FLTK3_EXPORT ShapedWindow : public Window {
-  public:
+private:
+#if defined(__APPLE__)
+  CGImageRef mask;
+#endif
+public:
     ShapedWindow(int w, int h, const char* l = 0);
     ShapedWindow(int x, int y, int w, int h, const char* l = 0);
     ~ShapedWindow();
     void shape(Image* b);
     inline void shape(Image& b) { shape(&b); }
+    ShapedWindow* as_shaped_window() { return this; }
 
   protected:
     virtual void draw();

Modified: branches/branch-3.0/include/fltk3/Widget.h
===================================================================
--- branches/branch-3.0/include/fltk3/Widget.h  2012-09-28 08:07:47 UTC (rev 
9688)
+++ branches/branch-3.0/include/fltk3/Widget.h  2012-09-29 14:39:41 UTC (rev 
9689)
@@ -55,6 +55,7 @@
   class Widget; 
   class Group;
   class Window;
+  class ShapedWindow;
   class Image;
   class GLWindow;
   class Style;
@@ -1022,9 +1023,20 @@
      \note This method is provided to avoid dynamic_cast.
      \see fltk3::Widget::as_group(), fltk3::Widget::as_window()
      */
-    virtual class fltk3::GLWindow* as_gl_window() {return 0;}
+    virtual fltk3::GLWindow* as_gl_window() {return 0;}
     
-};
+    /** Returns an fltk3::ShapedWindow pointer if this widget is an 
fltk3::ShapedWindow.
+     
+     Use this method if you have a widget (pointer) and need to
+     know whether this widget is derived from fltk3::ShapedWindow. If it 
returns
+     non-NULL, then the widget in question is derived from fltk3::ShapedWindow.
+     
+     \retval NULL if this widget is not derived from fltk3::ShapedWindow.
+     \note This method is provided to avoid dynamic_cast.
+     \see fltk3::Widget::as_group(), fltk3::Widget::as_window()
+     */
+    virtual fltk3::ShapedWindow* as_shaped_window() {return 0;}
+  };
   
   
   /**

Modified: branches/branch-3.0/src/fltk3/ShapedWindow.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/ShapedWindow.cxx      2012-09-28 08:07:47 UTC 
(rev 9688)
+++ branches/branch-3.0/src/fltk3/ShapedWindow.cxx      2012-09-29 14:39:41 UTC 
(rev 9689)
@@ -37,15 +37,27 @@
 fltk3::ShapedWindow::ShapedWindow(int w, int h, const char* l)
        : Window(w, h, l), shape_(0), lw(0), lh(0), changed(false) {
          border(false);
-  }
+#if defined(__APPLE__)
+         mask = NULL;
+#endif
+       }
 
 fltk3::ShapedWindow::ShapedWindow(int x, int y, int w, int h, const char* l)
        : Window(x, y, w, h, l), shape_(0), lw(0), lh(0), changed(false) {
          border(false);
-  }
+#if defined(__APPLE__)
+         mask = NULL;
+#endif
+       }
 
 fltk3::ShapedWindow::~ShapedWindow() {
   //delete shape_;
+#if defined(__APPLE__)
+  if (mask) {
+    CGDataProviderRelease(CGImageGetDataProvider(mask));
+    CGImageRelease(mask);
+  }
+#endif
 }
 
 void fltk3::ShapedWindow::shape(fltk3::Image* b) {
@@ -139,7 +151,6 @@
 
 }
 #elif defined(__APPLE__)
-//# error I have no idea what to do here. Perhaps one of the more mac-knowing 
dev.s does?
 #endif
 
 namespace {
@@ -152,13 +163,29 @@
 
 }
 
+#if defined(__APPLE__)
+// 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};
+
+// bitwise inversion of a byte
+static inline uchar swap_byte(const uchar b) {
+  return (swapped[b & 0xF] << 4) | swapped[b >> 4];
+}
+
+static void MyProviderReleaseData (void *info, const void *data, size_t size) {
+  delete (fltk3::Image*)info;
+}
+#endif
+
 void fltk3::ShapedWindow::draw() {
   if ((lw != w() || lh != h() || changed) && shape_) {
-    // size of window has change since last time
+    // size of window has changed since last time
     lw = w();
     lh = h();
     fltk3::Image* temp = resize_bitmap(shape_, lw, lh);
+#if !defined(__APPLE__)
     fltk3::RGBImage* bitmap = new RGBImage((const uchar*)temp->data()[0], lw, 
lh, 4);
+#endif
 #if USE_X11
     Pixmap pbitmap = XCreateBitmapFromData(fl_display, fl_xid(this), 
                                        (const char*)bitmap->array,
@@ -166,22 +193,41 @@
     XShapeCombineMask(fl_display, fl_xid(this), ShapeBounding, 0, 0,
                       pbitmap, ShapeSet);
     if (pbitmap != None) XFreePixmap(fl_display, pbitmap);
+    delete bitmap;
+    delete temp;
 #elif defined(_WIN32)
     HRGN region = bitmap2region(bitmap);
     SetWindowRgn(fl_xid(this), region, TRUE);
+    delete bitmap;
+    delete temp;
 #elif defined(__APPLE__)
-    // not yet implemented for Apple
-    // see earlier #error
-//#error Not implemented!
+    if (mask) {
+      CGDataProviderRelease(CGImageGetDataProvider(mask));
+      CGImageRelease(mask);
+      }
+    // reverse mask bits and also perform bitwise inversion of all bytes
+    char *p = (char*)temp->data()[0];
+    char *q = p + (lw*lh)/8;
+    while (p < q) {
+      *p = swap_byte(~*p);
+      p++;
+      }
+    CGDataProviderRef provider = CGDataProviderCreateWithData(temp, 
temp->data()[0], (lw*lh)/8, MyProviderReleaseData);
+    mask = CGImageMaskCreate(lw, lh, 1, 1, lw/8, provider, NULL, false);
 #else 
     // any other window managers that FLTK3 supports will be added here
 #endif
     changed = 0;
-    delete bitmap;
-    delete temp;
   }
+#if defined(__APPLE__)
+  if (mask) CGContextClipToMask(fl_gc, CGRectMake(0,0,lw,lh), mask); // 
requires Mac OS 10.4
+  CGContextSaveGState(fl_gc);
+#endif
   // I get the feeling something inside Window::draw() is what's causing the 
artefacting......
   Window::draw();
+#if defined(__APPLE__)
+  CGContextRestoreGState(fl_gc);
+#endif
 }
 
 //

Modified: branches/branch-3.0/src/fltk3/cocoa.mm
===================================================================
--- branches/branch-3.0/src/fltk3/cocoa.mm      2012-09-28 08:07:47 UTC (rev 
9688)
+++ branches/branch-3.0/src/fltk3/cocoa.mm      2012-09-29 14:39:41 UTC (rev 
9689)
@@ -2163,7 +2163,11 @@
     FLView *myview = [[FLView alloc] init];
     [cw setContentView:myview];
     [cw setLevel:winlevel];
-    
+    if ( w->as_shaped_window() ) {
+      [cw setOpaque:NO];
+      [cw setBackgroundColor:[NSColor colorWithDeviceWhite:0 alpha:0]];
+      }
+
     q_set_window_title(cw, w->label(), w->iconlabel());
     if (!w->force_position()) {
       if (w->modal()) {

Modified: branches/branch-3.0/test/shapedwindow.cxx
===================================================================
--- branches/branch-3.0/test/shapedwindow.cxx   2012-09-28 08:07:47 UTC (rev 
9688)
+++ branches/branch-3.0/test/shapedwindow.cxx   2012-09-29 14:39:41 UTC (rev 
9689)
@@ -1,6 +1,7 @@
 #include <fltk3/run.h>
 #include <fltk3/ShapedWindow.h>
 #include <fltk3/Bitmap.h>
+#include <fltk3/Button.h>
 
 #define x_width 200
 #define x_height 200
@@ -207,11 +208,42 @@
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 }; 
 
+void cb(fltk3::Widget *w, void *) {
+  fltk3::delete_widget(w->window());
+  fltk3::wait(0);
+}
+
+class mybox : public fltk3::BoxWidget {
+public:
+  mybox(int x, int y, int w, int h, const char *t=0) : BoxWidget(x,y,w,h,t) {};
+  int handle(int event) {
+    static int fromx, fromy, winx, winy;
+    if (event == fltk3::PUSH) {
+      fromx = fltk3::event_x_root();
+      fromy = fltk3::event_y_root();
+      winx = window()->x_root();
+      winy = window()->y_root();
+      return 1;
+      }
+    else if (event == fltk3::DRAG) {
+      int deltax = fltk3::event_x_root() - fromx;
+      int deltay = fltk3::event_y_root() - fromy;
+      window()->resize(winx + deltax, winy + deltay, window()->w(), 
window()->h());
+      return 1;
+      }
+    return 0;
+    }
+};
+
 int main() {
-    fltk3::Bitmap bmap(x_bits, x_width, x_height);
-    fltk3::ShapedWindow win1(100, 100, 640, 400, "Testing1");
-    win1.shape(bmap);
-    win1.resizable(win1);
-    win1.show();
-    return fltk3::run();
+  fltk3::Bitmap bmap(x_bits, x_width, x_height);
+  fltk3::ShapedWindow *win1 = new fltk3::ShapedWindow(100, 100, 640, 400, 
"Testing1");
+  win1->shape(bmap);
+  new mybox(0, 0, win1->w(), win1->h(), "Drag me");
+  fltk3::Button *b = new fltk3::Button(80,50,80,20,"Close");
+  b->callback(cb);
+  win1->end();
+  win1->resizable(win1);
+  win1->show();
+  return fltk3::run();
 }

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to