Skip to content

Commit

Permalink
Revert "Initial implementation of fine-grained text analysis (#9202)"
Browse files Browse the repository at this point in the history
This reverts commit 1c414a7.

Fixes #10034.
  • Loading branch information
DHowett committed May 11, 2021
1 parent b132fbe commit 440b626
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 53 deletions.
89 changes: 38 additions & 51 deletions src/renderer/dx/CustomTextLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ CustomTextLayout::CustomTextLayout(gsl::not_null<DxFontRenderData*> const fontRe
_runs{},
_breakpoints{},
_runIndex{ 0 },
_width{ gsl::narrow_cast<size_t>(fontRenderData->GlyphCell().width()) }
_width{ gsl::narrow_cast<size_t>(fontRenderData->GlyphCell().width()) },
_isEntireTextSimple{ false }
{
_localeName.resize(gsl::narrow_cast<size_t>(fontRenderData->DefaultTextFormat()->GetLocaleNameLength()) + 1); // +1 for null
THROW_IF_FAILED(fontRenderData->DefaultTextFormat()->GetLocaleName(_localeName.data(), gsl::narrow<UINT32>(_localeName.size())));
Expand All @@ -45,6 +46,7 @@ try
_runs.clear();
_breakpoints.clear();
_runIndex = 0;
_isEntireTextSimple = false;
_textClusterColumns.clear();
_text.clear();
_glyphScaleCorrections.clear();
Expand Down Expand Up @@ -101,6 +103,7 @@ CATCH_RETURN()
_formatInUse = _fontRenderData->DefaultTextFormat().Get();
_fontInUse = _fontRenderData->DefaultFontFace().Get();

RETURN_IF_FAILED(_AnalyzeTextComplexity());
RETURN_IF_FAILED(_AnalyzeRuns());
RETURN_IF_FAILED(_ShapeGlyphRuns());

Expand Down Expand Up @@ -135,6 +138,7 @@ CATCH_RETURN()
_formatInUse = drawingContext->useItalicFont ? _fontRenderData->ItalicTextFormat().Get() : _fontRenderData->DefaultTextFormat().Get();
_fontInUse = drawingContext->useItalicFont ? _fontRenderData->ItalicFontFace().Get() : _fontRenderData->DefaultFontFace().Get();

RETURN_IF_FAILED(_AnalyzeTextComplexity());
RETURN_IF_FAILED(_AnalyzeRuns());
RETURN_IF_FAILED(_ShapeGlyphRuns());
RETURN_IF_FAILED(_CorrectGlyphRuns());
Expand All @@ -150,9 +154,8 @@ CATCH_RETURN()

// Routine Description:
// - Uses the internal text information and the analyzers/font information from construction
// to determine the complexity of the text. During the process we break the text into initial
// runs based on their complexity. This allows us to further optimize the layout process
// of simple runs.
// 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:
// - <none> - Uses internal state
// Return Value:
Expand All @@ -167,30 +170,21 @@ CATCH_RETURN()
UINT32 uiLengthRead = 0;

// Start from the beginning.
UINT32 pos = 0;
const UINT32 glyphStart = 0;

_glyphIndices.resize(textLength);

while (pos < textLength)
{
const HRESULT hr = _fontRenderData->Analyzer()->GetTextComplexity(
&_text.at(pos),
textLength,
_fontInUse,
&isTextSimple,
&uiLengthRead,
&_glyphIndices.at(pos));

RETURN_IF_FAILED(hr);
_SetCurrentRun(pos);
_SplitCurrentRun(pos);
pos += std::max(uiLengthRead, 1u);
while (uiLengthRead > 0)
{
auto& run = _FetchNextRun(uiLengthRead);
run.isTextSimple = isTextSimple;
}
}
const HRESULT hr = _fontRenderData->Analyzer()->GetTextComplexity(
_text.c_str(),
textLength,
_fontInUse,
&isTextSimple,
&uiLengthRead,
&_glyphIndices.at(glyphStart));

RETURN_IF_FAILED(hr);

_isEntireTextSimple = isTextSimple && uiLengthRead == textLength;
}
CATCH_RETURN();
return S_OK;
Expand Down Expand Up @@ -224,26 +218,15 @@ CATCH_RETURN()
// Allocate enough room to have one breakpoint per code unit.
_breakpoints.resize(_text.size());

RETURN_IF_FAILED(_AnalyzeTextComplexity());

std::vector<std::pair<UINT32, UINT32>> complexRanges;
for (auto& run : _runs)
{
if (!run.isTextSimple)
{
complexRanges.push_back(std::make_pair(run.textStart, run.textLength));
}
}

for (auto& range : complexRanges)
if (!_isEntireTextSimple)
{
// Call each of the analyzers in sequence, recording their results.
RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeLineBreakpoints(this, range.first, range.second, this));
RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeBidi(this, range.first, range.second, this));
RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeScript(this, range.first, range.second, this));
RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeNumberSubstitution(this, range.first, range.second, this));
RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeLineBreakpoints(this, 0, textLength, this));
RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeBidi(this, 0, textLength, this));
RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeScript(this, 0, textLength, this));
RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeNumberSubstitution(this, 0, textLength, this));
// Perform our custom font fallback analyzer that mimics the pattern of the real analyzers.
RETURN_IF_FAILED(_AnalyzeFontFallback(this, range.first, range.second));
RETURN_IF_FAILED(_AnalyzeFontFallback(this, 0, textLength));
}

// Ensure that a font face is attached to every run
Expand Down Expand Up @@ -283,7 +266,6 @@ CATCH_RETURN()
_glyphOffsets.resize(estimatedGlyphCount);
_glyphAdvances.resize(estimatedGlyphCount);
_glyphClusters.resize(textLength);
_glyphDesignUnitAdvances.resize(textLength);

UINT32 glyphStart = 0;

Expand Down Expand Up @@ -357,7 +339,7 @@ CATCH_RETURN()
_glyphIndices.resize(totalGlyphsArrayCount);
}

if (run.isTextSimple)
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
Expand All @@ -366,6 +348,10 @@ CATCH_RETURN()
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);

USHORT designUnitsPerEm = metrics.designUnitsPerEm;

RETURN_IF_FAILED(_fontInUse->GetDesignGlyphAdvances(
Expand All @@ -374,14 +360,14 @@ CATCH_RETURN()
&_glyphDesignUnitAdvances.at(glyphStart),
run.isSideways));

for (UINT32 i = glyphStart; i < glyphStart + textLength; i++)
for (size_t i = glyphStart; i < _glyphAdvances.size(); i++)
{
_glyphAdvances.at(i) = (float)_glyphDesignUnitAdvances.at(i) / designUnitsPerEm * _formatInUse->GetFontSize() * run.fontScale;
}

// Set all the clusters as sequential. In a simple run, we're going 1 to 1.
// Fill the clusters sequentially from 0 to N-1.
std::iota(_glyphClusters.begin() + glyphStart, _glyphClusters.begin() + glyphStart + textLength, gsl::narrow_cast<unsigned short>(0));
std::iota(_glyphClusters.begin(), _glyphClusters.end(), gsl::narrow_cast<unsigned short>(0));

run.glyphCount = textLength;
glyphStart += textLength;
Expand Down Expand Up @@ -486,6 +472,12 @@ CATCH_RETURN()
{
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)
Expand Down Expand Up @@ -625,11 +617,6 @@ try
return S_FALSE; // Nothing to do..
}

if (run.isTextSimple)
{
return S_OK; // No need to correct run.
}

// We're going to walk through and check for advances that don't match the space that we expect to give out.

// Glyph Indices represents the number inside the selected font where the glyph image/paths are found.
Expand Down
6 changes: 4 additions & 2 deletions src/renderer/dx/CustomTextLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ namespace Microsoft::Console::Render
glyphCount(),
bidiLevel(),
script(),
isTextSimple(),
isNumberSubstituted(),
isSideways(),
fontFace{ nullptr },
Expand All @@ -91,7 +90,6 @@ namespace Microsoft::Console::Render
UINT32 glyphCount; // number of glyphs associated with this run of text
DWRITE_SCRIPT_ANALYSIS script;
UINT8 bidiLevel;
bool isTextSimple;
bool isNumberSubstituted;
bool isSideways;
::Microsoft::WRL::ComPtr<IDWriteFontFace1> fontFace;
Expand Down Expand Up @@ -178,6 +176,10 @@ namespace Microsoft::Console::Render
UINT32 _runIndex;

// Glyph shaping results

// Whether the entire text is determined to be simple and does not require full script shaping.
bool _isEntireTextSimple;

std::vector<DWRITE_GLYPH_OFFSET> _glyphOffsets;

// Clusters are complicated. They're in respect to each individual run.
Expand Down

0 comments on commit 440b626

Please sign in to comment.