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.
This commit is contained in:
Artur Wieczorek
2019-12-06 00:02:47 +01:00
parent 31c7073571
commit 994971e2df

View File

@@ -801,6 +801,20 @@ bool wxMSWDCImpl::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
return true; 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) void wxMSWDCImpl::DoCrossHair(wxCoord x, wxCoord y)
{ {
RECT rect; RECT rect;
@@ -813,23 +827,24 @@ void wxMSWDCImpl::DoCrossHair(wxCoord x, wxCoord y)
// We have optimized function to draw physical vertical or horizontal lines // 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 // with solid color and square ends so it can be used to draw a cross hair
// for: // for:
// - Solid lines with pen width > 0 because it doesn't support drawing // - Any shape of the lines ends because non-square line ends are drawn
// non-scaled 1-pixel wide lines when pen width is 0. Shape of the lines // outside the view and visible line ends are always square.
// ends doesn't matter 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 // - DC which coordinate system is not rotated (graphics mode
// of the DC != GM_ADVANCED). // of the DC != GM_ADVANCED) and not scaled.
if ( ::GetGraphicsMode(GetHdc()) != GM_ADVANCED && // ensure DC is not rotated if ( IsNonTransformedDC(GetHdc()) &&
m_pen.IsNonTransparent() && // this calls IsOk() too m_pen.IsNonTransparent() && // this calls IsOk() too
m_pen.GetStyle() == wxPENSTYLE_SOLID && m_pen.GetStyle() == wxPENSTYLE_SOLID
m_pen.GetWidth() > 0
) )
{ {
// 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()); COLORREF color = wxColourToRGB(m_pen.GetColour());
wxDrawHVLine(GetHdc(), XLOG2DEV(rect.left), YLOG2DEV(y), XLOG2DEV(rect.right), YLOG2DEV(y), 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), wxDrawHVLine(GetHdc(), XLOG2DEV(x), YLOG2DEV(rect.top), XLOG2DEV(x), YLOG2DEV(rect.bottom),
color, m_pen.GetWidth()); color, w);
} }
else 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 // in the device coordinate system is complex so we only check whether
// the line is horizontal/vertical in the logical coordinates and use // the line is horizontal/vertical in the logical coordinates and use
// optimized function only for DC which coordinate system is for sure // optimized function only for DC which coordinate system is for sure
// not rotated (graphics mode of the DC != GM_ADVANCED). // not rotated (graphics mode of the DC != GM_ADVANCED) and not scaled.
// 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.
if ( (x1 == x2 || y1 == y2) && 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.IsNonTransparent() && // this calls IsOk() too
m_pen.GetStyle() == wxPENSTYLE_SOLID && 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), 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 else
{ {