Skip to content

Commit

Permalink
Fix bugs introduced in #16821 (custom font fallback)
Browse files Browse the repository at this point in the history
  • Loading branch information
lhecker committed Apr 1, 2024
1 parent 3cc82a5 commit a74d6b5
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 29 deletions.
10 changes: 5 additions & 5 deletions src/cascadia/TerminalSettingsEditor/Appearances.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
BOOL hasPowerlineCharacters = FALSE;

til::iterate_font_families(fontFace, [&](wil::zwstring_view name) {
if (primaryFontName.empty())
{
primaryFontName = name;
}

std::wstring* accumulator = nullptr;

UINT32 index = 0;
Expand All @@ -434,11 +439,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
break;
}

if (primaryFontName.empty())
{
primaryFontName = name;
}

wil::com_ptr<IDWriteFontFamily> fontFamily;
THROW_IF_FAILED(fontCollection->GetFontFamily(index, fontFamily.addressof()));

Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsEditor/ProfileViewModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
UpdateFontList();
}
const auto& currentFontList{ CompleteFontList() };
fallbackFont = currentFontList.First().Current();
for (const auto& font : currentFontList)
{
if (font.LocalizedName() == name)
Expand Down
65 changes: 43 additions & 22 deletions src/renderer/atlas/AtlasEngine.api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//
// 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())
{
try
{
_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
if (FAILED(hr) && _updateWithNearbyFontCollection())
{
_api.s.write()->font.write()->fontCollection = FontCache::GetCached();
hr = _updateFont(fontInfoDesired, fontInfo, features, axes);
}
CATCH_LOG();
}

try
{
_updateFont(fontInfoDesired, fontInfo, features, axes);
return S_OK;
}
CATCH_RETURN();
return hr;
}

void AtlasEngine::UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept
Expand Down Expand Up @@ -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;
if (!features.empty())
Expand Down Expand Up @@ -616,9 +602,12 @@ void AtlasEngine::_updateFont(const FontInfoDesired& fontInfoDesired, FontInfo&
_resolveFontMetrics(fontInfoDesired, fontInfo, font);
font->fontFeatures = std::move(fontFeatures);
font->fontAxisValues = std::move(fontAxisValues);

return S_OK;
}
CATCH_RETURN()

void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics) const
void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics)
{
const auto& faceName = fontInfoDesired.GetFaceName();
const auto requestedFamily = fontInfoDesired.GetFamily();
Expand Down Expand Up @@ -659,6 +648,16 @@ void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, Fo
BOOL exists = false;
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 (!missingFontNames.empty())
Expand Down Expand Up @@ -869,3 +868,25 @@ void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, Fo
fontMetrics->colorGlyphs = fontInfoDesired.GetEnableColorGlyphs();
}
}

bool AtlasEngine::_updateWithNearbyFontCollection()
{
// _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;
}
5 changes: 3 additions & 2 deletions src/renderer/atlas/AtlasEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ namespace Microsoft::Console::Render::Atlas

// AtlasEngine.api.cpp
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);
void _resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics = nullptr) const;
[[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);
bool _updateWithNearbyFontCollection();

// AtlasEngine.r.cpp
ATLAS_ATTR_COLD void _recreateAdapter();
Expand Down

0 comments on commit a74d6b5

Please sign in to comment.