Skip to content

Commit

Permalink
Add support for italic and bold text in the software renderer's bitma…
Browse files Browse the repository at this point in the history
…p font path

In the screenshot tests this works by setting SLINT_DEFAULT_FONT to
pointer to a directory, instead of a file. We then load all fonts in
that directory and consider their families the default unless a family
is specified. This way for "Noto Sans" a regular as well as an italic
version is registered in fontdb and returned in the list of font
fallback ids. embed_glyphs in the compiler then embeds those variants
and we find them at run-time.
  • Loading branch information
tronical committed May 31, 2023
1 parent 057493b commit 6b8214c
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 136 deletions.
Binary file added examples/printerdemo/ui/fonts/NotoSans-Italic.ttf
Binary file not shown.
3 changes: 3 additions & 0 deletions examples/printerdemo/ui/fonts/NotoSans-Italic.ttf.license
@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: Google Inc. <https://fonts.google.com/noto/specimen/Noto+Sans/about>

SPDX-License-Identifier: OFL-1.1-RFN
1 change: 1 addition & 0 deletions examples/printerdemo/ui/fonts/convert.sh
Expand Up @@ -13,3 +13,4 @@ cp NotoSans-unhinted/LICENSE_OFL.txt .
for weight in Light Regular Bold; do
pyftsubset NotoSans-unhinted/NotoSans-$weight.ttf --unicodes="U+0020-007F,U+2026" --output-file=NotoSans-$weight.ttf
done
pyftsubset NotoSans-unhinted/NotoSans-Italic.ttf --unicodes="U+0020-007F,U+2026" --output-file=NotoSans-Italic.ttf
2 changes: 2 additions & 0 deletions examples/uefi-demo/demo.slint
Expand Up @@ -6,6 +6,8 @@ import {
StandardButton, StandardListView, TabWidget, VerticalBox
} from "std-widgets.slint";

import "../printerdemo/ui/fonts/NotoSans-Regular.ttf";

export component Demo inherits Window {
in property <string> firmware-vendor;
in property <string> firmware-version;
Expand Down
72 changes: 46 additions & 26 deletions internal/common/sharedfontdb.rs
Expand Up @@ -18,7 +18,9 @@ pub struct FontDatabase {
)))]
pub fontconfig_fallback_families: Vec<String>,
// Default font famiilies to use instead of SansSerif when SLINT_DEFAULT_FONT env var is set.
default_font_families: Vec<String>,
pub default_font_family_ids: Vec<fontdb::ID>,
// Same as default_font_families but reduced to unique family names
default_font_family_names: Vec<String>,
}

impl FontDatabase {
Expand All @@ -33,12 +35,12 @@ impl FontDatabase {
query.families = &single_family;
self.db.query(&query)
} else {
if self.default_font_families.is_empty() {
if self.default_font_family_ids.is_empty() {
query.families = &[fontdb::Family::SansSerif];
self.db.query(&query)
} else {
let family_storage = self
.default_font_families
.default_font_family_names
.iter()
.map(|name| fontdb::Family::Name(name))
.collect::<Vec<_>>();
Expand All @@ -65,29 +67,46 @@ fn init_fontdb() -> FontDatabase {
let mut font_db = fontdb::Database::new();

#[cfg(not(target_arch = "wasm32"))]
let default_font_families = std::env::var_os("SLINT_DEFAULT_FONT").and_then(|maybe_font_path| {
let path = std::path::Path::new(&maybe_font_path);
if path.extension().is_some() {
match font_db.load_font_file(path) {
Ok(()) => {
Some(font_db.faces().flat_map(|face_info| face_info.families.first().map(|(name, _)| name.clone())).collect())
},
Err(err) => {
eprintln!(
"Could not load the font set via `SLINT_DEFAULT_FONT`: {}: {}", path.display(), err,
);
None
},
}
} else {
eprintln!(
"The environment variable `SLINT_DEFAULT_FONT` is set, but its value is not referring to a file",
);
None
}
}).unwrap_or_default();
let (default_font_family_ids, default_font_family_names) =
std::env::var_os("SLINT_DEFAULT_FONT")
.and_then(|maybe_font_path| {
let path = std::path::Path::new(&maybe_font_path);
match if path.extension().is_some() {
font_db.load_font_file(path)
} else {
font_db.load_fonts_dir(path);
Ok(())
} {
Ok(_) => {
let mut family_ids = Vec::new();
let mut family_names = Vec::new();

for face_info in font_db.faces() {
family_ids.push(face_info.id);

let family_name = &face_info.families[0].0;
if let Err(insert_pos) = family_names.binary_search(family_name) {
family_names.insert(insert_pos, family_name.clone());
}
}

Some((family_ids, family_names))
}
Err(err) => {
eprintln!(
"Could not load the font set via `SLINT_DEFAULT_FONT`: {}: {}",
path.display(),
err,
);
None
}
}
})
.unwrap_or_default();

#[cfg(target_arch = "wasm32")]
let default_font_families = Vec::default();
let (default_font_family_ids, default_font_family_names) =
(Default::default(), Default::default());

#[cfg(not(any(
target_family = "windows",
Expand Down Expand Up @@ -136,7 +155,8 @@ fn init_fontdb() -> FontDatabase {
target_arch = "wasm32"
)))]
fontconfig_fallback_families,
default_font_families,
default_font_family_ids,
default_font_family_names,
}
}

Expand Down
2 changes: 2 additions & 0 deletions internal/compiler/embedded_resources.rs
Expand Up @@ -79,6 +79,8 @@ pub struct BitmapFont {
pub ascent: f32,
pub descent: f32,
pub glyphs: Vec<BitmapGlyphs>,
pub weight: u16,
pub italic: bool,
}

#[derive(Debug, Clone)]
Expand Down
6 changes: 4 additions & 2 deletions internal/compiler/generator/rust.rs
Expand Up @@ -228,7 +228,7 @@ pub fn generate(doc: &Document) -> TokenStream {
)
},
#[cfg(feature = "software-renderer")]
crate::embedded_resources::EmbeddedResourcesKind::BitmapFontData(crate::embedded_resources::BitmapFont { family_name, character_map, units_per_em, ascent, descent, glyphs }) => {
crate::embedded_resources::EmbeddedResourcesKind::BitmapFontData(crate::embedded_resources::BitmapFont { family_name, character_map, units_per_em, ascent, descent, glyphs, weight, italic }) => {

let character_map_size = character_map.len();

Expand Down Expand Up @@ -285,7 +285,9 @@ pub fn generate(doc: &Document) -> TokenStream {
#link_section
static GLYPHS : [slint::private_unstable_api::re_exports::BitmapGlyphs; #glyphs_size] = [#(#glyphs),*];
&GLYPHS
})
}),
weight: #weight,
italic: #italic,
};
)
},
Expand Down

0 comments on commit 6b8214c

Please sign in to comment.