Optimize drawing horizontal/vertical lines
On DC with a non-rotated coordinate system drawing a filled rectangle with ExtTextOut() Win API is faster than drawing a line with MoveTo()/LineTo() so on such DCs we can use ExtTextOut() to draw horizontal/vertical lines with solid colors and square ends instead of calling MoveTo()/LineTo(). See #18517.
This commit is contained in:
parent
8064d9420f
commit
bae8bb4c45
@ -1109,6 +1109,8 @@ extern WXDLLIMPEXP_CORE wxSize wxGetHiconSize(HICON hicon);
|
||||
|
||||
WXDLLIMPEXP_CORE void wxDrawLine(HDC hdc, int x1, int y1, int x2, int y2);
|
||||
|
||||
WXDLLIMPEXP_CORE void wxDrawHVLine(HDC hdc, int x1, int y1, int x2, int y2, COLORREF color, int width);
|
||||
|
||||
// fill the client rect of the given window on the provided dc using this brush
|
||||
inline void wxFillRect(HWND hwnd, HDC hdc, HBRUSH hbr)
|
||||
{
|
||||
|
@ -819,7 +819,31 @@ void wxMSWDCImpl::DoCrossHair(wxCoord x, wxCoord y)
|
||||
|
||||
void wxMSWDCImpl::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
|
||||
{
|
||||
wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2));
|
||||
// We have optimized function to draw physical vertical or horizontal lines
|
||||
// with solid color and square ends.
|
||||
// Because checking wheteher the line would be horizontal/vertical
|
||||
// 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.
|
||||
if ( (x1 == x2 || y1 == y2) &&
|
||||
::GetGraphicsMode(GetHdc()) != GM_ADVANCED && // ensure DC is not rotated
|
||||
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)
|
||||
)
|
||||
{
|
||||
wxDrawHVLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2),
|
||||
wxColourToRGB(m_pen.GetColour()), m_pen.GetWidth());
|
||||
}
|
||||
else
|
||||
{
|
||||
wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2));
|
||||
}
|
||||
|
||||
CalcBoundingBox(x1, y1);
|
||||
CalcBoundingBox(x2, y2);
|
||||
|
@ -209,6 +209,35 @@ void wxDrawLine(HDC hdc, int x1, int y1, int x2, int y2)
|
||||
MoveToEx(hdc, x1, y1, NULL); LineTo((HDC) hdc, x2, y2);
|
||||
}
|
||||
|
||||
// Function dedicated to drawing horizontal/vertical lines with solid color
|
||||
// It fills rectangle representing the line with ::ExtTextOut() API which
|
||||
// apparently is faster than ::MoveTo()/::LineTo() on DC with a non-rotated
|
||||
// coordinate system.
|
||||
void wxDrawHVLine(HDC hdc, int x1, int y1, int x2, int y2, COLORREF color, int width)
|
||||
{
|
||||
wxASSERT(x1 == x2 || y1 == y2);
|
||||
|
||||
int w1 = width / 2;
|
||||
int w2 = width - w1;
|
||||
RECT r;
|
||||
if ( y1 == y2 )
|
||||
{
|
||||
if ( x1 == x2 )
|
||||
return;
|
||||
::SetRect(&r, x1, y1 - w1, x2, y1 + w2);
|
||||
}
|
||||
else
|
||||
{
|
||||
::SetRect(&r, x1 - w1, y1, x2 + w2, y2);
|
||||
}
|
||||
|
||||
COLORREF bgColorOrig = ::GetBkColor(hdc);
|
||||
::SetBkColor(hdc, color);
|
||||
|
||||
::ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &r, L"", 0, NULL);
|
||||
|
||||
::SetBkColor(hdc, bgColorOrig);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Shell API wrappers
|
||||
|
Loading…
Reference in New Issue
Block a user