feat(fonts): add support for :b and :i in guifont (#769)

Close #709.
macos-click-through
smolck 3 years ago committed by GitHub
parent a0d076bbda
commit f99c21d971
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -42,8 +42,16 @@ impl CachingShaper {
let font_key = self let font_key = self
.options .options
.as_ref() .as_ref()
.map(|options| options.fallback_list.first().unwrap().clone().into()) .map(|options| FontKey {
.unwrap_or(FontKey::Default); 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 self.font_loader
.get_or_load(&font_key) .get_or_load(&font_key)
@ -134,21 +142,32 @@ impl CachingShaper {
// Add guifont fallback list // Add guifont fallback list
if let Some(options) = &self.options { if let Some(options) = &self.options {
font_fallback_keys.extend( font_fallback_keys.extend(options.fallback_list.iter().map(|font_name| FontKey {
options italic: options.italic,
.fallback_list bold: options.bold,
.iter() font_selection: font_name.into(),
.map(|font_name| font_name.into()), }));
);
} }
// Add default font // 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 // 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 // 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; let mut best = None;
// Use the cluster.map function to select a viable font from the fallback list // Use the cluster.map function to select a viable font from the fallback list

@ -46,36 +46,45 @@ pub struct FontLoader {
} }
#[derive(Debug, Hash, PartialEq, Eq, Clone)] #[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), Name(String),
Character(char), Character(char),
Default, Default,
LastResort, LastResort,
} }
impl From<&str> for FontKey { impl From<&str> for FontSelection {
fn from(string: &str) -> FontKey { fn from(string: &str) -> FontSelection {
let string = string.to_string(); let string = string.to_string();
FontKey::Name(string) FontSelection::Name(string)
} }
} }
impl From<&String> for FontKey { impl From<&String> for FontSelection {
fn from(string: &String) -> FontKey { fn from(string: &String) -> FontSelection {
let string = string.to_owned(); let string = string.to_owned();
FontKey::Name(string) FontSelection::Name(string)
} }
} }
impl From<String> for FontKey { impl From<String> for FontSelection {
fn from(string: String) -> FontKey { fn from(string: String) -> FontSelection {
FontKey::Name(string) FontSelection::Name(string)
} }
} }
impl From<char> for FontKey { impl From<char> for FontSelection {
fn from(character: char) -> FontKey { fn from(character: char) -> FontSelection {
FontKey::Character(character) FontSelection::Character(character)
} }
} }
@ -89,14 +98,19 @@ impl FontLoader {
} }
fn load(&mut self, font_key: FontKey) -> Option<FontPair> { fn load(&mut self, font_key: FontKey) -> Option<FontPair> {
match font_key { let font_style = match (font_key.bold, font_key.italic) {
FontKey::Name(name) => { (true, true) => FontStyle::bold_italic(),
let font_style = FontStyle::normal(); (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)?; let typeface = self.font_mgr.match_family_style(name, font_style)?;
FontPair::new(Font::from_typeface(typeface, self.font_size)) FontPair::new(Font::from_typeface(typeface, self.font_size))
} }
FontKey::Character(character) => { FontSelection::Character(character) => {
let font_style = FontStyle::normal();
let typeface = self.font_mgr.match_family_style_character( let typeface = self.font_mgr.match_family_style_character(
"", "",
font_style, font_style,
@ -105,13 +119,13 @@ impl FontLoader {
)?; )?;
FontPair::new(Font::from_typeface(typeface, self.font_size)) FontPair::new(Font::from_typeface(typeface, self.font_size))
} }
FontKey::Default => { FontSelection::Default => {
let default_font_data = Asset::get(DEFAULT_FONT).unwrap(); let default_font_data = Asset::get(DEFAULT_FONT).unwrap();
let data = Data::new_copy(&default_font_data); let data = Data::new_copy(&default_font_data);
let typeface = Typeface::from_data(data, 0).unwrap(); let typeface = Typeface::from_data(data, 0).unwrap();
FontPair::new(Font::from_typeface(typeface, self.font_size)) FontPair::new(Font::from_typeface(typeface, self.font_size))
} }
FontKey::LastResort => { FontSelection::LastResort => {
let default_font_data = Asset::get(LAST_RESORT_FONT).unwrap(); let default_font_data = Asset::get(LAST_RESORT_FONT).unwrap();
let data = Data::new_copy(&default_font_data); let data = Data::new_copy(&default_font_data);
let typeface = Typeface::from_data(data, 0).unwrap(); let typeface = Typeface::from_data(data, 0).unwrap();

@ -3,12 +3,16 @@ pub struct FontOptions {
guifont_setting: Option<String>, guifont_setting: Option<String>,
pub fallback_list: Vec<String>, pub fallback_list: Vec<String>,
pub size: f32, pub size: f32,
pub bold: bool,
pub italic: bool,
} }
impl FontOptions { impl FontOptions {
pub fn parse(guifont_setting: &str, default_size: f32) -> Option<FontOptions> { pub fn parse(guifont_setting: &str, default_size: f32) -> Option<FontOptions> {
let mut fallback_list = None; let mut fallback_list = None;
let mut size = default_size; let mut size = default_size;
let mut bold = false;
let mut italic = false;
let mut parts = guifont_setting.split(':').filter(|part| !part.is_empty()); 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::<f32>() { if let Ok(parsed_size) = part[1..].parse::<f32>() {
size = parsed_size size = parsed_size
} }
} else if part == "b" {
bold = true;
} else if part == "i" {
italic = true;
} }
} }
fallback_list.map(|fallback_list| FontOptions { fallback_list.map(|fallback_list| FontOptions {
guifont_setting: Some(guifont_setting.to_string()), guifont_setting: Some(guifont_setting.to_string()),
fallback_list, fallback_list,
bold,
italic,
size, size,
}) })
} }
@ -48,5 +58,7 @@ impl PartialEq for FontOptions {
self.fallback_list == other.fallback_list self.fallback_list == other.fallback_list
&& (self.size - other.size).abs() < std::f32::EPSILON && (self.size - other.size).abs() < std::f32::EPSILON
&& self.bold == other.bold
&& self.italic == other.italic
} }
} }

Loading…
Cancel
Save