Add fast lookup path for DxFontInfo (#10521)
Fixes the performance regression caused by DxFontInfo. DxFontInfo introduced in #9201
This commit is contained in:
parent
f152573058
commit
f339705ce7
|
@ -79,30 +79,3 @@ namespace Microsoft::Console::Render
|
|||
bool _didFallback;
|
||||
};
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<Microsoft::Console::Render::DxFontInfo>
|
||||
{
|
||||
size_t operator()(const Microsoft::Console::Render::DxFontInfo& fontInfo) const noexcept
|
||||
{
|
||||
const size_t h1 = std::hash<std::wstring_view>{}(fontInfo.GetFamilyName());
|
||||
const size_t h2 = std::hash<DWRITE_FONT_WEIGHT>{}(fontInfo.GetWeight());
|
||||
const size_t h3 = std::hash<DWRITE_FONT_STYLE>{}(fontInfo.GetStyle());
|
||||
const size_t h4 = std::hash<DWRITE_FONT_STRETCH>{}(fontInfo.GetStretch());
|
||||
const size_t h5 = std::hash<bool>{}(fontInfo.GetFallback());
|
||||
|
||||
static const auto combine = [](std::initializer_list<size_t> list) {
|
||||
size_t seed = 0;
|
||||
for (auto hash : list)
|
||||
{
|
||||
seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
return seed;
|
||||
};
|
||||
|
||||
return combine({ h1, h2, h3, h4, h5 });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -118,14 +118,14 @@ DxFontRenderData::DxFontRenderData(::Microsoft::WRL::ComPtr<IDWriteFactory1> dwr
|
|||
DWRITE_FONT_STYLE style,
|
||||
DWRITE_FONT_STRETCH stretch)
|
||||
{
|
||||
DxFontInfo fontInfo = _defaultFontInfo;
|
||||
fontInfo.SetWeight(weight);
|
||||
fontInfo.SetStyle(style);
|
||||
fontInfo.SetStretch(stretch);
|
||||
|
||||
const auto textFormatIt = _textFormatMap.find(fontInfo);
|
||||
const auto textFormatIt = _textFormatMap.find(_ToMapKey(weight, style, stretch));
|
||||
if (textFormatIt == _textFormatMap.end())
|
||||
{
|
||||
DxFontInfo fontInfo = _defaultFontInfo;
|
||||
fontInfo.SetWeight(weight);
|
||||
fontInfo.SetStyle(style);
|
||||
fontInfo.SetStretch(stretch);
|
||||
|
||||
// Create the font with the fractional pixel height size.
|
||||
// It should have an integer pixel width by our math.
|
||||
// Then below, apply the line spacing to the format to position the floating point pixel height characters
|
||||
|
@ -137,12 +137,12 @@ DxFontRenderData::DxFontRenderData(::Microsoft::WRL::ComPtr<IDWriteFactory1> dwr
|
|||
THROW_IF_FAILED(textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR));
|
||||
THROW_IF_FAILED(textFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP));
|
||||
|
||||
_textFormatMap.insert({ fontInfo, textFormat });
|
||||
_textFormatMap.emplace(_ToMapKey(weight, style, stretch), textFormat);
|
||||
return textFormat;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (*textFormatIt).second;
|
||||
return textFormatIt->second;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,23 +150,23 @@ DxFontRenderData::DxFontRenderData(::Microsoft::WRL::ComPtr<IDWriteFactory1> dwr
|
|||
DWRITE_FONT_STYLE style,
|
||||
DWRITE_FONT_STRETCH stretch)
|
||||
{
|
||||
DxFontInfo fontInfo = _defaultFontInfo;
|
||||
fontInfo.SetWeight(weight);
|
||||
fontInfo.SetStyle(style);
|
||||
fontInfo.SetStretch(stretch);
|
||||
|
||||
const auto fontFaceIt = _fontFaceMap.find(fontInfo);
|
||||
const auto fontFaceIt = _fontFaceMap.find(_ToMapKey(weight, style, stretch));
|
||||
if (fontFaceIt == _fontFaceMap.end())
|
||||
{
|
||||
DxFontInfo fontInfo = _defaultFontInfo;
|
||||
fontInfo.SetWeight(weight);
|
||||
fontInfo.SetStyle(style);
|
||||
fontInfo.SetStretch(stretch);
|
||||
|
||||
std::wstring fontLocaleName = UserLocaleName();
|
||||
Microsoft::WRL::ComPtr<IDWriteFontFace1> fontFace = fontInfo.ResolveFontFaceWithFallback(_dwriteFactory.Get(), fontLocaleName);
|
||||
|
||||
_fontFaceMap.insert({ fontInfo, fontFace });
|
||||
_fontFaceMap.emplace(_ToMapKey(weight, style, stretch), fontFace);
|
||||
return fontFace;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (*fontFaceIt).second;
|
||||
return fontFaceIt->second;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,26 +75,30 @@ namespace Microsoft::Console::Render
|
|||
[[nodiscard]] static HRESULT STDMETHODCALLTYPE s_CalculateBoxEffect(IDWriteTextFormat* format, size_t widthPixels, IDWriteFontFace1* face, float fontScale, IBoxDrawingEffect** effect) noexcept;
|
||||
|
||||
private:
|
||||
using FontAttributeMapKey = uint32_t;
|
||||
|
||||
// We use this to identify font variants with different attributes.
|
||||
static FontAttributeMapKey _ToMapKey(DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch) noexcept
|
||||
{
|
||||
return (weight << 16) | (style << 8) | stretch;
|
||||
};
|
||||
|
||||
void _BuildFontRenderData(const FontInfoDesired& desired, FontInfo& actual, const int dpi);
|
||||
Microsoft::WRL::ComPtr<IDWriteTextFormat> _BuildTextFormat(const DxFontInfo fontInfo, const std::wstring_view localeName);
|
||||
|
||||
::Microsoft::WRL::ComPtr<IDWriteFactory1> _dwriteFactory;
|
||||
|
||||
::Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1> _dwriteTextAnalyzer;
|
||||
|
||||
std::unordered_map<DxFontInfo, ::Microsoft::WRL::ComPtr<IDWriteTextFormat>> _textFormatMap;
|
||||
std::unordered_map<DxFontInfo, ::Microsoft::WRL::ComPtr<IDWriteFontFace1>> _fontFaceMap;
|
||||
std::unordered_map<FontAttributeMapKey, ::Microsoft::WRL::ComPtr<IDWriteTextFormat>> _textFormatMap;
|
||||
std::unordered_map<FontAttributeMapKey, ::Microsoft::WRL::ComPtr<IDWriteFontFace1>> _fontFaceMap;
|
||||
|
||||
::Microsoft::WRL::ComPtr<IBoxDrawingEffect> _boxDrawingEffect;
|
||||
|
||||
::Microsoft::WRL::ComPtr<IDWriteFontFallback> _systemFontFallback;
|
||||
mutable ::Microsoft::WRL::ComPtr<IDWriteFontCollection1> _nearbyCollection;
|
||||
::Microsoft::WRL::ComPtr<IDWriteFactory1> _dwriteFactory;
|
||||
::Microsoft::WRL::ComPtr<IDWriteTextAnalyzer1> _dwriteTextAnalyzer;
|
||||
|
||||
std::wstring _userLocaleName;
|
||||
DxFontInfo _defaultFontInfo;
|
||||
|
||||
float _fontSize;
|
||||
til::size _glyphCell;
|
||||
DWRITE_LINE_SPACING _lineSpacing;
|
||||
LineMetrics _lineMetrics;
|
||||
float _fontSize;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue