Add fast lookup path for DxFontInfo (#10521)

Fixes the performance regression caused by DxFontInfo.

DxFontInfo introduced in #9201
This commit is contained in:
Chester Liu 2021-07-10 04:19:20 +08:00 committed by GitHub
parent f152573058
commit f339705ce7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 53 deletions

View file

@ -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 });
}
};
}

View file

@ -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;
}
}

View file

@ -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;
};
}