Fix scale computation in wxBitmapBundle for some bitmap sizes

GetNextAvailableScale() returned wrong result when the bitmap size was
not exactly divisible by the scale, but this didn't matter for square
bitmaps because multiplying the default size by the not quite correct
scale still rounded to the correct size.

This was not the case for non-square bitmaps, however, as all our
computations use only bitmap height and dividing bitmap width by the
exact scale and multiplying it by the scale computed from the scaled and
unscaled height values could result in a value different from the
initial one, as shown by the newly added unit test, which failed before
this commit.

Fix this by computing the ratio of the bitmap to the base one and then
multiplying this ratio by the bitmap scale.

Closes #24433.
This commit is contained in:
Vadim Zeitlin
2024-03-22 18:48:10 +01:00
parent 3f7ed1fc8d
commit d94de56783
2 changed files with 23 additions and 1 deletions
+15 -1
View File
@@ -248,7 +248,21 @@ double wxBitmapBundleImplSet::GetNextAvailableScale(size_t& i) const
if ( entry.generated )
continue;
return static_cast<double>(entry.bitmap.GetSize().y) / GetDefaultSize().y;
const wxBitmap& bitmap = entry.bitmap;
// Determining the scale is not as simple as just dividing the bitmap
// height by the bundle height, because this could give us a scale
// different from the one actually used by the bitmap: e.g. the size of
// a bundle constructed from a single 16x16 bitmap using 1.5 scale
// would be 11x11 and 16/11 != 1.5 that we want.
//
// So instead compute the ratio of the bitmap size in DIPs to the
// bundle size, which uses the same rounding, and then multiply it by
// the scale factor of the bitmap to get the real scale.
const double ratio =
static_cast<double>(bitmap.GetDIPSize().y) / GetDefaultSize().y;
return ratio * bitmap.GetScaleFactor();
}
return 0.0;
+8
View File
@@ -313,6 +313,14 @@ TEST_CASE("BitmapBundle::GetPreferredSize", "[bmpbundle]")
CHECK_THAT( BitmapAtScale(b, 4.25), SameAs(4.0, 2.0) );
CHECK_THAT( BitmapAtScale(b, 4.50), SameAs(4.5, 1.5) );
CHECK_THAT( BitmapAtScale(b, 5 ), SameAs(5.0, 1.0) );
// Another check to detect that the scale is computed correctly even when
// rounding is involved.
wxBitmap nonSquare(wxSize(51, 41));
nonSquare.SetScaleFactor(1.5);
b = wxBitmapBundle::FromBitmap(nonSquare);
CHECK( b.GetPreferredBitmapSizeAtScale(1.5) == nonSquare.GetSize() );
}
#ifdef wxHAS_DPI_INDEPENDENT_PIXELS