Merge branch 'bitmap-create-log-size'

Add wxBitmap::CreateWithLogicalSize() and use it.

See #24199.
This commit is contained in:
Vadim Zeitlin 2024-01-12 18:37:20 +01:00
commit 565775a2c8
16 changed files with 106 additions and 18 deletions

View file

@ -178,6 +178,11 @@ public:
virtual bool Create(int width, int height, int depth = wxBITMAP_SCREEN_DEPTH) = 0;
virtual bool Create(const wxSize& sz, int depth = wxBITMAP_SCREEN_DEPTH) = 0;
// DIP size and logical size are the same thing for ports using scaling,
// i.e. where physical and logical sizes are different (e.g. wxGTK and
// wxOSX), but we want to have both sets of functions to use them in the
// ports where physical and logical sizes are the same (wxMSW).
bool CreateWithDIPSize(const wxSize& sz,
double scale,
int depth = wxBITMAP_SCREEN_DEPTH)
@ -187,6 +192,15 @@ public:
int depth = wxBITMAP_SCREEN_DEPTH)
{ return DoCreate(wxSize(width, height), scale, depth); }
bool CreateWithLogicalSize(const wxSize& sz,
double scale,
int depth = wxBITMAP_SCREEN_DEPTH)
{ return DoCreate(sz, scale, depth); }
bool CreateWithLogicalSize(int width, int height,
double scale,
int depth = wxBITMAP_SCREEN_DEPTH)
{ return DoCreate(wxSize(width, height), scale, depth); }
virtual int GetHeight() const = 0;
virtual int GetWidth() const = 0;
virtual int GetDepth() const = 0;

View file

@ -157,6 +157,14 @@ public:
int depth = wxBITMAP_SCREEN_DEPTH)
{ return CreateWithDIPSize(wxSize(width, height), scale, depth); }
bool CreateWithLogicalSize(const wxSize& sz,
double scale,
int depth = wxBITMAP_SCREEN_DEPTH);
bool CreateWithLogicalSize(int width, int height,
double scale,
int depth = wxBITMAP_SCREEN_DEPTH)
{ return CreateWithLogicalSize(wxSize(width, height), scale, depth); }
virtual bool LoadFile(const wxString& name, wxBitmapType type = wxBITMAP_DEFAULT_TYPE);
virtual bool SaveFile(const wxString& name, wxBitmapType type, const wxPalette *cmap = nullptr) const;

View file

@ -494,6 +494,10 @@ public:
Create a bitmap specifying its size in DPI-independent pixels and the
scale factor to use.
This should be used when the bitmap size is fixed (e.g. at
compile-time) and not if it comes from wxWindow::GetSize() or other
similar functions -- use CreateWithLogicalSize() in the latter case.
The physical size of the bitmap is obtained by multiplying the given
@a size by @a scale and rounding it to the closest integer.
@ -524,6 +528,43 @@ public:
double scale,
int depth = wxBITMAP_SCREEN_DEPTH);
/**
Create a bitmap specifying its size in logical pixels and the scale
factor to use.
This should be typically used when creating bitmaps associated to a
window area, e.g. to create a bitmap covering the entire window the
@a size parameter should be wxWindow::GetClientSize() and @a scale
should be the wxWindow::GetDPIScaleFactor().
The physical size of the bitmap created by this function depends on the
platform and will be the same as @a size on the platforms for which
`wxHAS_DPI_INDEPENDENT_PIXELS` is not defined (e.g. wxMSW) or @a size
multiplied by @a scale for those where it is (e.g. wxGTK3 and wxOSX).
In other words, this function is the same as CreateWithDIPSize() if
`wxHAS_DPI_INDEPENDENT_PIXELS` is defined, but not otherwise.
@param size
The size of the bitmap in logical pixels. Both width and
height must be strictly positive.
@param scale
Scale factor used by the bitmap, see SetScaleFactor().
@param depth
The number of bits used to represent each bitmap pixel.
@return @true if the creation was successful.
@since 3.3.0
*/
bool CreateWithLogicalSize(const wxSize& size,
double scale,
int depth = wxBITMAP_SCREEN_DEPTH);
/// @overload
bool CreateWithLogicalSize(int width, int height,
double scale,
int depth = wxBITMAP_SCREEN_DEPTH);
/**
Create a bitmap with a scale factor.

View file

@ -173,7 +173,7 @@ void wxAnimationCtrlBase::UpdateStaticImage()
m_bmpStaticReal.GetLogicalHeight() != sz.GetHeight())
{
// need to (re)create m_bmpStaticReal
if (!m_bmpStaticReal.CreateWithDIPSize(sz,
if (!m_bmpStaticReal.CreateWithLogicalSize(sz,
bmpCurrent.GetScaleFactor(),
bmpCurrent.GetDepth()))
{

View file

@ -84,7 +84,7 @@ private:
// we must always return a valid bitmap but creating a bitmap of
// size 0 would fail, so create a 1*1 bitmap in this case
buffer->CreateWithDIPSize(wxMax(w, 1), wxMax(h, 1), scale);
buffer->CreateWithLogicalSize(wxMax(w, 1), wxMax(h, 1), scale);
return buffer;
}

View file

@ -999,7 +999,7 @@ bool wxWizard::ResizeBitmap(wxBitmap& bmp)
if (!m_statbmp->GetBitmap().IsOk() || m_statbmp->GetBitmap().GetLogicalHeight() != bitmapHeight)
{
wxBitmap bitmap;
bitmap.CreateWithDIPSize(bitmapWidth, bitmapHeight, bmp.GetScaleFactor(), bmp.GetDepth());
bitmap.CreateWithLogicalSize(bitmapWidth, bitmapHeight, bmp.GetScaleFactor(), bmp.GetDepth());
{
wxMemoryDC dc;
dc.SelectObject(bitmap);

View file

@ -775,6 +775,17 @@ bool wxBitmap::CreateWithDIPSize(const wxSize& size, double scale, int depth)
return true;
}
bool
wxBitmap::CreateWithLogicalSize(const wxSize& size, double scale, int depth)
{
if ( !Create(size, depth) )
return false;
GetBitmapData()->m_scaleFactor = scale;
return true;
}
bool wxBitmap::DoCreate(int w, int h, int d, WXHDC hdc)
{
UnRef();

View file

@ -103,7 +103,7 @@ void wxOverlayImpl::Init(wxDC* dc, int , int , int , int )
m_rect.SetSize(m_window->GetClientSize());
m_rect.SetPosition(m_window->GetScreenPosition());
m_bitmap.CreateWithDIPSize(m_rect.GetSize(), m_window->GetDPIScaleFactor());
m_bitmap.CreateWithLogicalSize(m_rect.GetSize(), m_window->GetDPIScaleFactor());
m_overlayWindow = wxCreateOverlayWindow(m_rect);
}

View file

@ -718,8 +718,9 @@ void wxStaticBox::OnPaint(wxPaintEvent& WXUNUSED(event))
wxMemoryDC memdc(&dc);
const double scale = dc.GetContentScaleFactor();
wxBitmap bitmap(rc.right, rc.bottom);
bitmap.SetScaleFactor(scale);
wxBitmap bitmap;
// Physical and logical sizes are the same in wxMSW.
bitmap.CreateWithLogicalSize(rc.right, rc.bottom, scale);
memdc.SelectObject(bitmap);
PaintBackground(memdc, rc);

View file

@ -585,7 +585,7 @@ wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
const wxSize bitmapSize(subrect ? subrect->GetSize() : m_window->GetSize());
wxBitmap bitmap;
bitmap.CreateWithDIPSize(bitmapSize, m_contentScaleFactor);
bitmap.CreateWithLogicalSize(bitmapSize, m_contentScaleFactor);
NSView* view = (NSView*) m_window->GetHandle();
if ( [view isHiddenOrHasHiddenAncestor] == NO )
@ -617,7 +617,7 @@ wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
// The bitmap created by wxBitmap::CreateWithDIPSize() above is scaled,
// The bitmap created by wxBitmap::CreateWithLogicalSize() above is scaled,
// so we need to adjust the coordinates for it.
r.size.width /= m_contentScaleFactor;
r.size.height /= m_contentScaleFactor;

View file

@ -973,7 +973,7 @@ wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const
wxBitmap ret;
double scale = GetScaleFactor();
ret.CreateWithDIPSize( rect.GetSize(), scale, GetDepth() );
ret.CreateWithLogicalSize( rect.GetSize(), scale, GetDepth() );
wxASSERT_MSG( ret.IsOk(), wxT("GetSubBitmap error") );
if ( HasAlpha() )
ret.UseAlpha() ;

View file

@ -4607,10 +4607,10 @@ void wxPropertyGrid::OnResize( wxSizeEvent& event )
if ( !m_doubleBuffer )
{
// Create double buffer bitmap to draw on, if none
int w = wxMax(width, 250);
int h = wxMax(height + dblh, 400);
int w = wxMax(width, FromDIP(250));
int h = wxMax(height + dblh, FromDIP(400));
m_doubleBuffer = new wxBitmap;
m_doubleBuffer->CreateWithDIPSize( w, h, scaleFactor );
m_doubleBuffer->CreateWithLogicalSize( w, h, scaleFactor );
}
else
{
@ -4624,7 +4624,7 @@ void wxPropertyGrid::OnResize( wxSizeEvent& event )
if ( h < (height+dblh) ) h = height + dblh;
delete m_doubleBuffer;
m_doubleBuffer = new wxBitmap;
m_doubleBuffer->CreateWithDIPSize( w, h, scaleFactor );
m_doubleBuffer->CreateWithLogicalSize( w, h, scaleFactor );
}
}
}

View file

@ -3029,7 +3029,7 @@ bool wxRichTextCtrl::RecreateBuffer(const wxSize& size)
#if defined(__WXMSW__)
depth = 24;
#endif
m_bufferBitmap.CreateWithDIPSize(sz, GetDPIScaleFactor(), depth);
m_bufferBitmap.CreateWithLogicalSize(sz, GetDPIScaleFactor(), depth);
}
return m_bufferBitmap.IsOk();
}

View file

@ -292,8 +292,8 @@ void SurfaceImpl::InitPixMap(int width, int height, Surface *surface, WindowID w
hdcOwned = true;
if (width < 1) width = 1;
if (height < 1) height = 1;
bitmap = new wxBitmap(GETWIN(winid)->ToPhys(wxSize(width, height)));
bitmap->SetScaleFactor(GETWIN(winid)->GetDPIScaleFactor());
bitmap = new wxBitmap();
bitmap->CreateWithLogicalSize(width, height, GETWIN(winid)->GetDPIScaleFactor());
mdc->SelectObject(*bitmap);
}

View file

@ -109,8 +109,7 @@ public:
void DrawBack(const wxSize& size)
{
m_back = wxBitmap(ToPhys(size));
m_back.SetScaleFactor(GetDPIScaleFactor());
m_back.CreateWithLogicalSize(size, GetDPIScaleFactor());
wxMemoryDC mem(m_back);
Surface* surfaceWindow = Surface::Allocate(m_swx->technology);
surfaceWindow->Init(&mem, m_ct->wDraw.GetID());

View file

@ -1848,6 +1848,20 @@ TEST_CASE("Bitmap::ScaleFactor", "[bitmap][dc][scale]")
wxBitmap bmp3(img, dc);
CHECK( bmp3.GetScaleFactor() == 2 );
CHECK( bmp3.GetSize() == wxSize(16, 16) );
// And another way to create a bitmap with specified scale factor.
const wxSize sizeLog(10, 10);
wxBitmap bmp4;
bmp4.CreateWithLogicalSize(sizeLog, 2);
CHECK( bmp4.GetScaleFactor() == 2 );
CHECK( bmp4.GetLogicalSize() == sizeLog );
#ifdef wxHAS_DPI_INDEPENDENT_PIXELS
CHECK( bmp4.GetSize() == 2*sizeLog );
#else
CHECK( bmp4.GetSize() == sizeLog );
#endif
}
TEST_CASE("wxBitmap::GetSubBitmap", "[bitmap]")