Skip to content

Commit

Permalink
Add fontconfig support for font dirs and generic names
Browse files Browse the repository at this point in the history
  • Loading branch information
declantsien committed Aug 31, 2023
1 parent 6d57fbb commit fde5b51
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@ glutin-winit = "0.3.0"
winit = "0.28.6"
raw-window-handle = "0.5.0"

[target.'cfg(all(unix, not(any(target_os = "macos", target_os = "android"))))'.dependencies]
fontconfig-parser = "0.5"

[build-dependencies]
gl_generator = "0.14.0"
81 changes: 81 additions & 0 deletions src/layout/font/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,22 @@ impl FontLibraryBuilder {

/// Builds a library for the current configuration.
pub fn build(&mut self) -> FontLibrary {
#[cfg(all(unix, not(any(target_os = "macos", target_os = "android"))))]
let fontconfig = load_fontconfig();
#[cfg(all(unix, not(any(target_os = "macos", target_os = "android"))))]
{
let home = std::env::var("HOME");
fontconfig.dirs.iter().for_each(|dir| {
if dir.path.starts_with("~") {
if let Ok(ref home) = home {
let path = Path::new(home).join(dir.path.strip_prefix("~").unwrap());
self.add_dir(path);
}
} else {
self.add_dir(dir.clone().path);
};
});
}
let mut index = StaticIndex::default();
core::mem::swap(&mut index, &mut self.inner.index);
for family in index.families.iter_mut() {
Expand All @@ -150,6 +166,38 @@ impl FontLibraryBuilder {
if self.fallbacks {
index.setup_default_fallbacks();
}

#[cfg(all(unix, not(any(target_os = "macos", target_os = "android"))))]
{
use fontconfig_parser::Alias;

if self.generics {
fontconfig.aliases.iter().for_each(
|Alias {
alias,
default,
prefer,
accept,
}| {
let names = [&prefer[..], &accept[..], &default[..]].concat();
let find_family = |families: Vec<String>| {
for family in families {
if let Some(id) = index.base.family_map.get(family.as_str()) {
return Some(*id);
}
}
None
};
if let Some(generic_family) = GenericFamily::parse(alias) {
if let Some(id) = find_family(names.clone()) {
index.generic[generic_family as usize] = Some(id);
};
}
},
)
}
}

FontLibrary::new(index)
}
}
Expand Down Expand Up @@ -474,3 +522,36 @@ impl Scanner {
Some(())
}
}

#[cfg(all(unix, not(any(target_os = "macos", target_os = "android"))))]
fn load_fontconfig() -> fontconfig_parser::FontConfig {
let mut fontconfig = fontconfig_parser::FontConfig::default();
let home = std::env::var("HOME");

if let Ok(ref config_file) = std::env::var("FONTCONFIG_FILE") {
let _ = fontconfig.merge_config(Path::new(config_file));
} else {
let xdg_config_home = if let Ok(val) = std::env::var("XDG_CONFIG_HOME") {
Some(val.into())
} else if let Ok(ref home) = home {
// according to https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
// $XDG_CONFIG_HOME should default to $HOME/.config if not set
Some(Path::new(home).join(".config"))
} else {
None
};

let read_global = match xdg_config_home {
Some(p) => fontconfig
.merge_config(&p.join("fontconfig/fonts.conf"))
.is_err(),
None => true,
};

if read_global {
let _ = fontconfig.merge_config(Path::new("/etc/fonts/local.conf"));
}
let _ = fontconfig.merge_config(Path::new("/etc/fonts/fonts.conf"));
}
fontconfig
}

0 comments on commit fde5b51

Please sign in to comment.