From 0b0e95296a8a91aa61de00c0c903804555c884a2 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 1 Jun 2022 19:12:16 +0100 Subject: [PATCH] Upscale images by integer factors only Doing anything else results in really poor results, so don't even try scaling images by 2.25, for example -- scaling by 2 looks much better and the size difference is relatively insignificant and definitely not worth the difference in quality. --- src/common/bmpbndl.cpp | 13 +++++++++++-- tests/graphics/bmpbundle.cpp | 34 +++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/common/bmpbndl.cpp b/src/common/bmpbndl.cpp index a5300fbb9d..bd00552003 100644 --- a/src/common/bmpbndl.cpp +++ b/src/common/bmpbndl.cpp @@ -738,9 +738,18 @@ wxBitmapBundleImpl::DoGetPreferredSize(double scaleTarget, const double scaleMax = availableScales[n - 1]; // But check how far is it from the requested scale: if it's more than - // 1.5 times smaller, we should still scale it, notably to ensure that + // 1.5 times larger, we should still scale it, notably to ensure that // bitmaps of standard size are scaled when 2x DPI scaling is used. - scaleBest = scaleTarget / scaleMax >= 1.5 ? scaleTarget : scaleMax; + if ( scaleTarget >= 1.5*scaleMax ) + { + // However scaling by non-integer scales doesn't work well at all, so + // round it to the closest integer in this case. + scaleBest = wxRound(scaleTarget); + } + else // Target scale is not much greater than the biggest one we have. + { + scaleBest = scaleMax; + } } return GetDefaultSize()*scaleBest; diff --git a/tests/graphics/bmpbundle.cpp b/tests/graphics/bmpbundle.cpp index a703fe0bec..17367b02b4 100644 --- a/tests/graphics/bmpbundle.cpp +++ b/tests/graphics/bmpbundle.cpp @@ -51,13 +51,36 @@ TEST_CASE("BitmapBundle::FromBitmaps", "[bmpbundle]") TEST_CASE("BitmapBundle::GetPreferredSize", "[bmpbundle]") { - CHECK( wxBitmapBundle().GetPreferredBitmapSizeAtScale(1) == wxDefaultSize ); + // Check that empty bundle doesn't have any preferred size. + wxBitmapBundle b; + CHECK( b.GetPreferredBitmapSizeAtScale(1) == wxDefaultSize ); const wxSize normal(32, 32); const wxSize bigger(64, 64); + const wxSize triple(96, 96); - const wxBitmapBundle - b = wxBitmapBundle::FromBitmaps(wxBitmap(normal), wxBitmap(bigger)); + + // Then check what happens if there is only a single bitmap. + b = wxBitmapBundle::FromBitmap(wxBitmap(normal)); + + // We should avoid scaling as long as the size is close enough to the + // actual bitmap size. + CHECK( b.GetPreferredBitmapSizeAtScale(0 ) == normal ); + CHECK( b.GetPreferredBitmapSizeAtScale(1 ) == normal ); + CHECK( b.GetPreferredBitmapSizeAtScale(1.25) == normal ); + CHECK( b.GetPreferredBitmapSizeAtScale(1.4 ) == normal ); + + // Once it becomes too big, we're going to need to scale, but we should be + // scaling by an integer factor. + CHECK( b.GetPreferredBitmapSizeAtScale(1.5 ) == bigger ); + CHECK( b.GetPreferredBitmapSizeAtScale(1.75) == bigger ); + CHECK( b.GetPreferredBitmapSizeAtScale(2 ) == bigger ); + CHECK( b.GetPreferredBitmapSizeAtScale(2.25) == bigger ); + CHECK( b.GetPreferredBitmapSizeAtScale(2.5 ) == triple ); + + + // Now check what happens when there is also a double size bitmap. + b = wxBitmapBundle::FromBitmaps(wxBitmap(normal), wxBitmap(bigger)); // Check that the existing bitmaps are used without scaling for most of the // typical scaling values. @@ -71,8 +94,9 @@ TEST_CASE("BitmapBundle::GetPreferredSize", "[bmpbundle]") CHECK( b.GetPreferredBitmapSizeAtScale(2.5 ) == bigger ); // This scale is too big to use any of the existing bitmaps, so they will - // be scaled. - CHECK( b.GetPreferredBitmapSizeAtScale(3 ) == 3*normal ); + // be scaled, but use integer factors. + CHECK( b.GetPreferredBitmapSizeAtScale(3 ) == triple ); + CHECK( b.GetPreferredBitmapSizeAtScale(3.33) == triple ); } #ifdef wxHAS_DPI_INDEPENDENT_PIXELS