diff --git a/src/buffer/out/TextAttribute.hpp b/src/buffer/out/TextAttribute.hpp index 36fcc6c1d80..38f8aefde4a 100644 --- a/src/buffer/out/TextAttribute.hpp +++ b/src/buffer/out/TextAttribute.hpp @@ -163,6 +163,14 @@ class TextAttribute final return _foreground.IsRgb() || _background.IsRgb(); } + // In certain scenarios, we don't care about specifically the foreground color. + constexpr bool EqualsExceptForeground(const TextAttribute& other) const noexcept + { + return (_wAttrLegacy & META_ATTRS) == (other._wAttrLegacy & META_ATTRS) && + _background == other._background && + _extendedAttrs == other._extendedAttrs; + } + private: COLORREF _GetRgbForeground(std::basic_string_view colorTable, COLORREF defaultColor) const noexcept; diff --git a/src/renderer/base/renderer.cpp b/src/renderer/base/renderer.cpp index ae6a25ab364..e9fe6784e57 100644 --- a/src/renderer/base/renderer.cpp +++ b/src/renderer/base/renderer.cpp @@ -610,6 +610,12 @@ void Renderer::_PaintBufferOutput(_In_ IRenderEngine* const pEngine) } } +static bool _IsAllSpaces(const std::wstring_view v) +{ + // first non-space char is not found (is npos) + return v.find_first_not_of(L" ") == decltype(v)::npos; +} + void Renderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine, TextBufferCellIterator it, const COORD target, @@ -661,8 +667,14 @@ void Renderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine, { if (color != it->TextAttr()) { - color = it->TextAttr(); - break; + auto newAttr{ it->TextAttr() }; + // foreground doesn't matter for runs of spaces (!) + // if we trick it . . . we call Paint far fewer times for cmatrix + if (!_IsAllSpaces(it->Chars()) || !newAttr.EqualsExceptForeground(color)) + { + color = newAttr; + break; // vend this run + } } // Walk through the text data and turn it into rendering clusters.