]> git.saurik.com Git - wxWidgets.git/commitdiff
Applied John L's patches for curson scaling, image resizing
authorRobert Roebling <robert@roebling.de>
Fri, 4 Mar 2005 18:33:57 +0000 (18:33 +0000)
committerRobert Roebling <robert@roebling.de>
Fri, 4 Mar 2005 18:33:57 +0000 (18:33 +0000)
    without scaling and the art provider resize bitmap patch.
    I'll look into adapting the generic file dialog to it.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@32598 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

14 files changed:
docs/latex/wx/artprov.tex
docs/latex/wx/cursor.tex
docs/latex/wx/image.tex
docs/latex/wx/rect.tex
include/wx/artprov.h
include/wx/gdicmn.h
include/wx/image.h
src/common/artprov.cpp
src/common/image.cpp
src/gtk/artgtk.cpp
src/gtk1/artgtk.cpp
src/mac/carbon/cursor.cpp
src/mac/classic/cursor.cpp
src/msw/cursor.cpp

index 5ed81edb2fe95906f428e678bb80971e09b52eaa..d0b0fde2b694ed8a4b40186d0cb482e6b893c104 100644 (file)
@@ -176,6 +176,12 @@ The bitmap if one of registered providers recognizes the ID or wxNullBitmap othe
 Same as \helpref{wxArtProvider::GetBitmap}{wxartprovidergetbitmap}, but
 return a wxIcon object (or wxNullIcon on failure).
 
+\func{static wxSize}{GetSize}{\param{const wxArtClient\& }{client}, \param{bool }{platform_default = false}}
+
+Returns the default size for the given art {\it client} by either using the topmost 
+wxArtProvider or if {\it platform_default} is \true then return a suitable default size for 
+{\it client} depending on the current platform.
+
 \membersection{wxArtProvider::PopProvider}\label{wxartproviderctor}
 
 \func{static bool}{PopProvider}{\void}
index 1992f48e3a85de7afe4813c5316d64a5b36c881d..3f3d1a5d2490e9414d62b7d9daea5ac750c61f7e 100644 (file)
@@ -77,10 +77,10 @@ Constructs a cursor using a cursor identifier.
 Constructs a cursor from a wxImage. The cursor is monochrome, colors with the RGB elements all greater
 than 127 will be foreground, colors less than this background. The mask (if any) will be used as transparent.
 
-In MSW the foreground will be white and the background black. The cursor is resized to 32x32
+In MSW the foreground will be white and the background black. If the cursor is larger than 32x32 it is resized.
 In GTK, the two most frequent colors will be used for foreground and background. The cursor will be displayed
 at the size of the image.
-On MacOS the cursor is resized to 16x16 and currently only shown as black/white (mask respected).
+On MacOS if the cursor is larger than 16x16 it is resized and currently only shown as black/white (mask respected).
 
 \func{}{wxCursor}{\param{const wxCursor\&}{ cursor}}
 
index c3169fae76060b208ed72ed38fb3089a6b6708cd..379ce7fb72b14c980ea7de68b67faa4e5d22e4b6 100644 (file)
@@ -545,6 +545,14 @@ Gets the green value of the mask colour.
 Gets the red value of the mask colour.
 
 
+\membersection{wxImage::GetOrFindMaskColour}\label{wximagegetgetorsetmaskcolour}
+
+\constfunc{bool}{GetOrFindMaskColour}{\param{unsigned char}{ *r}, \param{unsigned char}{ *g}, \param{unsigned char}{ *b}}
+
+Get the current mask colour or find a suitable unused colour that could be 
+used as a mask colour. Returns {\tt true} if the image currently has a mask.
+
+
 \membersection{wxImage::GetPalette}\label{wximagegetpalette}
 
 \constfunc{const wxPalette\&}{GetPalette}{\void}
@@ -831,8 +839,8 @@ Replaces the colour specified by {\it r1,g1,b1} by the colour {\it r2,g2,b2}.
 
 \func{wxImage \&}{Rescale}{\param{int}{ width}, \param{int}{ height}}
 
-Changes the size of the image in-place: after a call to this function, the
-image will have the given width and height.
+Changes the size of the image in-place by scaling it: after a call to this function, 
+the image will have the given width and height.
 
 Returns the (modified) image itself.
 
@@ -841,6 +849,24 @@ Returns the (modified) image itself.
 \helpref{Scale}{wximagescale}
 
 
+\membersection{wxImage::Resize}\label{wximageresize}
+
+\func{wxImage \&}{Resize}{\param{const wxSize\&}{ size}, \param{const wxPoint&}{ pos}, \param{int}{ red = -1}, \param{int}{ green = -1}, \param{int}{ blue = -1}}
+
+Changes the size of the image in-place without scaling it by adding either a border 
+with the given colour or cropping as necessary. The image is pasted into a new 
+image with the given {\it size} and background colour at the position {\it pos} 
+relative to the upper left of the new image. If {\it red = green = blue = -1} 
+then use either the  current mask colour if set or find, use, and set a 
+suitable mask colour for any newly exposed areas.
+
+Returns the (modified) image itself.
+
+\wxheading{See also}
+
+\helpref{Size}{wximagesize}
+
+
 \membersection{wxImage::Rotate}\label{wximagerotate}
 
 \func{wxImage}{Rotate}{\param{double}{ angle}, \param{const wxPoint\& }{rotationCentre},
@@ -979,6 +1005,22 @@ Example:
 \helpref{Rescale}{wximagerescale}
 
 
+\membersection{wxImage::Size}\label{wximagesize}
+
+\constfunc{wxImage}{Size}{\param{const wxSize\&}{ size}, \param{const wxPoint&}{ pos}, \param{int}{ red = -1}, \param{int}{ green = -1}, \param{int}{ blue = -1}}
+
+Returns a resized version of this image without scaling it by adding either a border 
+with the given colour or cropping as necessary. The image is pasted into a new 
+image with the given {\it size} and background colour at the position {\it pos} 
+relative to the upper left of the new image. If {\it red = green = blue = -1} 
+then use either the current mask colour if set or find, use, and set a 
+suitable mask colour for any newly exposed areas.
+
+\wxheading{See also}
+
+\helpref{Resize}{wximageresize}
+
+
 \membersection{wxImage::SetAlpha}\label{wximagesetalpha}
 
 \func{void}{SetAlpha}{\param{unsigned char *}{alpha = {\tt NULL}}}
@@ -1093,6 +1135,15 @@ be set directly. In that case you will have to get access to the image data
 using the \helpref{GetData}{wximagegetdata} method.
 
 
+\membersection{wxImage::SetRGB}\label{wximagesetrgbrect}
+
+\func{void}{SetRGB}{\param{wxRect \& }{rect}, \param{unsigned char }{red}, \param{unsigned char }{green}, \param{unsigned char }{blue}}
+
+Sets the colour of the pixels within the given rectangle. This routine performs
+bounds-checks for the coordinate so it can be considered a safe way to manipulate the
+data.
+
+
 \membersection{wxImage::operator $=$}\label{wximageassign}
 
 \func{wxImage\& }{operator $=$}{\param{const wxImage\& }{image}}
index b537fd15ac07b551ba1ba13494bed0e6203348f7..8e3c6bf1de5034fdaa109f39ba22effc793da38e 100644 (file)
@@ -239,6 +239,14 @@ Returns {\tt true} if this rectangle has a non empty intersection with the
 rectangle {\it rect} and {\tt false} otherwise.
 
 
+\membersection{wxRect::IsEmpty}\label{wxrectisempty}
+
+\constfunc{bool}{IsEmpty}{}
+
+Returns {\tt true} if this rectangle has a width or height less than or equal to 
+0 and {\tt false} otherwise.
+
+
 \membersection{wxRect::Offset}\label{wxrectoffset}
 
 \func{void}{Offset}{\param{wxCoord }{dx}, \param{wxCoord }{dy}}
index 4afdfad882bf7be2b237f68bec7fbd5d45e46400..3576b4bad5fc766c2f2e186eb45f7987c155bdc0 100644 (file)
@@ -137,6 +137,10 @@ public:
                           const wxArtClient& client = wxART_OTHER,
                           const wxSize& size = wxDefaultSize);
 
+    // Get the size of an icon from a specific wxArtClient, queries 
+    // the topmost provider if platform_dependent = false
+    static wxSize GetSize(const wxArtClient& client, bool platform_dependent = false);
+
 protected:
     friend class wxArtProviderModule;
     // Initializes default provider
@@ -146,6 +150,12 @@ protected:
     // Destroy caches & all providers
     static void CleanUpProviders();
 
+    // Get the default size of an icon for a specific client
+    virtual wxSize DoGetSize(const wxArtClient& client) 
+    {
+        return GetSize(client, true);
+    }
+                             
     // Derived classes must override this method to create requested
     // art resource. This method is called only once per instance's
     // lifetime for each requested wxArtID.
index a4541556166fb8025c444614c42f329f9028c0a4..968feded8829599274169eb1782dac932d6dc368 100644 (file)
@@ -346,6 +346,8 @@ public:
     wxSize GetSize() const { return wxSize(width, height); }
     void SetSize( const wxSize &s ) { width = s.GetWidth(); height = s.GetHeight(); }
 
+    bool IsEmpty() const { return (width <= 0) || (height <= 0); }
+
     wxPoint GetTopLeft() const { return GetPosition(); }
     wxPoint GetLeftTop() const { return GetTopLeft(); }
     void SetTopLeft(const wxPoint &p) { SetPosition(p); }
index 77a6cb84f36f47647197132c107cd4bbcdd9f7ef..61f54d16cf83fe33ad69e76f061bd5d150894da8 100644 (file)
@@ -178,7 +178,14 @@ public:
     wxImage Copy() const;
 
     // return the new image with size width*height
-    wxImage GetSubImage( const wxRect& ) const;
+    wxImage GetSubImage( const wxRect& rect) const;
+
+    // Paste the image or part of this image into an image of the given size at the pos
+    //  any newly exposed areas will be filled with the rgb colour
+    //  by default if r = g = b = -1 then fill with this image's mask colour or find and 
+    //  set a suitable mask colour
+    wxImage Size( const wxSize& size, const wxPoint& pos, 
+                  int r = -1, int g = -1, int b = -1 ) const;
 
     // pastes image into this instance and takes care of
     // the mask colour and out of bounds problems
@@ -192,6 +199,10 @@ public:
     // rescales the image in place
     wxImage& Rescale( int width, int height ) { return *this = Scale(width, height); }
 
+    // resizes the image in place
+    wxImage& Resize( const wxSize& size, const wxPoint& pos, 
+                     int r = -1, int g = -1, int b = -1 ) { return *this = Size(size, pos, r, g, b); }
+
     // Rotates the image about the given point, 'angle' radians.
     // Returns the rotated image, leaving this image intact.
     wxImage Rotate(double angle, const wxPoint & centre_of_rotation,
@@ -210,6 +221,7 @@ public:
 
     // these routines are slow but safe
     void SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b );
+    void SetRGB( const wxRect& rect, unsigned char r, unsigned char g, unsigned char b );
     unsigned char GetRed( int x, int y ) const;
     unsigned char GetGreen( int x, int y ) const;
     unsigned char GetBlue( int x, int y ) const;
@@ -280,6 +292,9 @@ public:
 
     // Mask functions
     void SetMaskColour( unsigned char r, unsigned char g, unsigned char b );
+    // Get the current mask colour or find a suitable colour
+    // returns true if using current mask colour
+    bool GetOrFindMaskColour( unsigned char *r, unsigned char *g, unsigned char *b ) const;
     unsigned char GetMaskRed() const;
     unsigned char GetMaskGreen() const;
     unsigned char GetMaskBlue() const;
index 0b8018556ccb48e23c5c77b8839988f54ed46a68..5ebdb6aaa2ae274d40b761635fdd21ed60f6ff18 100644 (file)
@@ -151,14 +151,16 @@ wxArtProviderCache *wxArtProvider::sm_cache = NULL;
 
 /*static*/ wxBitmap wxArtProvider::GetBitmap(const wxArtID& id,
                                              const wxArtClient& client,
-                                             const wxSize& size)
+                                             const wxSize& reqSize)
 {
     // safety-check against writing client,id,size instead of id,client,size:
     wxASSERT_MSG( client.Last() == _T('C'), _T("invalid 'client' parameter") );
 
     wxCHECK_MSG( sm_providers, wxNullBitmap, _T("no wxArtProvider exists") );
 
-    wxString hashId = wxArtProviderCache::ConstructHashID(id, client, size);
+    wxSize bestSize = (reqSize != wxDefaultSize) ? reqSize : GetSize(client);
+
+    wxString hashId = wxArtProviderCache::ConstructHashID(id, client, bestSize);
 
     wxBitmap bmp;
     if ( !sm_cache->GetBitmap(hashId, &bmp) )
@@ -166,15 +168,25 @@ wxArtProviderCache *wxArtProvider::sm_cache = NULL;
         for (wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst();
              node; node = node->GetNext())
         {
-            bmp = node->GetData()->CreateBitmap(id, client, size);
+            bmp = node->GetData()->CreateBitmap(id, client, bestSize);
             if ( bmp.Ok() )
             {
 #if wxUSE_IMAGE
-                if ( size != wxDefaultSize &&
-                     (bmp.GetWidth() != size.x || bmp.GetHeight() != size.y) )
+                int bmp_w = bmp.GetWidth();
+                int bmp_h = bmp.GetHeight();
+                // want default size but it's smaller, paste into transparent image
+                if ((reqSize == wxDefaultSize) && 
+                    (bmp_h < bestSize.x) && (bmp_w < bestSize.y))
+                {
+                     wxPoint offset((bestSize.x - bmp_w)/2, (bestSize.y - bmp_h)/2);
+                     wxImage img = bmp.ConvertToImage();
+                     img.Resize(bestSize, offset);
+                     bmp = wxBitmap(img);
+                }
+                else if ( (bmp_w != bestSize.x) || (bmp_h != bestSize.y) )
                 {
                     wxImage img = bmp.ConvertToImage();
-                    img.Rescale(size.x, size.y);
+                    img.Rescale(bestSize.x, bestSize.y);
                     bmp = wxBitmap(img);
                 }
 #endif
@@ -203,6 +215,42 @@ wxArtProviderCache *wxArtProvider::sm_cache = NULL;
     return icon;
 }
 
+#ifdef __WXGTK__
+    #include <gtk/gtk.h>
+    extern GtkIconSize wxArtClientToIconSize(const wxArtClient& client);
+#endif // __WXGTK__
+
+/*static*/ wxSize wxArtProvider::GetSize(const wxArtClient& client, 
+                                         bool platform_dependent)
+{
+    if (!platform_dependent)
+    {
+        wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst();
+        if (node)
+            return node->GetData()->DoGetSize(client);
+            
+        // else return platform dependent size
+    }    
+    
+#ifdef __WXGTK__
+    GtkIconSize gtk_size = wxArtClientToIconSize(client);
+    gint width, height;
+    gtk_icon_size_lookup( gtk_size, &width, &height);
+    return wxSize(width, height);
+#else 
+    if (client == wxART_TOOLBAR)
+        return wxSize(32, 32);
+    else if (client == wxART_MENU)
+        return wxSize(16, 15);
+    else if (client == wxART_CMN_DIALOG || client == wxART_MESSAGE_BOX)
+        return wxSize(32, 32);
+    else if (client == wxART_BUTTON)
+        return wxSize(16, 15);
+    else
+        return wxSize(16, 15); // this is arbitrary    
+#endif 
+}
+
 
 class wxArtProviderModule: public wxModule
 {
index 627bcadcf2bfa83415e41e4421cede5e506562ab..3f90f3238a6d7e123884dfbea2f8395c519e0b12 100644 (file)
@@ -603,6 +603,44 @@ wxImage wxImage::GetSubImage( const wxRect &rect ) const
     return image;
 }
 
+wxImage wxImage::Size( const wxSize& size, const wxPoint& pos, 
+                       int r_, int g_, int b_ ) const
+{
+    wxImage image;
+
+    wxCHECK_MSG( Ok(), image, wxT("invalid image") );
+    wxCHECK_MSG( (size.GetWidth() > 0) && (size.GetHeight() > 0), image, wxT("invalid size") );
+
+    int width = GetWidth(), height = GetHeight();
+    image.Create(size.GetWidth(), size.GetHeight(), false);
+
+    unsigned char r = (unsigned char)r_;
+    unsigned char g = (unsigned char)g_;
+    unsigned char b = (unsigned char)b_;
+    if ((r_ == -1) && (g_ == -1) && (b_ == -1))
+    {
+        GetOrFindMaskColour( &r, &g, &b );
+        image.SetMaskColour(r, g, b);
+    }
+
+    image.SetRGB(wxRect(), r, g, b);
+
+    wxRect subRect(pos.x, pos.y, width, height);
+    wxRect finalRect(0, 0, size.GetWidth(), size.GetHeight());
+
+    subRect.Intersect(finalRect);
+
+    if (!subRect.IsEmpty())
+    {
+        if ((subRect.GetWidth() == width) && (subRect.GetHeight() == height))
+            image.Paste(*this, pos.x, pos.y);
+        else
+            image.Paste(GetSubImage(subRect), pos.x, pos.y);
+    }
+
+    return image;
+}
+
 void wxImage::Paste( const wxImage &image, int x, int y )
 {
     wxCHECK_RET( Ok(), wxT("invalid image") );
@@ -633,6 +671,7 @@ void wxImage::Paste( const wxImage &image, int x, int y )
     if (height < 1) return;
 
     if ((!HasMask() && !image.HasMask()) ||
+        (HasMask() && !image.HasMask()) ||
        ((HasMask() && image.HasMask() &&
          (GetMaskRed()==image.GetMaskRed()) &&
          (GetMaskGreen()==image.GetMaskGreen()) &&
@@ -759,6 +798,42 @@ void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned c
     M_IMGDATA->m_data[ pos+2 ] = b;
 }
 
+void wxImage::SetRGB( const wxRect& rect_, unsigned char r, unsigned char g, unsigned char b )
+{
+    wxCHECK_RET( Ok(), wxT("invalid image") );
+
+    wxRect rect(rect_);
+    wxRect imageRect(0, 0, GetWidth(), GetHeight());
+    if ( rect == wxRect() )
+    {
+        rect = imageRect;
+    }
+    else
+    {
+        wxCHECK_RET( imageRect.Inside(rect.GetTopLeft()) && 
+                     imageRect.Inside(rect.GetBottomRight()), 
+                     wxT("invalid bounding rectangle") );
+    }
+
+    int x1 = rect.GetLeft(),
+        y1 = rect.GetTop(),
+        x2 = rect.GetRight() + 1,
+        y2 = rect.GetBottom() + 1;
+
+    unsigned char *data = NULL;
+    int x, y, width = GetWidth();
+    for (y = y1; y < y2; y++)
+    {
+        data = M_IMGDATA->m_data + (y*width + x1)*3;
+        for (x = x1; x < x2; x++)
+        {
+            *data++ = r;
+            *data++ = g;
+            *data++ = b;
+        }
+    }
+}
+
 unsigned char wxImage::GetRed( int x, int y ) const
 {
     wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
@@ -991,6 +1066,24 @@ void wxImage::SetMaskColour( unsigned char r, unsigned char g, unsigned char b )
     M_IMGDATA->m_hasMask = true;
 }
 
+bool wxImage::GetOrFindMaskColour( unsigned char *r, unsigned char *g, unsigned char *b ) const
+{
+    wxCHECK_MSG( Ok(), false, wxT("invalid image") );
+
+    if (M_IMGDATA->m_hasMask)
+    {
+        if (r) *r = M_IMGDATA->m_maskRed;
+        if (g) *g = M_IMGDATA->m_maskGreen;
+        if (b) *b = M_IMGDATA->m_maskBlue;
+        return true;
+    }
+    else
+    {
+        FindFirstUnusedColour(r, g, b);
+        return false;
+    }
+}
+
 unsigned char wxImage::GetMaskRed() const
 {
     wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
index 209c58e6748d19ce4ae4acac89c1b960b3a335af..47aa4c93db6a2f7ed2641bc82938611b264b644b 100644 (file)
@@ -125,7 +125,7 @@ static const char *wxArtIDToStock(const wxArtID& id)
     #undef ART
 }
 
-static GtkIconSize wxArtClientToIconSize(const wxArtClient& client)
+GtkIconSize wxArtClientToIconSize(const wxArtClient& client)
 {
     if (client == wxART_TOOLBAR)
         return GTK_ICON_SIZE_LARGE_TOOLBAR;
index 209c58e6748d19ce4ae4acac89c1b960b3a335af..47aa4c93db6a2f7ed2641bc82938611b264b644b 100644 (file)
@@ -125,7 +125,7 @@ static const char *wxArtIDToStock(const wxArtID& id)
     #undef ART
 }
 
-static GtkIconSize wxArtClientToIconSize(const wxArtClient& client)
+GtkIconSize wxArtClientToIconSize(const wxArtClient& client)
 {
     if (client == wxART_TOOLBAR)
         return GTK_ICON_SIZE_LARGE_TOOLBAR;
index 9a271f6b1c0d9d5bdb841a5c4051df3c50de1254..6bb1ff40bc832053aaee8cad880e87b89eac4ba8 100644 (file)
@@ -303,20 +303,40 @@ void wxCursor::CreateFromImage(const wxImage & image)
 {
     m_refData = new wxCursorRefData;
 
-    wxImage image16 = image.Scale(16,16) ;
-       unsigned char * rgbBits = image16.GetData();
+    int w = 16;
+    int h = 16;
+
+    int hotSpotX = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X);
+    int hotSpotY = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y);
+    int image_w = image.GetWidth();
+    int image_h = image.GetHeight();
+
+    wxASSERT_MSG( hotSpotX >= 0 && hotSpotX < image_w &&
+                  hotSpotY >= 0 && hotSpotY < image_h,
+                  _T("invalid cursor hot spot coordinates") );
+
+    wxImage image16(image); // final image of correct size
  
+    // if image is too small then place it in the center, resize it if too big
+    if ((w > image_w) && (h > image_h))
+    {
+        wxPoint offset((w - image_w)/2, (h - image_h)/2);
+        hotSpotX = hotSpotX + offset.x;
+        hotSpotY = hotSpotY + offset.y;
     
-    int w = image16.GetWidth()  ;
-    int h = image16.GetHeight() ;
+        image16 = image.Size(wxSize(w, h), offset);
+    }
+    else if ((w != image_w) || (h != image_h))
+    {
+        hotSpotX = int(hotSpotX * double(w) / double(image_w)); 
+        hotSpotY = int(hotSpotY * double(h) / double(image_h)); 
+
+        image16 = image.Scale(w, h);
+    }
+
+    unsigned char * rgbBits = image16.GetData();
     bool bHasMask = image16.HasMask() ;
 
-       int hotSpotX = image16.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X);
-    int hotSpotY = image16.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y);
-    if (hotSpotX < 0 || hotSpotX >= w)
-            hotSpotX = 0;
-    if (hotSpotY < 0 || hotSpotY >= h)
-            hotSpotY = 0;
             
     PixMapHandle pm = (PixMapHandle) NewHandleClear( sizeof (PixMap))  ;
     short extent = 16 ;
index b780a675c9baa1f7ced9d82fc0052de733569aff..475c473b9175661536f809326442edd07de9eb13 100644 (file)
@@ -130,20 +130,39 @@ void wxCursor::CreateFromImage(const wxImage & image)
 {
     m_refData = new wxCursorRefData;
 
-    wxImage image16 = image.Scale(16,16) ;
-       unsigned char * rgbBits = image16.GetData();
+    int w = 16;
+    int h = 16;
  
+    int hotSpotX = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X);
+    int hotSpotY = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y);
+    int image_w = image.GetWidth();
+    int image_h = image.GetHeight();
     
-    int w = image16.GetWidth()  ;
-    int h = image16.GetHeight() ;
-    bool bHasMask = image16.HasMask() ;
+    wxASSERT_MSG( hotSpotX >= 0 && hotSpotX < image_w &&
+                  hotSpotY >= 0 && hotSpotY < image_h,
+                  _T("invalid cursor hot spot coordinates") );
+
+    wxImage image16(image); // final image of correct size
+
+    // if image is too small then place it in the center, resize it if too big
+    if ((w > image_w) && (h > image_h))
+    {
+        wxPoint offset((w - image_w)/2, (h - image_h)/2);
+        hotSpotX = hotSpotX + offset.x;
+        hotSpotY = hotSpotY + offset.y;
+
+        image16 = image.Size(wxSize(w, h), offset);
+    }
+    else if ((w != image_w) || (h != image_h))
+    {
+        hotSpotX = int(hotSpotX * double(w) / double(image_w)); 
+        hotSpotY = int(hotSpotY * double(h) / double(image_h)); 
 
-       int hotSpotX = image16.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X);
-    int hotSpotY = image16.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y);
-    if (hotSpotX < 0 || hotSpotX >= w)
-            hotSpotX = 0;
-    if (hotSpotY < 0 || hotSpotY >= h)
-            hotSpotY = 0;
+        image16 = image.Scale(w, h);
+    }
+
+    unsigned char * rgbBits = image16.GetData();
+    bool bHasMask = image16.HasMask() ;
             
 #if 0
     // monochrome implementation
index f546bd06b30fbc86abb8574e1c57b5a8cc277b9e..23495af1aa1d2bf746ccabddde3879046251d7f4 100644 (file)
@@ -180,19 +180,37 @@ wxCursor::wxCursor(const wxImage& image)
     const int w = wxCursorRefData::GetStandardWidth();
     const int h = wxCursorRefData::GetStandardHeight();
 
-    const int hotSpotX = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X);
-    const int hotSpotY = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y);
+    int hotSpotX = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X);
+    int hotSpotY = image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y);
+    int image_w = image.GetWidth();
+    int image_h = image.GetHeight();
 
-    wxASSERT_MSG( hotSpotX >= 0 && hotSpotX < w &&
-                    hotSpotY >= 0 && hotSpotY < h,
+    wxASSERT_MSG( hotSpotX >= 0 && hotSpotX < image_w &&
+                  hotSpotY >= 0 && hotSpotY < image_h,
                   _T("invalid cursor hot spot coordinates") );
 
-    HCURSOR hcursor = wxBitmapToHCURSOR
-                      (
-                        wxBitmap(image.Scale(w, h)),
-                        hotSpotX,
-                        hotSpotY
-                      );
+    wxImage imageSized(image); // final image of correct size
+
+    // if image is too small then place it in the center, resize it if too big
+    if ((w > image_w) && (h > image_h))
+    {
+        wxPoint offset((w - image_w)/2, (h - image_h)/2);
+        hotSpotX = hotSpotX + offset.x;
+        hotSpotY = hotSpotY + offset.y;
+
+        imageSized = image.Size(wxSize(w, h), offset);
+    }
+    else if ((w != image_w) || (h != image_h))
+    {
+        hotSpotX = int(hotSpotX * double(w) / double(image_w)); 
+        hotSpotY = int(hotSpotY * double(h) / double(image_h)); 
+
+        imageSized = image.Scale(w, h);
+    }
+
+    HCURSOR hcursor = wxBitmapToHCURSOR( wxBitmap(imageSized), 
+                                         hotSpotX, hotSpotY );
+
     if ( !hcursor )
     {
         wxLogWarning(_("Failed to create cursor."));