Use system fonts as catalog on Desktop App#4035
Use system fonts as catalog on Desktop App#4035Macman1234 wants to merge 5 commits intoGraphiteEditor:masterfrom
Conversation
There was a problem hiding this comment.
Code Review
This pull request adds system font loading for desktop environments using the parley crate. The implementation eagerly loads all system font data and sends it through the message system, which presents significant performance and memory efficiency concerns. Feedback suggests transitioning to lazy loading, avoiding expensive collection clones, and replacing unwrap() calls with safer error handling to prevent application panics. Additionally, the logging level for font discovery should be downgraded from error to debug.
| let mut font_data_vec = Vec::new(); | ||
| font_data_vec.extend(font.load(None).unwrap().data()); | ||
| responses.add(PortfolioMessage::FontLoaded { | ||
| font_family: name.to_owned(), | ||
| font_style: style.to_named_style(), | ||
| data: font_data_vec, | ||
| }); |
There was a problem hiding this comment.
Loading the full data for every system font and sending it through the message system is extremely inefficient. This will cause significant performance degradation and high memory consumption on startup, especially for users with many installed fonts. Font data should be loaded lazily only when a specific font is required for rendering, rather than populating the entire cache upfront.
| // simultaneously?? call font loaded a bunch of times to shove data into font data cache | ||
| let mut system_font_family_names = Vec::new(); | ||
| system_font_family_names.extend(system_font_collection.family_names()); | ||
| log::error!("fonts are: {:?}", system_font_family_names); |
There was a problem hiding this comment.
| log::error!("fonts are: {:?}", system_font_family_names); | ||
| let mut families_for_catalog = Vec::new(); | ||
| for name in system_font_family_names { | ||
| let family = system_font_collection_again.family_by_name(name).unwrap(); |
There was a problem hiding this comment.
Avoid using unwrap() on family_by_name. If a font family name returned by the collection is unexpectedly missing, this will cause the application to panic. It is safer to handle this case gracefully.
| let family = system_font_collection_again.family_by_name(name).unwrap(); | |
| let Some(family) = system_font_collection_again.family_by_name(name) else { continue }; |
| url: "".to_owned(), | ||
| }; | ||
| let mut font_data_vec = Vec::new(); | ||
| font_data_vec.extend(font.load(None).unwrap().data()); |
There was a problem hiding this comment.
| if Editor::environment().is_desktop() { | ||
| let system_font_context = FontContext::new(); // create system font context | ||
| let mut system_font_collection = system_font_context.collection; | ||
| let mut system_font_collection_again = system_font_collection.clone(); // because parley was not made correctly |
There was a problem hiding this comment.
2 issues found across 8 files
Confidence score: 3/5
- There is a concrete user-impacting risk in
editor/src/messages/portfolio/portfolio_message_handler.rs: uncheckedunwrap()calls during system font loading can panic if a system font is corrupted or unreadable. - Font catalog generation in
editor/src/messages/portfolio/portfolio_message_handler.rsruns synchronously in the portfolio message handler, which can block the dispatcher/event loop and lead to UI stalls on systems with large font sets. - Given the medium-to-high severities (6–7/10) and high confidence, this looks mergeable with caution but carries real regression risk unless these paths are hardened.
- Pay close attention to
editor/src/messages/portfolio/portfolio_message_handler.rs- panic handling in font loading and synchronous catalog generation may impact stability and responsiveness.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="editor/src/messages/portfolio/portfolio_message_handler.rs">
<violation number="1" location="editor/src/messages/portfolio/portfolio_message_handler.rs:375">
P2: System font catalog generation is performed synchronously in the portfolio message handler, which can block the dispatcher/event loop and cause UI stalls on machines with large font libraries.</violation>
<violation number="2" location="editor/src/messages/portfolio/portfolio_message_handler.rs:424">
P1: Unchecked `unwrap()` calls in system font loading can panic on corrupted or unreadable system fonts.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| for system_font_style in family.fonts() { | ||
| if (system_font_style.weight().value() as u32 == style.weight) && ((system_font_style.style() == FontStyle::Italic) == style.italic) { | ||
| let mut font_data_vec = Vec::new(); | ||
| font_data_vec.extend(system_font_style.load(None).unwrap().data()); |
There was a problem hiding this comment.
P1: Unchecked unwrap() calls in system font loading can panic on corrupted or unreadable system fonts.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At editor/src/messages/portfolio/portfolio_message_handler.rs, line 424:
<comment>Unchecked `unwrap()` calls in system font loading can panic on corrupted or unreadable system fonts.</comment>
<file context>
@@ -384,7 +413,28 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
+ for system_font_style in family.fonts() {
+ if (system_font_style.weight().value() as u32 == style.weight) && ((system_font_style.style() == FontStyle::Italic) == style.italic) {
+ let mut font_data_vec = Vec::new();
+ font_data_vec.extend(system_font_style.load(None).unwrap().data());
+ responses.add(PortfolioMessage::FontLoaded {
+ font_family: name.clone(),
</file context>
| } | ||
| PortfolioMessage::LoadFontCatalog => { | ||
| if Editor::environment().is_desktop() && preferences.system_fonts { | ||
| self.cached_data.system_font_collection.0 = Collection::new(CollectionOptions { shared: false, system_fonts: true }); |
There was a problem hiding this comment.
P2: System font catalog generation is performed synchronously in the portfolio message handler, which can block the dispatcher/event loop and cause UI stalls on machines with large font libraries.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At editor/src/messages/portfolio/portfolio_message_handler.rs, line 375:
<comment>System font catalog generation is performed synchronously in the portfolio message handler, which can block the dispatcher/event loop and cause UI stalls on machines with large font libraries.</comment>
<file context>
@@ -368,6 +370,33 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
}
+ PortfolioMessage::LoadFontCatalog => {
+ if Editor::environment().is_desktop() && preferences.system_fonts {
+ self.cached_data.system_font_collection.0 = Collection::new(CollectionOptions { shared: false, system_fonts: true });
+ // shove font metadata into cached data catalog
+ let system_font_family_names: Vec<String> = self.cached_data.system_font_collection.0.family_names().map(|n| n.to_owned()).collect();
</file context>
This PR adds functionality to optionally use system fonts instead of remote fonts on the desktop app. A user can switch between remote fonts and system fonts using a checkbox in the experimental section of Preferences.