Repository navigation
feat(theme): add a switch to use the system's UI font - #1362
Merged
Merged
Conversation
Theme -> "Use the system font" puts the system's own UI fonts ahead of the embedded Noto chain: Segoe UI Variable / Segoe UI with Nirmala UI, Leelawadee UI and the UI language's CJK font on Windows, San Francisco and its script fonts on macOS, fontconfig's default sans-serif on Linux. The embedded chain stays whole behind them, so it still draws any script the system fonts lack. The system fonts are named through a new fonts:System collection that matches a letter only in the family asked for. Avalonia's own system collection hands any letter to the platform fallback, which on Windows answers Yu Gothic UI for Han whatever the family, so a plain chain drew every language's Han in Japanese shapes. With the wrapper, Han keeps the UI language's font (#1121). Annotate's labels follow the same chain, as the text box they are typed in does. The setting is off by default and needs no schema step. Refs #1065 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GitHub's Windows Server images have a Segoe UI without Arabic, so the system-font chain rightly drew م in the embedded Noto Sans Arabic there and the test, which named Segoe UI, failed. The test now asks each system font in the chain, face by face at the weight drawn, whether it has the letter, and expects the first that does, else the embedded font. Han must still land in a font of the UI language's region. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Avalonia's font manager (12.1.4, FontManager.TryMatchCharacter) passes over a match whose family is named like its default font unless that family ends the chain, taking it for a collection's "nothing found" answer. On Windows the default is Segoe UI, so a letter Segoe UI Variable lacks, Arabic above all, skipped Segoe UI for the embedded Noto Sans Arabic. That is what CI's Windows jobs saw: the glyph check found م in Segoe UI, the chain gave Noto. SystemUiFontCollection only answers for the family asked for, so its answer for the default font is a real one: it now returns that family under an alias only it reads back. A test builds a chain with the default font in the middle and checks it is taken. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What users notice
Settings → Theme has a new switch, Use the system font. When it's on, Filee draws its UI in the font the system uses, like other apps: Segoe UI Variable on Windows 11 (Segoe UI on Windows 10), San Francisco on macOS, fontconfig's default sans-serif on Linux. The switch applies right away. Filee's built-in Noto fonts stay behind the system fonts and still draw any script those lack. Han still follows the interface language (#1121): on Windows, a Japanese UI draws it in Yu Gothic UI, a Korean or English one in Malgun Gothic, Simplified Chinese in Microsoft YaHei and Traditional Chinese in Microsoft JhengHei. The switch is off by default, so nothing changes for anyone who doesn't turn it on.
What changed
src/Filee.Core/Settings/AppSettings.cs: addsThemeSettings.UseSystemFont, false by default. Settings saved before it existed read it as false, so no schema step is needed.src/Filee.App/Services/SoftPalette.cs:FontFamilies(language, systemFont). With the switch on, the platform's UI fonts go first, followed by the embedded chain, which stays unchanged. Only fonts without Han go ahead of the CJK fonts. On Linux, a fontconfig default that has Han is left out, so a CJK default can't give every language its Han shapes.src/Filee.App/SystemUiFontCollection.cs(new, registered inProgram.csand the test app): the system fonts underfonts:System#…, which match a letter only in the family asked for. This is needed because Avalonia's own system collection doesn't look in the requested family. It hands the letter to the platform's fallback, and on Windows that returns Yu Gothic UI for Han whatever family or language is asked. I checked it:"Segoe UI, Malgun Gothic"and even"Malgun Gothic"alone matched 直 in Yu Gothic UI. Without the wrapper, every language would draw Han in Japanese shapes.FileeFontCollectiondoes the same for the embedded fonts ([Bug]: zh-CN UI renders some Han characters with Japanese/Korean glyph forms (bundled Noto Sans SC not used) #1095).ThemeService/AnnotationFonts: pass the switch through. Annotate's labels follow the same chain, because the text box they're typed in uses the UI font.ThemePage.axaml+ThemePageViewModel: the switch and its hint, in a card before "Reduce animations".theme.system_fontandtheme.system_font_hintin all 22 languages.docs/ARCHITECTURE.md: a short note on the font chain and whyfonts:Systemexists.Tests
SystemFontTests(App): for every language, the embedded chain is the unchanged tail of the system chain. The first Han font is still the UI language's, for ja, ko, zh-CN, zh-TW, en and ar. On Windows, real lookups for A, م, न, ก and 直 at regular and semibold weight expect the first system font in the chain whose face has the letter, or the embedded font when none does, never the platform fallback. Each machine is asked for its own fonts: on the GitHub Windows Server images Segoe UI has no Arabic, so م correctly lands in Noto Sans Arabic there. Han must also land in a font of the UI language's region. The collection only matches the family it's asked for. The page switch saves and swapsAppFontFamilylive.SystemFontSettingsTests(Core): off for new settings and for settings saved before this change, and kept once switched on.SystemFontTests,LocalizationTests,LocalizationResourceTests,FileeFontCollectionTests,ThemePageTests,MaterialYouThemeTests: all pass. In the fullFilee.App.Testssuite, 2266 passed, 33 were skipped and 2 failed, neither because of this change.RenderTests.Engines_page_shows_versions_descriptions_and_download_speedfails on this PC because it has its own Tesseract in Program Files, and an installed copy shows no version by design.DonutHighlightTests.A_lost_animation_frame_does_not_keep_the_slice_darkis a timing check that failed while the machine was busy; it passes when run on its own.dotnet format --verify-no-changesis clean on all four touched projects, andFilee.Setupstill builds (it linksSoftPalette).Not covered
.AppleSystemUIFont, thenSF Pro TextandSF Pro. Whether Skia on macOS resolves the hidden system name needs a real Mac. If it doesn't, the chain falls through to the embedded fonts as before.SoftPalette.SystemFontFamilies) uses plain system names. By the lookup above, it probably draws Han in Yu Gothic UI in every language.Closes #1065
🤖 Generated with Claude Code