Merge branch 'more-icon-fixes'

More icon fixes in wxMSW: fix transparency in wxImageList and size in
wxArtProvider.

See #22487.
This commit is contained in:
Vadim Zeitlin
2022-06-05 13:16:19 +01:00
2 changed files with 62 additions and 53 deletions

View File

@@ -304,6 +304,30 @@ void wxArtProvider::RescaleBitmap(wxBitmap& bmp, const wxSize& sizeNeeded)
}
#endif // WXWIN_COMPATIBILITY_3_0
#if wxUSE_IMAGE
namespace
{
bool CanUpscaleByInt(int w, int h, const wxSize& sizeNeeded)
{
return !(sizeNeeded.x % w) && !(sizeNeeded.y % h);
}
void ExtendBitmap(wxBitmap& bmp, const wxSize& sizeNeeded)
{
const wxSize size = bmp.GetSize();
wxPoint offset((sizeNeeded.x - size.x)/2, (sizeNeeded.y - size.y)/2);
wxImage img = bmp.ConvertToImage();
img.Resize(sizeNeeded, offset);
bmp = wxBitmap(img);
}
} // anonymous namespace
#endif // wxUSE_IMAGE
void
wxArtProvider::RescaleOrResizeIfNeeded(wxBitmap& bmp, const wxSize& sizeNeeded)
{
@@ -317,25 +341,42 @@ wxArtProvider::RescaleOrResizeIfNeeded(wxBitmap& bmp, const wxSize& sizeNeeded)
return;
#if wxUSE_IMAGE
// Allow upscaling by an integer factor: this looks not too horribly and is
// needed to use reasonably-sized bitmaps in the code not yet updated to
// use wxBitmapBundle but using custom art providers.
if ((bmp_w <= sizeNeeded.x) && (bmp_h <= sizeNeeded.y) &&
(sizeNeeded.x % bmp_w || sizeNeeded.y % bmp_h))
// Check if we need to increase or decrease the image size (mixed case is
// handled as decreasing).
if ((bmp_w <= sizeNeeded.x) && (bmp_h <= sizeNeeded.y))
{
// Allow upscaling by an integer factor: this looks not too horribly and is
// needed to use reasonably-sized bitmaps in the code not yet updated to
// use wxBitmapBundle but using custom art providers.
bool shouldUpscale = CanUpscaleByInt(bmp_w, bmp_h, sizeNeeded);
// And account for the common case of 16x15 bitmaps used for many wxMSW
// images: those can be resized to 16x16 and then upscaled if possible
// (and if 16x16 is the required size, there is no need to upscale, so
// don't handle this sub-case specially at all).
if (!shouldUpscale && bmp_w == 16 && bmp_h == 15 && sizeNeeded.y != 16)
{
// If we can't upscale it with its current height, perhaps we can
// if we resize it to 16 first?
if (CanUpscaleByInt(bmp_w, 16, sizeNeeded))
{
ExtendBitmap(bmp, wxSize(16, 16));
shouldUpscale = true;
}
}
// the caller wants default size, which is larger than
// the image we have; to avoid degrading it visually by
// scaling it up, paste it into transparent image instead:
wxPoint offset((sizeNeeded.x - bmp_w)/2, (sizeNeeded.y - bmp_h)/2);
wxImage img = bmp.ConvertToImage();
img.Resize(sizeNeeded, offset);
bmp = wxBitmap(img);
if (!shouldUpscale)
{
ExtendBitmap(bmp, sizeNeeded);
return;
}
}
else // scale (down or mixed, but not up, or at least not by an int factor)
#endif // wxUSE_IMAGE
{
wxBitmap::Rescale(bmp, sizeNeeded);
}
wxBitmap::Rescale(bmp, sizeNeeded);
}
/*static*/ wxBitmap wxArtProvider::GetBitmap(const wxArtID& id,

View File

@@ -328,26 +328,11 @@ int wxImageList::Add(const wxBitmap& bitmap, const wxColour& maskColour)
// Adds a bitmap and mask from an icon.
int wxImageList::Add(const wxIcon& icon)
{
// ComCtl32 prior 6.0 doesn't support images with alpha
// channel so if we have 32-bit icon with transparency
// we need to add it as a wxBitmap via dedicated method
// where alpha channel will be converted to the mask.
if ( wxApp::GetComCtl32Version() < 600 )
{
wxBitmap bmp(icon);
if ( bmp.HasAlpha() )
{
return Add(bmp);
}
}
int index = ImageList_AddIcon(GetHImageList(), GetHiconOf(icon));
if ( index == -1 )
{
wxLogError(_("Couldn't add an image to the image list."));
}
return index;
// We don't use ImageList_AddIcon() here as this only works for icons with
// masks when using ILC_MASK, which we usually don't do, so reuse the
// bitmap function instead -- even if it's slightly less efficient due to
// extra conversions, it's simpler than handling all the various cases here.
return Add(wxBitmap(icon));
}
// Replaces a bitmap, optionally passing a mask bitmap.
@@ -372,26 +357,9 @@ bool wxImageList::Replace(int index,
// Replaces a bitmap and mask from an icon.
bool wxImageList::Replace(int i, const wxIcon& icon)
{
// ComCtl32 prior 6.0 doesn't support images with alpha
// channel so if we have 32-bit icon with transparency
// we need to replace it as a wxBitmap via dedicated method
// where alpha channel will be converted to the mask.
if ( wxApp::GetComCtl32Version() < 600 )
{
wxBitmap bmp(icon);
if ( bmp.HasAlpha() )
{
return Replace(i, bmp);
}
}
bool ok = ImageList_ReplaceIcon(GetHImageList(), i, GetHiconOf(icon)) != -1;
if ( !ok )
{
wxLogLastError(wxT("ImageList_ReplaceIcon()"));
}
return ok;
// Same as in Add() above, just reuse the existing function for simplicity
// even if it means an extra conversion.
return Replace(i, wxBitmap(icon));
}
// Removes the image at the given index.