diff --git a/src/generic/imaglist.cpp b/src/generic/imaglist.cpp index f7b34cea71..670d2b82fe 100644 --- a/src/generic/imaglist.cpp +++ b/src/generic/imaglist.cpp @@ -54,7 +54,7 @@ bool wxGenericImageList::Create( int width, int height, bool mask, int WXUNUSED( namespace { -wxBitmap GetImageListBitmap(const wxBitmap& bitmap, bool useMask) +wxBitmap GetImageListBitmap(const wxBitmap& bitmap, bool useMask, const wxSize& imgSize) { wxBitmap bmp(bitmap); if ( useMask ) @@ -115,7 +115,30 @@ wxBitmap GetImageListBitmap(const wxBitmap& bitmap, bool useMask) } } - return bmp; + // Ensure image size is the same as the size of the images on the image list. + wxBitmap bmpResized; + const wxSize sz = bmp.GetSize(); + if ( sz.x == imgSize.x && sz.y == imgSize.y ) + { + bmpResized = bmp; + } + else if ( sz.x > imgSize.x && sz.y > imgSize.y ) + { + wxRect r(0, 0, imgSize.x, imgSize.y); + bmpResized = bmp.GetSubBitmap(r); + } + else + { +#if wxUSE_IMAGE + wxImage img = bmp.ConvertToImage(); + wxImage imgResized = img.Size(imgSize, wxPoint(0, 0), 0, 0, 0); + bmpResized = imgResized; +#else + bmpResized = bmp; +#endif // wxUSE_IMAGE + } + + return bmpResized; } }; @@ -131,29 +154,27 @@ int wxGenericImageList::Add( const wxBitmap &bitmap ) // size: adopt the size of our first bitmap as image size. m_size = bitmapSize; } - else // We already have a fixed size, check that the bitmap conforms to it. + + // There is a special case: a bitmap may contain more than one image, + // in which case we're supposed to chop it in parts, just as Windows + // ImageList_Add() does. + if ( bitmapSize.x == m_size.x ) { - // There is a special case: a bitmap may contain more than one image, - // in which case we're supposed to chop it in parts, just as Windows - // ImageList_Add() does. - if ( bitmapSize.x > m_size.x && (bitmapSize.x % m_size.x == 0) ) - { - const int numImages = bitmapSize.x / m_size.x; - for (int subIndex = 0; subIndex < numImages; subIndex++) - { - wxRect rect(m_size.x * subIndex, 0, m_size.x, m_size.y); - Add(bitmap.GetSubBitmap(rect)); - } - - return GetImageCount() - 1; - } - - wxASSERT_MSG( bitmapSize == m_size, - "All bitmaps in wxImageList must have the same size" ); + m_images.push_back(GetImageListBitmap(bitmap, m_useMask, m_size)); + } + else if ( bitmapSize.x > m_size.x ) + { + const int numImages = bitmapSize.x / m_size.x; + for (int subIndex = 0; subIndex < numImages; subIndex++) + { + wxRect rect(m_size.x * subIndex, 0, m_size.x, m_size.y); + m_images.push_back(GetImageListBitmap(bitmap.GetSubBitmap(rect), m_useMask, m_size)); + } + } + else + { + return -1; } - - wxBitmap bmp = GetImageListBitmap(bitmap, m_useMask); - m_images.push_back(bmp); return GetImageCount() - 1; } @@ -175,8 +196,8 @@ int wxGenericImageList::Add( const wxBitmap& bitmap, const wxColour& maskColour const wxBitmap *wxGenericImageList::DoGetPtr( int index ) const { - wxCHECK_MSG( index >= 0 && (size_t)index < m_images.size(), - NULL, wxT("wrong index in image list") ); + if ( index < 0 || (size_t)index >= m_images.size() ) + return NULL; return &m_images[index]; } @@ -216,7 +237,7 @@ wxGenericImageList::Replace(int index, if ( mask.IsOk() ) bmp.SetMask(new wxMask(mask)); - m_images[index] = GetImageListBitmap(bmp, m_useMask); + m_images[index] = GetImageListBitmap(bmp, m_useMask, m_size); return true; } diff --git a/tests/graphics/imagelist.cpp b/tests/graphics/imagelist.cpp index a4ca7d6efb..67c478c2d6 100644 --- a/tests/graphics/imagelist.cpp +++ b/tests/graphics/imagelist.cpp @@ -195,6 +195,243 @@ TEST_CASE("ImageList:WithMask", "[imagelist][withmask]") CHECK(bmp2.GetWidth() == 32); CHECK(bmp2.GetHeight() == 32); } + + SECTION("Add images with incompatible sizes") + { + il.RemoveAll(); + wxSize sz = il.GetSize(); + + wxBitmap bmpSmallerW(sz.GetWidth() / 2, sz.GetHeight(), 24); + { + wxMemoryDC mdc(bmpSmallerW); + mdc.SetBackground(*wxBLUE_BRUSH); + mdc.Clear(); + } + REQUIRE(bmpSmallerW.IsOk()); + + wxBitmap bmpSmallerH(sz.GetWidth(), sz.GetHeight() / 2, 24); + { + wxMemoryDC mdc(bmpSmallerH); + mdc.SetBackground(*wxBLUE_BRUSH); + mdc.Clear(); + } + REQUIRE(bmpSmallerH.IsOk()); + + wxBitmap bmpSmallerWH(sz.GetWidth() / 2, sz.GetHeight() / 2, 24); + { + wxMemoryDC mdc(bmpSmallerWH); + mdc.SetBackground(*wxBLUE_BRUSH); + mdc.Clear(); + } + REQUIRE(bmpSmallerWH.IsOk()); + + wxBitmap bmpBiggerW(sz.GetWidth() * 3 / 2, sz.GetHeight(), 24); + { + wxMemoryDC mdc(bmpBiggerW); + mdc.SetBackground(*wxBLUE_BRUSH); + mdc.Clear(); + } + REQUIRE(bmpBiggerW.IsOk()); + + wxBitmap bmpBiggerW2x(sz.GetWidth() * 2, sz.GetHeight(), 24); + { + wxMemoryDC mdc(bmpBiggerW2x); + mdc.SetBackground(*wxBLUE_BRUSH); + mdc.Clear(); + } + REQUIRE(bmpBiggerW2x.IsOk()); + + wxBitmap bmpBiggerH(sz.GetWidth(), sz.GetHeight() * 3 / 2, 24); + { + wxMemoryDC mdc(bmpBiggerH); + mdc.SetBackground(*wxBLUE_BRUSH); + mdc.Clear(); + } + REQUIRE(bmpBiggerH.IsOk()); + + wxBitmap bmpBiggerH2x(sz.GetWidth(), sz.GetHeight() * 2, 24); + { + wxMemoryDC mdc(bmpBiggerH2x); + mdc.SetBackground(*wxBLUE_BRUSH); + mdc.Clear(); + } + REQUIRE(bmpBiggerH2x.IsOk()); + + wxBitmap bmpBiggerWH(sz.GetWidth() * 3 / 2, sz.GetHeight() * 3 / 2, 24); + { + wxMemoryDC mdc(bmpBiggerWH); + mdc.SetBackground(*wxBLUE_BRUSH); + mdc.Clear(); + } + REQUIRE(bmpBiggerWH.IsOk()); + + wxBitmap bmpBiggerWH2x(sz.GetWidth() * 2, sz.GetHeight() * 2, 24); + { + wxMemoryDC mdc(bmpBiggerWH2x); + mdc.SetBackground(*wxBLUE_BRUSH); + mdc.Clear(); + } + REQUIRE(bmpBiggerWH2x.IsOk()); + + // Adding + int cnt = il.GetImageCount(); + int idx = il.Add(bmpSmallerW); + CHECK(idx == -1); + CHECK(il.GetImageCount() == cnt); + + cnt = il.GetImageCount(); + idx = il.Add(bmpSmallerH); + CHECK(idx >= 0); + CHECK(il.GetImageCount() == cnt + 1); + wxBitmap bmp = il.GetBitmap(idx); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + idx = il.Add(bmpSmallerWH); + CHECK(idx == -1); + CHECK(il.GetImageCount() == cnt); + + cnt = il.GetImageCount(); + idx = il.Add(bmpBiggerW); + CHECK(idx >= 0); + CHECK(il.GetImageCount() == cnt + 1); + bmp = il.GetBitmap(idx); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + idx = il.Add(bmpBiggerW2x); + CHECK(idx >= 0); + CHECK(il.GetImageCount() == cnt + 2); + bmp = il.GetBitmap(idx); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + idx = il.Add(bmpBiggerH); + CHECK(idx >= 0); + CHECK(il.GetImageCount() == cnt + 1); + bmp = il.GetBitmap(idx); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + idx = il.Add(bmpBiggerH2x); + CHECK(idx >= 0); + CHECK(il.GetImageCount() == cnt + 1); + bmp = il.GetBitmap(idx); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + idx = il.Add(bmpBiggerWH); + CHECK(idx >= 0); + CHECK(il.GetImageCount() == cnt + 1); + bmp = il.GetBitmap(idx); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + idx = il.Add(bmpBiggerWH2x); + CHECK(idx >= 0); + CHECK(il.GetImageCount() == cnt + 2); + bmp = il.GetBitmap(idx); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + // Replacing + il.RemoveAll(); + + cnt = il.GetImageCount(); + bool ok = il.Replace(0, bmpRGBA); + CHECK(ok == false); + CHECK(il.GetImageCount() == cnt); + + // List with 1 image + idx = il.Add(bmpRGB); + CHECK(idx >= 0); + + cnt = il.GetImageCount(); + ok = il.Replace(0, bmpRGBA); + CHECK(ok == true); + CHECK(il.GetImageCount() == cnt); + bmp = il.GetBitmap(0); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + ok = il.Replace(0, bmpSmallerW); + CHECK(ok == true); + CHECK(il.GetImageCount() == cnt); + bmp = il.GetBitmap(0); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + ok = il.Replace(0, bmpSmallerH); + CHECK(ok == true); + CHECK(il.GetImageCount() == cnt); + bmp = il.GetBitmap(0); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + ok = il.Replace(0, bmpSmallerWH); + CHECK(ok == true); + CHECK(il.GetImageCount() == cnt); + bmp = il.GetBitmap(0); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + ok = il.Replace(0, bmpBiggerW); + CHECK(ok == true); + CHECK(il.GetImageCount() == cnt); + bmp = il.GetBitmap(0); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + ok = il.Replace(0, bmpBiggerW2x); + CHECK(ok == true); + CHECK(il.GetImageCount() == cnt); + bmp = il.GetBitmap(0); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + ok = il.Replace(0, bmpBiggerH); + CHECK(ok == true); + CHECK(il.GetImageCount() == cnt); + bmp = il.GetBitmap(0); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + ok = il.Replace(0, bmpBiggerH2x); + CHECK(ok == true); + CHECK(il.GetImageCount() == cnt); + bmp = il.GetBitmap(0); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + ok = il.Replace(0, bmpBiggerWH); + CHECK(ok == true); + CHECK(il.GetImageCount() == cnt); + bmp = il.GetBitmap(0); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + + cnt = il.GetImageCount(); + ok = il.Replace(0, bmpBiggerWH2x); + CHECK(ok == true); + CHECK(il.GetImageCount() == cnt); + bmp = il.GetBitmap(0); + CHECK(bmp.GetWidth() == sz.GetWidth()); + CHECK(bmp.GetHeight() == sz.GetHeight()); + } } TEST_CASE("ImageList:NoMask", "[imagelist][nomask]")