Fix scale factor confusion in wxMac wxBitmap implementation

Merge ctors from (width, height) and (width, height, scale) into a
single one because the former really should be just a special case of
the latter for scale == 1 but, surprisingly and confusingly it wasn't,
because the latter also multiplied the size by scale, meaning that width
and height parameters had different meanings.

This resulted in at least 3 bugs when using scale factors different from
1: first, copying bitmaps wasn't done correctly because as
wxBitmapRefData copy ctor incorrectly scaled its size by scale again.
And second, creating bitmap from wxImage whose size wasn't divisible by
scale not just didn't work correctly but crashed when accessing memory
outside of the image because (unnecessarily) dividing and multiplying
the image size by scale wasn't idempotent. Finally, even for the images
of even size (assuming scale factor of 2), bitmaps created from them
used incorrect width and height, corresponding to the half of the image
dimensions, instead of the same ones, as they're supposed to be (the
scaled dimensions are supposed to be returned by GetScale{Width,Height}
methods).

Closes #17505.
This commit is contained in:
Vadim Zeitlin
2017-12-02 22:33:53 +01:00
parent 289fbcf5be
commit 3380a2438d

View File

@@ -49,8 +49,7 @@ class WXDLLEXPORT wxBitmapRefData: public wxGDIRefData
friend class WXDLLIMPEXP_FWD_CORE wxIcon;
friend class WXDLLIMPEXP_FWD_CORE wxCursor;
public:
wxBitmapRefData(int width , int height , int depth, double logicalscale);
wxBitmapRefData(int width , int height , int depth);
wxBitmapRefData(int width , int height , int depth, double logicalscale = 1.0);
wxBitmapRefData(CGContextRef context);
wxBitmapRefData(CGImageRef image, double scale);
wxBitmapRefData();
@@ -106,8 +105,7 @@ public:
int GetBytesPerRow() const { return m_bytesPerRow; }
private :
bool Create(int width , int height , int depth);
bool Create(int width , int height , int depth, double logicalScale);
bool Create(int width , int height , int depth, double logicalscale);
bool Create( CGImageRef image, double scale );
bool Create( CGContextRef bitmapcontext);
void Init();
@@ -269,13 +267,7 @@ wxBitmapRefData::wxBitmapRefData()
Init() ;
}
wxBitmapRefData::wxBitmapRefData( int w , int h , int d )
{
Init() ;
Create( w , h , d ) ;
}
wxBitmapRefData::wxBitmapRefData(int w , int h , int d, double logicalscale)
wxBitmapRefData::wxBitmapRefData( int w , int h , int d , double logicalscale)
{
Init() ;
Create( w , h , d, logicalscale ) ;
@@ -370,11 +362,12 @@ bool wxBitmapRefData::Create(CGContextRef context)
return m_ok ;
}
bool wxBitmapRefData::Create( int w , int h , int d )
bool wxBitmapRefData::Create( int w , int h , int d, double logicalscale )
{
m_width = wxMax(1, w);
m_height = wxMax(1, h);
m_depth = d ;
m_scaleFactor = logicalscale;
m_hBitmap = NULL ;
m_bytesPerRow = GetBestBytesPerRow( m_width * 4 ) ;
@@ -395,12 +388,6 @@ bool wxBitmapRefData::Create( int w , int h , int d )
return m_ok ;
}
bool wxBitmapRefData::Create( int w , int h , int d, double logicalScale )
{
m_scaleFactor = logicalScale;
return Create(w*logicalScale,h*logicalScale,d);
}
void wxBitmapRefData::UseAlpha( bool use )
{
if ( m_hasAlpha == use )
@@ -1125,7 +1112,7 @@ bool wxBitmap::CreateScaled(int w, int h, int d, double logicalScale)
if ( d < 0 )
d = wxDisplayDepth() ;
m_refData = new wxBitmapRefData( w , h , d, logicalScale );
m_refData = new wxBitmapRefData( w*logicalScale , h*logicalScale , d, logicalScale );
return M_BITMAPDATA->IsOk() ;
}
@@ -1220,7 +1207,7 @@ wxBitmap::wxBitmap(const wxImage& image, int depth, double scale)
wxBitmapRefData* bitmapRefData;
m_refData = bitmapRefData = new wxBitmapRefData( width/scale, height/scale, depth, scale) ;
m_refData = bitmapRefData = new wxBitmapRefData( width, height, depth, scale) ;
if ( bitmapRefData->IsOk())
{