Skip to content

Commit 0219781

Browse files
ZoeyRDHowett
authored andcommitted
Allow the DX rendering engine to run on Windows 7 (#1274)
Certain DirectX features are unavailable on windows 7. The important ones as they are used in the DX renderer are color font rendering and fallback font support. Color fonts did not exist at all on windows 7 so running basic glyphrun rendering should work just fine. Fallback font support was not exposed to the user in windows 7, making dealing with them difficult. Rather than try to get some workarounds to properly enable it I have opted to just conditionally disable the support on windows 7.
1 parent b9cc819 commit 0219781

File tree

5 files changed

+53
-33
lines changed

5 files changed

+53
-33
lines changed

src/renderer/dx/CustomTextLayout.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <wrl.h>
99
#include <wrl/client.h>
10+
#include <VersionHelpers.h>
1011

1112
using namespace Microsoft::Console::Render;
1213

@@ -19,10 +20,10 @@ using namespace Microsoft::Console::Render;
1920
// - font - The DirectWrite font face to use while calculating layout (by default, will fallback if necessary)
2021
// - clusters - From the backing buffer, the text to be displayed clustered by the columns it should consume.
2122
// - width - The count of pixels available per column (the expected pixel width of every column)
22-
CustomTextLayout::CustomTextLayout(IDWriteFactory2* const factory,
23+
CustomTextLayout::CustomTextLayout(IDWriteFactory1* const factory,
2324
IDWriteTextAnalyzer1* const analyzer,
24-
IDWriteTextFormat2* const format,
25-
IDWriteFontFace5* const font,
25+
IDWriteTextFormat* const format,
26+
IDWriteFontFace1* const font,
2627
std::basic_string_view<Cluster> const clusters,
2728
size_t const width) :
2829
_factory{ factory },
@@ -134,7 +135,11 @@ CustomTextLayout::CustomTextLayout(IDWriteFactory2* const factory,
134135
RETURN_IF_FAILED(_analyzer->AnalyzeNumberSubstitution(this, 0, textLength, this));
135136

136137
// Perform our custom font fallback analyzer that mimics the pattern of the real analyzers.
137-
RETURN_IF_FAILED(_AnalyzeFontFallback(this, 0, textLength));
138+
// Fallback routines are not available below Windows 8.1, so just skip them and let a replacement character happen.
139+
if (IsWindows8Point1OrGreater())
140+
{
141+
RETURN_IF_FAILED(_AnalyzeFontFallback(this, 0, textLength));
142+
}
138143

139144
// Ensure that a font face is attached to every run
140145
for (auto& run : _runs)

src/renderer/dx/CustomTextLayout.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ namespace Microsoft::Console::Render
1919
public:
2020
// Based on the Windows 7 SDK sample at https://github.com/pauldotknopf/WindowsSDK7-Samples/tree/master/multimedia/DirectWrite/CustomLayout
2121

22-
CustomTextLayout(IDWriteFactory2* const factory,
22+
CustomTextLayout(IDWriteFactory1* const factory,
2323
IDWriteTextAnalyzer1* const analyzer,
24-
IDWriteTextFormat2* const format,
25-
IDWriteFontFace5* const font,
24+
IDWriteTextFormat* const format,
25+
IDWriteFontFace1* const font,
2626
const std::basic_string_view<::Microsoft::Console::Render::Cluster> clusters,
2727
size_t const width);
2828

@@ -90,7 +90,7 @@ namespace Microsoft::Console::Render
9090
UINT8 bidiLevel;
9191
bool isNumberSubstituted;
9292
bool isSideways;
93-
::Microsoft::WRL::ComPtr<IDWriteFontFace5> fontFace;
93+
::Microsoft::WRL::ComPtr<IDWriteFontFace1> fontFace;
9494
FLOAT fontScale;
9595

9696
inline bool ContainsTextPosition(UINT32 desiredTextPosition) const
@@ -135,16 +135,16 @@ namespace Microsoft::Console::Render
135135
[[nodiscard]] static UINT32 _EstimateGlyphCount(const UINT32 textLength) noexcept;
136136

137137
private:
138-
const ::Microsoft::WRL::ComPtr<IDWriteFactory2> _factory;
138+
const ::Microsoft::WRL::ComPtr<IDWriteFactory1> _factory;
139139

140140
// DirectWrite analyzer
141141
const ::Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1> _analyzer;
142142

143143
// DirectWrite text format
144-
const ::Microsoft::WRL::ComPtr<IDWriteTextFormat2> _format;
144+
const ::Microsoft::WRL::ComPtr<IDWriteTextFormat> _format;
145145

146146
// DirectWrite font face
147-
const ::Microsoft::WRL::ComPtr<IDWriteFontFace5> _font;
147+
const ::Microsoft::WRL::ComPtr<IDWriteFontFace1> _font;
148148

149149
// The text we're analyzing and processing into a layout
150150
std::wstring _text;

src/renderer/dx/CustomTextRenderer.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <wrl.h>
99
#include <wrl/client.h>
10+
#include <VersionHelpers.h>
1011

1112
using namespace Microsoft::Console::Render;
1213

@@ -239,8 +240,8 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
239240
D2D1_POINT_2F baselineOrigin = origin;
240241
baselineOrigin.y += drawingContext->spacing.baseline;
241242

242-
::Microsoft::WRL::ComPtr<ID2D1DeviceContext4> d2dContext4;
243-
RETURN_IF_FAILED(drawingContext->renderTarget->QueryInterface(d2dContext4.GetAddressOf()));
243+
::Microsoft::WRL::ComPtr<ID2D1DeviceContext> d2dContext;
244+
RETURN_IF_FAILED(drawingContext->renderTarget->QueryInterface(d2dContext.GetAddressOf()));
244245

245246
// Draw the background
246247
D2D1_RECT_F rect;
@@ -254,13 +255,17 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
254255
rect.right += glyphRun->glyphAdvances[i];
255256
}
256257

257-
d2dContext4->FillRectangle(rect, drawingContext->backgroundBrush);
258+
d2dContext->FillRectangle(rect, drawingContext->backgroundBrush);
258259

259260
// Now go onto drawing the text.
260261

261262
// First check if we want a color font and try to extract color emoji first.
262-
if (WI_IsFlagSet(drawingContext->options, D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
263+
// Color emoji are only available on Windows 10+
264+
if (WI_IsFlagSet(drawingContext->options, D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT) && IsWindows10OrGreater())
263265
{
266+
::Microsoft::WRL::ComPtr<ID2D1DeviceContext4> d2dContext4;
267+
RETURN_IF_FAILED(d2dContext.As(&d2dContext4));
268+
264269
::Microsoft::WRL::ComPtr<IDWriteFactory4> dwriteFactory4;
265270
RETURN_IF_FAILED(drawingContext->dwriteFactory->QueryInterface(dwriteFactory4.GetAddressOf()));
266271

@@ -409,11 +414,11 @@ void CustomTextRenderer::_FillRectangle(void* clientDrawingContext,
409414
_In_ const DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription,
410415
ID2D1Brush* brush)
411416
{
412-
::Microsoft::WRL::ComPtr<ID2D1DeviceContext4> d2dContext4;
413-
RETURN_IF_FAILED(clientDrawingContext->renderTarget->QueryInterface(d2dContext4.GetAddressOf()));
417+
::Microsoft::WRL::ComPtr<ID2D1DeviceContext> d2dContext;
418+
RETURN_IF_FAILED(clientDrawingContext->renderTarget->QueryInterface(d2dContext.GetAddressOf()));
414419

415420
// Using the context is the easiest/default way of drawing.
416-
d2dContext4->DrawGlyphRun(baselineOrigin, glyphRun, glyphRunDescription, brush, measuringMode);
421+
d2dContext->DrawGlyphRun(baselineOrigin, glyphRun, glyphRunDescription, brush, measuringMode);
417422

418423
// However, we could probably add options here and switch out to one of these other drawing methods (making it
419424
// conditional based on the IUnknown* clientDrawingEffect or on some other switches and try these out instead:

src/renderer/dx/DxRenderer.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "../../types/inc/Viewport.hpp"
1111
#include "../../inc/unicode.hpp"
1212
#include "../../inc/DefaultSettings.h"
13+
#include <VersionHelpers.h>
1314

1415
#pragma hdrstop
1516

@@ -191,7 +192,16 @@ DxEngine::~DxEngine()
191192
SwapChainDesc.BufferCount = 2;
192193
SwapChainDesc.SampleDesc.Count = 1;
193194
SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
194-
SwapChainDesc.Scaling = DXGI_SCALING_NONE;
195+
196+
// DXGI_SCALING_NONE is only valid on Windows 8+
197+
if (IsWindows8OrGreater())
198+
{
199+
SwapChainDesc.Scaling = DXGI_SCALING_NONE;
200+
}
201+
else
202+
{
203+
SwapChainDesc.Scaling = DXGI_SCALING_STRETCH;
204+
}
195205

196206
switch (_chainMode)
197207
{
@@ -886,7 +896,7 @@ void DxEngine::_InvalidOr(RECT rc) noexcept
886896

887897
// Get the baseline for this font as that's where we draw from
888898
DWRITE_LINE_SPACING spacing;
889-
RETURN_IF_FAILED(_dwriteTextFormat->GetLineSpacing(&spacing));
899+
RETURN_IF_FAILED(_dwriteTextFormat->GetLineSpacing(&spacing.method, &spacing.height, &spacing.baseline));
890900

891901
// Assemble the drawing context information
892902
DrawingContext context(_d2dRenderTarget.Get(),
@@ -1248,9 +1258,9 @@ float DxEngine::GetScaling() const noexcept
12481258
FontInfo& pfiFontInfo,
12491259
int const iDpi) noexcept
12501260
{
1251-
Microsoft::WRL::ComPtr<IDWriteTextFormat2> format;
1261+
Microsoft::WRL::ComPtr<IDWriteTextFormat> format;
12521262
Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1> analyzer;
1253-
Microsoft::WRL::ComPtr<IDWriteFontFace5> face;
1263+
Microsoft::WRL::ComPtr<IDWriteFontFace1> face;
12541264

12551265
return _GetProposedFont(pfiFontInfoDesired,
12561266
pfiFontInfo,
@@ -1352,12 +1362,12 @@ float DxEngine::GetScaling() const noexcept
13521362
// - style - Normal, italic, etc.
13531363
// Return Value:
13541364
// - Smart pointer holding interface reference for queryable font data.
1355-
[[nodiscard]] Microsoft::WRL::ComPtr<IDWriteFontFace5> DxEngine::_FindFontFace(const std::wstring& familyName,
1365+
[[nodiscard]] Microsoft::WRL::ComPtr<IDWriteFontFace1> DxEngine::_FindFontFace(const std::wstring& familyName,
13561366
DWRITE_FONT_WEIGHT weight,
13571367
DWRITE_FONT_STRETCH stretch,
13581368
DWRITE_FONT_STYLE style) const
13591369
{
1360-
Microsoft::WRL::ComPtr<IDWriteFontFace5> fontFace;
1370+
Microsoft::WRL::ComPtr<IDWriteFontFace1> fontFace;
13611371

13621372
Microsoft::WRL::ComPtr<IDWriteFontCollection> fontCollection;
13631373
THROW_IF_FAILED(_dwriteFactory->GetSystemFontCollection(&fontCollection, false));
@@ -1394,9 +1404,9 @@ float DxEngine::GetScaling() const noexcept
13941404
[[nodiscard]] HRESULT DxEngine::_GetProposedFont(const FontInfoDesired& desired,
13951405
FontInfo& actual,
13961406
const int dpi,
1397-
Microsoft::WRL::ComPtr<IDWriteTextFormat2>& textFormat,
1407+
Microsoft::WRL::ComPtr<IDWriteTextFormat>& textFormat,
13981408
Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1>& textAnalyzer,
1399-
Microsoft::WRL::ComPtr<IDWriteFontFace5>& fontFace) const noexcept
1409+
Microsoft::WRL::ComPtr<IDWriteFontFace1>& fontFace) const noexcept
14001410
{
14011411
try
14021412
{
@@ -1508,7 +1518,7 @@ float DxEngine::GetScaling() const noexcept
15081518

15091519
fontFace = face;
15101520

1511-
THROW_IF_FAILED(textFormat->SetLineSpacing(&lineSpacing));
1521+
THROW_IF_FAILED(textFormat->SetLineSpacing(lineSpacing.method, lineSpacing.height, lineSpacing.baseline));
15121522
THROW_IF_FAILED(textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR));
15131523
THROW_IF_FAILED(textFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP));
15141524

src/renderer/dx/DxRenderer.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ namespace Microsoft::Console::Render
146146

147147
// Device-Independent Resources
148148
::Microsoft::WRL::ComPtr<ID2D1Factory> _d2dFactory;
149-
::Microsoft::WRL::ComPtr<IDWriteFactory2> _dwriteFactory;
150-
::Microsoft::WRL::ComPtr<IDWriteTextFormat2> _dwriteTextFormat;
151-
::Microsoft::WRL::ComPtr<IDWriteFontFace5> _dwriteFontFace;
149+
::Microsoft::WRL::ComPtr<IDWriteFactory1> _dwriteFactory;
150+
::Microsoft::WRL::ComPtr<IDWriteTextFormat> _dwriteTextFormat;
151+
::Microsoft::WRL::ComPtr<IDWriteFontFace1> _dwriteFontFace;
152152
::Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1> _dwriteTextAnalyzer;
153153
::Microsoft::WRL::ComPtr<CustomTextRenderer> _customRenderer;
154154

@@ -178,17 +178,17 @@ namespace Microsoft::Console::Render
178178

179179
[[nodiscard]] HRESULT _EnableDisplayAccess(const bool outputEnabled) noexcept;
180180

181-
[[nodiscard]] ::Microsoft::WRL::ComPtr<IDWriteFontFace5> _FindFontFace(const std::wstring& familyName,
181+
[[nodiscard]] ::Microsoft::WRL::ComPtr<IDWriteFontFace1> _FindFontFace(const std::wstring& familyName,
182182
DWRITE_FONT_WEIGHT weight,
183183
DWRITE_FONT_STRETCH stretch,
184184
DWRITE_FONT_STYLE style) const;
185185

186186
[[nodiscard]] HRESULT _GetProposedFont(const FontInfoDesired& desired,
187187
FontInfo& actual,
188188
const int dpi,
189-
::Microsoft::WRL::ComPtr<IDWriteTextFormat2>& textFormat,
189+
::Microsoft::WRL::ComPtr<IDWriteTextFormat>& textFormat,
190190
::Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1>& textAnalyzer,
191-
::Microsoft::WRL::ComPtr<IDWriteFontFace5>& fontFace) const noexcept;
191+
::Microsoft::WRL::ComPtr<IDWriteFontFace1>& fontFace) const noexcept;
192192

193193
[[nodiscard]] COORD _GetFontSize() const noexcept;
194194

0 commit comments

Comments
 (0)