From f99c21d971c4cdcafeb71aea3c2e5c1b8300b1e5 Mon Sep 17 00:00:00 2001 From: smolck <46855713+smolck@users.noreply.github.com> Date: Mon, 28 Jun 2021 14:08:35 -0500 Subject: [PATCH] feat(fonts): add support for :b and :i in guifont (#769) Close #709. --- src/renderer/fonts/caching_shaper.rs | 41 +++++++++++++++------ src/renderer/fonts/font_loader.rs | 54 +++++++++++++++++----------- src/renderer/fonts/font_options.rs | 12 +++++++ 3 files changed, 76 insertions(+), 31 deletions(-) diff --git a/src/renderer/fonts/caching_shaper.rs b/src/renderer/fonts/caching_shaper.rs index 12a856f..1b633c0 100644 --- a/src/renderer/fonts/caching_shaper.rs +++ b/src/renderer/fonts/caching_shaper.rs @@ -42,8 +42,16 @@ impl CachingShaper { let font_key = self .options .as_ref() - .map(|options| options.fallback_list.first().unwrap().clone().into()) - .unwrap_or(FontKey::Default); + .map(|options| FontKey { + italic: options.italic, + bold: options.bold, + font_selection: options.fallback_list.first().unwrap().clone().into(), + }) + .unwrap_or(FontKey { + italic: true, + bold: true, + font_selection: FontSelection::Default, + }); self.font_loader .get_or_load(&font_key) @@ -134,21 +142,32 @@ impl CachingShaper { // Add guifont fallback list if let Some(options) = &self.options { - font_fallback_keys.extend( - options - .fallback_list - .iter() - .map(|font_name| font_name.into()), - ); + font_fallback_keys.extend(options.fallback_list.iter().map(|font_name| FontKey { + italic: options.italic, + bold: options.bold, + font_selection: font_name.into(), + })); } // Add default font - font_fallback_keys.push(FontKey::Default); + font_fallback_keys.push(FontKey { + italic: true, + bold: true, + font_selection: FontSelection::Default, + }); // Add skia fallback - font_fallback_keys.push(cluster.chars()[0].ch.into()); + font_fallback_keys.push(FontKey { + italic: true, + bold: true, + font_selection: cluster.chars()[0].ch.into(), + }); // Add last resort - font_fallback_keys.push(FontKey::LastResort); + font_fallback_keys.push(FontKey { + italic: true, + bold: true, + font_selection: FontSelection::LastResort, + }); let mut best = None; // Use the cluster.map function to select a viable font from the fallback list diff --git a/src/renderer/fonts/font_loader.rs b/src/renderer/fonts/font_loader.rs index 7ae0178..49a03bd 100644 --- a/src/renderer/fonts/font_loader.rs +++ b/src/renderer/fonts/font_loader.rs @@ -46,36 +46,45 @@ pub struct FontLoader { } #[derive(Debug, Hash, PartialEq, Eq, Clone)] -pub enum FontKey { +pub struct FontKey { + // TODO(smolck): Could make these private and add constructor method(s)? + // Would theoretically make things safer I guess, but not sure . . . + pub bold: bool, + pub italic: bool, + pub font_selection: FontSelection, +} + +#[derive(Debug, Hash, PartialEq, Eq, Clone)] +pub enum FontSelection { Name(String), Character(char), Default, LastResort, } -impl From<&str> for FontKey { - fn from(string: &str) -> FontKey { +impl From<&str> for FontSelection { + fn from(string: &str) -> FontSelection { let string = string.to_string(); - FontKey::Name(string) + FontSelection::Name(string) } } -impl From<&String> for FontKey { - fn from(string: &String) -> FontKey { +impl From<&String> for FontSelection { + fn from(string: &String) -> FontSelection { let string = string.to_owned(); - FontKey::Name(string) + FontSelection::Name(string) } } -impl From for FontKey { - fn from(string: String) -> FontKey { - FontKey::Name(string) +impl From for FontSelection { + fn from(string: String) -> FontSelection { + FontSelection::Name(string) } } -impl From for FontKey { - fn from(character: char) -> FontKey { - FontKey::Character(character) +impl From for FontSelection { + fn from(character: char) -> FontSelection { + FontSelection::Character(character) } } @@ -89,14 +98,19 @@ impl FontLoader { } fn load(&mut self, font_key: FontKey) -> Option { - match font_key { - FontKey::Name(name) => { - let font_style = FontStyle::normal(); + let font_style = match (font_key.bold, font_key.italic) { + (true, true) => FontStyle::bold_italic(), + (false, true) => FontStyle::italic(), + (true, false) => FontStyle::bold(), + (false, false) => FontStyle::normal(), + }; + + match font_key.font_selection { + FontSelection::Name(name) => { let typeface = self.font_mgr.match_family_style(name, font_style)?; FontPair::new(Font::from_typeface(typeface, self.font_size)) } - FontKey::Character(character) => { - let font_style = FontStyle::normal(); + FontSelection::Character(character) => { let typeface = self.font_mgr.match_family_style_character( "", font_style, @@ -105,13 +119,13 @@ impl FontLoader { )?; FontPair::new(Font::from_typeface(typeface, self.font_size)) } - FontKey::Default => { + FontSelection::Default => { let default_font_data = Asset::get(DEFAULT_FONT).unwrap(); let data = Data::new_copy(&default_font_data); let typeface = Typeface::from_data(data, 0).unwrap(); FontPair::new(Font::from_typeface(typeface, self.font_size)) } - FontKey::LastResort => { + FontSelection::LastResort => { let default_font_data = Asset::get(LAST_RESORT_FONT).unwrap(); let data = Data::new_copy(&default_font_data); let typeface = Typeface::from_data(data, 0).unwrap(); diff --git a/src/renderer/fonts/font_options.rs b/src/renderer/fonts/font_options.rs index ee7689e..d73b079 100644 --- a/src/renderer/fonts/font_options.rs +++ b/src/renderer/fonts/font_options.rs @@ -3,12 +3,16 @@ pub struct FontOptions { guifont_setting: Option, pub fallback_list: Vec, pub size: f32, + pub bold: bool, + pub italic: bool, } impl FontOptions { pub fn parse(guifont_setting: &str, default_size: f32) -> Option { let mut fallback_list = None; let mut size = default_size; + let mut bold = false; + let mut italic = false; let mut parts = guifont_setting.split(':').filter(|part| !part.is_empty()); @@ -29,12 +33,18 @@ impl FontOptions { if let Ok(parsed_size) = part[1..].parse::() { size = parsed_size } + } else if part == "b" { + bold = true; + } else if part == "i" { + italic = true; } } fallback_list.map(|fallback_list| FontOptions { guifont_setting: Some(guifont_setting.to_string()), fallback_list, + bold, + italic, size, }) } @@ -48,5 +58,7 @@ impl PartialEq for FontOptions { self.fallback_list == other.fallback_list && (self.size - other.size).abs() < std::f32::EPSILON + && self.bold == other.bold + && self.italic == other.italic } }