mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-12 18:41:01 -06:00
* Since `FindFontWithLocalizedName` is broken (intentionally and temporarily until #16943 is fixed) we have to be extra be careful not to return a nullptr `Font`. * Portable builds may not have a broken font cache, but also not have the given font (Cascadia Mono for instance) installed. This requires us to load the nearby fonts even if there aren't any exceptions. ## Validation Steps Performed * Open `src/cascadia/CascadiaResources.build.items` and remove the `Condition` for .ttf files * Deploy on a clean Windows 10 VM * Cascadia Mono loads without issues ✅ * Open the `Settings > Defaults > Appearance`, enter a non-existing font and hit Save * Doesn't crash ✅
This commit is contained in:
parent
3cc82a51d8
commit
9f3dbab7bf
@ -419,6 +419,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
BOOL hasPowerlineCharacters = FALSE;
|
BOOL hasPowerlineCharacters = FALSE;
|
||||||
|
|
||||||
til::iterate_font_families(fontFace, [&](wil::zwstring_view name) {
|
til::iterate_font_families(fontFace, [&](wil::zwstring_view name) {
|
||||||
|
if (primaryFontName.empty())
|
||||||
|
{
|
||||||
|
primaryFontName = name;
|
||||||
|
}
|
||||||
|
|
||||||
std::wstring* accumulator = nullptr;
|
std::wstring* accumulator = nullptr;
|
||||||
|
|
||||||
UINT32 index = 0;
|
UINT32 index = 0;
|
||||||
@ -434,11 +439,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (primaryFontName.empty())
|
|
||||||
{
|
|
||||||
primaryFontName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
wil::com_ptr<IDWriteFontFamily> fontFamily;
|
wil::com_ptr<IDWriteFontFamily> fontFamily;
|
||||||
THROW_IF_FAILED(fontCollection->GetFontFamily(index, fontFamily.addressof()));
|
THROW_IF_FAILED(fontCollection->GetFontFamily(index, fontFamily.addressof()));
|
||||||
|
|
||||||
|
|||||||
@ -187,6 +187,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||||||
UpdateFontList();
|
UpdateFontList();
|
||||||
}
|
}
|
||||||
const auto& currentFontList{ CompleteFontList() };
|
const auto& currentFontList{ CompleteFontList() };
|
||||||
|
fallbackFont = currentFontList.First().Current();
|
||||||
for (const auto& font : currentFontList)
|
for (const auto& font : currentFontList)
|
||||||
{
|
{
|
||||||
if (font.LocalizedName() == name)
|
if (font.LocalizedName() == name)
|
||||||
|
|||||||
@ -482,32 +482,17 @@ void AtlasEngine::SetWarningCallback(std::function<void(HRESULT, wil::zwstring_v
|
|||||||
// commit 9e86c98 (PR #16196), because it showed that it's definitely not due to FindFamilyName() failing.
|
// commit 9e86c98 (PR #16196), because it showed that it's definitely not due to FindFamilyName() failing.
|
||||||
//
|
//
|
||||||
// The workaround is to catch the exception and retry it with our nearby fonts manually loaded in.
|
// The workaround is to catch the exception and retry it with our nearby fonts manually loaded in.
|
||||||
|
HRESULT hr = _updateFont(fontInfoDesired, fontInfo, features, axes);
|
||||||
|
|
||||||
if constexpr (Feature_NearbyFontLoading::IsEnabled())
|
if constexpr (Feature_NearbyFontLoading::IsEnabled())
|
||||||
{
|
{
|
||||||
try
|
if (FAILED(hr) && _updateWithNearbyFontCollection())
|
||||||
{
|
{
|
||||||
_updateFont(fontInfoDesired, fontInfo, features, axes);
|
hr = _updateFont(fontInfoDesired, fontInfo, features, axes);
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
CATCH_LOG();
|
|
||||||
|
|
||||||
// _resolveFontMetrics() checks `_api.s->font->fontCollection` for a pre-existing font collection,
|
|
||||||
// before falling back to using the system font collection. This way we can inject our custom one.
|
|
||||||
// Doing it this way is a bit hacky, but it does have the benefit that we can cache a font collection
|
|
||||||
// instance across font changes, like when zooming the font size rapidly using the scroll wheel.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_api.s.write()->font.write()->fontCollection = FontCache::GetCached();
|
|
||||||
}
|
|
||||||
CATCH_LOG();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
return hr;
|
||||||
{
|
|
||||||
_updateFont(fontInfoDesired, fontInfo, features, axes);
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
CATCH_RETURN();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtlasEngine::UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept
|
void AtlasEngine::UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept
|
||||||
@ -536,7 +521,8 @@ void AtlasEngine::_resolveTransparencySettings() noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtlasEngine::_updateFont(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map<std::wstring_view, uint32_t>& features, const std::unordered_map<std::wstring_view, float>& axes)
|
[[nodiscard]] HRESULT AtlasEngine::_updateFont(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map<std::wstring_view, uint32_t>& features, const std::unordered_map<std::wstring_view, float>& axes) noexcept
|
||||||
|
try
|
||||||
{
|
{
|
||||||
std::vector<DWRITE_FONT_FEATURE> fontFeatures;
|
std::vector<DWRITE_FONT_FEATURE> fontFeatures;
|
||||||
if (!features.empty())
|
if (!features.empty())
|
||||||
@ -616,9 +602,12 @@ void AtlasEngine::_updateFont(const FontInfoDesired& fontInfoDesired, FontInfo&
|
|||||||
_resolveFontMetrics(fontInfoDesired, fontInfo, font);
|
_resolveFontMetrics(fontInfoDesired, fontInfo, font);
|
||||||
font->fontFeatures = std::move(fontFeatures);
|
font->fontFeatures = std::move(fontFeatures);
|
||||||
font->fontAxisValues = std::move(fontAxisValues);
|
font->fontAxisValues = std::move(fontAxisValues);
|
||||||
}
|
|
||||||
|
|
||||||
void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics) const
|
return S_OK;
|
||||||
|
}
|
||||||
|
CATCH_RETURN()
|
||||||
|
|
||||||
|
void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics)
|
||||||
{
|
{
|
||||||
const auto& faceName = fontInfoDesired.GetFaceName();
|
const auto& faceName = fontInfoDesired.GetFaceName();
|
||||||
const auto requestedFamily = fontInfoDesired.GetFamily();
|
const auto requestedFamily = fontInfoDesired.GetFamily();
|
||||||
@ -659,6 +648,16 @@ void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, Fo
|
|||||||
BOOL exists = false;
|
BOOL exists = false;
|
||||||
THROW_IF_FAILED(fontCollection->FindFamilyName(fontName.c_str(), &index, &exists));
|
THROW_IF_FAILED(fontCollection->FindFamilyName(fontName.c_str(), &index, &exists));
|
||||||
|
|
||||||
|
// In case of a portable build, the given font may not be installed and instead be bundled next to our executable.
|
||||||
|
if constexpr (Feature_NearbyFontLoading::IsEnabled())
|
||||||
|
{
|
||||||
|
if (!exists && _updateWithNearbyFontCollection())
|
||||||
|
{
|
||||||
|
fontCollection = _api.s->font->fontCollection;
|
||||||
|
THROW_IF_FAILED(fontCollection->FindFamilyName(fontName.c_str(), &index, &exists));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!exists)
|
if (!exists)
|
||||||
{
|
{
|
||||||
if (!missingFontNames.empty())
|
if (!missingFontNames.empty())
|
||||||
@ -869,3 +868,29 @@ void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, Fo
|
|||||||
fontMetrics->colorGlyphs = fontInfoDesired.GetEnableColorGlyphs();
|
fontMetrics->colorGlyphs = fontInfoDesired.GetEnableColorGlyphs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nearby fonts are described a couple of times throughout the file.
|
||||||
|
// This abstraction in particular helps us avoid retrying when it's pointless:
|
||||||
|
// After all, if the font collection didn't change (no nearby fonts, loading failed, it's already loaded),
|
||||||
|
// we don't need to try it again. It returns true if retrying is necessary.
|
||||||
|
[[nodiscard]] bool AtlasEngine::_updateWithNearbyFontCollection() noexcept
|
||||||
|
{
|
||||||
|
// _resolveFontMetrics() checks `_api.s->font->fontCollection` for a pre-existing font collection,
|
||||||
|
// before falling back to using the system font collection. This way we can inject our custom one.
|
||||||
|
// Doing it this way is a bit hacky, but it does have the benefit that we can cache a font collection
|
||||||
|
// instance across font changes, like when zooming the font size rapidly using the scroll wheel.
|
||||||
|
wil::com_ptr<IDWriteFontCollection> collection;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
collection = FontCache::GetCached();
|
||||||
|
}
|
||||||
|
CATCH_LOG();
|
||||||
|
|
||||||
|
if (!collection || _api.s->font->fontCollection == collection)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_api.s.write()->font.write()->fontCollection = std::move(collection);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@ -94,8 +94,9 @@ namespace Microsoft::Console::Render::Atlas
|
|||||||
|
|
||||||
// AtlasEngine.api.cpp
|
// AtlasEngine.api.cpp
|
||||||
void _resolveTransparencySettings() noexcept;
|
void _resolveTransparencySettings() noexcept;
|
||||||
void _updateFont(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map<std::wstring_view, uint32_t>& features, const std::unordered_map<std::wstring_view, float>& axes);
|
[[nodiscard]] HRESULT _updateFont(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map<std::wstring_view, uint32_t>& features, const std::unordered_map<std::wstring_view, float>& axes) noexcept;
|
||||||
void _resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics = nullptr) const;
|
void _resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics = nullptr);
|
||||||
|
[[nodiscard]] bool _updateWithNearbyFontCollection() noexcept;
|
||||||
|
|
||||||
// AtlasEngine.r.cpp
|
// AtlasEngine.r.cpp
|
||||||
ATLAS_ATTR_COLD void _recreateAdapter();
|
ATLAS_ATTR_COLD void _recreateAdapter();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user