diff --git a/NOTICE.md b/NOTICE.md
index 5c153f6ab63..5a44327592d 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -276,6 +276,41 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
+## xxHash
+
+**Source**: [https://github.com/Cyan4973/xxHash](https://github.com/Cyan4973/xxHash)
+
+### License
+
+```
+xxHash Library
+Copyright (c) 2012-2020 Yann Collet
+All rights reserved.
+
+BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+```
+
## ConEmu
**Source**: [https://github.com/Maximus5/ConEmu](https://github.com/Maximus5/ConEmu)
diff --git a/oss/xxhash/MAINTAINER_README.md b/oss/xxhash/MAINTAINER_README.md
new file mode 100644
index 00000000000..00ecf4b065b
--- /dev/null
+++ b/oss/xxhash/MAINTAINER_README.md
@@ -0,0 +1,3 @@
+### Notes for Future Maintainers
+
+At the time of writing xxHash (specifically XXH3) is only used in a modified form for the function `AtlasEngine::XXH3_len_32_64b`.
diff --git a/oss/xxhash/cgmanifest.json b/oss/xxhash/cgmanifest.json
new file mode 100644
index 00000000000..57b4514df07
--- /dev/null
+++ b/oss/xxhash/cgmanifest.json
@@ -0,0 +1,13 @@
+{"Registrations":[
+ {
+ "component": {
+ "type": "git",
+ "git": {
+ "repositoryUrl": "hhttps://github.com/Cyan4973/xxHash",
+ "commitHash": "9058687747c533a2fea7215fd72346e756da2034"
+ }
+ }
+ }
+ ],
+ "Version": 1
+}
diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.xaml b/src/cascadia/TerminalSettingsEditor/Profiles.xaml
index 46655ab1486..c860578aa2b 100644
--- a/src/cascadia/TerminalSettingsEditor/Profiles.xaml
+++ b/src/cascadia/TerminalSettingsEditor/Profiles.xaml
@@ -483,7 +483,7 @@
ClearSettingValue="{x:Bind State.Profile.ClearUseAtlasEngine}"
HasSettingValue="{x:Bind State.Profile.HasUseAtlasEngine, Mode=OneWay}"
SettingOverrideSource="{x:Bind State.Profile.UseAtlasEngineOverrideSource, Mode=OneWay}"
- Visibility="{x:Bind State.Profile.EditableUnfocusedAppearance}">
+ Visibility="{x:Bind State.Profile.AtlasEngineAvailable}">
diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.h b/src/cascadia/TerminalSettingsModel/TerminalSettings.h
index 0d726318130..4d4686af368 100644
--- a/src/cascadia/TerminalSettingsModel/TerminalSettings.h
+++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.h
@@ -125,7 +125,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, hstring, FontFace, DEFAULT_FONT_FACE);
INHERITABLE_SETTING(Model::TerminalSettings, int32_t, FontSize, DEFAULT_FONT_SIZE);
- INHERITABLE_SETTING(Model::TerminalSettings, winrt::Windows::UI::Text::FontWeight, FontWeight, DEFAULT_FONT_WEIGHT);
+ INHERITABLE_SETTING(Model::TerminalSettings, winrt::Windows::UI::Text::FontWeight, FontWeight);
INHERITABLE_SETTING(Model::TerminalSettings, IFontAxesMap, FontAxes);
INHERITABLE_SETTING(Model::TerminalSettings, IFontFeatureMap, FontFeatures);
diff --git a/src/host/exe/Host.EXE.vcxproj b/src/host/exe/Host.EXE.vcxproj
index 60b6628197e..c21bb27c8a2 100644
--- a/src/host/exe/Host.EXE.vcxproj
+++ b/src/host/exe/Host.EXE.vcxproj
@@ -43,12 +43,12 @@
{af0a096a-8b3a-4949-81ef-7df8f0fee91f}
-
- {48d21369-3d7b-4431-9967-24e81292cf62}
-
{8222900C-8B6C-452A-91AC-BE95DB04B95F}
+
+ {48d21369-3d7b-4431-9967-24e81292cf62}
+
{1c959542-bac2-4e55-9a6d-13251914cbb9}
diff --git a/src/host/ft_fuzzer/Host.FuzzWrapper.vcxproj b/src/host/ft_fuzzer/Host.FuzzWrapper.vcxproj
index e351317812f..8486a9e4894 100644
--- a/src/host/ft_fuzzer/Host.FuzzWrapper.vcxproj
+++ b/src/host/ft_fuzzer/Host.FuzzWrapper.vcxproj
@@ -38,6 +38,9 @@
{af0a096a-8b3a-4949-81ef-7df8f0fee91f}
+
+ {8222900C-8B6C-452A-91AC-BE95DB04B95F}
+
{48d21369-3d7b-4431-9967-24e81292cf62}
@@ -71,6 +74,7 @@
..;%(AdditionalIncludeDirectories)
+ winmm.lib;%(AdditionalDependencies)
Console
diff --git a/src/host/ft_host/CJK_DbcsTests.cpp b/src/host/ft_host/CJK_DbcsTests.cpp
index 4b86120042b..c6b150069bb 100644
--- a/src/host/ft_host/CJK_DbcsTests.cpp
+++ b/src/host/ft_host/CJK_DbcsTests.cpp
@@ -2320,9 +2320,6 @@ void ReadStringWithReadConsoleInputAHelper(HANDLE hIn, PCSTR pszExpectedText, si
while (cchRead < cchExpectedText)
{
- // expected read is either the size of the buffer or the number of characters remaining, whichever is smaller.
- DWORD const dwReadExpected = (DWORD)std::min(cbBuffer, cchExpectedText - cchRead);
-
DWORD dwRead;
if (!VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleInputA(hIn, irRead, (DWORD)cbBuffer, &dwRead), L"Attempt to read input into buffer."))
{
diff --git a/src/host/getset.cpp b/src/host/getset.cpp
index 6203aef0e54..5ee114e6d82 100644
--- a/src/host/getset.cpp
+++ b/src/host/getset.cpp
@@ -274,7 +274,8 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
const FontInfo& fontInfo = activeScreenInfo.GetCurrentFont();
consoleFontInfoEx.FontFamily = fontInfo.GetFamily();
consoleFontInfoEx.FontWeight = fontInfo.GetWeight();
- fontInfo.FillLegacyNameBuffer(consoleFontInfoEx.FaceName);
+
+ RETURN_IF_FAILED(fontInfo.FillLegacyNameBuffer(gsl::make_span(consoleFontInfoEx.FaceName)));
return S_OK;
}
diff --git a/src/host/selection.cpp b/src/host/selection.cpp
index 90bb5668f3e..7814bfae9c9 100644
--- a/src/host/selection.cpp
+++ b/src/host/selection.cpp
@@ -255,14 +255,6 @@ void Selection::ExtendSelection(_In_ COORD coordBufferPos)
srNewSelection.Top = _coordSelectionAnchor.Y;
}
- // This function is called on WM_MOUSEMOVE.
- // Prevent triggering an invalidation just because the mouse moved
- // in the same cell without changing the actual (visible) selection.
- if (_srSelectionRect == srNewSelection)
- {
- return;
- }
-
// call special update method to modify the displayed selection in-place
// NOTE: Using HideSelection, editing the rectangle, then ShowSelection will cause flicker.
//_PaintUpdateSelection(&srNewSelection);
diff --git a/src/host/settings.cpp b/src/host/settings.cpp
index 75b34a235c5..2d224af5813 100644
--- a/src/host/settings.cpp
+++ b/src/host/settings.cpp
@@ -815,7 +815,9 @@ void Settings::SetTerminalScrolling(const bool terminalScrollingEnabled) noexcep
// - Determines whether our primary renderer should be DirectX or GDI.
// - This is based on user preference and velocity hold back state.
// Return Value:
-// - True means use DirectX renderer. False means use GDI renderer.
+// - case 1: DxEngine
+// - case 2: AtlasEngine
+// - default: GdiEngine
DWORD Settings::GetUseDx() const noexcept
{
return _fUseDx;
diff --git a/src/host/ut_host/Host.UnitTests.vcxproj b/src/host/ut_host/Host.UnitTests.vcxproj
index 486965b2fb9..6b5bedf1b11 100644
--- a/src/host/ut_host/Host.UnitTests.vcxproj
+++ b/src/host/ut_host/Host.UnitTests.vcxproj
@@ -52,6 +52,9 @@
{ef3e32a7-5ff6-42b4-b6e2-96cd7d033f00}
+
+ {8222900C-8B6C-452A-91AC-BE95DB04B95F}
+
{48d21369-3d7b-4431-9967-24e81292cf62}
diff --git a/src/interactivity/win32/ut_interactivity_win32/Interactivity.Win32.UnitTests.vcxproj b/src/interactivity/win32/ut_interactivity_win32/Interactivity.Win32.UnitTests.vcxproj
index 2330bee3aa6..fa2fa30b086 100644
--- a/src/interactivity/win32/ut_interactivity_win32/Interactivity.Win32.UnitTests.vcxproj
+++ b/src/interactivity/win32/ut_interactivity_win32/Interactivity.Win32.UnitTests.vcxproj
@@ -22,6 +22,9 @@
{ef3e32a7-5ff6-42b4-b6e2-96cd7d033f00}
+
+ {8222900C-8B6C-452A-91AC-BE95DB04B95F}
+
{48d21369-3d7b-4431-9967-24e81292cf62}
@@ -76,4 +79,4 @@
-
\ No newline at end of file
+
diff --git a/src/interactivity/win32/ut_interactivity_win32/UiaTextRangeTests.cpp b/src/interactivity/win32/ut_interactivity_win32/UiaTextRangeTests.cpp
index 99ae12628ab..518dc87473f 100644
--- a/src/interactivity/win32/ut_interactivity_win32/UiaTextRangeTests.cpp
+++ b/src/interactivity/win32/ut_interactivity_win32/UiaTextRangeTests.cpp
@@ -735,7 +735,6 @@ class UiaTextRangeTests
TEST_METHOD(CanMoveByCharacter)
{
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().RightInclusive();
- const SHORT bottomRow = gsl::narrow(_pTextBuffer->TotalRowCount() - 1);
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
// instead of parsing through thousands of empty lines of text.
@@ -824,7 +823,6 @@ class UiaTextRangeTests
TEST_METHOD(CanMoveByLine)
{
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
- const SHORT bottomRow = gsl::narrow(_pTextBuffer->TotalRowCount() - 1);
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
// instead of parsing through thousands of empty lines of text.
@@ -913,7 +911,6 @@ class UiaTextRangeTests
TEST_METHOD(CanMoveEndpointByUnitCharacter)
{
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
- const SHORT bottomRow = static_cast(_pTextBuffer->TotalRowCount() - 1);
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
// instead of parsing through thousands of empty lines of text.
@@ -1197,7 +1194,6 @@ class UiaTextRangeTests
TEST_METHOD(CanMoveEndpointByUnitDocument)
{
- const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
const SHORT bottomRow = gsl::narrow(_pTextBuffer->TotalRowCount() - 1);
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
diff --git a/src/interactivity/win32/window.cpp b/src/interactivity/win32/window.cpp
index 48f93912c86..59db497a208 100644
--- a/src/interactivity/win32/window.cpp
+++ b/src/interactivity/win32/window.cpp
@@ -26,8 +26,10 @@
#include "../../renderer/base/renderer.hpp"
#include "../../renderer/gdi/gdirenderer.hpp"
-#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
+#if TIL_FEATURE_ATLASENGINE_ENABLED
#include "../../renderer/atlas/AtlasEngine.h"
+#endif
+#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
#include "../../renderer/dx/DxRenderer.hpp"
#endif
@@ -211,6 +213,8 @@ void Window::_UpdateSystemMetrics() const
GdiEngine* pGdiEngine = nullptr;
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
DxEngine* pDxEngine = nullptr;
+#endif
+#if TIL_FEATURE_ATLASENGINE_ENABLED
AtlasEngine* pAtlasEngine = nullptr;
#endif
try
@@ -228,6 +232,8 @@ void Window::_UpdateSystemMetrics() const
THROW_IF_FAILED(pDxEngine->SetHwnd(nullptr));
g.pRender->AddRenderEngine(pDxEngine);
break;
+#endif
+#if TIL_FEATURE_ATLASENGINE_ENABLED
case 2:
pAtlasEngine = new AtlasEngine();
g.pRender->AddRenderEngine(pAtlasEngine);
@@ -333,7 +339,10 @@ void Window::_UpdateSystemMetrics() const
status = NTSTATUS_FROM_WIN32(HRESULT_CODE((pDxEngine->Enable())));
}
}
- else if (pAtlasEngine)
+ else
+#endif
+#if TIL_FEATURE_ATLASENGINE_ENABLED
+ if (pAtlasEngine)
{
status = NTSTATUS_FROM_WIN32(HRESULT_CODE((pAtlasEngine->SetHwnd(hWnd))));
}
diff --git a/src/renderer/atlas/AtlasEngine.api.cpp b/src/renderer/atlas/AtlasEngine.api.cpp
index f8dc60341f2..b8a13fa231d 100644
--- a/src/renderer/atlas/AtlasEngine.api.cpp
+++ b/src/renderer/atlas/AtlasEngine.api.cpp
@@ -40,7 +40,7 @@ constexpr HRESULT vec2_narrow(U x, U y, AtlasEngine::vec2& out) noexcept
[[nodiscard]] HRESULT AtlasEngine::Invalidate(const SMALL_RECT* const psrRegion) noexcept
{
- assert(psrRegion->Top <= psrRegion->Bottom && psrRegion->Top >= 0 && psrRegion->Bottom <= _api.cellCount.y);
+ assert(psrRegion->Top < psrRegion->Bottom && psrRegion->Top >= 0 && psrRegion->Bottom <= _api.cellCount.y);
// BeginPaint() protects against invalid out of bounds numbers.
_api.invalidatedRows.x = std::min(_api.invalidatedRows.x, gsl::narrow_cast(psrRegion->Top));
@@ -173,10 +173,24 @@ constexpr HRESULT vec2_narrow(U x, U y, AtlasEngine::vec2& out) noexcept
[[nodiscard]] HRESULT AtlasEngine::GetProposedFont(const FontInfoDesired& fontInfoDesired, _Out_ FontInfo& fontInfo, const int dpi) noexcept
try
{
- const auto& requestedFaceName = fontInfoDesired.GetFaceName();
+ const wchar_t* requestedFaceName = fontInfoDesired.GetFaceName().data();
const auto requestedFamily = fontInfoDesired.GetFamily();
- const auto requestedWeight = fontInfoDesired.GetWeight();
- const auto requestedSize = fontInfoDesired.GetEngineSize();
+ auto requestedWeight = fontInfoDesired.GetWeight();
+ auto requestedSize = fontInfoDesired.GetEngineSize();
+
+ if (!requestedFaceName)
+ {
+ requestedFaceName = L"Consolas";
+ }
+ if (!requestedWeight)
+ {
+ requestedWeight = DWRITE_FONT_WEIGHT_NORMAL;
+ }
+ if (!requestedSize.Y)
+ {
+ requestedSize = { 0, 16 };
+ }
+
std::wstring faceNameBuffer;
std::wstring_view resultingFaceName = requestedFaceName;
COORD resultingCellSize{};
@@ -237,7 +251,7 @@ try
#endif
{
wil::com_ptr textFormat;
- THROW_IF_FAILED(_createTextFormat(requestedFaceName.c_str(), static_cast(requestedWeight), DWRITE_FONT_STYLE_NORMAL, requestedSize.Y, textFormat.addressof()));
+ THROW_IF_FAILED(_createTextFormat(requestedFaceName, static_cast(requestedWeight), DWRITE_FONT_STYLE_NORMAL, requestedSize.Y, textFormat.addressof()));
wil::com_ptr textLayout;
THROW_IF_FAILED(_sr.dwriteFactory->CreateTextLayout(L"M", 1, textFormat.get(), FLT_MAX, FLT_MAX, textLayout.addressof()));
diff --git a/src/renderer/atlas/AtlasEngine.cpp b/src/renderer/atlas/AtlasEngine.cpp
index 2ca384f9d6a..40aae390dfa 100644
--- a/src/renderer/atlas/AtlasEngine.cpp
+++ b/src/renderer/atlas/AtlasEngine.cpp
@@ -4,6 +4,7 @@
#include "pch.h"
#include "AtlasEngine.h"
+#include
#include
#include
@@ -48,6 +49,17 @@ struct TextAnalyzer final : IDWriteTextAnalysisSource, IDWriteTextAnalysisSink
Ensures(_text.size() <= UINT32_MAX);
}
+#ifndef NDEBUG
+private:
+ ULONG _refCount = 1;
+
+public:
+ ~TextAnalyzer()
+ {
+ assert(_refCount == 1);
+ }
+#endif
+
HRESULT __stdcall QueryInterface(const IID& riid, void** ppvObject) noexcept override
{
__assume(ppvObject != nullptr);
@@ -64,14 +76,20 @@ struct TextAnalyzer final : IDWriteTextAnalysisSource, IDWriteTextAnalysisSink
ULONG __stdcall AddRef() noexcept override
{
- assert(false);
+#ifdef NDEBUG
return 1;
+#else
+ return ++_refCount;
+#endif
}
ULONG __stdcall Release() noexcept override
{
- assert(false);
+#ifdef NDEBUG
return 1;
+#else
+ return --_refCount;
+#endif
}
HRESULT __stdcall GetTextAtPosition(UINT32 textPosition, const WCHAR** textString, UINT32* textLength) noexcept override
@@ -209,18 +227,19 @@ try
}
WI_ClearAllFlags(_invalidations, InvalidationFlags::device | InvalidationFlags::size | InvalidationFlags::font | InvalidationFlags::settings);
- std::ignore = InvalidateAll();
+ _api.invalidatedRows = invalidatedRowsAll;
}
- // Clamp invalidation rects into valid value ranges.
if (_api.invalidatedRows == invalidatedRowsAll)
{
+ // Skip all the partial updates, since we redraw everything anyways.
_api.invalidatedCursorArea = invalidatedAreaNone;
_api.invalidatedRows = { 0, _api.cellCount.y };
_api.scrollOffset = 0;
}
else
{
+ // Clamp invalidation rects into valid value ranges.
{
_api.invalidatedCursorArea.left = std::min(_api.invalidatedCursorArea.left, _api.cellCount.x);
_api.invalidatedCursorArea.top = std::min(_api.invalidatedCursorArea.top, _api.cellCount.y);
@@ -235,50 +254,50 @@ try
const auto limit = gsl::narrow_cast(_api.cellCount.y & 0x7fff);
_api.scrollOffset = clamp(_api.scrollOffset, -limit, limit);
}
- }
-
- // Scroll the buffer by the given offset and mark the newly uncovered rows as "invalid".
- if (_api.scrollOffset != 0)
- {
- const auto data = _r.cells.data();
- auto count = _r.cells.size();
- const auto offset = static_cast(_api.scrollOffset) * _api.cellCount.x;
- Cell* dst;
- Cell* src;
- if (_api.scrollOffset < 0)
- {
- // Scroll up (for instance when new text is being written at the end of the buffer).
- dst = data;
- src = data - offset;
- count += offset;
- _api.invalidatedRows.x = std::min(_api.invalidatedRows.x, _api.cellCount.y + _api.scrollOffset);
- _api.invalidatedRows.y = _api.cellCount.y;
- }
- else
+ // Scroll the buffer by the given offset and mark the newly uncovered rows as "invalid".
+ if (_api.scrollOffset != 0)
{
- // Scroll down.
- dst = data + offset;
- src = data;
- count -= offset;
- _api.invalidatedRows.x = 0;
- _api.invalidatedRows.y = std::max(_api.invalidatedRows.y, _api.scrollOffset);
- }
+ const auto nothingInvalid = _api.invalidatedRows.x == _api.invalidatedRows.y;
+ const auto offset = static_cast(_api.scrollOffset) * _api.cellCount.x;
+ const auto data = _r.cells.data();
+ auto count = _r.cells.size();
+ Cell* dst;
+ Cell* src;
+
+ if (_api.scrollOffset < 0)
+ {
+ // Scroll up (for instance when new text is being written at the end of the buffer).
+ dst = data;
+ src = data - offset;
+ count += offset;
+
+ const u16 endRow = _api.cellCount.y + _api.scrollOffset;
+ _api.invalidatedRows.x = nothingInvalid ? endRow : std::min(_api.invalidatedRows.x, endRow);
+ _api.invalidatedRows.y = _api.cellCount.y;
+ }
+ else
+ {
+ // Scroll down.
+ dst = data + offset;
+ src = data;
+ count -= offset;
- memmove(dst, src, count * sizeof(Cell));
- }
+ _api.invalidatedRows.x = 0;
+ _api.invalidatedRows.y = nothingInvalid ? _api.scrollOffset : std::max(_api.invalidatedRows.y, _api.scrollOffset);
+ }
- {
- // _api.dirtyRect is an inclusive rectangle, whereas _api.invalidatedRows is an exclusive range.
- // --> We need to subtract 1 from the bottom row index.
- // However .x could be equal to .y (for instance both could be 0), so we
- // need to ensure top isn't greater than bottom after the subtraction.
- const auto right = static_cast(_api.cellCount.x);
- const auto bottom = static_cast(_api.invalidatedRows.y);
- const auto top = static_cast(_api.invalidatedRows.x);
- _api.dirtyRect = til::rectangle{ 0u, top, right, bottom };
+ memmove(dst, src, count * sizeof(Cell));
+ }
}
+ _api.dirtyRect = til::rectangle{
+ static_cast(0),
+ static_cast(_api.invalidatedRows.x),
+ static_cast(_api.cellCount.x),
+ static_cast(_api.invalidatedRows.y),
+ };
+
return S_OK;
}
catch (const wil::ResultException& exception)
@@ -411,7 +430,7 @@ try
// # What do we want?
//
// Segment a line of text (_api.bufferLine) into unicode "clusters".
- // Each cluster is one "whole" glyph with diacritics, ligatures, zero-width-joiners
+ // Each cluster is one "whole" glyph with diacritics, ligatures, zero width joiners
// and whatever else, that should be cached as a whole in our texture atlas.
//
// # How do we get that?
@@ -425,7 +444,7 @@ try
//
// ## The actual approach
//
- // DirectWrite has 2 APIs which can segment text properly (including ligatures and zero width joiner for instance):
+ // DirectWrite has 2 APIs which can segment text properly (including ligatures and zero width joiners):
// * IDWriteTextAnalyzer1::GetTextComplexity
// * IDWriteTextAnalyzer::GetGlyphs
//
@@ -619,57 +638,6 @@ CATCH_RETURN()
#pragma endregion
-#pragma region Helper classes
-
-// XXH3 for exactly 32 bytes.
-uint64_t AtlasEngine::XXH3_len_32_64b(const void* data) noexcept
-{
- static constexpr uint64_t dataSize = 32;
- static constexpr auto XXH3_mul128_fold64 = [](uint64_t lhs, uint64_t rhs) noexcept {
- uint64_t lo, hi;
-
-#if defined(_M_AMD64)
- lo = _umul128(lhs, rhs, &hi);
-#elif defined(_M_ARM64)
- lo = lhs * rhs;
- hi = __umulh(lhs, rhs);
-#else
- const uint64_t lo_lo = __emulu(lhs, rhs);
- const uint64_t hi_lo = __emulu(lhs >> 32, rhs);
- const uint64_t lo_hi = __emulu(lhs, rhs >> 32);
- const uint64_t hi_hi = __emulu(lhs >> 32, rhs >> 32);
- const uint64_t cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
- hi = (hi_lo >> 32) + (cross >> 32) + hi_hi;
- lo = (cross << 32) | (lo_lo & 0xFFFFFFFF);
-#endif
-
- return lo ^ hi;
- };
-
- // If executed on little endian CPUs these 4 numbers will
- // equal the first 32 byte of the original XXH3_kSecret.
- static constexpr uint64_t XXH3_kSecret[4] = {
- UINT64_C(0xbe4ba423396cfeb8),
- UINT64_C(0x1cad21f72c81017c),
- UINT64_C(0xdb979083e96dd4de),
- UINT64_C(0x1f67b3b7a4a44072),
- };
-
- uint64_t inputs[4];
- memcpy(&inputs[0], data, 32);
-
-#pragma warning(suppress : 26450) // Arithmetic overflow: '*' operation causes overflow at compile time. Use a wider type to store the operands (io.1).
- uint64_t acc = dataSize * UINT64_C(0x9E3779B185EBCA87);
- acc += XXH3_mul128_fold64(inputs[0] ^ XXH3_kSecret[0], inputs[1] ^ XXH3_kSecret[1]);
- acc += XXH3_mul128_fold64(inputs[2] ^ XXH3_kSecret[2], inputs[3] ^ XXH3_kSecret[3]);
- acc = acc ^ (acc >> 37);
- acc *= UINT64_C(0x165667919E3779F9);
- acc = acc ^ (acc >> 32);
- return acc;
-}
-
-#pragma endregion
-
[[nodiscard]] HRESULT AtlasEngine::_handleException(const wil::ResultException& exception) noexcept
{
const auto hr = exception.GetErrorCode();
@@ -696,21 +664,25 @@ void AtlasEngine::_createResources()
#ifndef NDEBUG
// DXGI debug messages + enabling D3D11_CREATE_DEVICE_DEBUG if the Windows SDK was installed.
- if (const wil::unique_hmodule module{ LoadLibraryExW(L"dxgidebug.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32) })
+ if (const wil::unique_hmodule module{ LoadLibraryExW(L"dxgi.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32) })
{
deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
- const auto DXGIGetDebugInterface = reinterpret_cast(GetProcAddress(module.get(), "DXGIGetDebugInterface"));
- THROW_LAST_ERROR_IF(!DXGIGetDebugInterface);
-
- wil::com_ptr infoQueue;
- if (SUCCEEDED(DXGIGetDebugInterface(IID_PPV_ARGS(infoQueue.addressof()))))
+ if (const auto DXGIGetDebugInterface1 = GetProcAddressByFunctionDeclaration(module.get(), DXGIGetDebugInterface1))
{
- // I didn't want to link with dxguid.lib just for getting DXGI_DEBUG_ALL. This GUID is publicly documented.
- static constexpr GUID dxgiDebguAll = { 0xe48ae283, 0xda80, 0x490b, { 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x8 } };
- for (const auto severity : std::array{ DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING })
+ if (wil::com_ptr infoQueue; SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(infoQueue.addressof()))))
+ {
+ // I didn't want to link with dxguid.lib just for getting DXGI_DEBUG_ALL. This GUID is publicly documented.
+ static constexpr GUID dxgiDebugAll = { 0xe48ae283, 0xda80, 0x490b, { 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x8 } };
+ for (const auto severity : std::array{ DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING })
+ {
+ infoQueue->SetBreakOnSeverity(dxgiDebugAll, severity, true);
+ }
+ }
+
+ if (wil::com_ptr debug; SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(debug.addressof()))))
{
- infoQueue->SetBreakOnSeverity(dxgiDebguAll, severity, true);
+ debug->EnableLeakTrackingForThread();
}
}
}
diff --git a/src/renderer/atlas/AtlasEngine.h b/src/renderer/atlas/AtlasEngine.h
index 797a8fae8fb..4c24d16f1e5 100644
--- a/src/renderer/atlas/AtlasEngine.h
+++ b/src/renderer/atlas/AtlasEngine.h
@@ -105,6 +105,7 @@ namespace Microsoft::Console::Render
constexpr vec2 operator/(const vec2& rhs) noexcept
{
+ assert(rhs.x != 0 && rhs.y != 0);
return { gsl::narrow_cast(x / rhs.x), gsl::narrow_cast(y / rhs.y) };
}
};
@@ -409,7 +410,7 @@ namespace Microsoft::Console::Render
wil::unique_process_heap_string fontName; // changes are flagged as InvalidationFlags::font|size
u16 fontSize = 0; // changes are flagged as InvalidationFlags::font|size
- u16 fontWeight = DWRITE_FONT_WEIGHT_NORMAL; // changes are flagged as InvalidationFlags::font
+ u16 fontWeight = 0; // changes are flagged as InvalidationFlags::font
u16 dpi = USER_DEFAULT_SCREEN_DPI; // changes are flagged as InvalidationFlags::font|size
u16 antialiasingMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; // changes are flagged as InvalidationFlags::font
diff --git a/src/renderer/atlas/AtlasEngine.xxh.cpp b/src/renderer/atlas/AtlasEngine.xxh.cpp
new file mode 100644
index 00000000000..44ef277b8e2
--- /dev/null
+++ b/src/renderer/atlas/AtlasEngine.xxh.cpp
@@ -0,0 +1,57 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include "AtlasEngine.h"
+
+using namespace Microsoft::Console::Render;
+
+// XXH3 for exactly 32 bytes.
+uint64_t AtlasEngine::XXH3_len_32_64b(const void* data) noexcept
+{
+ static constexpr uint64_t dataSize = 32;
+ static constexpr auto XXH3_mul128_fold64 = [](uint64_t lhs, uint64_t rhs) noexcept {
+ uint64_t lo, hi;
+
+#if defined(_M_AMD64)
+ lo = _umul128(lhs, rhs, &hi);
+#elif defined(_M_ARM64)
+ lo = lhs * rhs;
+ hi = __umulh(lhs, rhs);
+#else
+// Implemented as a macro as MSVC tends to call __allmul otherwise.
+#define XXH_mult32to64(x, y) __emulu(gsl::narrow_cast(x), gsl::narrow_cast(y))
+ const uint64_t lo_lo = XXH_mult32to64(lhs, rhs);
+ const uint64_t hi_lo = XXH_mult32to64(lhs >> 32, rhs);
+ const uint64_t lo_hi = XXH_mult32to64(lhs, rhs >> 32);
+ const uint64_t hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32);
+ const uint64_t cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
+ hi = (hi_lo >> 32) + (cross >> 32) + hi_hi;
+ lo = (cross << 32) | (lo_lo & 0xFFFFFFFF);
+#undef XXH_mult32to64
+#endif
+
+ return lo ^ hi;
+ };
+
+ // If executed on little endian CPUs these 4 numbers will
+ // equal the first 32 byte of the original XXH3_kSecret.
+ static constexpr uint64_t XXH3_kSecret[4] = {
+ UINT64_C(0xbe4ba423396cfeb8),
+ UINT64_C(0x1cad21f72c81017c),
+ UINT64_C(0xdb979083e96dd4de),
+ UINT64_C(0x1f67b3b7a4a44072),
+ };
+
+ uint64_t inputs[4];
+ memcpy(&inputs[0], data, 32);
+
+#pragma warning(suppress : 26450) // Arithmetic overflow: '*' operation causes overflow at compile time. Use a wider type to store the operands (io.1).
+ uint64_t acc = dataSize * UINT64_C(0x9E3779B185EBCA87);
+ acc += XXH3_mul128_fold64(inputs[0] ^ XXH3_kSecret[0], inputs[1] ^ XXH3_kSecret[1]);
+ acc += XXH3_mul128_fold64(inputs[2] ^ XXH3_kSecret[2], inputs[3] ^ XXH3_kSecret[3]);
+ acc = acc ^ (acc >> 37);
+ acc *= UINT64_C(0x165667919E3779F9);
+ acc = acc ^ (acc >> 32);
+ return acc;
+}
diff --git a/src/renderer/atlas/atlas.vcxproj b/src/renderer/atlas/atlas.vcxproj
index 1e51a34efbe..7b50a8888c7 100644
--- a/src/renderer/atlas/atlas.vcxproj
+++ b/src/renderer/atlas/atlas.vcxproj
@@ -12,6 +12,7 @@
+
Create
diff --git a/src/renderer/base/FontInfoBase.cpp b/src/renderer/base/FontInfoBase.cpp
index d4ceb74e8a9..40891cf4940 100644
--- a/src/renderer/base/FontInfoBase.cpp
+++ b/src/renderer/base/FontInfoBase.cpp
@@ -43,7 +43,7 @@ FontInfoBase::~FontInfoBase()
{
}
-unsigned char FontInfoBase::GetFamily() const noexcept
+unsigned char FontInfoBase::GetFamily() const
{
return _family;
}
@@ -51,22 +51,22 @@ unsigned char FontInfoBase::GetFamily() const noexcept
// When the default raster font is forced set from the engine, this is how we differentiate it from a simple apply.
// Default raster font is internally represented as a blank face name and zeros for weight, family, and size. This is
// the hint for the engine to use whatever comes back from GetStockObject(OEM_FIXED_FONT) (at least in the GDI world).
-bool FontInfoBase::WasDefaultRasterSetFromEngine() const noexcept
+bool FontInfoBase::WasDefaultRasterSetFromEngine() const
{
return _fDefaultRasterSetFromEngine;
}
-unsigned int FontInfoBase::GetWeight() const noexcept
+unsigned int FontInfoBase::GetWeight() const
{
return _weight;
}
-const std::wstring& FontInfoBase::GetFaceName() const noexcept
+const std::wstring_view FontInfoBase::GetFaceName() const noexcept
{
return _faceName;
}
-unsigned int FontInfoBase::GetCodePage() const noexcept
+unsigned int FontInfoBase::GetCodePage() const
{
return _codePage;
}
@@ -77,7 +77,7 @@ unsigned int FontInfoBase::GetCodePage() const noexcept
// Arguments:
// - buffer: the buffer into which to copy characters
// - size: the size of buffer
-HRESULT FontInfoBase::FillLegacyNameBuffer(gsl::span buffer) const noexcept
+HRESULT FontInfoBase::FillLegacyNameBuffer(gsl::span buffer) const
try
{
auto toCopy = std::min(buffer.size() - 1, _faceName.size());
@@ -91,7 +91,7 @@ CATCH_RETURN();
void FontInfoBase::SetFromEngine(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
- const bool fSetDefaultRasterFont) noexcept
+ const bool fSetDefaultRasterFont)
{
_faceName = faceName;
_family = family;
@@ -101,12 +101,12 @@ void FontInfoBase::SetFromEngine(const std::wstring_view faceName,
// Internally, default raster font is represented by empty facename, and zeros for weight, family, and size. Since
// FontInfoBase doesn't have sizing information, this helper checks everything else.
-bool FontInfoBase::IsDefaultRasterFontNoSize() const noexcept
+bool FontInfoBase::IsDefaultRasterFontNoSize() const
{
return (_weight == 0 && _family == 0 && _faceName.empty());
}
-void FontInfoBase::ValidateFont() noexcept
+void FontInfoBase::ValidateFont()
{
// If we were given a blank name, it meant raster fonts, which to us is always Terminal.
if (!IsDefaultRasterFontNoSize() && s_pFontDefaultList != nullptr)
@@ -128,7 +128,7 @@ void FontInfoBase::ValidateFont() noexcept
}
}
-bool FontInfoBase::IsTrueTypeFont() const noexcept
+bool FontInfoBase::IsTrueTypeFont() const
{
return WI_IsFlagSet(_family, TMPF_TRUETYPE);
}
diff --git a/src/renderer/base/FontInfoDesired.cpp b/src/renderer/base/FontInfoDesired.cpp
index a3741bb4cf3..c293d141a40 100644
--- a/src/renderer/base/FontInfoDesired.cpp
+++ b/src/renderer/base/FontInfoDesired.cpp
@@ -11,7 +11,7 @@ bool operator==(const FontInfoDesired& a, const FontInfoDesired& b)
a._coordSizeDesired == b._coordSizeDesired);
}
-COORD FontInfoDesired::GetEngineSize() const noexcept
+COORD FontInfoDesired::GetEngineSize() const
{
COORD coordSize = _coordSizeDesired;
if (IsTrueTypeFont())
@@ -41,7 +41,7 @@ FontInfoDesired::FontInfoDesired(const FontInfo& fiFont) :
// This helper determines if this object represents the default raster font. This can either be because internally we're
// using the empty facename and zeros for size, weight, and family, or it can be because we were given explicit
// dimensions from the engine that were the result of loading the default raster font. See GdiEngine::_GetProposedFont().
-bool FontInfoDesired::IsDefaultRasterFont() const noexcept
+bool FontInfoDesired::IsDefaultRasterFont() const
{
// Either the raster was set from the engine...
// OR the face name is empty with a size of 0x0 or 8x12.
diff --git a/src/renderer/base/fontinfo.cpp b/src/renderer/base/fontinfo.cpp
index 55a113b4e19..ef3c37e8cda 100644
--- a/src/renderer/base/fontinfo.cpp
+++ b/src/renderer/base/fontinfo.cpp
@@ -33,12 +33,12 @@ FontInfo::FontInfo(const FontInfo& fiFont) :
{
}
-COORD FontInfo::GetUnscaledSize() const noexcept
+COORD FontInfo::GetUnscaledSize() const
{
return _coordSizeUnscaled;
}
-COORD FontInfo::GetSize() const noexcept
+COORD FontInfo::GetSize() const
{
return _coordSize;
}
@@ -48,7 +48,7 @@ void FontInfo::SetFromEngine(const std::wstring_view faceName,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const COORD coordSize,
- const COORD coordSizeUnscaled) noexcept
+ const COORD coordSizeUnscaled)
{
FontInfoBase::SetFromEngine(faceName,
family,
diff --git a/src/renderer/base/renderer.cpp b/src/renderer/base/renderer.cpp
index 314800c5dea..13a72d4bade 100644
--- a/src/renderer/base/renderer.cpp
+++ b/src/renderer/base/renderer.cpp
@@ -1253,7 +1253,12 @@ std::vector Renderer::_GetSelectionRects() const
const auto lineRendition = buffer.GetLineRendition(rect.Top());
rect = Viewport::FromInclusive(BufferToScreenLine(rect.ToInclusive(), lineRendition));
- auto sr = view.ConvertToOrigin(rect).ToExclusive();
+ auto sr = view.ConvertToOrigin(rect).ToInclusive();
+
+ // hopefully temporary, we should be receiving the right selection sizes without correction.
+ sr.Right++;
+ sr.Bottom++;
+
result.emplace_back(sr);
}
diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp
index 6f17d2cec3e..1bc99e2f580 100644
--- a/src/renderer/dx/DxRenderer.cpp
+++ b/src/renderer/dx/DxRenderer.cpp
@@ -8,6 +8,7 @@
#include "../../interactivity/win32/CustomWindowMessages.h"
#include "../../types/inc/Viewport.hpp"
+#include "../../inc/unicode.hpp"
#include "../../inc/DefaultSettings.h"
#include
@@ -15,12 +16,11 @@
#include "ScreenVertexShader.h"
#include
#include
+#include
using namespace DirectX;
-using namespace Microsoft::Console::Render;
-using namespace Microsoft::Console::Types;
-std::atomic DxEngine::_tracelogCount{ 0 };
+std::atomic Microsoft::Console::Render::DxEngine::_tracelogCount{ 0 };
#pragma warning(suppress : 26477) // We don't control tracelogging macros
TRACELOGGING_DEFINE_PROVIDER(g_hDxRenderProvider,
"Microsoft.Windows.Terminal.Renderer.DirectX",
@@ -49,6 +49,11 @@ D3D11_INPUT_ELEMENT_DESC _shaderInputLayout[] = {
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
+#pragma hdrstop
+
+using namespace Microsoft::Console::Render;
+using namespace Microsoft::Console::Types;
+
// Routine Description:
// - Constructs a DirectX-based renderer for console text
// which primarily uses DirectWrite on a Direct2D surface
diff --git a/src/renderer/inc/FontInfo.hpp b/src/renderer/inc/FontInfo.hpp
index eedf13f7b24..56065881e59 100644
--- a/src/renderer/inc/FontInfo.hpp
+++ b/src/renderer/inc/FontInfo.hpp
@@ -37,15 +37,15 @@ class FontInfo : public FontInfoBase
FontInfo(const FontInfo& fiFont);
- COORD GetSize() const noexcept;
- COORD GetUnscaledSize() const noexcept;
+ COORD GetSize() const;
+ COORD GetUnscaledSize() const;
void SetFromEngine(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const COORD coordSize,
- const COORD coordSizeUnscaled) noexcept;
+ const COORD coordSizeUnscaled);
bool GetFallback() const noexcept;
void SetFallback(const bool didFallback) noexcept;
diff --git a/src/renderer/inc/FontInfoBase.hpp b/src/renderer/inc/FontInfoBase.hpp
index 7d232356753..aa9f3cddbb6 100644
--- a/src/renderer/inc/FontInfoBase.hpp
+++ b/src/renderer/inc/FontInfoBase.hpp
@@ -36,22 +36,22 @@ class FontInfoBase
~FontInfoBase();
- unsigned char GetFamily() const noexcept;
- unsigned int GetWeight() const noexcept;
- const std::wstring& GetFaceName() const noexcept;
- unsigned int GetCodePage() const noexcept;
+ unsigned char GetFamily() const;
+ unsigned int GetWeight() const;
+ const std::wstring_view GetFaceName() const noexcept;
+ unsigned int GetCodePage() const;
- HRESULT FillLegacyNameBuffer(gsl::span buffer) const noexcept;
+ HRESULT FillLegacyNameBuffer(gsl::span buffer) const;
- bool IsTrueTypeFont() const noexcept;
+ bool IsTrueTypeFont() const;
void SetFromEngine(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
- const bool fSetDefaultRasterFont) noexcept;
+ const bool fSetDefaultRasterFont);
- bool WasDefaultRasterSetFromEngine() const noexcept;
- void ValidateFont() noexcept;
+ bool WasDefaultRasterSetFromEngine() const;
+ void ValidateFont();
static Microsoft::Console::Render::IFontDefaultList* s_pFontDefaultList;
static void s_SetFontDefaultList(_In_ Microsoft::Console::Render::IFontDefaultList* const pFontDefaultList);
@@ -59,7 +59,7 @@ class FontInfoBase
friend bool operator==(const FontInfoBase& a, const FontInfoBase& b);
protected:
- bool IsDefaultRasterFontNoSize() const noexcept;
+ bool IsDefaultRasterFontNoSize() const;
private:
std::wstring _faceName;
diff --git a/src/renderer/inc/FontInfoDesired.hpp b/src/renderer/inc/FontInfoDesired.hpp
index 8064f5466ce..a680f18561e 100644
--- a/src/renderer/inc/FontInfoDesired.hpp
+++ b/src/renderer/inc/FontInfoDesired.hpp
@@ -32,8 +32,8 @@ class FontInfoDesired : public FontInfoBase
FontInfoDesired(const FontInfo& fiFont);
- COORD GetEngineSize() const noexcept;
- bool IsDefaultRasterFont() const noexcept;
+ COORD GetEngineSize() const;
+ bool IsDefaultRasterFont() const;
friend bool operator==(const FontInfoDesired& a, const FontInfoDesired& b);