From a8eaeb0276604ae6256bb1fafa3e528ee59bc8d5 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 4 Jun 2022 18:28:49 +0100 Subject: [PATCH] Fix using wxGraphicsContext with scrolled wxDC in wxMSW The changes of 4f9186f1a1 (Increase usable scrolling range in wxMSW by a factor of 10,000, 2022-04-30) broke using wxGraphicsContext, and wxGCDC, with scrolled wxDC, as GDI+ wasn't aware about the origin shift in it any more, now that it's not done at MSW level any longer. Fix this by shifting the origin before constructing the Graphics object from HDC to restore the old behaviour. Note that this means that the origin shift is still limited to 2^27 (instead of the full int range) when using wxGCDC, which is not ideal, but better than breaking it completely (and when using wxGraphicsContext directly, world transformation can, and should, be used to avoid this limit). Closes #22480. --- src/msw/graphics.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/msw/graphics.cpp b/src/msw/graphics.cpp index 360d570c27..0d963eb02e 100644 --- a/src/msw/graphics.cpp +++ b/src/msw/graphics.cpp @@ -1865,6 +1865,33 @@ wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, const wxDC& dc HDC hdc = (HDC) dc.GetHDC(); wxSize sz = dc.GetSize(); + // We don't set HDC origin at MSW level in wxDC because this limits it to + // 2^27 range and we prefer to handle it ourselves to allow using the full + // 2^32 range of int coordinates, but we need to let GDI+ know about the + // origin shift. It would seem that using TranslateTransform() should be + // the right way to do it, but using it results in drawing artifacts when + // scrolling (see #22480), so we temporarily set the origin instead: this + // won't work for the shifts beyond 2^27 GDI range, but is better than + // nothing. + class TempSetViewportOrg + { + public: + TempSetViewportOrg(HDC hdc, const wxPoint& origin) + : m_hdc(hdc) + { + ::SetViewportOrgEx(m_hdc, origin.x, origin.y, &m_originPrev); + } + + ~TempSetViewportOrg() + { + ::SetViewportOrgEx(m_hdc, m_originPrev.x, m_originPrev.y, NULL); + } + + private: + const HDC m_hdc; + POINT m_originPrev; + } tempSetViewportOrg(hdc, dc.GetDeviceOrigin()); + Init(new Graphics(hdc), sz.x, sz.y); }