mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-29 13:03:27 +03:00
Try to load fallback fonts instead of panicking when a font is not found (#3891)
This PR adjusts our font resolution code to attempt to use a fallback font if the specified font cannot be found. Right now our fallback font stack is `Zed Mono`, followed by `Helvetica` (in practice we should always be able to resolve `Zed Mono` since we bundle it with the app). In the future we'll want to surface the ability to set the fallback font stack from GPUI consumers, and potentially even support specifying font stacks in the user settings (as opposed to a single font family). Release Notes: - Fixed a panic when trying to load a font that could not be found.
This commit is contained in:
parent
3d1023ef52
commit
e4aa7ba4f2
@ -9565,7 +9565,7 @@ impl InputHandler for Editor {
|
||||
) -> Option<gpui::Bounds<Pixels>> {
|
||||
let text_layout_details = self.text_layout_details(cx);
|
||||
let style = &text_layout_details.editor_style;
|
||||
let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
|
||||
let font_id = cx.text_system().resolve_font(&style.text.font());
|
||||
let font_size = style.text.font_size.to_pixels(cx.rem_size());
|
||||
let line_height = style.text.line_height_in_pixels(cx.rem_size());
|
||||
let em_width = cx
|
||||
|
@ -1775,7 +1775,7 @@ impl EditorElement {
|
||||
let snapshot = editor.snapshot(cx);
|
||||
let style = self.style.clone();
|
||||
|
||||
let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
|
||||
let font_id = cx.text_system().resolve_font(&style.text.font());
|
||||
let font_size = style.text.font_size.to_pixels(cx.rem_size());
|
||||
let line_height = style.text.line_height_in_pixels(cx.rem_size());
|
||||
let em_width = cx
|
||||
@ -3782,7 +3782,7 @@ fn compute_auto_height_layout(
|
||||
}
|
||||
|
||||
let style = editor.style.as_ref().unwrap();
|
||||
let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
|
||||
let font_id = cx.text_system().resolve_font(&style.text.font());
|
||||
let font_size = style.text.font_size.to_pixels(cx.rem_size());
|
||||
let line_height = style.text.line_height_in_pixels(cx.rem_size());
|
||||
let em_width = cx
|
||||
|
@ -15,8 +15,9 @@ use crate::{
|
||||
use anyhow::anyhow;
|
||||
use collections::FxHashMap;
|
||||
use core::fmt;
|
||||
use itertools::Itertools;
|
||||
use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard};
|
||||
use smallvec::SmallVec;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::{
|
||||
cmp,
|
||||
fmt::{Debug, Display, Formatter},
|
||||
@ -42,6 +43,7 @@ pub struct TextSystem {
|
||||
raster_bounds: RwLock<FxHashMap<RenderGlyphParams, Bounds<DevicePixels>>>,
|
||||
wrapper_pool: Mutex<FxHashMap<FontIdWithSize, Vec<LineWrapper>>>,
|
||||
font_runs_pool: Mutex<Vec<Vec<FontRun>>>,
|
||||
fallback_font_stack: SmallVec<[Font; 2]>,
|
||||
}
|
||||
|
||||
impl TextSystem {
|
||||
@ -54,6 +56,12 @@ impl TextSystem {
|
||||
font_ids_by_font: RwLock::default(),
|
||||
wrapper_pool: Mutex::default(),
|
||||
font_runs_pool: Mutex::default(),
|
||||
fallback_font_stack: smallvec![
|
||||
// TODO: This is currently Zed-specific.
|
||||
// We should allow GPUI users to provide their own fallback font stack.
|
||||
font("Zed Mono"),
|
||||
font("Helvetica")
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,6 +80,33 @@ impl TextSystem {
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolves the specified font, falling back to the default font stack if
|
||||
/// the font fails to load.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the font and none of the fallbacks can be resolved.
|
||||
pub fn resolve_font(&self, font: &Font) -> FontId {
|
||||
if let Ok(font_id) = self.font_id(font) {
|
||||
return font_id;
|
||||
}
|
||||
|
||||
for fallback in &self.fallback_font_stack {
|
||||
if let Ok(font_id) = self.font_id(fallback) {
|
||||
return font_id;
|
||||
}
|
||||
}
|
||||
|
||||
panic!(
|
||||
"failed to resolve font '{}' or any of the fallbacks: {}",
|
||||
font.family,
|
||||
self.fallback_font_stack
|
||||
.iter()
|
||||
.map(|fallback| &fallback.family)
|
||||
.join(", ")
|
||||
);
|
||||
}
|
||||
|
||||
pub fn bounding_box(&self, font_id: FontId, font_size: Pixels) -> Bounds<Pixels> {
|
||||
self.read_metrics(font_id, |metrics| metrics.bounding_box(font_size))
|
||||
}
|
||||
@ -159,7 +194,7 @@ impl TextSystem {
|
||||
) -> Result<Arc<LineLayout>> {
|
||||
let mut font_runs = self.font_runs_pool.lock().pop().unwrap_or_default();
|
||||
for run in runs.iter() {
|
||||
let font_id = self.font_id(&run.font)?;
|
||||
let font_id = self.resolve_font(&run.font);
|
||||
if let Some(last_run) = font_runs.last_mut() {
|
||||
if last_run.font_id == font_id {
|
||||
last_run.len += run.len;
|
||||
|
@ -421,7 +421,7 @@ impl TerminalElement {
|
||||
let rem_size = cx.rem_size();
|
||||
let font_pixels = text_style.font_size.to_pixels(rem_size);
|
||||
let line_height = font_pixels * line_height.to_pixels(rem_size);
|
||||
let font_id = cx.text_system().font_id(&text_style.font()).unwrap();
|
||||
let font_id = cx.text_system().resolve_font(&text_style.font());
|
||||
|
||||
// todo!(do we need to keep this unwrap?)
|
||||
let cell_width = text_system
|
||||
|
Loading…
Reference in New Issue
Block a user