Skip to content

Commit c849fed

Browse files
committed
feat: working system fonts
1 parent 4ffb740 commit c849fed

File tree

3 files changed

+112
-14
lines changed

3 files changed

+112
-14
lines changed

crates/bevy_text/src/font.rs

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,76 @@ use bevy_reflect::TypePath;
1616
///
1717
/// Bevy currently loads a single font face as a single `Font` asset.
1818
#[derive(Debug, TypePath, Clone, Asset)]
19-
pub struct Font {
19+
pub enum Font {
2020
/// Content of a font file as bytes
21-
pub data: Arc<Vec<u8>>,
21+
Data(Arc<Vec<u8>>),
22+
/// Reference a system font by its name
23+
System {
24+
/// A list of font families that satisfy this font requirement
25+
families: Vec<Family>,
26+
/// Specifies the weight of glyphs in the font, their degree of blackness or stroke thickness.
27+
///
28+
/// See [`cosmic_text::Weight`] for details.
29+
weight: cosmic_text::Weight,
30+
/// A face [width](https://docs.microsoft.com/en-us/typography/opentype/spec/os2#uswidthclass).
31+
///
32+
/// See [`cosmic_text::Stretch`] for details.
33+
stretch: cosmic_text::Stretch,
34+
/// Allows italic or oblique faces to be selected.
35+
///
36+
/// See [`cosmic_text::Style`] for details.
37+
style: cosmic_text::Style,
38+
},
39+
}
40+
41+
/// A [font family](https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#propdef-font-family).
42+
///
43+
/// See [`cosmic_text::Family`] for details.
44+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
45+
pub enum Family {
46+
/// The name of a font family of choice.
47+
///
48+
/// This must be a *Typographic Family* (ID 16) or a *Family Name* (ID 1) in terms of TrueType.
49+
/// Meaning you have to pass a family without any additional suffixes like _Bold_, _Italic_,
50+
/// _Regular_, etc.
51+
///
52+
/// Localized names are allowed.
53+
Name(String),
54+
55+
/// Serif fonts represent the formal text style for a script.
56+
Serif,
57+
58+
/// Glyphs in sans-serif fonts, as the term is used in CSS, are generally low contrast
59+
/// and have stroke endings that are plain — without any flaring, cross stroke,
60+
/// or other ornamentation.
61+
SansSerif,
62+
63+
/// Glyphs in cursive fonts generally use a more informal script style,
64+
/// and the result looks more like handwritten pen or brush writing than printed letterwork.
65+
Cursive,
66+
67+
/// Fantasy fonts are primarily decorative or expressive fonts that
68+
/// contain decorative or expressive representations of characters.
69+
Fantasy,
70+
71+
/// The sole criterion of a monospace font is that all glyphs have the same fixed width.
72+
MonoSpace,
73+
}
74+
75+
impl Family {
76+
/// References variants to create a [`cosmic_text::Family`].
77+
///
78+
/// This is required for querying the underlying [`cosmic_text::fontdb::Database`]
79+
pub fn as_fontdb_family(&self) -> cosmic_text::Family<'_> {
80+
match self {
81+
Family::Name(name) => cosmic_text::Family::Name(name),
82+
Family::Serif => cosmic_text::Family::Serif,
83+
Family::SansSerif => cosmic_text::Family::SansSerif,
84+
Family::Cursive => cosmic_text::Family::Cursive,
85+
Family::Fantasy => cosmic_text::Family::Fantasy,
86+
Family::MonoSpace => cosmic_text::Family::Monospace,
87+
}
88+
}
2289
}
2390

2491
impl Font {
@@ -28,8 +95,6 @@ impl Font {
2895
) -> Result<Self, cosmic_text::ttf_parser::FaceParsingError> {
2996
use cosmic_text::ttf_parser;
3097
ttf_parser::Face::parse(&font_data, 0)?;
31-
Ok(Self {
32-
data: Arc::new(font_data),
33-
})
98+
Ok(Self::Data(Arc::new(font_data)))
3499
}
35100
}

crates/bevy_text/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,16 @@ pub use pipeline::*;
5353
pub use text::*;
5454
pub use text_access::*;
5555

56+
pub use cosmic_text::{Stretch, Style, Weight};
57+
5658
/// The text prelude.
5759
///
5860
/// This includes the most common types in this crate, re-exported for your convenience.
5961
pub mod prelude {
6062
#[doc(hidden)]
6163
pub use crate::{
62-
Font, Justify, LineBreak, TextColor, TextError, TextFont, TextLayout, TextSpan,
64+
Family, Font, Justify, LineBreak, Stretch, Style, TextColor, TextError, TextFont,
65+
TextLayout, TextSpan, Weight,
6366
};
6467
}
6568

crates/bevy_text/src/pipeline.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use bevy_math::{Rect, UVec2, Vec2};
1313
use bevy_platform::collections::HashMap;
1414
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
1515

16-
use cosmic_text::{Attrs, Buffer, Family, Metrics, Shaping, Wrap};
16+
use cosmic_text::{Attrs, Buffer, Metrics, Shaping, Wrap};
1717

1818
use crate::{
1919
error::TextError, ComputedTextBlock, Font, FontAtlasSets, FontSmoothing, Justify, LineBreak,
@@ -44,6 +44,7 @@ impl CosmicFontSystem {
4444
if load_system_fonts {
4545
db.load_system_fonts();
4646
}
47+
4748
Self(cosmic_text::FontSystem::new_with_locale_and_db(locale, db))
4849
}
4950
}
@@ -515,17 +516,46 @@ pub fn load_font_to_fontdb(
515516
let font = fonts.get(font_handle.id()).expect(
516517
"Tried getting a font that was not available, probably due to not being loaded yet",
517518
);
518-
let data = Arc::clone(&font.data);
519-
let ids = font_system
520-
.db_mut()
521-
.load_font_source(cosmic_text::fontdb::Source::Binary(data));
522519

523-
// TODO: it is assumed this is the right font face
524-
let face_id = *ids.last().unwrap();
520+
let face_id = match font {
521+
Font::Data(data) => {
522+
let data = Arc::clone(data);
523+
524+
let ids = font_system
525+
.db_mut()
526+
.load_font_source(cosmic_text::fontdb::Source::Binary(data));
527+
528+
// TODO: it is assumed this is the right font face
529+
*ids.last().unwrap()
530+
}
531+
Font::System {
532+
families,
533+
weight,
534+
stretch,
535+
style,
536+
} => {
537+
let families = families
538+
.iter()
539+
.map(|family| family.as_fontdb_family())
540+
.collect::<Vec<_>>();
541+
let query = cosmic_text::fontdb::Query {
542+
families: &families,
543+
weight: *weight,
544+
stretch: *stretch,
545+
style: *style,
546+
};
547+
548+
//todo: unwrapping here is fallible
549+
font_system.db().query(&query).unwrap()
550+
}
551+
};
552+
525553
let face = font_system.db().face(face_id).unwrap();
526554
let family_name = Arc::from(face.families[0].0.as_str());
527555

528556
(face_id, family_name)
557+
558+
//let other_id = font_system.db().query(query)
529559
});
530560
let face = font_system.db().face(*face_id).unwrap();
531561

@@ -547,7 +577,7 @@ fn get_attrs<'a>(
547577
) -> Attrs<'a> {
548578
Attrs::new()
549579
.metadata(span_index)
550-
.family(Family::Name(&face_info.family_name))
580+
.family(cosmic_text::Family::Name(&face_info.family_name))
551581
.stretch(face_info.stretch)
552582
.style(face_info.style)
553583
.weight(face_info.weight)

0 commit comments

Comments
 (0)