# HG changeset patch # User Christian Brabandt # Date 1512477004 -3600 # Node ID 18e6f4addce91f5c103828c598a79f66e11b2846 # Parent a1775dd0e979a0d239e7e2bd78a8061554991594 patch 8.0.1369: MS-Windows: drawing underline slow, mFallbackDC not updated commit https://github.com/vim/vim/commit/92467d3351853de769329f62121bf34d28647546 Author: Bram Moolenaar Date: Tue Dec 5 13:22:16 2017 +0100 patch 8.0.1369: MS-Windows: drawing underline slow, mFallbackDC not updated Problem: MS-Windows: drawing underline, curl and strike-throw is slow, mFallbackDC not properly updated. Solution: Several performance improvements. (Ken Takata, Taro Muraoka, Yasuhiro Matsumoto, closes #2401) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -6122,9 +6122,10 @@ A jump table for the options with a shor geom pixelGeometry int 0 - 2 (see below) renmode renderingMode int 0 - 6 (see below) taamode textAntialiasMode int 0 - 3 (see below) - - See this URL for detail: - http://msdn.microsoft.com/en-us/library/dd368190.aspx + scrlines Scroll Lines int >= 0 (see below) + + See this URL for detail (except for scrlines): + https://msdn.microsoft.com/en-us/library/dd368190.aspx For geom: structure of a device pixel. 0 - DWRITE_PIXEL_GEOMETRY_FLAT @@ -6132,7 +6133,7 @@ A jump table for the options with a shor 2 - DWRITE_PIXEL_GEOMETRY_BGR See this URL for detail: - http://msdn.microsoft.com/en-us/library/dd368114.aspx + https://msdn.microsoft.com/en-us/library/dd368114.aspx For renmode: method of rendering glyphs. 0 - DWRITE_RENDERING_MODE_DEFAULT @@ -6144,7 +6145,7 @@ A jump table for the options with a shor 6 - DWRITE_RENDERING_MODE_OUTLINE See this URL for detail: - http://msdn.microsoft.com/en-us/library/dd368118.aspx + https://msdn.microsoft.com/en-us/library/dd368118.aspx For taamode: antialiasing mode used for drawing text. 0 - D2D1_TEXT_ANTIALIAS_MODE_DEFAULT @@ -6153,7 +6154,25 @@ A jump table for the options with a shor 3 - D2D1_TEXT_ANTIALIAS_MODE_ALIASED See this URL for detail: - http://msdn.microsoft.com/en-us/library/dd368170.aspx + https://msdn.microsoft.com/en-us/library/dd368170.aspx + + For scrlines: threshold for lines to be scrolled. + 0 - Always use scrolling. (default) + 1 - Use full page redrawing. + > 1 - If the lines to be scrolled is grater or equal to the + specified value, use redrawing. Otherwise use + scrolling. + + If you feel scrolling a page (CTRL-F) is too slow with DirectX + renderer, try this "scrlines" option. + When set it "1", Vim uses full page redrawing instead of + scrolling. Redrawing a page is faster than scrolling a + page in some environments. + After that, when you feel scrolling lines (CTRL-Y) becomes + slow, please try "2" or greater value for this option. + It works threshold line number to switch scrolling to + redrawing. Scrolling a few lines might be faster than + redrawing a page in some environments. Example: > set encoding=utf-8 @@ -6162,13 +6181,12 @@ A jump table for the options with a shor < If select a raster font (Courier, Terminal or FixedSys which have ".fon" extension in file name) to 'guifont', it will be - drawn by GDI as a fallback. This fallback will cause - significant slow down on drawing. + drawn by GDI as a fallback. NOTE: It is known that some fonts and options combination causes trouble on drawing glyphs. - - 'rendmode:5' and 'renmode:6' will not work with some + - 'renmode:5' and 'renmode:6' will not work with some special made fonts (True-Type fonts which includes only bitmap glyphs). - 'taamode:3' will not work with some vector fonts. diff --git a/src/gui_dwrite.cpp b/src/gui_dwrite.cpp --- a/src/gui_dwrite.cpp +++ b/src/gui_dwrite.cpp @@ -263,14 +263,24 @@ private: } }; +enum DrawingMode { + DM_GDI = 0, + DM_DIRECTX = 1, + DM_INTEROP = 2, +}; + struct DWriteContext { HDC mHDC; + RECT mBindRect; + DrawingMode mDMode; + HDC mInteropHDC; bool mDrawing; bool mFallbackDC; ID2D1Factory *mD2D1Factory; ID2D1DCRenderTarget *mRT; + ID2D1GdiInteropRenderTarget *mGDIRT; ID2D1SolidColorBrush *mBrush; IDWriteFactory *mDWriteFactory; @@ -292,6 +302,10 @@ struct DWriteContext { virtual ~DWriteContext(); + HRESULT CreateDeviceResources(); + + void DiscardDeviceResources(); + HRESULT CreateTextFormatFromLOGFONT(const LOGFONTW &logFont, IDWriteTextFormat **ppTextFormat); @@ -299,17 +313,21 @@ struct DWriteContext { void SetFont(HFONT hFont); - void BindDC(HDC hdc, RECT *rect); + void BindDC(HDC hdc, const RECT *rect); - void AssureDrawing(); + HRESULT SetDrawingMode(DrawingMode mode); ID2D1Brush* SolidBrush(COLORREF color); - void DrawText(const WCHAR* text, int len, + void DrawText(const WCHAR *text, int len, int x, int y, int w, int h, int cellWidth, COLORREF color, - UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx); + UINT fuOptions, const RECT *lprc, const INT *lpDx); + + void FillRect(const RECT *rc, COLORREF color); - void FillRect(RECT *rc, COLORREF color); + void DrawLine(int x1, int y1, int x2, int y2, COLORREF color); + + void SetPixel(int x, int y, COLORREF color); void Flush(); @@ -561,10 +579,14 @@ private: DWriteContext::DWriteContext() : mHDC(NULL), + mBindRect(), + mDMode(DM_GDI), + mInteropHDC(NULL), mDrawing(false), mFallbackDC(false), mD2D1Factory(NULL), mRT(NULL), + mGDIRT(NULL), mBrush(NULL), mDWriteFactory(NULL), mDWriteFactory2(NULL), @@ -584,25 +606,7 @@ DWriteContext::DWriteContext() : _RPT2(_CRT_WARN, "D2D1CreateFactory: hr=%p p=%p\n", hr, mD2D1Factory); if (SUCCEEDED(hr)) - { - D2D1_RENDER_TARGET_PROPERTIES props = { - D2D1_RENDER_TARGET_TYPE_DEFAULT, - { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE }, - 0, 0, - D2D1_RENDER_TARGET_USAGE_NONE, - D2D1_FEATURE_LEVEL_DEFAULT - }; - hr = mD2D1Factory->CreateDCRenderTarget(&props, &mRT); - _RPT2(_CRT_WARN, "CreateDCRenderTarget: hr=%p p=%p\n", hr, mRT); - } - - if (SUCCEEDED(hr)) - { - hr = mRT->CreateSolidColorBrush( - D2D1::ColorF(D2D1::ColorF::Black), - &mBrush); - _RPT2(_CRT_WARN, "CreateSolidColorBrush: hr=%p p=%p\n", hr, mBrush); - } + hr = CreateDeviceResources(); if (SUCCEEDED(hr)) { @@ -645,11 +649,67 @@ DWriteContext::~DWriteContext() SafeRelease(&mDWriteFactory); SafeRelease(&mDWriteFactory2); SafeRelease(&mBrush); + SafeRelease(&mGDIRT); SafeRelease(&mRT); SafeRelease(&mD2D1Factory); } HRESULT +DWriteContext::CreateDeviceResources() +{ + HRESULT hr; + + if (mRT != NULL) + return S_OK; + + D2D1_RENDER_TARGET_PROPERTIES props = { + D2D1_RENDER_TARGET_TYPE_DEFAULT, + { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE }, + 0, 0, + D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE, + D2D1_FEATURE_LEVEL_DEFAULT + }; + hr = mD2D1Factory->CreateDCRenderTarget(&props, &mRT); + _RPT2(_CRT_WARN, "CreateDCRenderTarget: hr=%p p=%p\n", hr, mRT); + + if (SUCCEEDED(hr)) + { + // This always succeeds. + mRT->QueryInterface( + __uuidof(ID2D1GdiInteropRenderTarget), + reinterpret_cast(&mGDIRT)); + _RPT1(_CRT_WARN, "GdiInteropRenderTarget: p=%p\n", mGDIRT); + } + + if (SUCCEEDED(hr)) + { + hr = mRT->CreateSolidColorBrush( + D2D1::ColorF(D2D1::ColorF::Black), + &mBrush); + _RPT2(_CRT_WARN, "CreateSolidColorBrush: hr=%p p=%p\n", hr, mBrush); + } + + if (SUCCEEDED(hr)) + { + if (mHDC != NULL) + { + mRT->BindDC(mHDC, &mBindRect); + mRT->SetTransform(D2D1::IdentityMatrix()); + } + } + + return hr; +} + + void +DWriteContext::DiscardDeviceResources() +{ + SafeRelease(&mBrush); + SafeRelease(&mGDIRT); + SafeRelease(&mRT); +} + + HRESULT DWriteContext::CreateTextFormatFromLOGFONT(const LOGFONTW &logFont, IDWriteTextFormat **ppTextFormat) { @@ -817,27 +877,77 @@ DWriteContext::SetFont(HFONT hFont) item.pTextFormat = mTextFormat; item.fontWeight = mFontWeight; item.fontStyle = mFontStyle; + mFallbackDC = false; } + else + mFallbackDC = true; mFontCache.put(item); } void -DWriteContext::BindDC(HDC hdc, RECT *rect) +DWriteContext::BindDC(HDC hdc, const RECT *rect) { Flush(); mRT->BindDC(hdc, rect); mRT->SetTransform(D2D1::IdentityMatrix()); mHDC = hdc; + mBindRect = *rect; } - void -DWriteContext::AssureDrawing() + HRESULT +DWriteContext::SetDrawingMode(DrawingMode mode) { - if (mDrawing == false) + HRESULT hr = S_OK; + + switch (mode) { - mRT->BeginDraw(); - mDrawing = true; + default: + case DM_GDI: + if (mInteropHDC != NULL) + { + mGDIRT->ReleaseDC(NULL); + mInteropHDC = NULL; + } + if (mDrawing) + { + hr = mRT->EndDraw(); + if (hr == D2DERR_RECREATE_TARGET) + { + hr = S_OK; + DiscardDeviceResources(); + CreateDeviceResources(); + } + mDrawing = false; + } + break; + + case DM_DIRECTX: + if (mInteropHDC != NULL) + { + mGDIRT->ReleaseDC(NULL); + mInteropHDC = NULL; + } + else if (mDrawing == false) + { + CreateDeviceResources(); + mRT->BeginDraw(); + mDrawing = true; + } + break; + + case DM_INTEROP: + if (mDrawing == false) + { + CreateDeviceResources(); + mRT->BeginDraw(); + mDrawing = true; + } + if (mInteropHDC == NULL) + hr = mGDIRT->GetDC(D2D1_DC_INITIALIZE_MODE_COPY, &mInteropHDC); + break; } + mDMode = mode; + return hr; } ID2D1Brush* @@ -849,22 +959,31 @@ DWriteContext::SolidBrush(COLORREF color } void -DWriteContext::DrawText(const WCHAR* text, int len, +DWriteContext::DrawText(const WCHAR *text, int len, int x, int y, int w, int h, int cellWidth, COLORREF color, - UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx) + UINT fuOptions, const RECT *lprc, const INT *lpDx) { if (mFallbackDC) { - Flush(); - ExtTextOutW(mHDC, x, y, fuOptions, lprc, text, len, lpDx); + // Fall back to GDI rendering. + HRESULT hr = SetDrawingMode(DM_INTEROP); + if (SUCCEEDED(hr)) + { + HGDIOBJ hFont = ::GetCurrentObject(mHDC, OBJ_FONT); + HGDIOBJ hOldFont = ::SelectObject(mInteropHDC, hFont); + ::SetTextColor(mInteropHDC, color); + ::SetBkMode(mInteropHDC, ::GetBkMode(mHDC)); + ::ExtTextOutW(mInteropHDC, x, y, fuOptions, lprc, text, len, lpDx); + ::SelectObject(mInteropHDC, hOldFont); + } return; } - AssureDrawing(); - HRESULT hr; IDWriteTextLayout *textLayout = NULL; + SetDrawingMode(DM_DIRECTX); + hr = mDWriteFactory->CreateTextLayout(text, len, mTextFormat, FLOAT(w), FLOAT(h), &textLayout); @@ -883,23 +1002,74 @@ DWriteContext::DrawText(const WCHAR* tex } void -DWriteContext::FillRect(RECT *rc, COLORREF color) +DWriteContext::FillRect(const RECT *rc, COLORREF color) +{ + if (mDMode == DM_INTEROP) + { + // GDI functions are used before this call. Keep using GDI. + // (Switching to Direct2D causes terrible slowdown.) + HBRUSH hbr = ::CreateSolidBrush(color); + ::FillRect(mInteropHDC, rc, hbr); + ::DeleteObject(HGDIOBJ(hbr)); + } + else + { + SetDrawingMode(DM_DIRECTX); + mRT->FillRectangle( + D2D1::RectF(FLOAT(rc->left), FLOAT(rc->top), + FLOAT(rc->right), FLOAT(rc->bottom)), + SolidBrush(color)); + } +} + + void +DWriteContext::DrawLine(int x1, int y1, int x2, int y2, COLORREF color) { - AssureDrawing(); - mRT->FillRectangle( - D2D1::RectF(FLOAT(rc->left), FLOAT(rc->top), - FLOAT(rc->right), FLOAT(rc->bottom)), - SolidBrush(color)); + if (mDMode == DM_INTEROP) + { + // GDI functions are used before this call. Keep using GDI. + // (Switching to Direct2D causes terrible slowdown.) + HPEN hpen = ::CreatePen(PS_SOLID, 1, color); + HGDIOBJ old_pen = ::SelectObject(mInteropHDC, HGDIOBJ(hpen)); + ::MoveToEx(mInteropHDC, x1, y1, NULL); + ::LineTo(mInteropHDC, x2, y2); + ::SelectObject(mInteropHDC, old_pen); + ::DeleteObject(HGDIOBJ(hpen)); + } + else + { + SetDrawingMode(DM_DIRECTX); + mRT->DrawLine( + D2D1::Point2F(FLOAT(x1), FLOAT(y1) + 0.5f), + D2D1::Point2F(FLOAT(x2), FLOAT(y2) + 0.5f), + SolidBrush(color)); + } +} + + void +DWriteContext::SetPixel(int x, int y, COLORREF color) +{ + if (mDMode == DM_INTEROP) + { + // GDI functions are used before this call. Keep using GDI. + // (Switching to Direct2D causes terrible slowdown.) + ::SetPixel(mInteropHDC, x, y, color); + } + else + { + SetDrawingMode(DM_DIRECTX); + // Direct2D doesn't have SetPixel API. Use DrawLine instead. + mRT->DrawLine( + D2D1::Point2F(FLOAT(x), FLOAT(y) + 0.5f), + D2D1::Point2F(FLOAT(x+1), FLOAT(y) + 0.5f), + SolidBrush(color)); + } } void DWriteContext::Flush() { - if (mDrawing) - { - mRT->EndDraw(); - mDrawing = false; - } + SetDrawingMode(DM_GDI); } void @@ -1000,7 +1170,7 @@ DWriteContext_Open(void) } void -DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect) +DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, const RECT *rect) { if (ctx != NULL) ctx->BindDC(hdc, rect); @@ -1016,7 +1186,7 @@ DWriteContext_SetFont(DWriteContext *ctx void DWriteContext_DrawText( DWriteContext *ctx, - const WCHAR* text, + const WCHAR *text, int len, int x, int y, @@ -1025,8 +1195,8 @@ DWriteContext_DrawText( int cellWidth, COLORREF color, UINT fuOptions, - CONST RECT *lprc, - CONST INT * lpDx) + const RECT *lprc, + const INT *lpDx) { if (ctx != NULL) ctx->DrawText(text, len, x, y, w, h, cellWidth, color, @@ -1034,13 +1204,28 @@ DWriteContext_DrawText( } void -DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color) +DWriteContext_FillRect(DWriteContext *ctx, const RECT *rc, COLORREF color) { if (ctx != NULL) ctx->FillRect(rc, color); } void +DWriteContext_DrawLine(DWriteContext *ctx, int x1, int y1, int x2, int y2, + COLORREF color) +{ + if (ctx != NULL) + ctx->DrawLine(x1, y1, x2, y2, color); +} + + void +DWriteContext_SetPixel(DWriteContext *ctx, int x, int y, COLORREF color) +{ + if (ctx != NULL) + ctx->SetPixel(x, y, color); +} + + void DWriteContext_Flush(DWriteContext *ctx) { if (ctx != NULL) diff --git a/src/gui_dwrite.h b/src/gui_dwrite.h --- a/src/gui_dwrite.h +++ b/src/gui_dwrite.h @@ -55,11 +55,11 @@ void DWrite_Init(void); void DWrite_Final(void); DWriteContext *DWriteContext_Open(void); -void DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect); +void DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, const RECT *rect); void DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont); void DWriteContext_DrawText( DWriteContext *ctx, - const WCHAR* text, + const WCHAR *text, int len, int x, int y, @@ -68,9 +68,12 @@ void DWriteContext_DrawText( int cellWidth, COLORREF color, UINT fuOptions, - CONST RECT *lprc, - CONST INT * lpDx); -void DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color); + const RECT *lprc, + const INT *lpDx); +void DWriteContext_FillRect(DWriteContext *ctx, const RECT *rc, COLORREF color); +void DWriteContext_DrawLine(DWriteContext *ctx, int x1, int y1, int x2, int y2, + COLORREF color); +void DWriteContext_SetPixel(DWriteContext *ctx, int x, int y, COLORREF color); void DWriteContext_Flush(DWriteContext *ctx); void DWriteContext_Close(DWriteContext *ctx); diff --git a/src/gui_w32.c b/src/gui_w32.c --- a/src/gui_w32.c +++ b/src/gui_w32.c @@ -33,6 +33,7 @@ static DWriteContext *s_dwc = NULL; static int s_directx_enabled = 0; static int s_directx_load_attempted = 0; +static int s_directx_scrlines = 0; # define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL) static int directx_enabled(void); static void directx_binddc(void); @@ -57,6 +58,7 @@ gui_mch_set_rendering_options(char_u *s) int dx_geom = 0; int dx_renmode = 0; int dx_taamode = 0; + int dx_scrlines = 0; /* parse string as rendering options. */ for (p = s; p != NULL && *p != NUL; ) @@ -117,6 +119,10 @@ gui_mch_set_rendering_options(char_u *s) if (dx_taamode < 0 || dx_taamode > 3) return FAIL; } + else if (STRCMP(name, "scrlines") == 0) + { + dx_scrlines = atoi((char *)value); + } else return FAIL; } @@ -147,6 +153,7 @@ gui_mch_set_rendering_options(char_u *s) } } s_directx_enabled = dx_enable; + s_directx_scrlines = dx_scrlines; return OK; #else @@ -283,6 +290,7 @@ typedef int UINT_PTR; #endif static void _OnPaint( HWND hwnd); +static void fill_rect(const RECT *rcp, HBRUSH hbr, COLORREF color); static void clear_rect(RECT *rcp); static WORD s_dlgfntheight; /* height of the dialog font */ @@ -605,10 +613,7 @@ gui_mch_set_blinking(long wait, long on, blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime, (TIMERPROC)_OnBlinkTimer); } -#if defined(FEAT_DIRECTX) - if (IS_ENABLE_DIRECTX()) - DWriteContext_Flush(s_dwc); -#endif + gui_mch_flush(); } static void @@ -634,7 +639,10 @@ gui_mch_stop_blink(void) { gui_mswin_rm_blink_timer(); if (blink_state == BLINK_OFF) + { gui_update_cursor(TRUE, FALSE); + gui_mch_flush(); + } blink_state = BLINK_NONE; } @@ -654,6 +662,7 @@ gui_mch_start_blink(void) (TIMERPROC)_OnBlinkTimer); blink_state = BLINK_ON; gui_update_cursor(TRUE, FALSE); + gui_mch_flush(); } } @@ -1730,7 +1739,6 @@ gui_mch_draw_part_cursor( int h, guicolor_T color) { - HBRUSH hbr; RECT rc; /* @@ -1746,14 +1754,7 @@ gui_mch_draw_part_cursor( rc.right = rc.left + w; rc.bottom = rc.top + h; -#if defined(FEAT_DIRECTX) - if (IS_ENABLE_DIRECTX()) - DWriteContext_Flush(s_dwc); -#endif - - hbr = CreateSolidBrush(color); - FillRect(s_hdc, &rc, hbr); - DeleteBrush(hbr); + fill_rect(&rc, NULL, color); } @@ -3122,13 +3123,8 @@ gui_mch_delete_lines( int num_lines) { RECT rc; - - intel_gpu_workaround(); - #if defined(FEAT_DIRECTX) - // Commit drawing queue before ScrollWindowEx. - if (IS_ENABLE_DIRECTX()) - DWriteContext_Flush(s_dwc); + int use_redraw = 0; #endif rc.left = FILL_X(gui.scroll_region_left); @@ -3136,8 +3132,24 @@ gui_mch_delete_lines( rc.top = FILL_Y(row); rc.bottom = FILL_Y(gui.scroll_region_bot + 1); - ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height, +#if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX()) + { + if (s_directx_scrlines > 0 && s_directx_scrlines <= num_lines) + { + RedrawWindow(s_textArea, &rc, NULL, RDW_INVALIDATE); + use_redraw = 1; + } + else + DWriteContext_Flush(s_dwc); + } + if (!use_redraw) +#endif + { + intel_gpu_workaround(); + ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height, &rc, &rc, NULL, NULL, get_scroll_flags()); + } UpdateWindow(s_textArea); /* This seems to be required to avoid the cursor disappearing when @@ -3161,23 +3173,35 @@ gui_mch_insert_lines( int num_lines) { RECT rc; - - intel_gpu_workaround(); - #if defined(FEAT_DIRECTX) - // Commit drawing queue before ScrollWindowEx. - if (IS_ENABLE_DIRECTX()) - DWriteContext_Flush(s_dwc); + int use_redraw = 0; #endif rc.left = FILL_X(gui.scroll_region_left); rc.right = FILL_X(gui.scroll_region_right + 1); rc.top = FILL_Y(row); rc.bottom = FILL_Y(gui.scroll_region_bot + 1); - /* The SW_INVALIDATE is required when part of the window is covered or - * off-screen. How do we avoid it when it's not needed? */ - ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height, + +#if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX()) + { + if (s_directx_scrlines > 0 && s_directx_scrlines <= num_lines) + { + RedrawWindow(s_textArea, &rc, NULL, RDW_INVALIDATE); + use_redraw = 1; + } + else + DWriteContext_Flush(s_dwc); + } + if (!use_redraw) +#endif + { + intel_gpu_workaround(); + /* The SW_INVALIDATE is required when part of the window is covered or + * off-screen. How do we avoid it when it's not needed? */ + ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height, &rc, &rc, NULL, NULL, get_scroll_flags()); + } UpdateWindow(s_textArea); @@ -5853,6 +5877,7 @@ gui_mch_set_sp_color(guicolor_T color) } } gui_update_cursor(TRUE, FALSE); + gui_mch_flush(); lResult = 0; break; } @@ -6181,6 +6206,67 @@ RevOut( HDC s_hdc, } #endif + static void +draw_line( + int x1, + int y1, + int x2, + int y2, + COLORREF color) +{ +#if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX()) + DWriteContext_DrawLine(s_dwc, x1, y1, x2, y2, color); + else +#endif + { + HPEN hpen = CreatePen(PS_SOLID, 1, color); + HPEN old_pen = SelectObject(s_hdc, hpen); + MoveToEx(s_hdc, x1, y1, NULL); + /* Note: LineTo() excludes the last pixel in the line. */ + LineTo(s_hdc, x2, y2); + DeleteObject(SelectObject(s_hdc, old_pen)); + } +} + + static void +set_pixel( + int x, + int y, + COLORREF color) +{ +#if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX()) + DWriteContext_SetPixel(s_dwc, x, y, color); + else +#endif + SetPixel(s_hdc, x, y, color); +} + + static void +fill_rect( + const RECT *rcp, + HBRUSH hbr, + COLORREF color) +{ +#if defined(FEAT_DIRECTX) + if (IS_ENABLE_DIRECTX()) + DWriteContext_FillRect(s_dwc, rcp, color); + else +#endif + { + HBRUSH hbr2; + + if (hbr == NULL) + hbr2 = CreateSolidBrush(color); + else + hbr2 = hbr; + FillRect(s_hdc, rcp, hbr2); + if (hbr == NULL) + DeleteBrush(hbr2); + } +} + void gui_mch_draw_string( int row, @@ -6200,7 +6286,6 @@ gui_mch_draw_string( static int unibuflen = 0; int n = 0; #endif - HPEN hpen, old_pen; int y; /* @@ -6263,11 +6348,7 @@ gui_mch_draw_string( brush_lru = !brush_lru; } -#if defined(FEAT_DIRECTX) - if (IS_ENABLE_DIRECTX()) - DWriteContext_FillRect(s_dwc, &rc, gui.currBgColor); -#endif - FillRect(s_hdc, &rc, hbr); + fill_rect(&rc, hbr, gui.currBgColor); SetBkMode(s_hdc, TRANSPARENT); @@ -6462,38 +6543,22 @@ gui_mch_draw_string( foptions, pcliprect, (char *)text, len, padding); } -#if defined(FEAT_DIRECTX) - if (IS_ENABLE_DIRECTX() && - (flags & (DRAW_UNDERL | DRAW_STRIKE | DRAW_UNDERC | DRAW_CURSOR))) - DWriteContext_Flush(s_dwc); -#endif - /* Underline */ if (flags & DRAW_UNDERL) { - hpen = CreatePen(PS_SOLID, 1, gui.currFgColor); - old_pen = SelectObject(s_hdc, hpen); /* When p_linespace is 0, overwrite the bottom row of pixels. * Otherwise put the line just below the character. */ y = FILL_Y(row + 1) - 1; if (p_linespace > 1) y -= p_linespace - 1; - MoveToEx(s_hdc, FILL_X(col), y, NULL); - /* Note: LineTo() excludes the last pixel in the line. */ - LineTo(s_hdc, FILL_X(col + len), y); - DeleteObject(SelectObject(s_hdc, old_pen)); + draw_line(FILL_X(col), y, FILL_X(col + len), y, gui.currFgColor); } /* Strikethrough */ if (flags & DRAW_STRIKE) { - hpen = CreatePen(PS_SOLID, 1, gui.currSpColor); - old_pen = SelectObject(s_hdc, hpen); y = FILL_Y(row + 1) - gui.char_height/2; - MoveToEx(s_hdc, FILL_X(col), y, NULL); - /* Note: LineTo() excludes the last pixel in the line. */ - LineTo(s_hdc, FILL_X(col + len), y); - DeleteObject(SelectObject(s_hdc, old_pen)); + draw_line(FILL_X(col), y, FILL_X(col + len), y, gui.currSpColor); } /* Undercurl */ @@ -6507,7 +6572,7 @@ gui_mch_draw_string( for (x = FILL_X(col); x < FILL_X(col + len); ++x) { offset = val[x % 8]; - SetPixel(s_hdc, x, y - offset, gui.currSpColor); + set_pixel(x, y - offset, gui.currSpColor); } } } @@ -6541,19 +6606,7 @@ gui_mch_flush(void) static void clear_rect(RECT *rcp) { - HBRUSH hbr; - -#if defined(FEAT_DIRECTX) - if (IS_ENABLE_DIRECTX()) - { - DWriteContext_FillRect(s_dwc, rcp, gui.back_pixel); - return; - } -#endif - - hbr = CreateSolidBrush(gui.back_pixel); - FillRect(s_hdc, rcp, hbr); - DeleteBrush(hbr); + fill_rect(rcp, NULL, gui.back_pixel); } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -772,6 +772,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1369, +/**/ 1368, /**/ 1367,