Skip to content

Commit

Permalink
AtlasEngine: Fix support for combining diacritics (#12307)
Browse files Browse the repository at this point in the history
`IDWriteTextAnalyzer::GetGlyphs` is not enough to get a
`DWRITE_SHAPING_TEXT_PROPERTIES::canBreakShapingAfter`
value that works for combining diacritical marks.
This requires an additional call to `GetGlyphPlacements`.
This commit increases CPU usage for complex text by ~10%.

## PR Checklist
* [x] Closes #11925
* [x] I work here
* [x] Tests added/passed

## Validation Steps Performed
* ``echo "[e`u{0301}`u{0301}]"`` prints an "e" with 2 accents ✅
  • Loading branch information
lhecker authored Feb 1, 2022
1 parent 27de97b commit 93be688
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/renderer/atlas/AtlasEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,8 @@ void AtlasEngine::_recreateSizeDependentResources()
_api.textProps = Buffer<DWRITE_SHAPING_TEXT_PROPERTIES>{ projectedTextSize };
_api.glyphIndices = Buffer<u16>{ projectedGlyphSize };
_api.glyphProps = Buffer<DWRITE_SHAPING_GLYPH_PROPERTIES>{ projectedGlyphSize };
_api.glyphAdvances = Buffer<f32>{ projectedGlyphSize };
_api.glyphOffsets = Buffer<DWRITE_GLYPH_OFFSET>{ projectedGlyphSize };

D3D11_BUFFER_DESC desc;
desc.ByteWidth = gsl::narrow<u32>(totalCellCount * sizeof(Cell)); // totalCellCount can theoretically be UINT32_MAX!
Expand Down Expand Up @@ -1370,6 +1372,37 @@ void AtlasEngine::_flushBufferLine()
break;
}

if (_api.glyphAdvances.size() < actualGlyphCount)
{
// Grow the buffer by at least 1.5x and at least of `actualGlyphCount` items.
// The 1.5x growth ensures we don't reallocate every time we need 1 more slot.
auto size = _api.glyphAdvances.size();
size = size + (size >> 1);
size = std::max<size_t>(size, actualGlyphCount);
_api.glyphAdvances = Buffer<f32>{ size };
_api.glyphOffsets = Buffer<DWRITE_GLYPH_OFFSET>{ size };
}

THROW_IF_FAILED(_sr.textAnalyzer->GetGlyphPlacements(
/* textString */ _api.bufferLine.data() + a.textPosition,
/* clusterMap */ _api.clusterMap.data(),
/* textProps */ _api.textProps.data(),
/* textLength */ a.textLength,
/* glyphIndices */ _api.glyphIndices.data(),
/* glyphProps */ _api.glyphProps.data(),
/* glyphCount */ actualGlyphCount,
/* fontFace */ mappedFontFace.get(),
/* fontEmSize */ _api.fontMetrics.fontSizeInDIP,
/* isSideways */ false,
/* isRightToLeft */ a.bidiLevel & 1,
/* scriptAnalysis */ &scriptAnalysis,
/* localeName */ nullptr,
/* features */ &features,
/* featureRangeLengths */ &featureRangeLengths,
/* featureRanges */ featureRanges,
/* glyphAdvances */ _api.glyphAdvances.data(),
/* glyphOffsets */ _api.glyphOffsets.data()));

_api.textProps[a.textLength - 1].canBreakShapingAfter = 1;

size_t beg = 0;
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/atlas/AtlasEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,8 @@ namespace Microsoft::Console::Render
Buffer<DWRITE_SHAPING_TEXT_PROPERTIES> textProps;
Buffer<u16> glyphIndices;
Buffer<DWRITE_SHAPING_GLYPH_PROPERTIES> glyphProps;
Buffer<f32> glyphAdvances;
Buffer<DWRITE_GLYPH_OFFSET> glyphOffsets;
std::vector<DWRITE_FONT_FEATURE> fontFeatures; // changes are flagged as ApiInvalidations::Font|Size
std::vector<DWRITE_FONT_AXIS_VALUE> fontAxisValues; // changes are flagged as ApiInvalidations::Font|Size
FontMetrics fontMetrics; // changes are flagged as ApiInvalidations::Font|Size
Expand Down

0 comments on commit 93be688

Please sign in to comment.