Respect bitmap content scale factor in wxMSW wxMemoryDC

Apply it manually because MSW doesn't do it automatically for us and
also adjust the font size in wxMemoryDC as the base class version only
does it for the device contexts associated with a window, but we also
need to do it when using a wxMemoryDC for a bitmap using scale factor
different from that of the main display.

As the result of these changes, contents drawn on wxMemoryDC, both
directly via its own methods, or via wxGraphicsContext (using either
GDI+ or Direct2D) created from it, it appears the same as in wxWindowDC
(e.g. wxPaintDC) created for a window using the same scale.

Closes #22130.

Closes #22234.
This commit is contained in:
Vadim Zeitlin
2022-03-26 01:38:59 +01:00
parent 74fa410b81
commit 9e5c8a8027
6 changed files with 39 additions and 7 deletions

View File

@@ -22,6 +22,8 @@ public:
wxMemoryDCImpl( wxMemoryDC *owner, wxDC *dc ); // Create compatible DC
// override some base class virtuals
virtual void SetFont(const wxFont& font) wxOVERRIDE;
virtual void DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) wxOVERRIDE;
virtual void DoGetSize(int* width, int* height) const wxOVERRIDE;
virtual void DoSelect(const wxBitmap& bitmap) wxOVERRIDE;

View File

@@ -2535,7 +2535,8 @@ void MyFrame::OnSave(wxCommandEvent& WXUNUSED(event))
else
#endif // wxUSE_POSTSCRIPT
{
wxBitmap bmp(width, height);
wxBitmap bmp;
bmp.CreateWithDIPSize(wxSize(width, height), GetDPIScaleFactor());
wxMemoryDC mdc(bmp);
mdc.SetBackground(*wxWHITE_BRUSH);
mdc.Clear();

View File

@@ -2648,7 +2648,7 @@ wxSize wxMSWDCImpl::GetPPI() const
if ( !ppi.x || !ppi.y )
{
ppi = wxGetDPIofHDC(GetHdc());
ppi = wxGetDPIofHDC(GetHdc())*GetContentScaleFactor();
}
return ppi;

View File

@@ -28,6 +28,8 @@
#include "wx/log.h"
#endif
#include "wx/display.h"
#include "wx/msw/private.h"
// ----------------------------------------------------------------------------
@@ -131,6 +133,23 @@ void wxMemoryDCImpl::DoSelect( const wxBitmap& bitmap )
{
m_oldBitmap = hBmp;
}
// Remember content scale factor used by the bitmap: we don't use it
// ourselves, but this can be needed later for creating fonts of the
// correct size.
m_contentScaleFactor = bitmap.GetScaleFactor();
// The font may need to be adjusted for the new scale factor.
SetFont(GetFont());
}
void wxMemoryDCImpl::SetFont(const wxFont& font)
{
// We need to adjust the font size by the ratio between the scale factor we
// use and the default/global scale factor used when creating fonts.
wxFont scaledFont = font;
scaledFont.WXAdjustToPPI(wxDisplay::GetStdPPI()*m_contentScaleFactor);
wxMSWDCImpl::SetFont(scaledFont);
}
void wxMemoryDCImpl::DoGetSize(int *width, int *height) const

View File

@@ -2503,9 +2503,9 @@ void wxGDIPlusContext::GetDPI(wxDouble* dpiX, wxDouble* dpiY) const
else
{
if ( dpiX )
*dpiX = GetGraphics()->GetDpiX();
*dpiX = GetGraphics()->GetDpiX()*GetContentScaleFactor();
if ( dpiY )
*dpiY = GetGraphics()->GetDpiY();
*dpiY = GetGraphics()->GetDpiY()*GetContentScaleFactor();
}
}
@@ -2730,6 +2730,14 @@ wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxMemoryDC& dc)
wxGDIPlusContext* context = new wxGDIPlusContext(this, dc);
context->EnableOffset(true);
// GDI+ uses the default system DPI, so we don't need to do anything if the
// scale factor of the associated bitmap is already the same, but we do
// need to scale it correctly if it is different from the scale factor for
// the default DPI. To get the latter, we would normally use a screen HDC
// but we already have a memory HDC at hand, so we can just use it instead.
const int defDPI = wxGetDPIofHDC(GetHdcOf(dc)).y;
context->SetContentScaleFactor(dc.GetContentScaleFactor() * 96.0 / defDPI);
return context;
}

View File

@@ -4965,9 +4965,9 @@ void wxD2DContext::GetDPI(wxDouble* dpiX, wxDouble* dpiY) const
GetRenderTarget()->GetDpi(&x, &y);
if ( dpiX )
*dpiX = x;
*dpiX = x*GetContentScaleFactor();
if ( dpiY )
*dpiY = y;
*dpiY = y*GetContentScaleFactor();
}
}
@@ -5131,8 +5131,10 @@ wxGraphicsContext* wxD2DRenderer::CreateContext(const wxMemoryDC& dc)
wxBitmap bmp = dc.GetSelectedBitmap();
wxASSERT_MSG( bmp.IsOk(), wxS("Should select a bitmap before creating wxGraphicsContext") );
return new wxD2DContext(this, m_direct2dFactory, dc.GetHDC(), &dc,
wxD2DContext* d2d = new wxD2DContext(this, m_direct2dFactory, dc.GetHDC(), &dc,
bmp.HasAlpha() ? D2D1_ALPHA_MODE_PREMULTIPLIED : D2D1_ALPHA_MODE_IGNORE);
d2d->SetContentScaleFactor(dc.GetContentScaleFactor());
return d2d;
}
#if wxUSE_PRINTING_ARCHITECTURE