From 1436ac65dff488759a1cef4582cac1b00733528d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 12 Mar 2014 22:54:42 +0000 Subject: [PATCH] Add support for loading icons in PNG format to wxImage. ICO files can contain data in PNG, as well as BMP, format in recent (i.e. from this millennium) versions of Windows, so check for this case in wxICOHandler and load such data using wxPNGHandler. See #15918. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_3_0_BRANCH@76127 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + src/common/imagbmp.cpp | 47 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/docs/changes.txt b/docs/changes.txt index 3074d1c7d3..6e358363d8 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -599,6 +599,7 @@ All (GUI): - Make wxHTML more efficient when displaying large tables (Kinaou Hervé). - Prevent wxGrid rows/columns from becoming too small on double click. - Fix wxGraphicsBitmap::ConvertToImage() when using Cairo. +- Support loading ICO files with data in PNG format (Artur Wieczorek). wxGTK: diff --git a/src/common/imagbmp.cpp b/src/common/imagbmp.cpp index ed6d4bff59..7cc667dbf9 100644 --- a/src/common/imagbmp.cpp +++ b/src/common/imagbmp.cpp @@ -1486,7 +1486,52 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream, if (offset != 0 && stream.SeekI(offset, wxFromCurrent) == wxInvalidOffset) return false; - bResult = LoadDib(image, stream, verbose, false /* not BMP */); +#if wxUSE_LIBPNG + // We can't fall back to loading an icon in the usual BMP format after + // trying to load it as PNG if we have an unseekable stream, so to + // avoid breaking the existing code which does successfully load icons + // from such streams, we only try to load them as PNGs if we can unwind + // back later. + // + // Ideal would be to modify LoadDib() to accept the first 8 bytes not + // coming from the stream but from the signature buffer below, as then + // we'd be able to load PNG icons from any kind of streams. + bool isPNG; + if ( stream.IsSeekable() ) + { + // Check for the PNG signature first to avoid wasting time on + // trying to load typical ICO files which are not PNGs at all. + static const unsigned char signaturePNG[] = + { + 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A + }; + static const int signatureLen = WXSIZEOF(signaturePNG); + + unsigned char signature[signatureLen]; + if ( !stream.ReadAll(signature, signatureLen) ) + return false; + + isPNG = memcmp(signature, signaturePNG, signatureLen) == 0; + + // Rewind to the beginning of the image in any case. + if ( stream.SeekI(-signatureLen, wxFromCurrent) == wxInvalidOffset ) + return false; + } + else // Not seekable stream + { + isPNG = false; + } + + if ( isPNG ) + { + wxPNGHandler handlerPNG; + bResult = handlerPNG.LoadFile(image, stream, verbose); + } + else +#endif // wxUSE_LIBPNG + { + bResult = LoadDib(image, stream, verbose, false /* not BMP */); + } bool bIsCursorType = (this->GetType() == wxBITMAP_TYPE_CUR) || (this->GetType() == wxBITMAP_TYPE_ANI); if ( bResult && bIsCursorType && nType == 2 ) {