mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
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)
This commit is contained in:
parent
ce6179c799
commit
92467d3351
@ -6122,9 +6122,10 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
geom pixelGeometry int 0 - 2 (see below)
|
geom pixelGeometry int 0 - 2 (see below)
|
||||||
renmode renderingMode int 0 - 6 (see below)
|
renmode renderingMode int 0 - 6 (see below)
|
||||||
taamode textAntialiasMode int 0 - 3 (see below)
|
taamode textAntialiasMode int 0 - 3 (see below)
|
||||||
|
scrlines Scroll Lines int >= 0 (see below)
|
||||||
|
|
||||||
See this URL for detail:
|
See this URL for detail (except for scrlines):
|
||||||
http://msdn.microsoft.com/en-us/library/dd368190.aspx
|
https://msdn.microsoft.com/en-us/library/dd368190.aspx
|
||||||
|
|
||||||
For geom: structure of a device pixel.
|
For geom: structure of a device pixel.
|
||||||
0 - DWRITE_PIXEL_GEOMETRY_FLAT
|
0 - DWRITE_PIXEL_GEOMETRY_FLAT
|
||||||
@ -6132,7 +6133,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
2 - DWRITE_PIXEL_GEOMETRY_BGR
|
2 - DWRITE_PIXEL_GEOMETRY_BGR
|
||||||
|
|
||||||
See this URL for detail:
|
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.
|
For renmode: method of rendering glyphs.
|
||||||
0 - DWRITE_RENDERING_MODE_DEFAULT
|
0 - DWRITE_RENDERING_MODE_DEFAULT
|
||||||
@ -6144,7 +6145,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
6 - DWRITE_RENDERING_MODE_OUTLINE
|
6 - DWRITE_RENDERING_MODE_OUTLINE
|
||||||
|
|
||||||
See this URL for detail:
|
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.
|
For taamode: antialiasing mode used for drawing text.
|
||||||
0 - D2D1_TEXT_ANTIALIAS_MODE_DEFAULT
|
0 - D2D1_TEXT_ANTIALIAS_MODE_DEFAULT
|
||||||
@ -6153,7 +6154,25 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
3 - D2D1_TEXT_ANTIALIAS_MODE_ALIASED
|
3 - D2D1_TEXT_ANTIALIAS_MODE_ALIASED
|
||||||
|
|
||||||
See this URL for detail:
|
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: >
|
Example: >
|
||||||
set encoding=utf-8
|
set encoding=utf-8
|
||||||
@ -6162,13 +6181,12 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
<
|
<
|
||||||
If select a raster font (Courier, Terminal or FixedSys which
|
If select a raster font (Courier, Terminal or FixedSys which
|
||||||
have ".fon" extension in file name) to 'guifont', it will be
|
have ".fon" extension in file name) to 'guifont', it will be
|
||||||
drawn by GDI as a fallback. This fallback will cause
|
drawn by GDI as a fallback.
|
||||||
significant slow down on drawing.
|
|
||||||
|
|
||||||
NOTE: It is known that some fonts and options combination
|
NOTE: It is known that some fonts and options combination
|
||||||
causes trouble on drawing glyphs.
|
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
|
special made fonts (True-Type fonts which includes only
|
||||||
bitmap glyphs).
|
bitmap glyphs).
|
||||||
- 'taamode:3' will not work with some vector fonts.
|
- 'taamode:3' will not work with some vector fonts.
|
||||||
|
@ -263,14 +263,24 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum DrawingMode {
|
||||||
|
DM_GDI = 0,
|
||||||
|
DM_DIRECTX = 1,
|
||||||
|
DM_INTEROP = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct DWriteContext {
|
struct DWriteContext {
|
||||||
HDC mHDC;
|
HDC mHDC;
|
||||||
|
RECT mBindRect;
|
||||||
|
DrawingMode mDMode;
|
||||||
|
HDC mInteropHDC;
|
||||||
bool mDrawing;
|
bool mDrawing;
|
||||||
bool mFallbackDC;
|
bool mFallbackDC;
|
||||||
|
|
||||||
ID2D1Factory *mD2D1Factory;
|
ID2D1Factory *mD2D1Factory;
|
||||||
|
|
||||||
ID2D1DCRenderTarget *mRT;
|
ID2D1DCRenderTarget *mRT;
|
||||||
|
ID2D1GdiInteropRenderTarget *mGDIRT;
|
||||||
ID2D1SolidColorBrush *mBrush;
|
ID2D1SolidColorBrush *mBrush;
|
||||||
|
|
||||||
IDWriteFactory *mDWriteFactory;
|
IDWriteFactory *mDWriteFactory;
|
||||||
@ -292,6 +302,10 @@ struct DWriteContext {
|
|||||||
|
|
||||||
virtual ~DWriteContext();
|
virtual ~DWriteContext();
|
||||||
|
|
||||||
|
HRESULT CreateDeviceResources();
|
||||||
|
|
||||||
|
void DiscardDeviceResources();
|
||||||
|
|
||||||
HRESULT CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
|
HRESULT CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
|
||||||
IDWriteTextFormat **ppTextFormat);
|
IDWriteTextFormat **ppTextFormat);
|
||||||
|
|
||||||
@ -299,17 +313,21 @@ struct DWriteContext {
|
|||||||
|
|
||||||
void SetFont(HFONT hFont);
|
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);
|
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,
|
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(RECT *rc, COLORREF color);
|
void FillRect(const 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();
|
void Flush();
|
||||||
|
|
||||||
@ -561,10 +579,14 @@ private:
|
|||||||
|
|
||||||
DWriteContext::DWriteContext() :
|
DWriteContext::DWriteContext() :
|
||||||
mHDC(NULL),
|
mHDC(NULL),
|
||||||
|
mBindRect(),
|
||||||
|
mDMode(DM_GDI),
|
||||||
|
mInteropHDC(NULL),
|
||||||
mDrawing(false),
|
mDrawing(false),
|
||||||
mFallbackDC(false),
|
mFallbackDC(false),
|
||||||
mD2D1Factory(NULL),
|
mD2D1Factory(NULL),
|
||||||
mRT(NULL),
|
mRT(NULL),
|
||||||
|
mGDIRT(NULL),
|
||||||
mBrush(NULL),
|
mBrush(NULL),
|
||||||
mDWriteFactory(NULL),
|
mDWriteFactory(NULL),
|
||||||
mDWriteFactory2(NULL),
|
mDWriteFactory2(NULL),
|
||||||
@ -584,25 +606,7 @@ DWriteContext::DWriteContext() :
|
|||||||
_RPT2(_CRT_WARN, "D2D1CreateFactory: hr=%p p=%p\n", hr, mD2D1Factory);
|
_RPT2(_CRT_WARN, "D2D1CreateFactory: hr=%p p=%p\n", hr, mD2D1Factory);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
hr = CreateDeviceResources();
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
@ -645,10 +649,66 @@ DWriteContext::~DWriteContext()
|
|||||||
SafeRelease(&mDWriteFactory);
|
SafeRelease(&mDWriteFactory);
|
||||||
SafeRelease(&mDWriteFactory2);
|
SafeRelease(&mDWriteFactory2);
|
||||||
SafeRelease(&mBrush);
|
SafeRelease(&mBrush);
|
||||||
|
SafeRelease(&mGDIRT);
|
||||||
SafeRelease(&mRT);
|
SafeRelease(&mRT);
|
||||||
SafeRelease(&mD2D1Factory);
|
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<void**>(&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
|
HRESULT
|
||||||
DWriteContext::CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
|
DWriteContext::CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
|
||||||
IDWriteTextFormat **ppTextFormat)
|
IDWriteTextFormat **ppTextFormat)
|
||||||
@ -817,27 +877,77 @@ DWriteContext::SetFont(HFONT hFont)
|
|||||||
item.pTextFormat = mTextFormat;
|
item.pTextFormat = mTextFormat;
|
||||||
item.fontWeight = mFontWeight;
|
item.fontWeight = mFontWeight;
|
||||||
item.fontStyle = mFontStyle;
|
item.fontStyle = mFontStyle;
|
||||||
|
mFallbackDC = false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
mFallbackDC = true;
|
||||||
mFontCache.put(item);
|
mFontCache.put(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DWriteContext::BindDC(HDC hdc, RECT *rect)
|
DWriteContext::BindDC(HDC hdc, const RECT *rect)
|
||||||
{
|
{
|
||||||
Flush();
|
Flush();
|
||||||
mRT->BindDC(hdc, rect);
|
mRT->BindDC(hdc, rect);
|
||||||
mRT->SetTransform(D2D1::IdentityMatrix());
|
mRT->SetTransform(D2D1::IdentityMatrix());
|
||||||
mHDC = hdc;
|
mHDC = hdc;
|
||||||
|
mBindRect = *rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
HRESULT
|
||||||
DWriteContext::AssureDrawing()
|
DWriteContext::SetDrawingMode(DrawingMode mode)
|
||||||
{
|
{
|
||||||
if (mDrawing == false)
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
{
|
{
|
||||||
mRT->BeginDraw();
|
default:
|
||||||
mDrawing = true;
|
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*
|
ID2D1Brush*
|
||||||
@ -849,22 +959,31 @@ DWriteContext::SolidBrush(COLORREF color)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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,
|
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)
|
if (mFallbackDC)
|
||||||
{
|
{
|
||||||
Flush();
|
// Fall back to GDI rendering.
|
||||||
ExtTextOutW(mHDC, x, y, fuOptions, lprc, text, len, lpDx);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssureDrawing();
|
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
IDWriteTextLayout *textLayout = NULL;
|
IDWriteTextLayout *textLayout = NULL;
|
||||||
|
|
||||||
|
SetDrawingMode(DM_DIRECTX);
|
||||||
|
|
||||||
hr = mDWriteFactory->CreateTextLayout(text, len, mTextFormat,
|
hr = mDWriteFactory->CreateTextLayout(text, len, mTextFormat,
|
||||||
FLOAT(w), FLOAT(h), &textLayout);
|
FLOAT(w), FLOAT(h), &textLayout);
|
||||||
|
|
||||||
@ -883,23 +1002,74 @@ DWriteContext::DrawText(const WCHAR* text, int len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DWriteContext::FillRect(RECT *rc, COLORREF color)
|
DWriteContext::FillRect(const RECT *rc, COLORREF color)
|
||||||
{
|
{
|
||||||
AssureDrawing();
|
if (mDMode == DM_INTEROP)
|
||||||
mRT->FillRectangle(
|
{
|
||||||
D2D1::RectF(FLOAT(rc->left), FLOAT(rc->top),
|
// GDI functions are used before this call. Keep using GDI.
|
||||||
FLOAT(rc->right), FLOAT(rc->bottom)),
|
// (Switching to Direct2D causes terrible slowdown.)
|
||||||
SolidBrush(color));
|
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)
|
||||||
|
{
|
||||||
|
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
|
void
|
||||||
DWriteContext::Flush()
|
DWriteContext::Flush()
|
||||||
{
|
{
|
||||||
if (mDrawing)
|
SetDrawingMode(DM_GDI);
|
||||||
{
|
|
||||||
mRT->EndDraw();
|
|
||||||
mDrawing = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1000,7 +1170,7 @@ DWriteContext_Open(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect)
|
DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, const RECT *rect)
|
||||||
{
|
{
|
||||||
if (ctx != NULL)
|
if (ctx != NULL)
|
||||||
ctx->BindDC(hdc, rect);
|
ctx->BindDC(hdc, rect);
|
||||||
@ -1016,7 +1186,7 @@ DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont)
|
|||||||
void
|
void
|
||||||
DWriteContext_DrawText(
|
DWriteContext_DrawText(
|
||||||
DWriteContext *ctx,
|
DWriteContext *ctx,
|
||||||
const WCHAR* text,
|
const WCHAR *text,
|
||||||
int len,
|
int len,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
@ -1025,8 +1195,8 @@ DWriteContext_DrawText(
|
|||||||
int cellWidth,
|
int cellWidth,
|
||||||
COLORREF color,
|
COLORREF color,
|
||||||
UINT fuOptions,
|
UINT fuOptions,
|
||||||
CONST RECT *lprc,
|
const RECT *lprc,
|
||||||
CONST INT * lpDx)
|
const INT *lpDx)
|
||||||
{
|
{
|
||||||
if (ctx != NULL)
|
if (ctx != NULL)
|
||||||
ctx->DrawText(text, len, x, y, w, h, cellWidth, color,
|
ctx->DrawText(text, len, x, y, w, h, cellWidth, color,
|
||||||
@ -1034,12 +1204,27 @@ DWriteContext_DrawText(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color)
|
DWriteContext_FillRect(DWriteContext *ctx, const RECT *rc, COLORREF color)
|
||||||
{
|
{
|
||||||
if (ctx != NULL)
|
if (ctx != NULL)
|
||||||
ctx->FillRect(rc, color);
|
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
|
void
|
||||||
DWriteContext_Flush(DWriteContext *ctx)
|
DWriteContext_Flush(DWriteContext *ctx)
|
||||||
{
|
{
|
||||||
|
@ -55,11 +55,11 @@ void DWrite_Init(void);
|
|||||||
void DWrite_Final(void);
|
void DWrite_Final(void);
|
||||||
|
|
||||||
DWriteContext *DWriteContext_Open(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_SetFont(DWriteContext *ctx, HFONT hFont);
|
||||||
void DWriteContext_DrawText(
|
void DWriteContext_DrawText(
|
||||||
DWriteContext *ctx,
|
DWriteContext *ctx,
|
||||||
const WCHAR* text,
|
const WCHAR *text,
|
||||||
int len,
|
int len,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
@ -68,9 +68,12 @@ void DWriteContext_DrawText(
|
|||||||
int cellWidth,
|
int cellWidth,
|
||||||
COLORREF color,
|
COLORREF color,
|
||||||
UINT fuOptions,
|
UINT fuOptions,
|
||||||
CONST RECT *lprc,
|
const RECT *lprc,
|
||||||
CONST INT * lpDx);
|
const INT *lpDx);
|
||||||
void DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color);
|
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_Flush(DWriteContext *ctx);
|
||||||
void DWriteContext_Close(DWriteContext *ctx);
|
void DWriteContext_Close(DWriteContext *ctx);
|
||||||
|
|
||||||
|
187
src/gui_w32.c
187
src/gui_w32.c
@ -33,6 +33,7 @@
|
|||||||
static DWriteContext *s_dwc = NULL;
|
static DWriteContext *s_dwc = NULL;
|
||||||
static int s_directx_enabled = 0;
|
static int s_directx_enabled = 0;
|
||||||
static int s_directx_load_attempted = 0;
|
static int s_directx_load_attempted = 0;
|
||||||
|
static int s_directx_scrlines = 0;
|
||||||
# define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL)
|
# define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL)
|
||||||
static int directx_enabled(void);
|
static int directx_enabled(void);
|
||||||
static void directx_binddc(void);
|
static void directx_binddc(void);
|
||||||
@ -57,6 +58,7 @@ gui_mch_set_rendering_options(char_u *s)
|
|||||||
int dx_geom = 0;
|
int dx_geom = 0;
|
||||||
int dx_renmode = 0;
|
int dx_renmode = 0;
|
||||||
int dx_taamode = 0;
|
int dx_taamode = 0;
|
||||||
|
int dx_scrlines = 0;
|
||||||
|
|
||||||
/* parse string as rendering options. */
|
/* parse string as rendering options. */
|
||||||
for (p = s; p != NULL && *p != NUL; )
|
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)
|
if (dx_taamode < 0 || dx_taamode > 3)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
else if (STRCMP(name, "scrlines") == 0)
|
||||||
|
{
|
||||||
|
dx_scrlines = atoi((char *)value);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
@ -147,6 +153,7 @@ gui_mch_set_rendering_options(char_u *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
s_directx_enabled = dx_enable;
|
s_directx_enabled = dx_enable;
|
||||||
|
s_directx_scrlines = dx_scrlines;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
#else
|
#else
|
||||||
@ -283,6 +290,7 @@ typedef int UINT_PTR;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void _OnPaint( HWND hwnd);
|
static void _OnPaint( HWND hwnd);
|
||||||
|
static void fill_rect(const RECT *rcp, HBRUSH hbr, COLORREF color);
|
||||||
static void clear_rect(RECT *rcp);
|
static void clear_rect(RECT *rcp);
|
||||||
|
|
||||||
static WORD s_dlgfntheight; /* height of the dialog font */
|
static WORD s_dlgfntheight; /* height of the dialog font */
|
||||||
@ -605,10 +613,7 @@ _OnBlinkTimer(
|
|||||||
blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime,
|
blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime,
|
||||||
(TIMERPROC)_OnBlinkTimer);
|
(TIMERPROC)_OnBlinkTimer);
|
||||||
}
|
}
|
||||||
#if defined(FEAT_DIRECTX)
|
gui_mch_flush();
|
||||||
if (IS_ENABLE_DIRECTX())
|
|
||||||
DWriteContext_Flush(s_dwc);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -634,7 +639,10 @@ gui_mch_stop_blink(void)
|
|||||||
{
|
{
|
||||||
gui_mswin_rm_blink_timer();
|
gui_mswin_rm_blink_timer();
|
||||||
if (blink_state == BLINK_OFF)
|
if (blink_state == BLINK_OFF)
|
||||||
|
{
|
||||||
gui_update_cursor(TRUE, FALSE);
|
gui_update_cursor(TRUE, FALSE);
|
||||||
|
gui_mch_flush();
|
||||||
|
}
|
||||||
blink_state = BLINK_NONE;
|
blink_state = BLINK_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -654,6 +662,7 @@ gui_mch_start_blink(void)
|
|||||||
(TIMERPROC)_OnBlinkTimer);
|
(TIMERPROC)_OnBlinkTimer);
|
||||||
blink_state = BLINK_ON;
|
blink_state = BLINK_ON;
|
||||||
gui_update_cursor(TRUE, FALSE);
|
gui_update_cursor(TRUE, FALSE);
|
||||||
|
gui_mch_flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1730,7 +1739,6 @@ gui_mch_draw_part_cursor(
|
|||||||
int h,
|
int h,
|
||||||
guicolor_T color)
|
guicolor_T color)
|
||||||
{
|
{
|
||||||
HBRUSH hbr;
|
|
||||||
RECT rc;
|
RECT rc;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1746,14 +1754,7 @@ gui_mch_draw_part_cursor(
|
|||||||
rc.right = rc.left + w;
|
rc.right = rc.left + w;
|
||||||
rc.bottom = rc.top + h;
|
rc.bottom = rc.top + h;
|
||||||
|
|
||||||
#if defined(FEAT_DIRECTX)
|
fill_rect(&rc, NULL, color);
|
||||||
if (IS_ENABLE_DIRECTX())
|
|
||||||
DWriteContext_Flush(s_dwc);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hbr = CreateSolidBrush(color);
|
|
||||||
FillRect(s_hdc, &rc, hbr);
|
|
||||||
DeleteBrush(hbr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3122,13 +3123,8 @@ gui_mch_delete_lines(
|
|||||||
int num_lines)
|
int num_lines)
|
||||||
{
|
{
|
||||||
RECT rc;
|
RECT rc;
|
||||||
|
|
||||||
intel_gpu_workaround();
|
|
||||||
|
|
||||||
#if defined(FEAT_DIRECTX)
|
#if defined(FEAT_DIRECTX)
|
||||||
// Commit drawing queue before ScrollWindowEx.
|
int use_redraw = 0;
|
||||||
if (IS_ENABLE_DIRECTX())
|
|
||||||
DWriteContext_Flush(s_dwc);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rc.left = FILL_X(gui.scroll_region_left);
|
rc.left = FILL_X(gui.scroll_region_left);
|
||||||
@ -3136,8 +3132,24 @@ gui_mch_delete_lines(
|
|||||||
rc.top = FILL_Y(row);
|
rc.top = FILL_Y(row);
|
||||||
rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
|
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());
|
&rc, &rc, NULL, NULL, get_scroll_flags());
|
||||||
|
}
|
||||||
|
|
||||||
UpdateWindow(s_textArea);
|
UpdateWindow(s_textArea);
|
||||||
/* This seems to be required to avoid the cursor disappearing when
|
/* This seems to be required to avoid the cursor disappearing when
|
||||||
@ -3161,23 +3173,35 @@ gui_mch_insert_lines(
|
|||||||
int num_lines)
|
int num_lines)
|
||||||
{
|
{
|
||||||
RECT rc;
|
RECT rc;
|
||||||
|
|
||||||
intel_gpu_workaround();
|
|
||||||
|
|
||||||
#if defined(FEAT_DIRECTX)
|
#if defined(FEAT_DIRECTX)
|
||||||
// Commit drawing queue before ScrollWindowEx.
|
int use_redraw = 0;
|
||||||
if (IS_ENABLE_DIRECTX())
|
|
||||||
DWriteContext_Flush(s_dwc);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rc.left = FILL_X(gui.scroll_region_left);
|
rc.left = FILL_X(gui.scroll_region_left);
|
||||||
rc.right = FILL_X(gui.scroll_region_right + 1);
|
rc.right = FILL_X(gui.scroll_region_right + 1);
|
||||||
rc.top = FILL_Y(row);
|
rc.top = FILL_Y(row);
|
||||||
rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
|
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? */
|
#if defined(FEAT_DIRECTX)
|
||||||
ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height,
|
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());
|
&rc, &rc, NULL, NULL, get_scroll_flags());
|
||||||
|
}
|
||||||
|
|
||||||
UpdateWindow(s_textArea);
|
UpdateWindow(s_textArea);
|
||||||
|
|
||||||
@ -5853,6 +5877,7 @@ _OnImeNotify(HWND hWnd, DWORD dwCommand, DWORD dwData UNUSED)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
gui_update_cursor(TRUE, FALSE);
|
gui_update_cursor(TRUE, FALSE);
|
||||||
|
gui_mch_flush();
|
||||||
lResult = 0;
|
lResult = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -6181,6 +6206,67 @@ RevOut( HDC s_hdc,
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
void
|
||||||
gui_mch_draw_string(
|
gui_mch_draw_string(
|
||||||
int row,
|
int row,
|
||||||
@ -6200,7 +6286,6 @@ gui_mch_draw_string(
|
|||||||
static int unibuflen = 0;
|
static int unibuflen = 0;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
#endif
|
#endif
|
||||||
HPEN hpen, old_pen;
|
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -6263,11 +6348,7 @@ gui_mch_draw_string(
|
|||||||
brush_lru = !brush_lru;
|
brush_lru = !brush_lru;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(FEAT_DIRECTX)
|
fill_rect(&rc, hbr, gui.currBgColor);
|
||||||
if (IS_ENABLE_DIRECTX())
|
|
||||||
DWriteContext_FillRect(s_dwc, &rc, gui.currBgColor);
|
|
||||||
#endif
|
|
||||||
FillRect(s_hdc, &rc, hbr);
|
|
||||||
|
|
||||||
SetBkMode(s_hdc, TRANSPARENT);
|
SetBkMode(s_hdc, TRANSPARENT);
|
||||||
|
|
||||||
@ -6462,38 +6543,22 @@ gui_mch_draw_string(
|
|||||||
foptions, pcliprect, (char *)text, len, padding);
|
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 */
|
/* Underline */
|
||||||
if (flags & DRAW_UNDERL)
|
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.
|
/* When p_linespace is 0, overwrite the bottom row of pixels.
|
||||||
* Otherwise put the line just below the character. */
|
* Otherwise put the line just below the character. */
|
||||||
y = FILL_Y(row + 1) - 1;
|
y = FILL_Y(row + 1) - 1;
|
||||||
if (p_linespace > 1)
|
if (p_linespace > 1)
|
||||||
y -= p_linespace - 1;
|
y -= p_linespace - 1;
|
||||||
MoveToEx(s_hdc, FILL_X(col), y, NULL);
|
draw_line(FILL_X(col), y, FILL_X(col + len), y, gui.currFgColor);
|
||||||
/* Note: LineTo() excludes the last pixel in the line. */
|
|
||||||
LineTo(s_hdc, FILL_X(col + len), y);
|
|
||||||
DeleteObject(SelectObject(s_hdc, old_pen));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Strikethrough */
|
/* Strikethrough */
|
||||||
if (flags & DRAW_STRIKE)
|
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;
|
y = FILL_Y(row + 1) - gui.char_height/2;
|
||||||
MoveToEx(s_hdc, FILL_X(col), y, NULL);
|
draw_line(FILL_X(col), y, FILL_X(col + len), y, gui.currSpColor);
|
||||||
/* Note: LineTo() excludes the last pixel in the line. */
|
|
||||||
LineTo(s_hdc, FILL_X(col + len), y);
|
|
||||||
DeleteObject(SelectObject(s_hdc, old_pen));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Undercurl */
|
/* Undercurl */
|
||||||
@ -6507,7 +6572,7 @@ gui_mch_draw_string(
|
|||||||
for (x = FILL_X(col); x < FILL_X(col + len); ++x)
|
for (x = FILL_X(col); x < FILL_X(col + len); ++x)
|
||||||
{
|
{
|
||||||
offset = val[x % 8];
|
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
|
static void
|
||||||
clear_rect(RECT *rcp)
|
clear_rect(RECT *rcp)
|
||||||
{
|
{
|
||||||
HBRUSH hbr;
|
fill_rect(rcp, NULL, gui.back_pixel);
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -771,6 +771,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1369,
|
||||||
/**/
|
/**/
|
||||||
1368,
|
1368,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user