Avoid bitmap scaling in wxArtProvider::GetBitmapBundle()

Instead of immediately constructing the bitmap with the requested size,
possibly by downscaling a higher-resolution bitmap, and then potentially
having to upscale it if we actually need a bitmap of a bigger size, just
retrieve the bitmap in the actually needed size from wxArtProvider when
needed.

This makes bitmaps obtained from wxArtProvider::GetBitmapBundle() look
good, rather than fuzzy and ugly, in high DPI if they're actually
available in the appropriate size.
This commit is contained in:
Vadim Zeitlin
2021-12-17 23:59:19 +00:00
parent 072390258c
commit f78db92462
3 changed files with 84 additions and 8 deletions

View File

@@ -234,14 +234,11 @@ protected:
return wxNullBitmap;
}
// Derived classes must override CreateBitmapBundle if they provide
// a bundle that cannot be represented through an ordinary bitmap.
// Default implementation creates a wxBitmapBundle which returns the
// specified art resource in whichever size it is being asked for.
virtual wxBitmapBundle CreateBitmapBundle(const wxArtID& id,
const wxArtClient& client,
const wxSize& size)
{
return wxBitmapBundle(CreateBitmap(id, client, size));
}
const wxSize& size);
virtual wxIconBundle CreateIconBundle(const wxArtID& WXUNUSED(id),
const wxArtClient& WXUNUSED(client))

View File

@@ -307,7 +307,9 @@ public:
@param client
wxArtClient identifier of the client (i.e. who is asking for the bitmap).
@param size
Default size for the returned bundle.
Default size for the returned bundle, i.e. the size of the bitmap
in normal DPI (this implies that wxWindow::FromDIP() must @e not be
used with it).
@return If any of the registered providers recognizes the ID in its
CreateBitmapBundle(), this bundle is returned. Otherwise, if any of

View File

@@ -138,6 +138,77 @@ wxArtProviderCache::ConstructHashID(const wxArtID& id,
wxString::Format(wxT("%d-%d"), size.x, size.y);
}
// ----------------------------------------------------------------------------
// wxBitmapBundleImplArt: uses art provider to get the bitmaps
// ----------------------------------------------------------------------------
namespace
{
class wxBitmapBundleImplArt : public wxBitmapBundleImpl
{
public:
wxBitmapBundleImplArt(const wxArtID& id,
const wxArtClient& client,
const wxSize& size)
: m_artId(id),
m_artClient(client),
m_sizeDefault(GetValidSize(id, client, size))
{
}
virtual wxSize GetDefaultSize() const wxOVERRIDE
{
return m_sizeDefault;
}
virtual wxSize GetPreferredSizeAtScale(double scale) const wxOVERRIDE
{
// We have no preferred sizes.
return m_sizeDefault*scale;
}
virtual wxBitmap GetBitmap(const wxSize& size) wxOVERRIDE
{
return wxArtProvider::GetBitmap(m_artId, m_artClient, size);
}
private:
static wxSize GetValidSize(const wxArtID& id,
const wxArtClient& client,
const wxSize& size)
{
// If valid size is provided, just use it.
if ( size != wxDefaultSize )
return size;
// Otherwise, try to get the size we'd use without creating a bitmap
// immediately.
const wxSize sizeHint = wxArtProvider::GetSizeHint(client);
if ( sizeHint != wxDefaultSize )
return sizeHint;
// If we really have to, do create a bitmap just to get its size. Note
// we need the size in logical pixels here, it will be scaled later if
// necessary, so use GetScaledSize() and not GetSize().
const wxBitmap bitmap = wxArtProvider::GetBitmap(id, client);
if ( bitmap.IsOk() )
return bitmap.GetScaledSize();
// We really need some default size, so just return this hardcoded
// value if all else fails -- what else can we do.
return wxSize(16, 16);
}
const wxArtID m_artId;
const wxArtClient m_artClient;
const wxSize m_sizeDefault;
wxDECLARE_NO_COPY_CLASS(wxBitmapBundleImplArt);
};
} // anonymous namespace
// ============================================================================
// wxArtProvider class
// ============================================================================
@@ -305,7 +376,7 @@ wxBitmapBundle wxArtProvider::GetBitmapBundle(const wxArtID& id,
wxCHECK_MSG( sm_providers, wxNullBitmap, wxT("no wxArtProvider exists") );
wxString hashId = wxArtProviderCache::ConstructHashID(id, client);
wxString hashId = wxArtProviderCache::ConstructHashID(id, client, size);
wxBitmapBundle bitmapbundle; // (DoGetIconBundle(id, client));
@@ -325,6 +396,12 @@ wxBitmapBundle wxArtProvider::GetBitmapBundle(const wxArtID& id,
return bitmapbundle;
}
wxBitmapBundle wxArtProvider::CreateBitmapBundle(const wxArtID& id,
const wxArtClient& client,
const wxSize& size)
{
return wxBitmapBundle::FromImpl(new wxBitmapBundleImplArt(id, client, size));
}
/*static*/
wxIconBundle wxArtProvider::GetIconBundle(const wxArtID& id, const wxArtClient& client)