From 98e050de873601b9b2ef1b87243c0660dd9e4994 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Wed, 24 Jun 2020 15:24:18 -0700 Subject: [PATCH] Revert "Skip ... analysis when the ... text is simple (6206)" (#6665) This reverts commit 94eab6e391a099814ce8f9a08c8cccf9f588b7d1. We'll reintroduce this again after making sure it plays nicely with recycling and box drawing glyphs. Fixes #6488 Fixes #6664 (cherry picked from commit 653716fd8d15db105282eb0921135d87c6ff7e87) --- src/renderer/dx/CustomTextLayout.cpp | 91 +++------------------------- src/renderer/dx/CustomTextLayout.h | 7 --- 2 files changed, 9 insertions(+), 89 deletions(-) diff --git a/src/renderer/dx/CustomTextLayout.cpp b/src/renderer/dx/CustomTextLayout.cpp index d19d2d0c338..7593e17d7de 100644 --- a/src/renderer/dx/CustomTextLayout.cpp +++ b/src/renderer/dx/CustomTextLayout.cpp @@ -41,8 +41,7 @@ CustomTextLayout::CustomTextLayout(gsl::not_null const factory _runs{}, _breakpoints{}, _runIndex{ 0 }, - _width{ width }, - _isEntireTextSimple{ false } + _width{ width } { // Fetch the locale name out once now from the format _localeName.resize(gsl::narrow_cast(format->GetLocaleNameLength()) + 1); // +1 for null @@ -77,7 +76,6 @@ CustomTextLayout::CustomTextLayout(gsl::not_null const factory RETURN_HR_IF_NULL(E_INVALIDARG, columns); *columns = 0; - RETURN_IF_FAILED(_AnalyzeTextComplexity()); RETURN_IF_FAILED(_AnalyzeRuns()); RETURN_IF_FAILED(_ShapeGlyphRuns()); @@ -108,7 +106,6 @@ CustomTextLayout::CustomTextLayout(gsl::not_null const factory FLOAT originX, FLOAT originY) noexcept { - RETURN_IF_FAILED(_AnalyzeTextComplexity()); RETURN_IF_FAILED(_AnalyzeRuns()); RETURN_IF_FAILED(_ShapeGlyphRuns()); RETURN_IF_FAILED(_CorrectGlyphRuns()); @@ -122,44 +119,6 @@ CustomTextLayout::CustomTextLayout(gsl::not_null const factory return S_OK; } -// Routine Description: -// - Uses the internal text information and the analyzers/font information from construction -// to determine the complexity of the text. If the text is determined to be entirely simple, -// we'll have more chances to optimize the layout process. -// Arguments: -// - - Uses internal state -// Return Value: -// - S_OK or suitable DirectWrite or STL error code -[[nodiscard]] HRESULT CustomTextLayout::_AnalyzeTextComplexity() noexcept -{ - try - { - const auto textLength = gsl::narrow(_text.size()); - - BOOL isTextSimple = FALSE; - UINT32 uiLengthRead = 0; - - // Start from the beginning. - const UINT32 glyphStart = 0; - - _glyphIndices.resize(textLength); - - const HRESULT hr = _analyzer->GetTextComplexity( - _text.c_str(), - textLength, - _font.Get(), - &isTextSimple, - &uiLengthRead, - &_glyphIndices.at(glyphStart)); - - RETURN_IF_FAILED(hr); - - _isEntireTextSimple = isTextSimple && uiLengthRead == textLength; - } - CATCH_RETURN(); - return S_OK; -} - // Routine Description: // - Uses the internal text information and the analyzers/font information from construction // to determine the complexity of the text inside this layout, compute the subsections (or runs) @@ -190,7 +149,11 @@ CustomTextLayout::CustomTextLayout(gsl::not_null const factory // Allocate enough room to have one breakpoint per code unit. _breakpoints.resize(_text.size()); - if (!_isEntireTextSimple) + BOOL isTextSimple = FALSE; + UINT32 uiLengthRead = 0; + RETURN_IF_FAILED(_analyzer->GetTextComplexity(_text.c_str(), textLength, _font.Get(), &isTextSimple, &uiLengthRead, NULL)); + + if (!(isTextSimple && uiLengthRead == _text.size())) { // Call each of the analyzers in sequence, recording their results. RETURN_IF_FAILED(_analyzer->AnalyzeLineBreakpoints(this, 0, textLength, this)); @@ -311,39 +274,6 @@ CustomTextLayout::CustomTextLayout(gsl::not_null const factory _glyphIndices.resize(totalGlyphsArrayCount); } - if (_isEntireTextSimple) - { - // When the entire text is simple, we can skip GetGlyphs and directly retrieve glyph indices and - // advances(in font design unit). With the help of font metrics, we can calculate the actual glyph - // advances without the need of GetGlyphPlacements. This shortcut will significantly reduce the time - // needed for text analysis. - DWRITE_FONT_METRICS1 metrics; - run.fontFace->GetMetrics(&metrics); - - // With simple text, there's only one run. The actual glyph count is the same as textLength. - _glyphDesignUnitAdvances.resize(textLength); - _glyphAdvances.resize(textLength); - _glyphOffsets.resize(textLength); - - USHORT designUnitsPerEm = metrics.designUnitsPerEm; - - RETURN_IF_FAILED(_font->GetDesignGlyphAdvances( - textLength, - &_glyphIndices.at(glyphStart), - &_glyphDesignUnitAdvances.at(glyphStart), - run.isSideways)); - - for (size_t i = glyphStart; i < _glyphAdvances.size(); i++) - { - _glyphAdvances.at(i) = (float)_glyphDesignUnitAdvances.at(i) / designUnitsPerEm * _format->GetFontSize() * run.fontScale; - } - - run.glyphCount = textLength; - glyphStart += textLength; - - return S_OK; - } - std::vector textProps(textLength); std::vector glyphProps(maxGlyphCount); @@ -441,12 +371,6 @@ CustomTextLayout::CustomTextLayout(gsl::not_null const factory { try { - // For simple text, there is no need to correct runs. - if (_isEntireTextSimple) - { - return S_OK; - } - // Correct each run separately. This is needed whenever script, locale, // or reading direction changes. for (UINT32 runIndex = 0; runIndex < _runs.size(); ++runIndex) @@ -584,6 +508,9 @@ try // We're going to walk through and check for advances that don't match the space that we expect to give out. + DWRITE_FONT_METRICS1 metrics; + run.fontFace->GetMetrics(&metrics); + // Glyph Indices represents the number inside the selected font where the glyph image/paths are found. // Text represents the original text we gave in. // Glyph Clusters represents the map between Text and Glyph Indices. diff --git a/src/renderer/dx/CustomTextLayout.h b/src/renderer/dx/CustomTextLayout.h index f3916419dcc..37097227416 100644 --- a/src/renderer/dx/CustomTextLayout.h +++ b/src/renderer/dx/CustomTextLayout.h @@ -134,7 +134,6 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT STDMETHODCALLTYPE _AnalyzeBoxDrawing(gsl::not_null const source, UINT32 textPosition, UINT32 textLength); [[nodiscard]] HRESULT STDMETHODCALLTYPE _SetBoxEffect(UINT32 textPosition, UINT32 textLength); - [[nodiscard]] HRESULT _AnalyzeTextComplexity() noexcept; [[nodiscard]] HRESULT _AnalyzeRuns() noexcept; [[nodiscard]] HRESULT _ShapeGlyphRuns() noexcept; [[nodiscard]] HRESULT _ShapeGlyphRun(const UINT32 runIndex, UINT32& glyphStart) noexcept; @@ -181,9 +180,6 @@ namespace Microsoft::Console::Render // Glyph shaping results - // Whether the entire text is determined to be simple and does not require full script shaping. - bool _isEntireTextSimple; - std::vector _glyphOffsets; // Clusters are complicated. They're in respect to each individual run. @@ -195,9 +191,6 @@ namespace Microsoft::Console::Render // This appears to be the index of the glyph inside each font. std::vector _glyphIndices; - // This is for calculating glyph advances when the entire text is simple. - std::vector _glyphDesignUnitAdvances; - std::vector _glyphAdvances; struct ScaleCorrection