Fine-grained DWrite text analysis based on text complexity #12568

Open
opened 2026-01-31 03:19:01 +00:00 by claunia · 0 comments
Owner

Originally created by @skyline75489 on GitHub (Feb 14, 2021).

Description of the new feature/enhancement

Inspired by https://github.com/microsoft/cascadia-code/issues/411, certain ASCII characters sometimes break the simplicity of the entire text, depending on the font being used. The current implementation skips dwrite analysis when the entire text is simple:

if (!_isEntireTextSimple)
{
    // Call each of the analyzers in sequence, recording their results.
    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, 0, textLength));
}

With for example Fira Code, in most cases the optimization only applies to lines with 120 spaces, which is not good.

Proposed technical implementation details (optional)

GetTextComplexity can provide a breakdown report of the text, showing which specific range of the text is simple, we should be able to utilize it like this:

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

See #6695 for the introduction of text complexity analysis.

Originally created by @skyline75489 on GitHub (Feb 14, 2021). <!-- 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨 I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING: 1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement. 2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement. 3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number). 4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement. 5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement. All good? Then proceed! --> # Description of the new feature/enhancement Inspired by https://github.com/microsoft/cascadia-code/issues/411, certain ASCII characters sometimes break the simplicity of the entire text, depending on the font being used. The current implementation skips dwrite analysis when the entire text is simple: ```cpp if (!_isEntireTextSimple) { // Call each of the analyzers in sequence, recording their results. 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, 0, textLength)); } ``` With for example `Fira Code`, in most cases the optimization only applies to lines with 120 spaces, which is not good. <!-- A clear and concise description of what the problem is that the new feature would solve. Describe why and how a user would use this new functionality (if applicable). --> # Proposed technical implementation details (optional) `GetTextComplexity` can provide a breakdown report of the text, showing which specific range of the text is simple, we should be able to utilize it like this: ```cpp for (auto range : complexRanges) { // Call each of the analyzers in sequence, recording their results. RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeLineBreakpoints(this, range, this)); RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeBidi(this, range , this)); RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeScript(this, range , this)); RETURN_IF_FAILED(_fontRenderData->Analyzer()->AnalyzeNumberSubstitution(this, range, this)); // Perform our custom font fallback analyzer that mimics the pattern of the real analyzers. RETURN_IF_FAILED(_AnalyzeFontFallback(this, range)); } ``` See #6695 for the introduction of text complexity analysis. <!-- A clear and concise description of what you want to happen. -->
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#12568