diff --git a/src/renderer/vt/paint.cpp b/src/renderer/vt/paint.cpp index 0a4fa55817f..cf345211e97 100644 --- a/src/renderer/vt/paint.cpp +++ b/src/renderer/vt/paint.cpp @@ -334,17 +334,17 @@ using namespace Microsoft::Console::Types; { RETURN_IF_FAILED(_MoveCursor(coord)); - std::wstring wstr; - wstr.reserve(clusters.size()); + _bufferLine.clear(); + _bufferLine.reserve(clusters.size()); short totalWidth = 0; for (const auto& cluster : clusters) { - wstr.append(cluster.GetText()); + _bufferLine.append(cluster.GetText()); RETURN_IF_FAILED(ShortAdd(totalWidth, gsl::narrow(cluster.GetColumns()), &totalWidth)); } - RETURN_IF_FAILED(VtEngine::_WriteTerminalAscii(wstr)); + RETURN_IF_FAILED(VtEngine::_WriteTerminalAscii(_bufferLine)); // Update our internal tracker of the cursor's position _lastText.X += totalWidth; @@ -371,21 +371,21 @@ using namespace Microsoft::Console::Types; return S_OK; } - std::wstring unclusteredString; - unclusteredString.reserve(clusters.size()); + _bufferLine.clear(); + _bufferLine.reserve(clusters.size()); short totalWidth = 0; for (const auto& cluster : clusters) { - unclusteredString.append(cluster.GetText()); + _bufferLine.append(cluster.GetText()); RETURN_IF_FAILED(ShortAdd(totalWidth, static_cast(cluster.GetColumns()), &totalWidth)); } - const size_t cchLine = unclusteredString.size(); + const size_t cchLine = _bufferLine.size(); bool foundNonspace = false; size_t lastNonSpace = 0; for (size_t i = 0; i < cchLine; i++) { - if (unclusteredString.at(i) != L'\x20') + if (_bufferLine.at(i) != L'\x20') { lastNonSpace = i; foundNonspace = true; @@ -479,8 +479,7 @@ using namespace Microsoft::Console::Types; RETURN_IF_FAILED(_MoveCursor(coord)); // Write the actual text string - std::wstring wstr = std::wstring(unclusteredString.data(), cchActual); - RETURN_IF_FAILED(VtEngine::_WriteTerminalUtf8(wstr)); + RETURN_IF_FAILED(VtEngine::_WriteTerminalUtf8({ _bufferLine.data(), cchActual })); // GH#4415, GH#5181 // If the renderer told us that this was a wrapped line, then mark diff --git a/src/renderer/vt/state.cpp b/src/renderer/vt/state.cpp index 432779c0df3..05dab05e153 100644 --- a/src/renderer/vt/state.cpp +++ b/src/renderer/vt/state.cpp @@ -49,7 +49,8 @@ VtEngine::VtEngine(_In_ wil::unique_hfile pipe, _newBottomLine{ false }, _deferredCursorPos{ INVALID_COORDS }, _inResizeRequest{ false }, - _trace{} + _trace{}, + _bufferLine{} { #ifndef UNIT_TESTING // When unit testing, we can instantiate a VtEngine without a pipe. diff --git a/src/renderer/vt/vtrenderer.hpp b/src/renderer/vt/vtrenderer.hpp index dd0158c2c4c..0d346229fc1 100644 --- a/src/renderer/vt/vtrenderer.hpp +++ b/src/renderer/vt/vtrenderer.hpp @@ -204,6 +204,9 @@ namespace Microsoft::Console::Render bool _WillWriteSingleChar() const; + // buffer space for these two functions to build their lines + // so they don't have to alloc/free in a tight loop + std::wstring _bufferLine; [[nodiscard]] HRESULT _PaintUtf8BufferLine(std::basic_string_view const clusters, const COORD coord, const bool lineWrapped) noexcept;