Merge branch 'phys-pixels-convert'

Add function for converting between logical and physical pixels too.

See #22013.
This commit is contained in:
Vadim Zeitlin
2022-01-16 23:39:50 +01:00
6 changed files with 226 additions and 23 deletions

View File

@@ -981,6 +981,57 @@ public:
// wxWidgets public API.
virtual void WXAdjustFontToOwnPPI(wxFont& WXUNUSED(font)) const { }
// All pixel coordinates used in wx API are in logical pixels, which
// are the same as physical screen pixels under MSW, but same as DIPs
// (see below) under the other ports. The functions defined here can be
// used under all platforms to convert between them without using any
// preprocessor checks.
#ifdef wxHAS_DPI_INDEPENDENT_PIXELS
static wxSize FromPhys(wxSize sz, const wxWindowBase* w);
#else
static wxSize FromPhys(const wxSize& sz, const wxWindowBase* WXUNUSED(w))
{
return sz;
}
#endif
static wxPoint FromPhys(const wxPoint& pt, const wxWindowBase* w)
{
const wxSize sz = FromPhys(wxSize(pt.x, pt.y), w);
return wxPoint(sz.x, sz.y);
}
static int FromPhys(int d, const wxWindowBase* w)
{
return FromPhys(wxSize(d, 0), w).x;
}
wxSize FromPhys(const wxSize& sz) const { return FromPhys(sz, this); }
wxPoint FromPhys(const wxPoint& pt) const { return FromPhys(pt, this); }
int FromPhys(int d) const { return FromPhys(d, this); }
#ifdef wxHAS_DPI_INDEPENDENT_PIXELS
static wxSize ToPhys(wxSize sz, const wxWindowBase* w);
#else
static wxSize ToPhys(const wxSize& sz, const wxWindowBase* WXUNUSED(w))
{
return sz;
}
#endif // wxHAS_DPI_INDEPENDENT_PIXELS
static wxPoint ToPhys(const wxPoint& pt, const wxWindowBase* w)
{
const wxSize sz = ToPhys(wxSize(pt.x, pt.y), w);
return wxPoint(sz.x, sz.y);
}
static int ToPhys(int d, const wxWindowBase* w)
{
return ToPhys(wxSize(d, 0), w).x;
}
wxSize ToPhys(const wxSize& sz) const { return ToPhys(sz, this); }
wxPoint ToPhys(const wxPoint& pt) const { return ToPhys(pt, this); }
int ToPhys(int d) const { return ToPhys(d, this); }
// DPI-independent pixels, or DIPs, are pixel values for the standard
// 96 DPI display, they are scaled to take the current resolution into
// account (i.e. multiplied by the same factor as returned by

View File

@@ -1198,6 +1198,103 @@ public:
/// @overload
static int ToDIP(int d, const wxWindow* w);
/**
Convert from physical pixels to logical pixels.
All window coordinates in wxWidgets API are always expressed in logical
pixels, but the meaning of logical pixels depends on the platform.
Physical pixels always mean the same thing and refer to the actual
display pixels or, also, sizes of the bitmaps. Under some platforms
logical pixels are actually the same as physical ones (this is the case
for MSW), but under other platforms (e.g. GTK or macOS) this is not the
case and GetContentScaleFactor() defines the ratio between one logical
and one physical pixel.
This function can be used to convert a value in physical pixels to
logical pixels independently of the platform used. It simply does
nothing under MSW, but divides the input value by the content scale
factor under the other platforms.
Note that dividing an integer value by scale factor doesn't always
yield an integer value. This function always round the resulting value
up, e.g. 15 physical pixels are translated to 8, not 7, logical pixels
in 200% DPI scaling. This ensures that a physical bitmap of size 15 is
not truncated if the result of this function is used to create a window
to show it, but it does mean that there will be one extra pixel left.
@see FromDIP(), ToPhys()
@since 3.1.6
*/
wxSize FromPhys(const wxSize& sz) const;
/// @overload
wxPoint FromPhys(const wxPoint& pt) const;
/// @overload
int FromPhys(int d) const;
/**
Convert from physical pixels to logical pixels for any window.
This function can be used without any window pointer, i.e. @a w can be
@NULL. In this case, it uses the content scale factor of the main
screen if supported or just does nothing (i.e. uses scale factor of 1)
otherwise.
Using member overloads is always preferable, if possible, as they
always use the actually appropriate content scale factor.
@since 3.1.6
*/
static wxSize FromPhys(const wxSize& sz, const wxWindow* w);
/// @overload
static wxPoint FromPhys(const wxPoint& pt, const wxWindow* w);
/// @overload
static int FromPhys(int d, const wxWindow* w);
/**
Convert from logical pixels to physical pixels.
This function performs the transformation in the converse direction
compared to FromPhys().
@since 3.1.6
*/
wxSize ToPhys(const wxSize& sz) const;
/// @overload
wxPoint ToPhys(const wxPoint& pt) const;
/// @overload
int ToPhys(int d) const;
/**
Convert from logical pixels to physical pixels for any window.
This function can be used without any window pointer, i.e. @a w can be
@NULL. In this case, it uses the content scale factor of the main
screen if supported or just does nothing (i.e. uses scale factor of 1)
otherwise.
Using member overloads is always preferable, if possible, as they
always use the actually appropriate content scale factor.
@since 3.1.6
*/
static wxSize ToPhys(const wxSize& sz, const wxWindow* w);
/// @overload
static wxPoint ToPhys(const wxPoint& pt, const wxWindow* w);
/// @overload
static int ToPhys(int d, const wxWindow* w);
/**
This functions returns the best acceptable minimal size for the window.

View File

@@ -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 / wnd->GetContentScaleFactor();
tot_width -= wnd->FromPhys(m_activeCloseBmp.GetPreferredSizeFor(wnd).x);
if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON)
tot_width -= m_activeWindowListBmp.GetPreferredSizeFor(wnd).x / wnd->GetContentScaleFactor();
tot_width -= wnd->FromPhys(m_activeWindowListBmp.GetPreferredSizeFor(wnd).x);
if (tab_count > 0)
{
@@ -705,7 +705,7 @@ wxSize wxAuiGenericTabArt::GetTabSize(wxDC& dc,
{
// 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();
const wxSize bitmapSize = wnd->FromPhys(bitmap.GetPreferredSizeFor(wnd));
// increase by bitmap plus right side bitmap padding
tab_width += bitmapSize.x + wnd->FromDIP(3);

View File

@@ -306,7 +306,7 @@ wxSize wxAuiMSWTabArt::GetTabSize(wxDC& dc,
// if there's a bitmap, add space for it
if ( bitmap.IsOk() )
{
const wxSize bitmapSize = bitmap.GetPreferredSizeFor(wnd);
const wxSize bitmapSize = wnd->FromPhys(bitmap.GetPreferredSizeFor(wnd));
tabWidth += bitmapSize.x + wnd->FromDIP(3); // bitmap padding
tabHeight = wxMax(tabHeight, bitmapSize.y + wnd->FromDIP(2));

View File

@@ -24,8 +24,6 @@
#include "wx/statbmp.h"
#include <math.h>
extern WXDLLEXPORT_DATA(const char) wxStaticBitmapNameStr[] = "staticBitmap";
// ---------------------------------------------------------------------------
@@ -94,20 +92,7 @@ wxStaticBitmapBase::~wxStaticBitmapBase()
wxSize wxStaticBitmapBase::DoGetBestSize() const
{
if ( m_bitmapBundle.IsOk() )
{
// We return the scaled (i.e. in logical pixels) size of the bitmap
// that would be returned by GetBitmap(), but without bothering to
// actually create the bitmap here.
//
// 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 wxHAS_DPI_INDEPENDENT_PIXELS (e.g. wxMSW) anyhow.
const wxSize size = m_bitmapBundle.GetPreferredSizeFor(this);
const double scale = GetContentScaleFactor();
// We have to round up the size to avoid truncating the bitmap.
return wxSize(ceil(size.x/scale), ceil(size.y/scale));
}
return FromPhys(m_bitmapBundle.GetPreferredSizeFor(this));
// the fall back size is completely arbitrary
return wxSize(16, 16);

View File

@@ -77,6 +77,13 @@
#include "wx/private/rescale.h"
#include "wx/private/window.h"
#if defined(__WXOSX__)
// We need wxOSXGetMainScreenContentScaleFactor() declaration.
#include "wx/osx/core/private.h"
#endif
#include <math.h>
// Windows List
WXDLLIMPEXP_DATA_CORE(wxWindowList) wxTopLevelWindows;
@@ -2859,7 +2866,7 @@ void wxWindowBase::OnInternalIdle()
}
// ----------------------------------------------------------------------------
// DPI-independent pixels and dialog units translations
// Conversions between various pixel kinds and dialog units translations
// ----------------------------------------------------------------------------
wxSize wxWindowBase::GetDPI() const
@@ -2867,7 +2874,70 @@ wxSize wxWindowBase::GetDPI() const
return wxDisplay(static_cast<const wxWindow*>(this)).GetPPI();
}
#ifndef wxHAS_DPI_INDEPENDENT_PIXELS
#ifdef wxHAS_DPI_INDEPENDENT_PIXELS
// In this case logical pixels are DIPs, so we don't need to define conversion
// to/from them (or, rather, they are already defined as trivial inline
// functions in the header), but we do need to define conversions to/from
// physical pixels.
namespace
{
double GetContentScaleFactorFor(const wxWindowBase* w)
{
if ( w )
return w->GetContentScaleFactor();
#ifdef __WXOSX__
return wxOSXGetMainScreenContentScaleFactor();
#else
return 1.0;
#endif
}
} // anonymous namespace
/* static */
wxSize wxWindowBase::FromPhys(wxSize sz, const wxWindowBase* w)
{
const double scale = GetContentScaleFactorFor(w);
if ( scale != 1.0 )
{
// We prefer to round up the size so that conversion from physical
// pixels to logical and back doesn't result in smaller value, as this
// would e.g. truncate the bitmap of odd size when drawing it at 200%
// scaling. Leaving an extra pixel in this case seems like a lesser
// evil, even if not ideal.
if ( sz.x != wxDefaultCoord )
sz.x = ceil(sz.x) / scale;
if ( sz.y != wxDefaultCoord )
sz.y = ceil(sz.y) / scale;
}
return sz;
}
/* static */
wxSize wxWindowBase::ToPhys(wxSize sz, const wxWindowBase* w)
{
const double scale = GetContentScaleFactorFor(w);
if ( scale != 1.0 )
{
if ( sz.x != wxDefaultCoord )
sz.x *= scale;
if ( sz.y != wxDefaultCoord )
sz.y *= scale;
}
return sz;
}
#else // !wxHAS_DPI_INDEPENDENT_PIXELS
// In this case we have non-trivial implementations for DIP conversions only.
namespace
{
@@ -2910,7 +2980,7 @@ wxWindowBase::ToDIP(const wxSize& sz, const wxWindowBase* w)
return wxRescaleCoord(sz).From(dpi).To(baseline);
}
#endif // !wxHAS_DPI_INDEPENDENT_PIXELS
#endif // wxHAS_DPI_INDEPENDENT_PIXELS/!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