dx: Render all gridlines (and, bonus: the box cursor) properly (#2491)

Since we're rendering with antialiasing enabled, we need to make sure
we're stroking actual pixels; to do that, we need to adjust all of our
coordinates by the StrokeWidth / 2. We're always using a stroke width of
1, so that means 0.5.

While I was here, I took the opportunity to fix the color of the grid
lines. Fixes #543.
This commit is contained in:
Dustin L. Howett (MSFT) 2019-08-20 16:14:26 -07:00 committed by GitHub
parent 8096d7cf2f
commit 28b767d00b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 12 deletions

View file

@ -295,6 +295,17 @@ DxEngine::~DxEngine()
RETURN_IF_FAILED(_d2dRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White),
&_d2dBrushForeground));
const D2D1_STROKE_STYLE_PROPERTIES strokeStyleProperties{
D2D1_CAP_STYLE_SQUARE, // startCap
D2D1_CAP_STYLE_SQUARE, // endCap
D2D1_CAP_STYLE_SQUARE, // dashCap
D2D1_LINE_JOIN_MITER, // lineJoin
0.f, // miterLimit
D2D1_DASH_STYLE_SOLID, // dashStyle
0.f, // dashOffset
};
RETURN_IF_FAILED(_d2dFactory->CreateStrokeStyle(&strokeStyleProperties, nullptr, 0, &_strokeStyle));
// If in composition mode, apply scaling factor matrix
if (_chainMode == SwapChainMode::ForComposition)
{
@ -936,7 +947,7 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
const auto existingColor = _d2dBrushForeground->GetColor();
const auto restoreBrushOnExit = wil::scope_exit([&] { _d2dBrushForeground->SetColor(existingColor); });
_d2dBrushForeground->SetColor(D2D1::ColorF(color));
_d2dBrushForeground->SetColor(_ColorFFromColorRef(color));
const auto font = _GetFontSize();
D2D_POINT_2F target;
@ -948,14 +959,15 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
for (size_t i = 0; i < cchLine; i++)
{
start = target;
// 0.5 pixel offset for crisp lines
start = { target.x + 0.5f, target.y + 0.5f };
if (lines & GridLines::Top)
{
end = start;
end.x += font.X;
_d2dRenderTarget->DrawLine(start, end, _d2dBrushForeground.Get());
_d2dRenderTarget->DrawLine(start, end, _d2dBrushForeground.Get(), 1.0f, _strokeStyle.Get());
}
if (lines & GridLines::Left)
@ -963,7 +975,7 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
end = start;
end.y += font.Y;
_d2dRenderTarget->DrawLine(start, end, _d2dBrushForeground.Get());
_d2dRenderTarget->DrawLine(start, end, _d2dBrushForeground.Get(), 1.0f, _strokeStyle.Get());
}
// NOTE: Watch out for inclusive/exclusive rectangles here.
@ -973,26 +985,25 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
// The bottom left corner inclusive is at 0,15 which is Y (0) + Font Height (16) - 1 = 15.
// The top right corner inclusive is at 7,0 which is X (0) + Font Height (8) - 1 = 7.
start = target;
start.y += font.Y - 1;
// 0.5 pixel offset for crisp lines; -0.5 on the Y to fit _in_ the cell, not outside it.
start = { target.x + 0.5f, target.y + font.Y - 0.5f };
if (lines & GridLines::Bottom)
{
end = start;
end.x += font.X;
end.x += font.X - 1.f;
_d2dRenderTarget->DrawLine(start, end, _d2dBrushForeground.Get());
_d2dRenderTarget->DrawLine(start, end, _d2dBrushForeground.Get(), 1.0f, _strokeStyle.Get());
}
start = target;
start.x += font.X - 1;
start = { target.x + font.X - 0.5f, target.y + 0.5f };
if (lines & GridLines::Right)
{
end = start;
end.y += font.Y;
end.y += font.Y - 1.f;
_d2dRenderTarget->DrawLine(start, end, _d2dBrushForeground.Get());
_d2dRenderTarget->DrawLine(start, end, _d2dBrushForeground.Get(), 1.0f, _strokeStyle.Get());
}
// Move to the next character in this run.
@ -1125,6 +1136,13 @@ enum class CursorPaintType
}
case CursorPaintType::Outline:
{
// DrawRectangle in straddles physical pixels in an attempt to draw a line
// between them. To avoid this, bump the rectangle around by half the stroke width.
rect.top += 0.5f;
rect.left += 0.5f;
rect.bottom -= 0.5f;
rect.right -= 0.5f;
_d2dRenderTarget->DrawRectangle(rect, brush.Get());
break;
}

View file

@ -151,6 +151,7 @@ namespace Microsoft::Console::Render
::Microsoft::WRL::ComPtr<IDWriteFontFace1> _dwriteFontFace;
::Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1> _dwriteTextAnalyzer;
::Microsoft::WRL::ComPtr<CustomTextRenderer> _customRenderer;
::Microsoft::WRL::ComPtr<ID2D1StrokeStyle> _strokeStyle;
// Device-Dependent Resources
bool _haveDeviceResources;