From 994971e2df9edbbdddcb5373d9c46c7460f8489f Mon Sep 17 00:00:00 2001 From: Artur Wieczorek Date: Fri, 6 Dec 2019 00:02:47 +0100 Subject: [PATCH] Draw horizontal/vertical lines with optimized function only on non-scaled DCs It turned out that drawing horizontal/vertical lines with optimized function based on ExtTextOut() Win API works as expected only for non-scaled DC. Therefore we can use this optimized way of drawing only for non-rotated and non-scaled DCs. On not-scaled DCs we can use optimized function to draw also 0-pixel width lines (as a 1-pixel wide lines for compatibility with Win API). Closes #18612. --- src/msw/dc.cpp | 50 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index cd31f1ba18..dd1a6c540f 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -801,6 +801,20 @@ bool wxMSWDCImpl::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const return true; } +// Check whether DC is not rotated and not scaled +static bool IsNonTransformedDC(HDC hdc) +{ + // Ensure DC is not rotated + if ( ::GetGraphicsMode(hdc) == GM_ADVANCED ) + return false; + // and not scaled + SIZE devExt; + ::GetViewportExtEx(hdc, &devExt); + SIZE logExt; + ::GetWindowExtEx(hdc, &logExt); + return devExt.cx == logExt.cx && devExt.cy == logExt.cy; +} + void wxMSWDCImpl::DoCrossHair(wxCoord x, wxCoord y) { RECT rect; @@ -813,23 +827,24 @@ void wxMSWDCImpl::DoCrossHair(wxCoord x, wxCoord y) // We have optimized function to draw physical vertical or horizontal lines // with solid color and square ends so it can be used to draw a cross hair // for: - // - Solid lines with pen width > 0 because it doesn't support drawing - // non-scaled 1-pixel wide lines when pen width is 0. Shape of the lines - // ends doesn't matter because non-square line ends are drawn outside - // the view and visible line ends are always square. + // - Any shape of the lines ends because non-square line ends are drawn + // outside the view and visible line ends are always square. // - DC which coordinate system is not rotated (graphics mode - // of the DC != GM_ADVANCED). - if ( ::GetGraphicsMode(GetHdc()) != GM_ADVANCED && // ensure DC is not rotated + // of the DC != GM_ADVANCED) and not scaled. + if ( IsNonTransformedDC(GetHdc()) && m_pen.IsNonTransparent() && // this calls IsOk() too - m_pen.GetStyle() == wxPENSTYLE_SOLID && - m_pen.GetWidth() > 0 + m_pen.GetStyle() == wxPENSTYLE_SOLID ) { + // Since we are drawing on a non-scaled DC, a 0-pixel width line + // can be safely drawn as a 1-pixel wide one. + int w = m_pen.GetWidth() > 0 ? m_pen.GetWidth() : 1; + COLORREF color = wxColourToRGB(m_pen.GetColour()); wxDrawHVLine(GetHdc(), XLOG2DEV(rect.left), YLOG2DEV(y), XLOG2DEV(rect.right), YLOG2DEV(y), - color, m_pen.GetWidth()); + color, w); wxDrawHVLine(GetHdc(), XLOG2DEV(x), YLOG2DEV(rect.top), XLOG2DEV(x), YLOG2DEV(rect.bottom), - color, m_pen.GetWidth()); + color, w); } else { @@ -849,20 +864,19 @@ void wxMSWDCImpl::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) // in the device coordinate system is complex so we only check whether // the line is horizontal/vertical in the logical coordinates and use // optimized function only for DC which coordinate system is for sure - // not rotated (graphics mode of the DC != GM_ADVANCED). - // Moreover, optimized function can be used only for regular lines with pen - // width > 0 because it doesn't support drawing non-scaled 1-pixel wide - // lines when pen width is 0. + // not rotated (graphics mode of the DC != GM_ADVANCED) and not scaled. if ( (x1 == x2 || y1 == y2) && - ::GetGraphicsMode(GetHdc()) != GM_ADVANCED && // ensure DC is not rotated + IsNonTransformedDC(GetHdc()) && m_pen.IsNonTransparent() && // this calls IsOk() too m_pen.GetStyle() == wxPENSTYLE_SOLID && - m_pen.GetWidth() > 0 && - (m_pen.GetWidth() == 1 || m_pen.GetCap() == wxCAP_BUTT) + (m_pen.GetWidth() <= 1 || m_pen.GetCap() == wxCAP_BUTT) ) { + // Since we are drawing on a non-scaled DC, a 0-pixel width line + // can be safely drawn as a 1-pixel wide one. wxDrawHVLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2), - wxColourToRGB(m_pen.GetColour()), m_pen.GetWidth()); + wxColourToRGB(m_pen.GetColour()), + m_pen.GetWidth() > 0 ? m_pen.GetWidth() : 1); } else {