in winrt/lib/text/CanvasTextAnalyzer.cpp [907:1072]
IFACEMETHODIMP CanvasTextAnalyzer::GetGlyphsWithAllOptions(
CanvasCharacterRange characterRange,
ICanvasFontFace* fontFace,
float fontSize,
boolean isSideways,
boolean isRightToLeft,
CanvasAnalyzedScript script,
HSTRING locale,
ICanvasNumberSubstitution* numberSubstitution,
IVectorView<IKeyValuePair<CanvasCharacterRange, CanvasTypography*>*>* typographyRanges,
uint32_t* clusterMapIndexCount,
int** clusterMapIndexElements,
uint32_t* isShapedAloneCount,
boolean** isShapedAloneElements,
uint32_t* glyphShapingCount,
CanvasGlyphShaping** glyphShapingElements,
uint32_t* valueCount,
CanvasGlyph** valueElements)
{
return ExceptionBoundary(
[&]
{
CheckInPointer(fontFace);
CheckAndClearOutPointer(valueElements);
ThrowIfNegative(characterRange.CharacterIndex);
ThrowIfNegative(characterRange.CharacterCount);
wchar_t const* text;
uint32_t textLength;
text = WindowsGetStringRawBuffer(m_text, &textLength);
ThrowIfInvalidCharacterRange(textLength, characterRange);
text += characterRange.CharacterIndex;
textLength = characterRange.CharacterCount;
auto dwriteScriptAnalysis = ToDWriteScriptAnalysis(script);
std::vector<uint16_t> clusterMap;
clusterMap.resize(textLength);
std::vector<DWRITE_SHAPING_TEXT_PROPERTIES> shapingTextProperties;
shapingTextProperties.resize(textLength);
auto dwriteFontFace = As<ICanvasFontFaceInternal>(fontFace)->GetRealizedFontFace();
ComPtr<IDWriteNumberSubstitution> dwriteNumberSubstitution;
if (numberSubstitution)
dwriteNumberSubstitution = GetWrappedResource<IDWriteNumberSubstitution>(numberSubstitution);
uint32_t typographyRangeCount = 0;
DWriteTypographyRangeData dwriteTypographyRangeData;
if (typographyRanges)
{
GetDWriteTypographyRanges(characterRange, typographyRanges, &typographyRangeCount, &dwriteTypographyRangeData);
}
std::vector<DWRITE_TYPOGRAPHIC_FEATURES> featuresPerSpan;
std::vector<uint16_t> glyphIndices;
std::vector<DWRITE_SHAPING_GLYPH_PROPERTIES> shapingGlyphProperties;
uint32_t actualGlyphCount{};
RetryWithIncreasingGlyphCount(
textLength,
[&](uint32_t maxGlyphCount)
{
glyphIndices.resize(maxGlyphCount);
shapingGlyphProperties.resize(maxGlyphCount);
return m_customFontManager->GetTextAnalyzer()->GetGlyphs(
text,
textLength,
dwriteFontFace.Get(),
isSideways,
isRightToLeft,
&dwriteScriptAnalysis,
WindowsGetStringRawBuffer(locale, nullptr),
dwriteNumberSubstitution.Get(),
typographyRanges ? dwriteTypographyRangeData.FeatureDataPointers.data() : nullptr,
typographyRanges ? dwriteTypographyRangeData.FeatureRangeLengths.data() : nullptr,
typographyRangeCount,
maxGlyphCount,
clusterMap.data(),
shapingTextProperties.data(),
glyphIndices.data(),
shapingGlyphProperties.data(),
&actualGlyphCount);
});
std::vector<float> glyphAdvances;
glyphAdvances.resize(actualGlyphCount);
std::vector<DWRITE_GLYPH_OFFSET> glyphOffsets;
glyphOffsets.resize(actualGlyphCount);
ThrowIfFailed(m_customFontManager->GetTextAnalyzer()->GetGlyphPlacements(
text,
clusterMap.data(),
shapingTextProperties.data(),
textLength,
glyphIndices.data(),
shapingGlyphProperties.data(),
actualGlyphCount,
dwriteFontFace.Get(),
fontSize,
isSideways,
isRightToLeft,
&dwriteScriptAnalysis,
WindowsGetStringRawBuffer(locale, nullptr),
typographyRanges ? dwriteTypographyRangeData.FeatureDataPointers.data() : nullptr,
typographyRanges ? dwriteTypographyRangeData.FeatureRangeLengths.data() : nullptr,
typographyRangeCount,
glyphAdvances.data(),
glyphOffsets.data()));
ComArray<CanvasGlyph> glyphs(actualGlyphCount);
for (uint32_t i = 0; i < actualGlyphCount; ++i)
{
glyphs[i].Index = glyphIndices[i];
glyphs[i].Advance = glyphAdvances[i];
glyphs[i].AdvanceOffset = glyphOffsets[i].advanceOffset;
glyphs[i].AscenderOffset = glyphOffsets[i].ascenderOffset;
}
glyphs.Detach(valueCount, valueElements);
if (clusterMapIndexElements)
{
auto clusterMapResult = TransformToComArray<int>(clusterMap.begin(), clusterMap.end(),
[](uint16_t value)
{
return static_cast<int>(value);
});
clusterMapResult.Detach(clusterMapIndexCount, clusterMapIndexElements);
}
if (isShapedAloneElements)
{
auto isShapedAloneResult = TransformToComArray<boolean>(shapingTextProperties.begin(), shapingTextProperties.end(),
[](DWRITE_SHAPING_TEXT_PROPERTIES const& value)
{
return !!value.isShapedAlone;
});
isShapedAloneResult.Detach(isShapedAloneCount, isShapedAloneElements);
}
if (glyphShapingElements)
{
auto glyphShaping = TransformToComArray<CanvasGlyphShaping>(shapingGlyphProperties.begin(), shapingGlyphProperties.begin() + actualGlyphCount,
[](DWRITE_SHAPING_GLYPH_PROPERTIES const& dwriteValue)
{
CanvasGlyphShaping result{};
result.Justification = ToCanvasGlyphJustification(dwriteValue.justification);
result.IsClusterStart = dwriteValue.isClusterStart;
result.IsDiacritic = dwriteValue.isDiacritic;
result.IsZeroWidthSpace = dwriteValue.isZeroWidthSpace;
return result;
});
glyphShaping.Detach(glyphShapingCount, glyphShapingElements);
}
});
}