Really fix setting wxBitmap scale factor

Optimization of 2ae80673ff (Avoid unnecessarily unsharing bitmaps in
wxMSW, 2022-02-02) broke setting the scale factor because we didn't
update the right bitmap data in case bitmap hadn't had exclusive
ownership of its data before. Fix this by not using a reference which
may refer to another object after AllocExclusive() call.

Also change the other ports to unshared the bitmap when modifying its
scale factor so that the new unit test passes for them too.
This commit is contained in:
Vadim Zeitlin
2022-02-10 13:13:59 +00:00
parent eaa769a73a
commit 20d1188e82
4 changed files with 40 additions and 5 deletions

View File

@@ -1001,7 +1001,12 @@ void wxBitmap::SetScaleFactor(double scale)
{ {
wxCHECK_RET(m_refData, "invalid bitmap"); wxCHECK_RET(m_refData, "invalid bitmap");
M_BMPDATA->m_scaleFactor = scale; if ( M_BMPDATA->m_scaleFactor != scale )
{
AllocExclusive();
M_BMPDATA->m_scaleFactor = scale;
}
} }
double wxBitmap::GetScaleFactor() const double wxBitmap::GetScaleFactor() const

View File

@@ -346,12 +346,13 @@ void wxGDIImage::SetScaleFactor(double scale)
{ {
wxCHECK_RET( IsOk(), wxT("invalid bitmap") ); wxCHECK_RET( IsOk(), wxT("invalid bitmap") );
double& scaleCurrent = GetGDIImageData()->m_scaleFactor; if ( GetGDIImageData()->m_scaleFactor != scale )
if ( scale != scaleCurrent )
{ {
AllocExclusive(); AllocExclusive();
scaleCurrent = scale; // Note that GetGDIImageData() result may have changed after calling
// AllocExclusive(), so don't be tempted to optimize it.
GetGDIImageData()->m_scaleFactor = scale;
} }
} }

View File

@@ -1391,7 +1391,12 @@ void wxBitmap::SetScaleFactor(double scale)
{ {
wxCHECK_RET( IsOk(), wxT("invalid bitmap") ); wxCHECK_RET( IsOk(), wxT("invalid bitmap") );
return GetBitmapData()->SetScaleFactor(scale) ; if ( GetBitmapData()->GetScaleFactor() != scale )
{
AllocExclusive();
GetBitmapData()->SetScaleFactor(scale) ;
}
} }
double wxBitmap::GetScaleFactor() const double wxBitmap::GetScaleFactor() const

View File

@@ -159,3 +159,27 @@ TEST_CASE("BitmapBundle::ArtProvider", "[bmpbundle][art]")
CHECK( b.IsOk() ); CHECK( b.IsOk() );
CHECK( b.GetDefaultSize() == size ); CHECK( b.GetDefaultSize() == size );
} }
// This test only makes sense for the ports that actually support scaled
// bitmaps, which is the case for the ports using real logical pixels (they
// have to support bitmap scale for things to work) and MSW, which doesn't, but
// still implements support for at least storing and retrieving bitmap scale in
// its wxBitmap.
#if defined(wxHAS_DPI_INDEPENDENT_PIXELS) || defined(__WXMSW__)
TEST_CASE("BitmapBundle::Scale", "[bmpbundle][scale]")
{
// This is not a wxBitmapBundle test, strictly speaking, but check that
// setting scale factor works correctly for bitmaps, as wxBitmapBundle does
// this internally.
wxBitmap bmp(16, 16);
bmp.SetScaleFactor(2);
CHECK( bmp.GetScaleFactor() == 2 );
wxBitmap bmp2(bmp);
bmp.SetScaleFactor(3);
CHECK( bmp2.GetScaleFactor() == 2 );
CHECK( bmp.GetScaleFactor() == 3 );
}
#endif // ports with scaled bitmaps support