From a1e4dca06774701b28d267e03cf18a7a0b7e6154 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 16 Dec 2021 01:15:17 +0000 Subject: [PATCH 01/16] Store scale factor in wxMSW bitmaps too Even though it's not really used by MSW code itself, the scale factor is still needed to determine the correct default bitmap bundle size, for example: it should be possible to create a bundle with just a single 64x64 bitmap and use it unscaled in 200% DPI, for example, rather than scaling it up to 128x128 bitmap. --- include/wx/msw/gdiimage.h | 11 +++++++++++ src/msw/bitmap.cpp | 23 ++++++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/include/wx/msw/gdiimage.h b/include/wx/msw/gdiimage.h index 94b6f01091..39f8af2979 100644 --- a/include/wx/msw/gdiimage.h +++ b/include/wx/msw/gdiimage.h @@ -36,6 +36,8 @@ public: { m_width = m_height = m_depth = 0; + m_scaleFactor = 1.0; + m_handle = NULL; } @@ -45,6 +47,8 @@ public: m_height = data.m_height; m_depth = data.m_depth; + m_scaleFactor = data.m_scaleFactor; + // can't copy handles like this, derived class copy ctor must do it! m_handle = NULL; } @@ -65,6 +69,9 @@ public: // the depth of the image int m_depth; + // scale factor of the image + double m_scaleFactor; + // the handle to it union { @@ -111,6 +118,10 @@ public: int GetWidth() const { return IsNull() ? 0 : GetGDIImageData()->m_width; } int GetHeight() const { return IsNull() ? 0 : GetGDIImageData()->m_height; } int GetDepth() const { return IsNull() ? 0 : GetGDIImageData()->m_depth; } + double GetScaleFactor() const + { + return IsNull() ? 1.0 : GetGDIImageData()->m_scaleFactor; + } wxSize GetSize() const { diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index c63dd61089..c7ed47429a 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -499,6 +499,8 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon, int w = icon.GetWidth(), h = icon.GetHeight(); + refData->m_scaleFactor = icon.GetScaleFactor(); + if ( iconInfo.hbmColor ) { refData->m_width = w; @@ -1366,33 +1368,36 @@ bool wxBitmap::InitFromHBITMAP(WXHBITMAP bmp, int width, int height, int depth) // scale factor-related functions // ---------------------------------------------------------------------------- -// Note: currently we don't use scale factor at all and don't even store it -// because this seems useless, but we define these functions out of line here -// and not inline in the header to make it possible to change this later -// without breaking ABI if necessary. +// wxMSW doesn't really use scale factor, but we must still store it to use the +// correct sizes in the code which uses it to decide on the bitmap size to use. -void wxBitmap::SetScaleFactor(double WXUNUSED(scale)) +void wxBitmap::SetScaleFactor(double scale) { + wxCHECK_RET( IsOk(), wxT("invalid bitmap") ); + + GetBitmapData()->m_scaleFactor = scale; } double wxBitmap::GetScaleFactor() const { - return 1.0; + wxCHECK_MSG( IsOk(), -1, wxT("invalid bitmap") ); + + return GetBitmapData()->m_scaleFactor; } double wxBitmap::GetScaledWidth() const { - return GetWidth(); + return GetWidth() / GetScaleFactor(); } double wxBitmap::GetScaledHeight() const { - return GetHeight(); + return GetHeight() / GetScaleFactor(); } wxSize wxBitmap::GetScaledSize() const { - return GetSize(); + return GetSize() / GetScaleFactor(); } // ---------------------------------------------------------------------------- From d78696243b67e96af44df891f7db4039524ddfcb Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 16 Dec 2021 01:17:35 +0000 Subject: [PATCH 02/16] Set scale factor correctly for icons loaded from resources ::LoadIcon() selects the icon of scaled size in the DPI-aware programs, which is nice, but only works right if we actually set the scale factor for the icon correctly. --- include/wx/msw/icon.h | 2 +- src/msw/gdiimage.cpp | 21 ++++++++++++++++++++- src/msw/icon.cpp | 3 ++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/wx/msw/icon.h b/include/wx/msw/icon.h index 2c89f2597a..294e4577b1 100644 --- a/include/wx/msw/icon.h +++ b/include/wx/msw/icon.h @@ -71,7 +71,7 @@ public: #endif // WXWIN_COMPATIBILITY_3_0 WXHICON GetHICON() const { return (WXHICON)GetHandle(); } - bool InitFromHICON(WXHICON icon, int width, int height); + bool InitFromHICON(WXHICON icon, int width, int height, double scale = 1.0); // create from bitmap (which should have a mask unless it's monochrome): // there shouldn't be any implicit bitmap -> icon conversion (i.e. no diff --git a/src/msw/gdiimage.cpp b/src/msw/gdiimage.cpp index 6b43e76c5d..fe2d3b2b52 100644 --- a/src/msw/gdiimage.cpp +++ b/src/msw/gdiimage.cpp @@ -586,7 +586,26 @@ bool wxICOResourceHandler::LoadIcon(wxIcon *icon, } } - return icon->CreateFromHICON((WXHICON)hicon); + if ( !hicon ) + return false; + + wxSize size; + double scale = 1.0; + if ( hasSize ) + { + size.x = desiredWidth; + size.y = desiredHeight; + } + else // We loaded an icon of default size. + { + // LoadIcon() returns icons of scaled size, so we must use the correct + // scaling factor of them. + size = wxGetHiconSize(hicon); + if ( const wxWindow* win = wxApp::GetMainTopWindow() ) + scale = win->GetDPIScaleFactor(); + } + + return icon->InitFromHICON((WXHICON)hicon, size.x, size.y, scale); } #if wxUSE_PNG_RESOURCE_HANDLER diff --git a/src/msw/icon.cpp b/src/msw/icon.cpp index 37758ee692..e2dedb2cc0 100644 --- a/src/msw/icon.cpp +++ b/src/msw/icon.cpp @@ -154,7 +154,7 @@ bool wxIcon::CreateFromHICON(WXHICON icon) return InitFromHICON(icon, size.GetWidth(), size.GetHeight()); } -bool wxIcon::InitFromHICON(WXHICON icon, int width, int height) +bool wxIcon::InitFromHICON(WXHICON icon, int width, int height, double scale) { #if wxDEBUG_LEVEL >= 2 if ( icon != NULL ) @@ -170,6 +170,7 @@ bool wxIcon::InitFromHICON(WXHICON icon, int width, int height) GetGDIImageData()->m_handle = (WXHANDLE)icon; GetGDIImageData()->m_width = width; GetGDIImageData()->m_height = height; + GetGDIImageData()->m_scaleFactor = scale; return IsOk(); } From b35ffa5e4133ead0e5e782c0283386e779c79cf6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 17 Dec 2021 21:05:33 +0000 Subject: [PATCH 03/16] Use per-window DPI scale factor in wxAuiGenericTabArt 8dcedf56d7 (Add wxWindow parameter to wxAuiTabArt::SetSizingInfo(), 2021-11-13) added "wnd" argument to SetSizingInfo(), so use it instead of always using the DPI of the main monitor. --- src/aui/tabart.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/aui/tabart.cpp b/src/aui/tabart.cpp index ef12247cc7..e7aea1f3ba 100644 --- a/src/aui/tabart.cpp +++ b/src/aui/tabart.cpp @@ -245,7 +245,7 @@ void wxAuiGenericTabArt::SetSizingInfo(const wxSize& tab_ctrl_size, m_fixedTabWidth = wnd->FromDIP(100); - int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - wxWindow::FromDIP(4, NULL); + int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - wnd->FromDIP(4); if (m_flags & wxAUI_NB_CLOSE_BUTTON) tot_width -= m_activeCloseBmp.GetPreferredSizeFor(wnd).x; @@ -258,12 +258,12 @@ void wxAuiGenericTabArt::SetSizingInfo(const wxSize& tab_ctrl_size, } - m_fixedTabWidth = wxMax(m_fixedTabWidth, wxWindow::FromDIP(100, NULL)); + m_fixedTabWidth = wxMax(m_fixedTabWidth, wnd->FromDIP(100)); if (m_fixedTabWidth > tot_width/2) m_fixedTabWidth = tot_width/2; - m_fixedTabWidth = wxMin(m_fixedTabWidth, wxWindow::FromDIP(220, NULL)); + m_fixedTabWidth = wxMin(m_fixedTabWidth, wnd->FromDIP(220)); m_tabCtrlHeight = tab_ctrl_size.y; } @@ -976,7 +976,7 @@ void wxAuiSimpleTabArt::SetSizingInfo(const wxSize& tab_ctrl_size, m_fixedTabWidth = wnd->FromDIP(100); - int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - wxWindow::FromDIP(4, NULL); + int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - wnd->FromDIP(4); if (m_flags & wxAUI_NB_CLOSE_BUTTON) tot_width -= m_activeCloseBmp.GetBitmapFor(wnd).GetScaledWidth(); @@ -989,12 +989,12 @@ void wxAuiSimpleTabArt::SetSizingInfo(const wxSize& tab_ctrl_size, } - m_fixedTabWidth = wxMax(m_fixedTabWidth, wxWindow::FromDIP(100, NULL)); + m_fixedTabWidth = wxMax(m_fixedTabWidth, wnd->FromDIP(100)); if (m_fixedTabWidth > tot_width/2) m_fixedTabWidth = tot_width/2; - m_fixedTabWidth = wxMin(m_fixedTabWidth, wxWindow::FromDIP(220, NULL)); + m_fixedTabWidth = wxMin(m_fixedTabWidth, wnd->FromDIP(220)); } void wxAuiSimpleTabArt::SetColour(const wxColour& colour) From 603c45fbe95d8308ea1aad7ce05a9463ce6f38c6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 17 Dec 2021 21:12:02 +0000 Subject: [PATCH 04/16] Make sure the icon fits into the AUI pane title bar vertically With scaled bitmaps, the preferred bitmap version might be too big for the pane. Perhaps it's the title bar height which is too small, but it seems to have been hardcoded to 17 pixels since the very first version in 50acee04cd (Initial commit of wxAUI, 2006-06-06), so don't change it. --- src/aui/dockart.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/aui/dockart.cpp b/src/aui/dockart.cpp index 51f0fbb724..8a1c4868e2 100644 --- a/src/aui/dockart.cpp +++ b/src/aui/dockart.cpp @@ -684,9 +684,16 @@ wxAuiDefaultDockArt::DrawIcon(wxDC& dc, wxWindow *window, const wxRect& rect, wx wxCHECK_RET( window, "must have some window" ); } + // Ensure the icon fits into the title bar. + wxSize iconSize = pane.icon.GetPreferredSizeFor(window); + if (iconSize.y > rect.height) + { + iconSize *= static_cast(rect.height) / iconSize.y; + } + // Draw the icon centered vertically int xOffset = window->FromDIP(2); - const wxBitmap& icon = pane.icon.GetBitmapFor(window); + const wxBitmap& icon = pane.icon.GetBitmap(iconSize); dc.DrawBitmap(icon, rect.x+xOffset, rect.y+(rect.height-icon.GetScaledHeight())/2, true); From d12ba79ffb77cafd9469a7a7a3fc5ca26f27c6ce Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 17 Dec 2021 23:31:53 +0000 Subject: [PATCH 05/16] Remove useless SetToolBitmapSize() calls from the AUI sample wxAuiToolBar::SetToolBitmapSize() doesn't do anything and never did ever since it was added back in 1154f91b6a (added wxAuiToolBar, 2008-08-24), so don't bother calling it, this just makes the sample code confusing as no effect from passing different sizes to SetToolBitmapSize() can be seen during run-time. --- samples/aui/auidemo.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/samples/aui/auidemo.cpp b/samples/aui/auidemo.cpp index 2593018dcd..08c4f266d8 100644 --- a/samples/aui/auidemo.cpp +++ b/samples/aui/auidemo.cpp @@ -781,7 +781,6 @@ MyFrame::MyFrame(wxWindow* parent, // create some toolbars wxAuiToolBar* tb1 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW); - tb1->SetToolBitmapSize(FromDIP(wxSize(48,48))); tb1->AddTool(ID_SampleItem+1, "Test", wxArtProvider::GetBitmap(wxART_ERROR)); tb1->AddSeparator(); tb1->AddTool(ID_SampleItem+2, "Test", wxArtProvider::GetBitmap(wxART_QUESTION)); @@ -794,7 +793,6 @@ MyFrame::MyFrame(wxWindow* parent, wxAuiToolBar* tb2 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW | wxAUI_TB_HORIZONTAL); - tb2->SetToolBitmapSize(FromDIP(wxSize(16,16))); wxBitmap tb2_bmp1 = wxArtProvider::GetBitmap(wxART_QUESTION, wxART_OTHER, FromDIP(wxSize(16,16))); tb2->AddTool(ID_SampleItem+6, "Disabled", tb2_bmp1); @@ -816,7 +814,6 @@ MyFrame::MyFrame(wxWindow* parent, wxAuiToolBar* tb3 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW); - tb3->SetToolBitmapSize(FromDIP(wxSize(16,16))); wxBitmap tb3_bmp1 = wxArtProvider::GetBitmap(wxART_FOLDER, wxART_OTHER, FromDIP(wxSize(16,16))); tb3->AddTool(ID_SampleItem+16, "Check 1", tb3_bmp1, "Check 1", wxITEM_CHECK); tb3->AddTool(ID_SampleItem+17, "Check 2", tb3_bmp1, "Check 2", wxITEM_CHECK); @@ -839,7 +836,6 @@ MyFrame::MyFrame(wxWindow* parent, wxAUI_TB_OVERFLOW | wxAUI_TB_TEXT | wxAUI_TB_HORZ_TEXT); - tb4->SetToolBitmapSize(FromDIP(wxSize(16,16))); wxBitmap tb4_bmp1 = wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_OTHER, FromDIP(wxSize(16,16))); tb4->AddTool(ID_DropDownToolbarItem, "Item 1", tb4_bmp1); tb4->AddTool(ID_SampleItem+23, "Item 2", tb4_bmp1); @@ -863,7 +859,6 @@ MyFrame::MyFrame(wxWindow* parent, wxAuiToolBar* tb5 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW | wxAUI_TB_VERTICAL); - tb5->SetToolBitmapSize(FromDIP(wxSize(48,48))); tb5->AddTool(ID_SampleItem+30, "Test", wxArtProvider::GetBitmap(wxART_ERROR)); tb5->AddSeparator(); tb5->AddTool(ID_SampleItem+31, "Test", wxArtProvider::GetBitmap(wxART_QUESTION)); From 072390258cc9c9601cc424220d333b6f54326a68 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 17 Dec 2021 23:56:46 +0000 Subject: [PATCH 06/16] Use wxBitmapBundle for wxTreeCtrl images in the AUI sample This sample is supposed to look good in high DPI and this requires using wxBitmapBundle rather than wxImageList, so change it to do it. --- samples/aui/auidemo.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/samples/aui/auidemo.cpp b/samples/aui/auidemo.cpp index 08c4f266d8..51fb69fe91 100644 --- a/samples/aui/auidemo.cpp +++ b/samples/aui/auidemo.cpp @@ -1584,11 +1584,11 @@ wxTreeCtrl* MyFrame::CreateTreeCtrl() FromDIP(wxSize(160,250)), wxTR_DEFAULT_STYLE | wxNO_BORDER); - wxSize size = FromDIP(wxSize(16, 16)); - wxImageList* imglist = new wxImageList(size.x, size.y, true, 2); - imglist->Add(wxArtProvider::GetBitmap(wxART_FOLDER, wxART_OTHER, size)); - imglist->Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_OTHER, size)); - tree->AssignImageList(imglist); + wxSize size(16, 16); + wxVector images; + images.push_back(wxArtProvider::GetBitmapBundle(wxART_FOLDER, wxART_OTHER, size)); + images.push_back(wxArtProvider::GetBitmapBundle(wxART_NORMAL_FILE, wxART_OTHER, size)); + tree->SetImages(images); wxTreeItemId root = tree->AddRoot("wxAUI Project", 0); wxArrayTreeItemIds items; From f78db924624e49615637a7eab07cc69076b155a9 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 17 Dec 2021 23:59:19 +0000 Subject: [PATCH 07/16] Avoid bitmap scaling in wxArtProvider::GetBitmapBundle() Instead of immediately constructing the bitmap with the requested size, possibly by downscaling a higher-resolution bitmap, and then potentially having to upscale it if we actually need a bitmap of a bigger size, just retrieve the bitmap in the actually needed size from wxArtProvider when needed. This makes bitmaps obtained from wxArtProvider::GetBitmapBundle() look good, rather than fuzzy and ugly, in high DPI if they're actually available in the appropriate size. --- include/wx/artprov.h | 9 ++--- interface/wx/artprov.h | 4 ++- src/common/artprov.cpp | 79 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 8 deletions(-) diff --git a/include/wx/artprov.h b/include/wx/artprov.h index b8cbd199b1..dd067d5144 100644 --- a/include/wx/artprov.h +++ b/include/wx/artprov.h @@ -234,14 +234,11 @@ protected: return wxNullBitmap; } - // Derived classes must override CreateBitmapBundle if they provide - // a bundle that cannot be represented through an ordinary bitmap. + // Default implementation creates a wxBitmapBundle which returns the + // specified art resource in whichever size it is being asked for. virtual wxBitmapBundle CreateBitmapBundle(const wxArtID& id, const wxArtClient& client, - const wxSize& size) - { - return wxBitmapBundle(CreateBitmap(id, client, size)); - } + const wxSize& size); virtual wxIconBundle CreateIconBundle(const wxArtID& WXUNUSED(id), const wxArtClient& WXUNUSED(client)) diff --git a/interface/wx/artprov.h b/interface/wx/artprov.h index 8f0c1ff0d7..e8b0931783 100644 --- a/interface/wx/artprov.h +++ b/interface/wx/artprov.h @@ -307,7 +307,9 @@ public: @param client wxArtClient identifier of the client (i.e. who is asking for the bitmap). @param size - Default size for the returned bundle. + Default size for the returned bundle, i.e. the size of the bitmap + in normal DPI (this implies that wxWindow::FromDIP() must @e not be + used with it). @return If any of the registered providers recognizes the ID in its CreateBitmapBundle(), this bundle is returned. Otherwise, if any of diff --git a/src/common/artprov.cpp b/src/common/artprov.cpp index 66327070fb..0d7aa76e54 100644 --- a/src/common/artprov.cpp +++ b/src/common/artprov.cpp @@ -138,6 +138,77 @@ wxArtProviderCache::ConstructHashID(const wxArtID& id, wxString::Format(wxT("%d-%d"), size.x, size.y); } +// ---------------------------------------------------------------------------- +// wxBitmapBundleImplArt: uses art provider to get the bitmaps +// ---------------------------------------------------------------------------- + +namespace +{ + +class wxBitmapBundleImplArt : public wxBitmapBundleImpl +{ +public: + wxBitmapBundleImplArt(const wxArtID& id, + const wxArtClient& client, + const wxSize& size) + : m_artId(id), + m_artClient(client), + m_sizeDefault(GetValidSize(id, client, size)) + { + } + + virtual wxSize GetDefaultSize() const wxOVERRIDE + { + return m_sizeDefault; + } + + virtual wxSize GetPreferredSizeAtScale(double scale) const wxOVERRIDE + { + // We have no preferred sizes. + return m_sizeDefault*scale; + } + + virtual wxBitmap GetBitmap(const wxSize& size) wxOVERRIDE + { + return wxArtProvider::GetBitmap(m_artId, m_artClient, size); + } + +private: + static wxSize GetValidSize(const wxArtID& id, + const wxArtClient& client, + const wxSize& size) + { + // If valid size is provided, just use it. + if ( size != wxDefaultSize ) + return size; + + // Otherwise, try to get the size we'd use without creating a bitmap + // immediately. + const wxSize sizeHint = wxArtProvider::GetSizeHint(client); + if ( sizeHint != wxDefaultSize ) + return sizeHint; + + // If we really have to, do create a bitmap just to get its size. Note + // we need the size in logical pixels here, it will be scaled later if + // necessary, so use GetScaledSize() and not GetSize(). + const wxBitmap bitmap = wxArtProvider::GetBitmap(id, client); + if ( bitmap.IsOk() ) + return bitmap.GetScaledSize(); + + // We really need some default size, so just return this hardcoded + // value if all else fails -- what else can we do. + return wxSize(16, 16); + } + + const wxArtID m_artId; + const wxArtClient m_artClient; + const wxSize m_sizeDefault; + + wxDECLARE_NO_COPY_CLASS(wxBitmapBundleImplArt); +}; + +} // anonymous namespace + // ============================================================================ // wxArtProvider class // ============================================================================ @@ -305,7 +376,7 @@ wxBitmapBundle wxArtProvider::GetBitmapBundle(const wxArtID& id, wxCHECK_MSG( sm_providers, wxNullBitmap, wxT("no wxArtProvider exists") ); - wxString hashId = wxArtProviderCache::ConstructHashID(id, client); + wxString hashId = wxArtProviderCache::ConstructHashID(id, client, size); wxBitmapBundle bitmapbundle; // (DoGetIconBundle(id, client)); @@ -325,6 +396,12 @@ wxBitmapBundle wxArtProvider::GetBitmapBundle(const wxArtID& id, return bitmapbundle; } +wxBitmapBundle wxArtProvider::CreateBitmapBundle(const wxArtID& id, + const wxArtClient& client, + const wxSize& size) +{ + return wxBitmapBundle::FromImpl(new wxBitmapBundleImplArt(id, client, size)); +} /*static*/ wxIconBundle wxArtProvider::GetIconBundle(const wxArtID& id, const wxArtClient& client) From bbdbee3e57bc7278bbde20653c93e5c20fc8c34a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 18 Dec 2021 00:01:37 +0000 Subject: [PATCH 08/16] Use wxArtProvider::GetBitmapBundle() in the AUI sample This sweeps under the carpet the regression which resulted in bitmaps returned from wxArtProvider::GetBitmap() not looking the same since starting to use wxBitmapBundle in AUI, but OTOH it just doesn't seem possible to both preserve the compatibility and allow actually using appropriate, not scaled, bitmaps in different resolutions. The new code is as simple as the old version, follows the official advice to use GetBitmapBundle() rather than GetBitmap(), and looks good in high DPI, which should compensate for the behaviour change. --- samples/aui/auidemo.cpp | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/samples/aui/auidemo.cpp b/samples/aui/auidemo.cpp index 51fb69fe91..1e415b311b 100644 --- a/samples/aui/auidemo.cpp +++ b/samples/aui/auidemo.cpp @@ -781,12 +781,12 @@ MyFrame::MyFrame(wxWindow* parent, // create some toolbars wxAuiToolBar* tb1 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW); - tb1->AddTool(ID_SampleItem+1, "Test", wxArtProvider::GetBitmap(wxART_ERROR)); + tb1->AddTool(ID_SampleItem+1, "Test", wxArtProvider::GetBitmapBundle(wxART_ERROR)); tb1->AddSeparator(); - tb1->AddTool(ID_SampleItem+2, "Test", wxArtProvider::GetBitmap(wxART_QUESTION)); - tb1->AddTool(ID_SampleItem+3, "Test", wxArtProvider::GetBitmap(wxART_INFORMATION)); - tb1->AddTool(ID_SampleItem+4, "Test", wxArtProvider::GetBitmap(wxART_WARNING)); - tb1->AddTool(ID_SampleItem+5, "Test", wxArtProvider::GetBitmap(wxART_MISSING_IMAGE)); + tb1->AddTool(ID_SampleItem+2, "Test", wxArtProvider::GetBitmapBundle(wxART_QUESTION)); + tb1->AddTool(ID_SampleItem+3, "Test", wxArtProvider::GetBitmapBundle(wxART_INFORMATION)); + tb1->AddTool(ID_SampleItem+4, "Test", wxArtProvider::GetBitmapBundle(wxART_WARNING)); + tb1->AddTool(ID_SampleItem+5, "Test", wxArtProvider::GetBitmapBundle(wxART_MISSING_IMAGE)); tb1->SetCustomOverflowItems(prepend_items, append_items); tb1->Realize(); @@ -794,7 +794,7 @@ MyFrame::MyFrame(wxWindow* parent, wxAuiToolBar* tb2 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW | wxAUI_TB_HORIZONTAL); - wxBitmap tb2_bmp1 = wxArtProvider::GetBitmap(wxART_QUESTION, wxART_OTHER, FromDIP(wxSize(16,16))); + wxBitmapBundle tb2_bmp1 = wxArtProvider::GetBitmapBundle(wxART_QUESTION, wxART_OTHER, wxSize(16,16)); tb2->AddTool(ID_SampleItem+6, "Disabled", tb2_bmp1); tb2->AddTool(ID_SampleItem+7, "Test", tb2_bmp1); tb2->AddTool(ID_SampleItem+8, "Test", tb2_bmp1); @@ -814,7 +814,7 @@ MyFrame::MyFrame(wxWindow* parent, wxAuiToolBar* tb3 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW); - wxBitmap tb3_bmp1 = wxArtProvider::GetBitmap(wxART_FOLDER, wxART_OTHER, FromDIP(wxSize(16,16))); + wxBitmapBundle tb3_bmp1 = wxArtProvider::GetBitmapBundle(wxART_FOLDER, wxART_OTHER, wxSize(16,16)); tb3->AddTool(ID_SampleItem+16, "Check 1", tb3_bmp1, "Check 1", wxITEM_CHECK); tb3->AddTool(ID_SampleItem+17, "Check 2", tb3_bmp1, "Check 2", wxITEM_CHECK); tb3->AddTool(ID_SampleItem+18, "Check 3", tb3_bmp1, "Check 3", wxITEM_CHECK); @@ -836,7 +836,7 @@ MyFrame::MyFrame(wxWindow* parent, wxAUI_TB_OVERFLOW | wxAUI_TB_TEXT | wxAUI_TB_HORZ_TEXT); - wxBitmap tb4_bmp1 = wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_OTHER, FromDIP(wxSize(16,16))); + wxBitmapBundle tb4_bmp1 = wxArtProvider::GetBitmapBundle(wxART_NORMAL_FILE, wxART_OTHER, wxSize(16,16)); tb4->AddTool(ID_DropDownToolbarItem, "Item 1", tb4_bmp1); tb4->AddTool(ID_SampleItem+23, "Item 2", tb4_bmp1); tb4->SetToolSticky(ID_SampleItem+23, true); @@ -859,12 +859,12 @@ MyFrame::MyFrame(wxWindow* parent, wxAuiToolBar* tb5 = new wxAuiToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_OVERFLOW | wxAUI_TB_VERTICAL); - tb5->AddTool(ID_SampleItem+30, "Test", wxArtProvider::GetBitmap(wxART_ERROR)); + tb5->AddTool(ID_SampleItem+30, "Test", wxArtProvider::GetBitmapBundle(wxART_ERROR)); tb5->AddSeparator(); - tb5->AddTool(ID_SampleItem+31, "Test", wxArtProvider::GetBitmap(wxART_QUESTION)); - tb5->AddTool(ID_SampleItem+32, "Test", wxArtProvider::GetBitmap(wxART_INFORMATION)); - tb5->AddTool(ID_SampleItem+33, "Test", wxArtProvider::GetBitmap(wxART_WARNING)); - tb5->AddTool(ID_SampleItem+34, "Test", wxArtProvider::GetBitmap(wxART_MISSING_IMAGE)); + tb5->AddTool(ID_SampleItem+31, "Test", wxArtProvider::GetBitmapBundle(wxART_QUESTION)); + tb5->AddTool(ID_SampleItem+32, "Test", wxArtProvider::GetBitmapBundle(wxART_INFORMATION)); + tb5->AddTool(ID_SampleItem+33, "Test", wxArtProvider::GetBitmapBundle(wxART_WARNING)); + tb5->AddTool(ID_SampleItem+34, "Test", wxArtProvider::GetBitmapBundle(wxART_MISSING_IMAGE)); tb5->SetCustomOverflowItems(prepend_items, append_items); tb5->Realize(); @@ -923,9 +923,9 @@ MyFrame::MyFrame(wxWindow* parent, m_mgr.AddPane(wnd10, wxAuiPaneInfo(). Name("test10").Caption("Text Pane with Hide Prompt"). Bottom().Layer(1).Position(1). - Icon(wxArtProvider::GetBitmap(wxART_WARNING, - wxART_OTHER, - wxSize(iconSize, iconSize)))); + Icon(wxArtProvider::GetBitmapBundle(wxART_WARNING, + wxART_OTHER, + wxSize(iconSize, iconSize)))); m_mgr.AddPane(CreateSizeReportCtrl(), wxAuiPaneInfo(). Name("test11").Caption("Fixed Pane"). @@ -1484,6 +1484,7 @@ void MyFrame::OnDropDownToolbarItem(wxAuiToolBarEvent& evt) // create the popup menu wxMenu menuPopup; + // TODO: Use GetBitmapBundle() when wxMenuItem is updated to use it too. wxBitmap bmp = wxArtProvider::GetBitmap(wxART_QUESTION, wxART_OTHER, FromDIP(wxSize(16,16))); wxMenuItem* m1 = new wxMenuItem(&menuPopup, 10001, _("Drop Down Item 1")); @@ -1650,7 +1651,7 @@ wxAuiNotebook* MyFrame::CreateNotebook() m_notebook_style); ctrl->Freeze(); - wxBitmap page_bmp = wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_OTHER, FromDIP(wxSize(16,16))); + wxBitmapBundle page_bmp = wxArtProvider::GetBitmapBundle(wxART_NORMAL_FILE, wxART_OTHER, wxSize(16,16)); ctrl->AddPage(CreateHTMLCtrl(ctrl), "Welcome to wxAUI" , false, page_bmp); ctrl->SetPageToolTip(0, "Welcome to wxAUI (this is a page tooltip)"); From 10977b0eb606f4d93333fbb8a16deb5a2ef0e51e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 6 Jan 2022 15:43:57 +0000 Subject: [PATCH 09/16] Don't make wxBitmap::GetScaledXXX() virtual There should be never any need to override them, their behaviour is fixed. No real changes. --- include/wx/bitmap.h | 7 ++++--- include/wx/msw/bitmap.h | 7 ++++--- interface/wx/bitmap.h | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/wx/bitmap.h b/include/wx/bitmap.h index 8713884001..ae0bd262c5 100644 --- a/include/wx/bitmap.h +++ b/include/wx/bitmap.h @@ -189,9 +189,10 @@ public: // support for scaled bitmaps virtual void SetScaleFactor(double scale); virtual double GetScaleFactor() const; - virtual double GetScaledWidth() const; - virtual double GetScaledHeight() const; - virtual wxSize GetScaledSize() const; + + double GetScaledWidth() const; + double GetScaledHeight() const; + wxSize GetScaledSize() const; #if wxUSE_IMAGE virtual wxImage ConvertToImage() const = 0; diff --git a/include/wx/msw/bitmap.h b/include/wx/msw/bitmap.h index 21ebdec47f..34132fd0ab 100644 --- a/include/wx/msw/bitmap.h +++ b/include/wx/msw/bitmap.h @@ -187,9 +187,10 @@ public: // provide stabs of scaled bitmaps functions, they are trivial here virtual void SetScaleFactor(double scale); virtual double GetScaleFactor() const; - virtual double GetScaledWidth() const; - virtual double GetScaledHeight() const; - virtual wxSize GetScaledSize() const; + + double GetScaledWidth() const; + double GetScaledHeight() const; + wxSize GetScaledSize() const; // implementation only from now on // ------------------------------- diff --git a/interface/wx/bitmap.h b/interface/wx/bitmap.h index c45a34a583..c2fb3b1643 100644 --- a/interface/wx/bitmap.h +++ b/interface/wx/bitmap.h @@ -604,7 +604,7 @@ public: @since 2.9.5 */ - virtual double GetScaledHeight() const; + double GetScaledHeight() const; /** Returns the scaled size of the bitmap. @@ -620,7 +620,7 @@ public: @since 2.9.5 */ - virtual wxSize GetScaledSize() const; + wxSize GetScaledSize() const; /** Returns the scaled width of the bitmap. @@ -631,7 +631,7 @@ public: @since 2.9.5 */ - virtual double GetScaledWidth() const; + double GetScaledWidth() const; /** Returns the size of the bitmap in pixels. From 2945278334794921bc1dd6ded7951851873879cf Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 6 Jan 2022 18:50:04 +0000 Subject: [PATCH 10/16] Rename wxHAVE_DPI_INDEPENDENT_PIXELS to wxHAS_XXX and document it Using wxHAS_ prefix is more consistent with all the other similar symbols, using wxHAVE_ was a mistake, that we have to pay for by preserving the old name now (as it is actually already used in some code outside of the library). The fact that it's used also shows that it's better to document this symbol, even if just to explain that it normally shouldn't be used, as we can't really hide it anyhow. --- docs/doxygen/mainpages/const_cpp.h | 7 +++++++ include/wx/window.h | 13 ++++++++----- interface/wx/window.h | 4 ++-- src/common/dcsvg.cpp | 4 ++-- src/common/statbmpcmn.cpp | 2 +- src/common/wincmn.cpp | 4 ++-- src/html/htmlwin.cpp | 2 +- 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/docs/doxygen/mainpages/const_cpp.h b/docs/doxygen/mainpages/const_cpp.h index 919e0c54c4..d489df55b4 100644 --- a/docs/doxygen/mainpages/const_cpp.h +++ b/docs/doxygen/mainpages/const_cpp.h @@ -176,6 +176,13 @@ Currently the following symbols exist: supports template Read() and Write() methods in wxConfig.} @itemdef{wxHAS_DEPRECATED_ATTR, Defined if C++14 @c [[deprecated]] attribute is supported (this symbol only exists in wxWidgets 3.1.6 or later).} +@itemdef{wxHAS_DPI_INDEPENDENT_PIXELS, Defined if pixel coordinates on the + current platform scale with DPI, i.e. if the given length in pixels has the + same apparent size on the display independently of the DPI (this symbol + only exists in wxWidgets 3.1.6 or later). Note that it should rarely, if + ever, be necessary to use this symbol directly, functions such as + wxWindow::FromDIP() and wxBitmap::GetScaledSize() exist to hide the + differences between the platforms with and without DPI-independent pixels.} @itemdef{wxHAS_MEMBER_DEFAULT, Defined if the currently used compiler supports C++11 @c =default.} @itemdef{wxHAS_LARGE_FILES, Defined if wxFile supports files more than 4GB in diff --git a/include/wx/window.h b/include/wx/window.h index c9b8869895..557b7f7ac4 100644 --- a/include/wx/window.h +++ b/include/wx/window.h @@ -50,6 +50,9 @@ #endif // __WXUNIVERSAL__/!__WXUNIVERSAL__ #if defined(__WXGTK3__) || defined(__WXMAC__) + #define wxHAS_DPI_INDEPENDENT_PIXELS + + // This is an older synonym kept only for compatibility #define wxHAVE_DPI_INDEPENDENT_PIXELS #endif @@ -542,7 +545,7 @@ public: // Return the magnification of the content of this window for the platforms // using logical pixels different from physical ones, i.e. those for which - // wxHAVE_DPI_INDEPENDENT_PIXELS is defined. For the other ones, always + // wxHAS_DPI_INDEPENDENT_PIXELS is defined. For the other ones, always // returns 1, regardless of DPI scale factor returned by the function below. virtual double GetContentScaleFactor() const; @@ -997,14 +1000,14 @@ public: // horizontal and vertical directions, but this could, in principle, // change too, so prefer using the overloads taking wxPoint or wxSize. -#ifdef wxHAVE_DPI_INDEPENDENT_PIXELS +#ifdef wxHAS_DPI_INDEPENDENT_PIXELS static wxSize FromDIP(const wxSize& sz, const wxWindowBase* WXUNUSED(w)) { return sz; } #else static wxSize FromDIP(const wxSize& sz, const wxWindowBase* w); -#endif // wxHAVE_DPI_INDEPENDENT_PIXELS +#endif // wxHAS_DPI_INDEPENDENT_PIXELS static wxPoint FromDIP(const wxPoint& pt, const wxWindowBase* w) { const wxSize sz = FromDIP(wxSize(pt.x, pt.y), w); @@ -1019,14 +1022,14 @@ public: wxPoint FromDIP(const wxPoint& pt) const { return FromDIP(pt, this); } int FromDIP(int d) const { return FromDIP(d, this); } -#ifdef wxHAVE_DPI_INDEPENDENT_PIXELS +#ifdef wxHAS_DPI_INDEPENDENT_PIXELS static wxSize ToDIP(const wxSize& sz, const wxWindowBase* WXUNUSED(w)) { return sz; } #else static wxSize ToDIP(const wxSize& sz, const wxWindowBase* w); -#endif // wxHAVE_DPI_INDEPENDENT_PIXELS +#endif // wxHAS_DPI_INDEPENDENT_PIXELS static wxPoint ToDIP(const wxPoint& pt, const wxWindowBase* w) { const wxSize sz = ToDIP(wxSize(pt.x, pt.y), w); diff --git a/interface/wx/window.h b/interface/wx/window.h index 93186d4189..98f20adce4 100644 --- a/interface/wx/window.h +++ b/interface/wx/window.h @@ -1416,7 +1416,7 @@ public: For the platforms not doing any pixel mapping, i.e. where logical and physical pixels are one and the same, this function always returns 1.0 and so using it is, in principle, unnecessary and could be avoided by - using preprocessor check for @c wxHAVE_DPI_INDEPENDENT_PIXELS @e not + using preprocessor check for @c wxHAS_DPI_INDEPENDENT_PIXELS @e not being defined, however using this function unconditionally under all platforms is usually simpler and so preferable. @@ -1424,7 +1424,7 @@ public: 3.0, but different from its behaviour in versions 3.1.0 to 3.1.3, where it returned the same value as GetDPIScaleFactor(). Please use the other function if you need to use a scaling factor greater than - 1.0 even for the platforms without @c wxHAVE_DPI_INDEPENDENT_PIXELS, + 1.0 even for the platforms without @c wxHAS_DPI_INDEPENDENT_PIXELS, such as wxMSW. @since 2.9.5 diff --git a/src/common/dcsvg.cpp b/src/common/dcsvg.cpp index 96efcccc1c..6104c349d3 100644 --- a/src/common/dcsvg.cpp +++ b/src/common/dcsvg.cpp @@ -361,7 +361,7 @@ void SetScaledScreenDCFont(wxScreenDC& sDC, const wxFont& font) { // When using DPI-independent pixels, the results of GetTextExtent() and // similar don't depend on DPI anyhow. -#ifndef wxHAVE_DPI_INDEPENDENT_PIXELS +#ifndef wxHAS_DPI_INDEPENDENT_PIXELS static const int SVG_DPI = 96; const double screenDPI = sDC.GetPPI().y; @@ -380,7 +380,7 @@ void SetScaledScreenDCFont(wxScreenDC& sDC, const wxFont& font) sDC.SetFont(scaledFont); } else -#endif // !wxHAVE_DPI_INDEPENDENT_PIXELS +#endif // !wxHAS_DPI_INDEPENDENT_PIXELS { sDC.SetFont(font); } diff --git a/src/common/statbmpcmn.cpp b/src/common/statbmpcmn.cpp index 013e40cb97..95500ba1d1 100644 --- a/src/common/statbmpcmn.cpp +++ b/src/common/statbmpcmn.cpp @@ -101,7 +101,7 @@ wxSize wxStaticBitmapBase::DoGetBestSize() const // // Note that we can use content scale factor rather than DPI scale // because the scaled size is the same as normal size on platforms - // without wxHAVE_DPI_INDEPENDENT_PIXELS (e.g. wxMSW) anyhow. + // without wxHAS_DPI_INDEPENDENT_PIXELS (e.g. wxMSW) anyhow. const wxSize size = m_bitmapBundle.GetPreferredSizeFor(this); const double scale = GetContentScaleFactor(); diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index d700afb064..fc2e20cac4 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -2867,7 +2867,7 @@ wxSize wxWindowBase::GetDPI() const return wxDisplay(static_cast(this)).GetPPI(); } -#ifndef wxHAVE_DPI_INDEPENDENT_PIXELS +#ifndef wxHAS_DPI_INDEPENDENT_PIXELS namespace { @@ -2910,7 +2910,7 @@ wxWindowBase::ToDIP(const wxSize& sz, const wxWindowBase* w) return wxRescaleCoord(sz).From(dpi).To(baseline); } -#endif // !wxHAVE_DPI_INDEPENDENT_PIXELS +#endif // !wxHAS_DPI_INDEPENDENT_PIXELS // Windows' computes dialog units using average character width over upper- // and lower-case ASCII alphabet and not using the average character width diff --git a/src/html/htmlwin.cpp b/src/html/htmlwin.cpp index 63a14ab885..835de23b05 100644 --- a/src/html/htmlwin.cpp +++ b/src/html/htmlwin.cpp @@ -489,7 +489,7 @@ bool wxHtmlWindow::DoSetPage(const wxString& source) SetBackgroundImage(wxNullBitmap); double pixelScale = 1.0; -#ifndef wxHAVE_DPI_INDEPENDENT_PIXELS +#ifndef wxHAS_DPI_INDEPENDENT_PIXELS pixelScale = GetDPIScaleFactor(); #endif From afe3d0ebaeb6d67ea1ba9d68902e11673b651a13 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 6 Jan 2022 18:53:48 +0000 Subject: [PATCH 11/16] Move wxHAS_DPI_INDEPENDENT_PIXELS definition to wx/features.h This is going to be used in wxBitmap code, where wx/window.h is not included. --- include/wx/features.h | 15 +++++++++++++++ include/wx/window.h | 7 ------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/wx/features.h b/include/wx/features.h index 7f28d4915e..e2dd300e58 100644 --- a/include/wx/features.h +++ b/include/wx/features.h @@ -111,5 +111,20 @@ // compiler, so this symbol exists purely for compatibility. #define wxHAS_EVENT_BIND + +/* + Some platforms use DPI-independent pixels, i.e. pixels actually scale with + DPI and a 100px-wide window has the same apparent size on the display in + normal and high (i.e. 2x, or 200% scaling) DPI, while others always use + physical pixels and a window must be 200px wide to have the same apparent + size in high DPI as in normal DPI. + */ +#if defined(__WXGTK3__) || defined(__WXMAC__) + #define wxHAS_DPI_INDEPENDENT_PIXELS + + // This is an older synonym kept only for compatibility + #define wxHAVE_DPI_INDEPENDENT_PIXELS +#endif + #endif /* _WX_FEATURES_H_ */ diff --git a/include/wx/window.h b/include/wx/window.h index 557b7f7ac4..48efebc63d 100644 --- a/include/wx/window.h +++ b/include/wx/window.h @@ -49,13 +49,6 @@ #define wxUSE_MENUS_NATIVE wxUSE_MENUS #endif // __WXUNIVERSAL__/!__WXUNIVERSAL__ -#if defined(__WXGTK3__) || defined(__WXMAC__) - #define wxHAS_DPI_INDEPENDENT_PIXELS - - // This is an older synonym kept only for compatibility - #define wxHAVE_DPI_INDEPENDENT_PIXELS -#endif - // ---------------------------------------------------------------------------- // forward declarations // ---------------------------------------------------------------------------- From f6fbc97c7be8db9c83c1694fd4e596fc42a06ea6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 6 Jan 2022 18:54:39 +0000 Subject: [PATCH 12/16] Only return really scaled bitmap size under platforms using DIPs wxBitmap::GetScaledXXX() functions are useful for obtaining the coordinates in logical pixels, so they should only divide by the scaling factor on the platforms where logical pixels are actually different from the physical ones, i.e. those using DPI-independent pixels. This ensures that their behaviour under MSW remains unchanged even after a1e4dca067 (Store scale factor in wxMSW bitmaps too, 2021-12-16), which is the correct way to avoid breaking wxAUI (and other) drawing. --- include/wx/bitmap.h | 3 +++ include/wx/msw/bitmap.h | 4 +++- interface/wx/bitmap.h | 16 +++++++++++----- src/common/bmpbase.cpp | 21 +++++++++++++++++++++ src/msw/bitmap.cpp | 6 +++--- 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/include/wx/bitmap.h b/include/wx/bitmap.h index ae0bd262c5..dabc68f950 100644 --- a/include/wx/bitmap.h +++ b/include/wx/bitmap.h @@ -190,6 +190,9 @@ public: virtual void SetScaleFactor(double scale); virtual double GetScaleFactor() const; + // These functions return the corresponding metrics divided by the scale + // factor on platforms with DPI-independent pixels (e.g. GTK, Mac) and just + // the same thing as the non-scaled accessors elsewhere (e.g. MSW). double GetScaledWidth() const; double GetScaledHeight() const; wxSize GetScaledSize() const; diff --git a/include/wx/msw/bitmap.h b/include/wx/msw/bitmap.h index 34132fd0ab..1f3d143c70 100644 --- a/include/wx/msw/bitmap.h +++ b/include/wx/msw/bitmap.h @@ -184,10 +184,12 @@ public: void UseAlpha(bool use = true); void ResetAlpha() { UseAlpha(false); } - // provide stabs of scaled bitmaps functions, they are trivial here + // allow setting and storing the scale factor virtual void SetScaleFactor(double scale); virtual double GetScaleFactor() const; + // but scaled metrics accessors return the same thing as non-scaled ones, + // just as in all the other ports without wxHAS_DPI_INDEPENDENT_PIXELS. double GetScaledWidth() const; double GetScaledHeight() const; wxSize GetScaledSize() const; diff --git a/interface/wx/bitmap.h b/interface/wx/bitmap.h index c2fb3b1643..8299dd6f5c 100644 --- a/interface/wx/bitmap.h +++ b/interface/wx/bitmap.h @@ -609,12 +609,18 @@ public: /** Returns the scaled size of the bitmap. - The scaled size of the bitmap is its size in pixels, as returned by + For the platforms using DPI-independent pixels, i.e. those where @c + wxHAS_DPI_INDEPENDENT_PIXELS is defined, such as wxOSX or wxGTK 3, + this function returns the physical size of the bitmap, as returned by GetSize(), divided by its scale factor, as returned by - GetScaleFactor(), and so is the same as the normal size for bitmaps - with the default scale factor of 1 and always less than the physical - size for the higher resolution bitmaps supposed to be used on high DPI - screens. + GetScaleFactor(), while for the other platforms, it simply returns the + same thing as GetSize(). + + This ensures that the result of this function is always expressed in + the pixel coordinates appropriate for the current platform, i.e. its + return value is always in logical pixels, used for window and wxDC + coordinates, whether these pixels are the same as physical pixels, + which are returned by GetSize(), or not. @see GetScaledWidth(), GetScaledHeight(), GetSize() diff --git a/src/common/bmpbase.cpp b/src/common/bmpbase.cpp index 1b76bc3a1a..e3998b862a 100644 --- a/src/common/bmpbase.cpp +++ b/src/common/bmpbase.cpp @@ -220,6 +220,8 @@ double wxBitmapBase::GetScaleFactor() const return 1.0; } +#ifdef wxHAS_DPI_INDEPENDENT_PIXELS + double wxBitmapBase::GetScaledWidth() const { return GetWidth() / GetScaleFactor(); @@ -235,6 +237,25 @@ wxSize wxBitmapBase::GetScaledSize() const return wxSize(wxRound(GetScaledWidth()), wxRound(GetScaledHeight())); } +#else // !wxHAS_DPI_INDEPENDENT_PIXELS + +double wxBitmapBase::GetScaledWidth() const +{ + return GetWidth(); +} + +double wxBitmapBase::GetScaledHeight() const +{ + return GetHeight(); +} + +wxSize wxBitmapBase::GetScaledSize() const +{ + return GetSize(); +} + +#endif // wxHAS_DPI_INDEPENDENT_PIXELS/!wxHAS_DPI_INDEPENDENT_PIXELS + #endif // wxUSE_BITMAP_BASE // ---------------------------------------------------------------------------- diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index c7ed47429a..bba052367d 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -1387,17 +1387,17 @@ double wxBitmap::GetScaleFactor() const double wxBitmap::GetScaledWidth() const { - return GetWidth() / GetScaleFactor(); + return GetWidth(); } double wxBitmap::GetScaledHeight() const { - return GetHeight() / GetScaleFactor(); + return GetHeight(); } wxSize wxBitmap::GetScaledSize() const { - return GetSize() / GetScaleFactor(); + return GetSize(); } // ---------------------------------------------------------------------------- From 03cf1f4359914a6c69a555f8c94ef2db817f6fca Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 6 Jan 2022 19:00:00 +0000 Subject: [PATCH 13/16] Remove wxHAS_BITMAP_SCALE_FACTOR Now wxMSW also stores the scale factor, even if it doesn't use it in its GetScaledXXX(), so it doesn't seem useful to have this symbol for distinguishing the platforms with and without bitmap scale factor support, when we can just use wxHAS_DPI_INDEPENDENT_PIXELS instead in the only place where this was used. And as this symbol was added quite recently, in 2c1f4c002d (Add wxBitmap::SetScaleFactor(), 2021-10-23), we can hopefully just remove it without breaking any existing code, if we do it right now. --- docs/doxygen/mainpages/const_cpp.h | 3 --- include/wx/gtk/bitmap.h | 6 +----- include/wx/osx/bitmap.h | 2 -- interface/wx/bitmap.h | 15 --------------- tests/graphics/bmpbundle.cpp | 4 ++-- 5 files changed, 3 insertions(+), 27 deletions(-) diff --git a/docs/doxygen/mainpages/const_cpp.h b/docs/doxygen/mainpages/const_cpp.h index d489df55b4..75a5b56c8d 100644 --- a/docs/doxygen/mainpages/const_cpp.h +++ b/docs/doxygen/mainpages/const_cpp.h @@ -167,9 +167,6 @@ Currently the following symbols exist: have an efficient (CPU-specific) implementation. Notice that the functions themselves are always available but can be prohibitively slow to use when implemented in a generic way, using a critical section.} -@itemdef{wxHAS_BITMAP_SCALE_FACTOR, Defined in @c wx/bitmap.h if bitmaps - actually use scale factor under the current platform, see - wxBitmap::SetScaleFactor().} @itemdef{wxHAS_BITMAPTOGGLEBUTTON, Defined in @c wx/tglbtn.h if wxBitmapToggleButton class is available in addition to wxToggleButton.} @itemdef{wxHAS_CONFIG_TEMPLATE_RW, Defined if the currently used compiler diff --git a/include/wx/gtk/bitmap.h b/include/wx/gtk/bitmap.h index f79c081393..975dff950f 100644 --- a/include/wx/gtk/bitmap.h +++ b/include/wx/gtk/bitmap.h @@ -17,10 +17,6 @@ typedef struct _GdkPixbuf GdkPixbuf; class WXDLLIMPEXP_FWD_CORE wxPixelDataBase; class WXDLLIMPEXP_FWD_CORE wxCursor; -#ifdef __WXGTK3__ - #define wxHAS_BITMAP_SCALE_FACTOR -#endif - //----------------------------------------------------------------------------- // wxMask //----------------------------------------------------------------------------- @@ -89,7 +85,7 @@ public: { return Create(sz.GetWidth(), sz.GetHeight(), depth); } bool Create(int width, int height, const wxDC& WXUNUSED(dc)) { return Create(width,height); } -#ifdef wxHAS_BITMAP_SCALE_FACTOR +#ifdef __WXGTK3__ virtual bool CreateScaled(int w, int h, int depth, double scale) wxOVERRIDE; virtual void SetScaleFactor(double scale) wxOVERRIDE; virtual double GetScaleFactor() const wxOVERRIDE; diff --git a/include/wx/osx/bitmap.h b/include/wx/osx/bitmap.h index 47c7e5fdc1..c8173abc59 100644 --- a/include/wx/osx/bitmap.h +++ b/include/wx/osx/bitmap.h @@ -13,8 +13,6 @@ #include "wx/palette.h" -#define wxHAS_BITMAP_SCALE_FACTOR - // Bitmap class WXDLLIMPEXP_FWD_CORE wxBitmap; class wxBitmapRefData ; diff --git a/interface/wx/bitmap.h b/interface/wx/bitmap.h index 8299dd6f5c..3ef0c30b94 100644 --- a/interface/wx/bitmap.h +++ b/interface/wx/bitmap.h @@ -816,21 +816,6 @@ public: When creating a new bitmap, CreateScaled() can be used to specify the correct scale factor from the beginning. - Note that this method exists in all ports, but simply does nothing in - those of them that don't use logical pixel scaling. The preprocessor - symbol @c wxHAS_BITMAP_SCALE_FACTOR can be tested to determine whether - the scale factor is really supported, e.g. - - @code - bitmap.SetScaleFactor(2); - - // In the other ports scale factor is always 1, so the assert would - // fail there. - #ifdef wxHAS_BITMAP_SCALE_FACTOR - wxASSERT( bitmap.GetScaleFactor() == 2 ); - #endif - @endcode - @since 3.1.6 */ virtual void SetScaleFactor(double scale); diff --git a/tests/graphics/bmpbundle.cpp b/tests/graphics/bmpbundle.cpp index cebbc0c110..b0f7cac236 100644 --- a/tests/graphics/bmpbundle.cpp +++ b/tests/graphics/bmpbundle.cpp @@ -73,7 +73,7 @@ TEST_CASE("BitmapBundle::GetPreferredSize", "[bmpbundle]") CHECK( b.GetPreferredSizeAtScale(3 ) == 3*normal ); } -#ifdef wxHAS_BITMAP_SCALE_FACTOR +#ifdef wxHAS_DPI_INDEPENDENT_PIXELS TEST_CASE("BitmapBundle::Scaled", "[bmpbundle]") { @@ -105,7 +105,7 @@ TEST_CASE("BitmapBundle::Scaled", "[bmpbundle]") CHECK( b.GetDefaultSize() == wxSize(32, 32) ); } -#endif // wxHAS_BITMAP_SCALE_FACTOR +#endif // wxHAS_DPI_INDEPENDENT_PIXELS #ifdef wxHAS_SVG From 7c7ff3cd42dc96f0dac8a71d818cea71ee10e1d1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 6 Jan 2022 19:17:28 +0000 Subject: [PATCH 14/16] Add wxBitmap::GetDIPSize() and use it in wxBitmapBundleImplArt This fixes the problem with wrong standard bitmaps size when using high DPI for the main monitor with wxMSW, as GetScaledSize() used here since 31f2892200 (Avoid bitmap scaling in wxArtProvider::GetBitmapBundle(), 2021-12-17) was not the right function to use there. Closes #19331. --- include/wx/bitmap.h | 8 +++++++- include/wx/msw/bitmap.h | 3 +++ interface/wx/bitmap.h | 16 ++++++++++++++++ src/common/artprov.cpp | 2 +- src/common/bmpbase.cpp | 5 +++++ src/msw/bitmap.cpp | 5 +++++ 6 files changed, 37 insertions(+), 2 deletions(-) diff --git a/include/wx/bitmap.h b/include/wx/bitmap.h index dabc68f950..67bed4ce30 100644 --- a/include/wx/bitmap.h +++ b/include/wx/bitmap.h @@ -186,10 +186,16 @@ public: wxSize GetSize() const { return wxSize(GetWidth(), GetHeight()); } - // support for scaled bitmaps + // Store or return the scale factor, which determines the ratio between the + // bitmap physical size and its DIP size (on all platforms). By default + // it's just 1. virtual void SetScaleFactor(double scale); virtual double GetScaleFactor() const; + // This function returns the size divided by the scale factor, so that a + // 64x64 bitmap with a scale factor of 2 has DIP size of 32x32 everywhere. + wxSize GetDIPSize() const; + // These functions return the corresponding metrics divided by the scale // factor on platforms with DPI-independent pixels (e.g. GTK, Mac) and just // the same thing as the non-scaled accessors elsewhere (e.g. MSW). diff --git a/include/wx/msw/bitmap.h b/include/wx/msw/bitmap.h index 1f3d143c70..a3c6d1279b 100644 --- a/include/wx/msw/bitmap.h +++ b/include/wx/msw/bitmap.h @@ -188,6 +188,9 @@ public: virtual void SetScaleFactor(double scale); virtual double GetScaleFactor() const; + // return the size divided by scale factor + wxSize GetDIPSize() const; + // but scaled metrics accessors return the same thing as non-scaled ones, // just as in all the other ports without wxHAS_DPI_INDEPENDENT_PIXELS. double GetScaledWidth() const; diff --git a/interface/wx/bitmap.h b/interface/wx/bitmap.h index 3ef0c30b94..c1605c0523 100644 --- a/interface/wx/bitmap.h +++ b/interface/wx/bitmap.h @@ -541,6 +541,22 @@ public: */ virtual int GetDepth() const; + /** + Returns the size of bitmap in DPI-independent units. + + This assumes that the bitmap was created using the value of scale + factor corresponding to the current DPI (see CreateScaled() and + SetScaleFactor()) and returns its physical size divided by this scale + factor. + + Unlike GetScaledSize(), this function returns the same value under all + platforms and so its result should @e not be used as window or device + context coordinates. + + @since 3.1.6 + */ + wxSize GetDIPSize() const; + /** Returns the static list of bitmap format handlers. diff --git a/src/common/artprov.cpp b/src/common/artprov.cpp index 0d7aa76e54..4a06f88e96 100644 --- a/src/common/artprov.cpp +++ b/src/common/artprov.cpp @@ -193,7 +193,7 @@ private: // necessary, so use GetScaledSize() and not GetSize(). const wxBitmap bitmap = wxArtProvider::GetBitmap(id, client); if ( bitmap.IsOk() ) - return bitmap.GetScaledSize(); + return bitmap.GetDIPSize(); // We really need some default size, so just return this hardcoded // value if all else fails -- what else can we do. diff --git a/src/common/bmpbase.cpp b/src/common/bmpbase.cpp index e3998b862a..3cb1c75471 100644 --- a/src/common/bmpbase.cpp +++ b/src/common/bmpbase.cpp @@ -220,6 +220,11 @@ double wxBitmapBase::GetScaleFactor() const return 1.0; } +wxSize wxBitmapBase::GetDIPSize() const +{ + return GetSize() / GetScaleFactor(); +} + #ifdef wxHAS_DPI_INDEPENDENT_PIXELS double wxBitmapBase::GetScaledWidth() const diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index bba052367d..86b936ef3a 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -1385,6 +1385,11 @@ double wxBitmap::GetScaleFactor() const return GetBitmapData()->m_scaleFactor; } +wxSize wxBitmap::GetDIPSize() const +{ + return GetSize() / GetScaleFactor(); +} + double wxBitmap::GetScaledWidth() const { return GetWidth(); From 109a6fa5b764c83644baf2819656a82eed1c5065 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Tue, 11 Jan 2022 22:30:19 +0100 Subject: [PATCH 15/16] Fix AUI tab size calculation for non MSW ports in high DPI The physical size returned by wxBitmapBundle::GetPreferredSizeFor() must be converted to logical pixels when it's used as a wxDC coordinate. This fixes a regression introduced in 391080e77d (Use wxBitmapBundle for AUI tab pages bitmaps, 2021-11-13). --- src/aui/tabart.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/aui/tabart.cpp b/src/aui/tabart.cpp index e7aea1f3ba..347d319928 100644 --- a/src/aui/tabart.cpp +++ b/src/aui/tabart.cpp @@ -703,7 +703,9 @@ wxSize wxAuiGenericTabArt::GetTabSize(wxDC& dc, // if there's a bitmap, add space for it if (bitmap.IsOk()) { - const wxSize bitmapSize = bitmap.GetPreferredSizeFor(wnd); + // we need the correct size of the bitmap to be used on this window in + // logical dimensions for drawing + const wxSize bitmapSize = bitmap.GetPreferredSizeFor(wnd) / wnd->GetContentScaleFactor(); // increase by bitmap plus right side bitmap padding tab_width += bitmapSize.x + wnd->FromDIP(3); From 2ed79f8f88fda8bff99af0047e29aa2d0b87477a Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Tue, 11 Jan 2022 22:30:19 +0100 Subject: [PATCH 16/16] Also fix AUI tab size calculation in high DPI This is similar to the parent commit and does the same thing for the total width calculation. --- src/aui/tabart.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/aui/tabart.cpp b/src/aui/tabart.cpp index 347d319928..8ceb85d5cb 100644 --- a/src/aui/tabart.cpp +++ b/src/aui/tabart.cpp @@ -248,9 +248,9 @@ void wxAuiGenericTabArt::SetSizingInfo(const wxSize& tab_ctrl_size, int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - wnd->FromDIP(4); if (m_flags & wxAUI_NB_CLOSE_BUTTON) - tot_width -= m_activeCloseBmp.GetPreferredSizeFor(wnd).x; + tot_width -= m_activeCloseBmp.GetPreferredSizeFor(wnd).x / wnd->GetContentScaleFactor(); if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON) - tot_width -= m_activeWindowListBmp.GetPreferredSizeFor(wnd).x; + tot_width -= m_activeWindowListBmp.GetPreferredSizeFor(wnd).x / wnd->GetContentScaleFactor(); if (tab_count > 0) {