]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/image.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / image.cpp
index 0cb1adf7886f143d508fd58617e1b0260fbb89fa..2c61998e6d3c226b9822dcd4750d60a75f2b61a9 100644 (file)
@@ -142,6 +142,7 @@ bool wxImage::Create(const char* const* xpmData)
     (*this) = decoder.ReadData(xpmData);
     return IsOk();
 #else
+    wxUnusedVar(xpmData);
     return false;
 #endif
 }
@@ -2234,10 +2235,105 @@ bool wxImage::HasOption(const wxString& name) const
 // image I/O
 // ----------------------------------------------------------------------------
 
-bool wxImage::LoadFile( const wxString& WXUNUSED_UNLESS_STREAMS(filename),
-                        wxBitmapType WXUNUSED_UNLESS_STREAMS(type),
+// Under Windows we can load wxImage not only from files but also from
+// resources.
+#if defined(__WINDOWS__) && wxUSE_WXDIB && wxUSE_IMAGE
+    #define HAS_LOAD_FROM_RESOURCE
+#endif
+
+#ifdef HAS_LOAD_FROM_RESOURCE
+
+#include "wx/msw/dib.h"
+#include "wx/msw/private.h"
+
+static wxImage LoadImageFromResource(const wxString &name, wxBitmapType type)
+{
+    AutoHBITMAP
+        hBitmap,
+        hMask;
+
+    if ( type == wxBITMAP_TYPE_BMP_RESOURCE )
+    {
+        hBitmap.Init( ::LoadBitmap(wxGetInstance(), name.t_str()) );
+
+        if ( !hBitmap )
+        {
+            wxLogError(_("Failed to load bitmap \"%s\" from resources."), name);
+        }
+    }
+    else if ( type == wxBITMAP_TYPE_ICO_RESOURCE )
+    {
+        const HICON hIcon = ::LoadIcon(wxGetInstance(), name.t_str());
+
+        if ( !hIcon )
+        {
+            wxLogError(_("Failed to load icon \"%s\" from resources."), name);
+        }
+        else
+        {
+            ICONINFO info;
+            if ( !::GetIconInfo(hIcon, &info) )
+            {
+                wxLogLastError(wxT("GetIconInfo"));
+                return wxImage();
+            }
+
+            hBitmap.Init(info.hbmColor);
+            hMask.Init(info.hbmMask);
+        }
+    }
+    else if ( type == wxBITMAP_TYPE_CUR_RESOURCE )
+    {
+        wxLogDebug(wxS("Loading cursors from resources is not implemented."));
+    }
+    else
+    {
+        wxFAIL_MSG(wxS("Invalid bitmap resource type."));
+    }
+
+    if ( !hBitmap )
+        return wxImage();
+
+    wxImage image = wxDIB(hBitmap).ConvertToImage();
+    if ( hMask )
+    {
+        const wxImage mask = wxDIB(hMask).ConvertToImage();
+        image.SetMaskFromImage(mask, 255, 255, 255);
+    }
+    else
+    {
+        // Light gray colour is a default mask
+        image.SetMaskColour(0xc0, 0xc0, 0xc0);
+    }
+
+    // We could have already loaded alpha from the resources, but if not,
+    // initialize it now using the mask.
+    if ( !image.HasAlpha() )
+        image.InitAlpha();
+
+    return image;
+}
+
+#endif // HAS_LOAD_FROM_RESOURCE
+
+bool wxImage::LoadFile( const wxString& filename,
+                        wxBitmapType type,
                         int WXUNUSED_UNLESS_STREAMS(index) )
 {
+#ifdef HAS_LOAD_FROM_RESOURCE
+    if (   type == wxBITMAP_TYPE_BMP_RESOURCE
+        || type == wxBITMAP_TYPE_ICO_RESOURCE
+        || type == wxBITMAP_TYPE_CUR_RESOURCE)
+    {
+        const wxImage image = ::LoadImageFromResource(filename, type);
+        if ( image.IsOk() )
+        {
+            *this = image;
+            return true;
+        }
+    }
+#endif // HAS_LOAD_FROM_RESOURCE
+
 #if HAS_FILE_STREAMS
     wxImageFileInputStream stream(filename);
     if ( stream.IsOk() )
@@ -2450,7 +2546,17 @@ bool wxImage::DoLoad(wxImageHandler& handler, wxInputStream& stream, int index)
         }
 
         if ( width != widthOrig || height != heightOrig )
+        {
+            // get the original size if it was set by the image handler
+            // but also in order to restore it after Rescale
+            int widthOrigOption = GetOptionInt(wxIMAGE_OPTION_ORIGINAL_WIDTH),
+                heightOrigOption = GetOptionInt(wxIMAGE_OPTION_ORIGINAL_HEIGHT);
+
             Rescale(width, height, wxIMAGE_QUALITY_HIGH);
+
+            SetOption(wxIMAGE_OPTION_ORIGINAL_WIDTH, widthOrigOption ? widthOrigOption : widthOrig);
+            SetOption(wxIMAGE_OPTION_ORIGINAL_HEIGHT, heightOrigOption ? heightOrigOption : heightOrig);
+        }
     }
 
     // Set this after Rescale, which currently does not preserve it
@@ -2565,6 +2671,7 @@ bool wxImage::SaveFile( wxOutputStream& stream, const wxString& mimetype ) const
     if ( !handler )
     {
         wxLogWarning( _("No image handler for type %s defined."), mimetype.GetData() );
+        return false;
     }
 
     return DoSave(*handler, stream);