diff --git a/contrib/Settings-sample.toml b/contrib/Settings-sample.toml index 61141b5c..793c97cd 100644 --- a/contrib/Settings-sample.toml +++ b/contrib/Settings-sample.toml @@ -26,6 +26,9 @@ time-format = "%H:%M" date-format = "%A, %B %-d, %Y" # Appends the tapped external URLs to this file. external-urls-queue = "bin/article_fetcher/urls.txt" +# UI fonts +font-family-sans = "Inter" +font-family-serif = "Libre Baskerville" # You can create libraries by adding further [[libraries]] entries. [[libraries]] diff --git a/crates/core/src/font/mod.rs b/crates/core/src/font/mod.rs index 45eca13d..1761511e 100644 --- a/crates/core/src/font/mod.rs +++ b/crates/core/src/font/mod.rs @@ -24,6 +24,7 @@ use crate::geom::{Point, Vec2}; use crate::helpers::IsHidden; use crate::framebuffer::Framebuffer; use crate::device::CURRENT_DEVICE; +use crate::settings::{Settings, DEFAULT_UI_FONT_FAMILY_SANS, DEFAULT_UI_FONT_FAMILY_SERIF}; // Font sizes in 1/64th of a point pub const FONT_SIZES: [u32; 3] = [349, 524, 629]; @@ -477,7 +478,7 @@ impl FontFamily { styles.get("Regular") .or_else(|| styles.get("Roman")) .or_else(|| styles.get("Book")) - .ok_or_else(|| format_err!("can't find regular style"))? + .ok_or_else(|| format_err!("can't find regular style for {family_name}"))? }; let italic_path = styles.get("Italic") .or_else(|| styles.get("Book Italic")) @@ -510,21 +511,34 @@ pub struct Fonts { } impl Fonts { - pub fn load() -> Result { + pub fn load(settings: &Settings) -> Result { let opener = FontOpener::new()?; + + // Default to builtin fonts + let mut sans_path = "fonts"; + let mut serif_path = "fonts"; + let mut font_family_sans = DEFAULT_UI_FONT_FAMILY_SANS; + let mut font_family_serif = DEFAULT_UI_FONT_FAMILY_SERIF; + + // Look for fonts in settings path if a custom font is given + if let Some(custom_sans) = &settings.font_family_sans { + sans_path = &settings.reader.font_path; + font_family_sans = custom_sans.as_str() + } + if let Some(custom_serif) = &settings.font_family_serif { + serif_path = &settings.reader.font_path; + font_family_serif = custom_serif.as_str() + } + let mut fonts = Fonts { - sans_serif: FontFamily { - regular: opener.open("fonts/NotoSans-Regular.ttf")?, - italic: opener.open("fonts/NotoSans-Italic.ttf")?, - bold: opener.open("fonts/NotoSans-Bold.ttf")?, - bold_italic: opener.open("fonts/NotoSans-BoldItalic.ttf")?, - }, - serif: FontFamily { - regular: opener.open("fonts/NotoSerif-Regular.ttf")?, - italic: opener.open("fonts/NotoSerif-Italic.ttf")?, - bold: opener.open("fonts/NotoSerif-Bold.ttf")?, - bold_italic: opener.open("fonts/NotoSerif-BoldItalic.ttf")?, - }, + sans_serif: FontFamily::from_name( + font_family_sans, + sans_path, + )?, + serif: FontFamily::from_name( + font_family_serif, + serif_path, + )?, monospace: FontFamily { regular: opener.open("fonts/SourceCodeVariable-Roman.otf")?, italic: opener.open("fonts/SourceCodeVariable-Italic.otf")?, diff --git a/crates/core/src/settings/mod.rs b/crates/core/src/settings/mod.rs index 2cffab5e..f6720f14 100644 --- a/crates/core/src/settings/mod.rs +++ b/crates/core/src/settings/mod.rs @@ -29,6 +29,8 @@ pub const DEFAULT_MARGIN_WIDTH: i32 = 8; pub const DEFAULT_LINE_HEIGHT: f32 = 1.2; // Default font family name. pub const DEFAULT_FONT_FAMILY: &str = "Libertinus Serif"; +pub const DEFAULT_UI_FONT_FAMILY_SANS: &str = "Noto Sans"; +pub const DEFAULT_UI_FONT_FAMILY_SERIF: &str = "Noto Serif"; // Default text alignment. pub const DEFAULT_TEXT_ALIGN: TextAlign = TextAlign::Left; pub const HYPHEN_PENALTY: i32 = 50; @@ -112,6 +114,8 @@ pub struct Settings { pub date_format: String, #[serde(skip_serializing_if = "Option::is_none")] pub external_urls_queue: Option, + pub font_family_sans: Option, + pub font_family_serif: Option, #[serde(skip_serializing_if = "Vec::is_empty")] pub libraries: Vec, pub intermissions: Intermissions, @@ -531,6 +535,8 @@ impl Default for Settings { inverted: false, sleep_cover: true, auto_share: false, + font_family_sans: None, + font_family_serif: None, rotation_lock: None, button_scheme: ButtonScheme::Natural, auto_suspend: 30.0, diff --git a/crates/emulator/src/main.rs b/crates/emulator/src/main.rs index 82a1b9f7..1db16901 100644 --- a/crates/emulator/src/main.rs +++ b/crates/emulator/src/main.rs @@ -61,7 +61,7 @@ pub fn build_context(fb: Box) -> Result { let battery = Box::new(FakeBattery::new()) as Box; let frontlight = Box::new(LightLevels::default()) as Box; let lightsensor = Box::new(0u16) as Box; - let fonts = Fonts::load()?; + let fonts = Fonts::load(&settings)?; Ok(Context::new(fb, None, library, settings, fonts, battery, frontlight, lightsensor)) diff --git a/crates/plato/src/app.rs b/crates/plato/src/app.rs index 980ba81e..bedee316 100644 --- a/crates/plato/src/app.rs +++ b/crates/plato/src/app.rs @@ -106,7 +106,7 @@ fn build_context(fb: Box) -> Result { let library_settings = &settings.libraries[settings.selected_library]; let library = Library::new(&library_settings.path, library_settings.mode)?; - let fonts = Fonts::load().context("can't load fonts")?; + let fonts = Fonts::load(&settings).context("can't load fonts")?; let battery = Box::new(KoboBattery::new().context("can't create battery")?) as Box;