]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/bitmap.cpp
refreshed makefiles to be in sync with filelist.txt
[wxWidgets.git] / src / mac / carbon / bitmap.cpp
index 1e6255f55162f1ea94dba34153f66508a6906847..d14b15ba7f3c7d936210fe0ef8e8339b1284cce5 100644 (file)
 #include "wx/icon.h"
 #include "wx/log.h"
 
-#if !USE_SHARED_LIBRARIES
+extern "C" 
+{
+       #include "xpm.h"
+} ;
+
 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
-#endif
+
+#include <PictUtils.h>
+
+CTabHandle wxMacCreateColorTable( int numColors )
+{
+       CTabHandle newColors; /* Handle to the new color table */
+       short index; /* Index into the table of colors */
+       /* Allocate memory for the color table */
+       newColors = (CTabHandle)NewHandleClear( sizeof (ColorTable) +
+       sizeof (ColorSpec) * (numColors - 1) );
+       if (newColors != nil)
+       {
+               /* Initialize the fields */
+               (**newColors).ctSeed = GetCTSeed();
+               (**newColors).ctFlags = 0;
+               (**newColors).ctSize = numColors - 1;
+               /* Initialize the table of colors */
+       }
+       return newColors ;
+}
+
+void wxMacDestroyColorTable( CTabHandle colors ) 
+{
+       DisposeHandle( (Handle) colors ) ;
+}
+
+void wxMacSetColorTableEntry( CTabHandle newColors , int index , int red , int green ,  int blue )
+{
+       (**newColors).ctTable[index].value = index;
+       (**newColors).ctTable[index].rgb.red = 0 ;// someRedValue;
+       (**newColors).ctTable[index].rgb.green = 0 ; // someGreenValue;
+       (**newColors).ctTable[index].rgb.blue = 0 ; // someBlueValue;
+}
+
+GWorldPtr wxMacCreateGWorld( int height , int width , int depth )
+{
+       OSErr err = noErr ;
+       GWorldPtr port ;
+       Rect rect = { 0 , 0 , width , height } ;
+       
+       if ( depth < 0 )
+       {
+               // get max pixel depth
+               CGrafPtr port ;
+               GetCWMgrPort( &port ) ; 
+               GDHandle maxDevice ;
+               
+               maxDevice = GetMaxDevice( &port->portRect ) ;
+               if ( maxDevice )
+                       depth = (**((**maxDevice).gdPMap)).pixelSize ;
+               else
+                       depth = 8 ; 
+       }
+               
+       err = NewGWorld( &port , depth , &rect , NULL , NULL , 0 ) ;
+       if ( err == noErr )
+       {
+               return port ;
+       }
+       return NULL ;
+} 
+
+void wxMacDestroyGWorld( GWorldPtr gw )
+{
+       if ( gw )
+               DisposeGWorld( gw ) ;
+}
 
 wxBitmapRefData::wxBitmapRefData()
 {
@@ -34,17 +104,43 @@ wxBitmapRefData::wxBitmapRefData()
     m_quality = 0;
     m_numColors = 0;
     m_bitmapMask = NULL;
+               m_hBitmap = NULL ;
+               m_hPict = NULL ;
+               m_bitmapType = kMacBitmapTypeUnknownType ;
 }
 
 wxBitmapRefData::~wxBitmapRefData()
 {
-    /*
-     * TODO: delete the bitmap data here.
-     */
-
-    if (m_bitmapMask)
-        delete m_bitmapMask;
+       switch (m_bitmapType)
+       {
+               case kMacBitmapTypePict :
+                       {
+                               if ( m_hPict )
+                               {
+                                       KillPicture( m_hPict ) ;
+                                       m_hPict = NULL ;
+                               }
+                       }
+                       break ;
+               case kMacBitmapTypeGrafWorld :
+                       {
+                               if ( m_hBitmap )
+                               {
+                                       wxMacDestroyGWorld( m_hBitmap ) ;
+                                       m_hBitmap = NULL ;
+                               }
+                       }
+                       break ;
+               default :
+                       // unkown type ?
+                       break ;
+       } ;
+       
+  if (m_bitmapMask)
+  {
+    delete m_bitmapMask;
     m_bitmapMask = NULL;
+  }
 }
 
 wxList wxBitmap::sm_handlers;
@@ -71,8 +167,57 @@ wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits
     M_BITMAPDATA->m_height = the_height ;
     M_BITMAPDATA->m_depth = no_bits ;
     M_BITMAPDATA->m_numColors = 0;
-
-    /* TODO: create the bitmap from data */
+               if ( no_bits == 1 )
+               {
+           M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
+           M_BITMAPDATA->m_hBitmap = wxMacCreateGWorld( the_width , the_height , no_bits ) ;
+                       M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
+       
+                       CGrafPtr        origPort ;
+                       GDHandle        origDevice ;
+                       
+                       GetGWorld( &origPort , &origDevice ) ;
+                       SetGWorld( M_BITMAPDATA->m_hBitmap , NULL ) ;
+       
+                       // bits is a word aligned array
+                       
+                       unsigned char* linestart = (unsigned char*) bits ;
+                       int linesize = ( the_width / 16 ) * 2  ;
+                       if ( the_width % 16 )
+                       {
+                               linesize += 2 ;
+                       } ;
+                       
+                       RGBColor colors[2] = { 
+                               { 0xFFFF , 0xFFFF , 0xFFFF } ,
+                               { 0, 0 , 0 } 
+                               } ;
+                       
+                       for( int y = 0 ; y < the_height ; ++y , linestart += linesize )
+                       {
+                               for( int x = 0 ; x < the_width ; ++x )
+                               {
+                                       int index = x / 8 ;
+                                       int bit = x % 8 ;
+                                       int mask = 1 << bit ;
+                                       if ( linestart[index] & mask )
+                                       {
+                                               SetCPixel( x , y , &colors[1] ) ;
+                                       }
+                                       else
+                                       {
+                                               SetCPixel( x , y , &colors[0] ) ;
+                                       }
+                               }
+                               
+                       }
+       
+               SetGWorld( origPort , origDevice ) ;
+          }
+          else
+          {
+                               //multicolor BITMAPs not yet implemented
+          }
 
     if ( wxTheBitmapList )
         wxTheBitmapList->AddBitmap(this);
@@ -102,13 +247,10 @@ wxBitmap::wxBitmap(const wxString& filename, long type)
         wxTheBitmapList->AddBitmap(this);
 }
 
-/* TODO: maybe allow creation from XPM
-// Create from data
 wxBitmap::wxBitmap(const char **data)
 {
     (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
 }
-*/
 
 bool wxBitmap::Create(int w, int h, int d)
 {
@@ -120,11 +262,19 @@ bool wxBitmap::Create(int w, int h, int d)
     M_BITMAPDATA->m_height = h;
     M_BITMAPDATA->m_depth = d;
 
-    /* TODO: create new bitmap */
-
+    M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
+    M_BITMAPDATA->m_hBitmap = wxMacCreateGWorld( w , h , d ) ;
+               M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
     return M_BITMAPDATA->m_ok;
 }
 
+void wxBitmap::SetHBITMAP(WXHBITMAP bmp)
+{
+    M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
+    M_BITMAPDATA->m_hBitmap = bmp ;
+               M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ;
+}
+
 bool wxBitmap::LoadFile(const wxString& filename, long type)
 {
     UnRef();
@@ -386,6 +536,52 @@ bool wxBitmapHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type,
  * Standard handlers
  */
 
+class WXDLLEXPORT wxPICTResourceHandler: public wxBitmapHandler
+{
+    DECLARE_DYNAMIC_CLASS(wxPICTResourceHandler)
+public:
+    inline wxPICTResourceHandler()
+    {
+        m_name = "Macintosh Pict resource";
+        m_extension = "";
+        m_type = wxBITMAP_TYPE_PICT_RESOURCE;
+    };
+
+    virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
+          int desiredWidth, int desiredHeight);
+};
+IMPLEMENT_DYNAMIC_CLASS(wxPICTResourceHandler, wxBitmapHandler)
+
+bool  wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
+          int desiredWidth, int desiredHeight)
+{
+       Str255 theName ;
+       
+       strcpy( (char*) theName , name ) ;
+       c2pstr( (char*) theName ) ;
+       
+       PicHandle thePict = (PicHandle ) GetNamedResource( 'PICT' , theName ) ;
+       if ( thePict )
+       {
+               PictInfo theInfo ;
+               
+               GetPictInfo( thePict , &theInfo , 0 , 0 , systemMethod , 0 ) ;
+               DetachResource( (Handle) thePict ) ;
+               M_BITMAPHANDLERDATA->m_bitmapType = kMacBitmapTypePict ;
+               M_BITMAPHANDLERDATA->m_hPict = thePict ;
+               M_BITMAPHANDLERDATA->m_width =  theInfo.sourceRect.right - theInfo.sourceRect.left ;
+               M_BITMAPHANDLERDATA->m_height = theInfo.sourceRect.bottom - theInfo.sourceRect.top ;
+               
+               M_BITMAPHANDLERDATA->m_depth = theInfo.depth ;
+               M_BITMAPHANDLERDATA->m_ok = true ;
+               M_BITMAPHANDLERDATA->m_numColors = theInfo.uniqueColors ;
+//             M_BITMAPHANDLERDATA->m_bitmapPalette;
+//             M_BITMAPHANDLERDATA->m_quality;
+               return TRUE ;
+       }
+       return FALSE ;
+}
+
 /* TODO: bitmap handlers, a bit like this:
 class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
 {
@@ -404,6 +600,251 @@ public:
 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
 */
 
+class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler
+{
+  DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
+public:
+  inline wxXPMFileHandler(void)
+  {
+  m_name = "XPM bitmap file";
+  m_extension = "xpm";
+  m_type = wxBITMAP_TYPE_XPM;
+  };
+
+  virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
+    int desiredWidth = -1, int desiredHeight = -1);
+  virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
+};
+IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
+
+bool wxXPMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
+    int desiredWidth, int desiredHeight)
+{
+#if USE_XPM_IN_MSW
+    XImage *ximage;
+    XpmAttributes xpmAttr;
+    HDC     dc;
+
+    M_BITMAPHANDLERDATA->m_ok = FALSE;
+    dc = CreateCompatibleDC(NULL);
+    if (dc)
+    {
+      xpmAttr.valuemask = XpmReturnPixels;
+      int errorStatus = XpmReadFileToImage(&dc, WXSTRINGCAST name, &ximage, (XImage **) NULL, &xpmAttr);
+      DeleteDC(dc);
+      if (errorStatus == XpmSuccess)
+      {
+        M_BITMAPHANDLERDATA->m_hBitmap = (WXHBITMAP) ximage->bitmap;
+
+        BITMAP  bm;
+        GetObject((HBITMAP)M_BITMAPHANDLERDATA->m_hBitmap, sizeof(bm), (LPSTR) & bm);
+
+        M_BITMAPHANDLERDATA->m_width = (bm.bmWidth);
+        M_BITMAPHANDLERDATA->m_height = (bm.bmHeight);
+        M_BITMAPHANDLERDATA->m_depth = (bm.bmPlanes * bm.bmBitsPixel);
+        M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
+        XpmFreeAttributes(&xpmAttr);
+        XImageFree(ximage);
+
+        M_BITMAPHANDLERDATA->m_ok = TRUE;
+        return TRUE;
+      }
+      else
+      {
+        M_BITMAPHANDLERDATA->m_ok = FALSE;
+        return FALSE;
+      }
+    }
+#endif
+
+    return FALSE;
+}
+
+bool wxXPMFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
+{
+#if USE_XPM_IN_MSW
+      HDC     dc = NULL;
+
+      Visual *visual = NULL;
+      XImage  ximage;
+
+      dc = CreateCompatibleDC(NULL);
+      if (dc)
+      {
+        if (SelectObject(dc, (HBITMAP) M_BITMAPHANDLERDATA->m_hBitmap))
+        { /* for following SetPixel */
+          /* fill the XImage struct 'by hand' */
+    ximage.width = M_BITMAPHANDLERDATA->m_width; 
+     ximage.height = M_BITMAPHANDLERDATA->m_height;
+    ximage.depth = M_BITMAPHANDLERDATA->m_depth; 
+     ximage.bitmap = (void *)M_BITMAPHANDLERDATA->m_hBitmap;
+    int errorStatus = XpmWriteFileFromImage(&dc, WXSTRINGCAST name,
+              &ximage, (XImage *) NULL, (XpmAttributes *) NULL);
+
+          if (dc)
+      DeleteDC(dc);
+
+    if (errorStatus == XpmSuccess)
+      return TRUE;    /* no error */
+    else
+      return FALSE;
+        } else return FALSE;
+      } else return FALSE;
+#else
+  return FALSE;
+#endif
+}
+
+
+class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
+{
+  DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
+public:
+  inline wxXPMDataHandler(void)
+  {
+  m_name = "XPM bitmap data";
+  m_extension = "xpm";
+  m_type = wxBITMAP_TYPE_XPM_DATA;
+  };
+
+  virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
+};
+IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
+
+bool wxXPMDataHandler::Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth)
+{
+               XImage *                ximage;
+       int                     ErrorStatus;
+       XpmAttributes   xpmAttr;
+
+    xpmAttr.valuemask = XpmReturnInfos; // get infos back
+    ErrorStatus = XpmCreateImageFromData( GetMainDevice() , (char **)data,
+         &ximage, (XImage **) NULL, &xpmAttr);
+
+    if (ErrorStatus == XpmSuccess)
+    {
+                       M_BITMAPHANDLERDATA->m_ok = FALSE;
+                       M_BITMAPHANDLERDATA->m_numColors = 0;
+                       M_BITMAPHANDLERDATA->m_hBitmap = ximage->gworldptr ;
+         
+                       M_BITMAPHANDLERDATA->m_width = ximage->width;
+                       M_BITMAPHANDLERDATA->m_height = ximage->height;
+                       M_BITMAPHANDLERDATA->m_depth = ximage->depth;
+                       M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
+       XpmFreeAttributes(&xpmAttr);
+           M_BITMAPHANDLERDATA->m_ok = TRUE;
+                       ximage->gworldptr = NULL ;
+                       XImageFree(ximage); // releases the malloc, but does not detroy
+                                 // the bitmap
+                       M_BITMAPHANDLERDATA->m_bitmapType = kMacBitmapTypeGrafWorld ;
+               
+                       return TRUE;
+    } 
+    else
+    {
+      M_BITMAPHANDLERDATA->m_ok = FALSE;
+      return FALSE;
+    }
+  return FALSE;
+}
+
+class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
+{
+    DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
+public:
+    inline wxBMPResourceHandler()
+    {
+        m_name = "Windows bitmap resource";
+        m_extension = "";
+        m_type = wxBITMAP_TYPE_BMP_RESOURCE;
+    };
+
+    virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
+          int desiredWidth, int desiredHeight);
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
+
+bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
+    int desiredWidth, int desiredHeight)
+{
+    // TODO: load colourmap.
+/*
+    M_BITMAPHANDLERDATA->m_hBitmap = (WXHBITMAP) ::LoadBitmap(wxGetInstance(), name);
+    if (M_BITMAPHANDLERDATA->m_hBitmap)
+    {
+      M_BITMAPHANDLERDATA->m_ok = TRUE;
+      BITMAP bm;
+      GetObject((HBITMAP) M_BITMAPHANDLERDATA->m_hBitmap, sizeof(BITMAP), (LPSTR) &bm);
+      M_BITMAPHANDLERDATA->m_width = bm.bmWidth;
+      M_BITMAPHANDLERDATA->m_height = bm.bmHeight;
+      M_BITMAPHANDLERDATA->m_depth = bm.bmBitsPixel;
+      return TRUE;
+    }
+*/
+  // it's probably not found
+  wxLogError("Can't load bitmap '%s' from resources! Check .rc file.", name.c_str());
+
+  return FALSE;
+}
+
+class WXDLLEXPORT wxBMPFileHandler: public wxBitmapHandler
+{
+  DECLARE_DYNAMIC_CLASS(wxBMPFileHandler)
+public:
+  inline wxBMPFileHandler(void)
+  {
+  m_name = "Windows bitmap file";
+  m_extension = "bmp";
+  m_type = wxBITMAP_TYPE_BMP;
+  };
+
+  virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
+      int desiredWidth, int desiredHeight);
+  virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
+
+bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
+    int desiredWidth, int desiredHeight)
+{
+#if USE_IMAGE_LOADING_IN_MSW
+    wxPalette *palette = NULL;
+    bool success = FALSE;
+/*
+    if (type & wxBITMAP_DISCARD_COLOURMAP)
+      success = wxLoadIntoBitmap(WXSTRINGCAST name, bitmap);
+    else
+*/
+    success = (wxLoadIntoBitmap(WXSTRINGCAST name, bitmap, &palette) != 0);
+    if (!success && palette)
+    {
+      delete palette;
+      palette = NULL;
+    }
+    if (palette)
+      M_BITMAPHANDLERDATA->m_bitmapPalette = *palette;
+    return success;
+#else
+  return FALSE;
+#endif
+}
+
+bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *pal)
+{
+#if USE_IMAGE_LOADING_IN_MSW
+    wxPalette *actualPalette = (wxPalette *)pal;
+    if (!actualPalette && (!M_BITMAPHANDLERDATA->m_bitmapPalette.IsNull()))
+      actualPalette = & (M_BITMAPHANDLERDATA->m_bitmapPalette);
+    return (wxSaveBitmap(WXSTRINGCAST name, bitmap, actualPalette) != 0);
+#else
+  return FALSE;
+#endif
+}
+
+
+
 void wxBitmap::CleanUpHandlers()
 {
     wxNode *node = sm_handlers.First();
@@ -419,12 +860,10 @@ void wxBitmap::CleanUpHandlers()
 
 void wxBitmap::InitStandardHandlers()
 {
-/* TODO: initialize all standard bitmap or derive class handlers here.
-    AddHandler(new wxBMPResourceHandler);
-    AddHandler(new wxBMPFileHandler);
-    AddHandler(new wxXPMFileHandler);
-    AddHandler(new wxXPMDataHandler);
-    AddHandler(new wxICOResourceHandler);
-    AddHandler(new wxICOFileHandler);
-*/
+       AddHandler( new wxPICTResourceHandler ) ;
+       AddHandler( new wxICONResourceHandler ) ;
+       AddHandler(new wxXPMFileHandler);
+  AddHandler(new wxXPMDataHandler);
+       AddHandler(new wxBMPResourceHandler);
+       AddHandler(new wxBMPFileHandler);
 }