| 29 |
29 |
|
/// Recursive Mono Linear Bold, used for the "af/" logo.
|
| 30 |
30 |
|
static LOGO_FONT: &[u8] = include_bytes!("../../fonts/RecursiveMonoLnrSt-Bold.ttf");
|
| 31 |
31 |
|
|
| 32 |
|
- |
/// The egui font family name for the logo font.
|
| 33 |
|
- |
pub const LOGO_FONT_FAMILY: &str = "RecursiveMono";
|
|
32 |
+ |
/// The file [`LOGO_FONT`] is compiled from, named again so the declaration
|
|
33 |
+ |
/// below can state which file backs the face. A test asserts the two agree.
|
|
34 |
+ |
const LOGO_FONT_FILE: &str = "RecursiveMonoLnrSt-Bold.ttf";
|
|
35 |
+ |
|
|
36 |
+ |
/// audiofiles' typography: the house two, plus the brand face over the display
|
|
37 |
+ |
/// slot.
|
|
38 |
+ |
///
|
|
39 |
+ |
/// The same layer MNW and goingson declare in their build scripts, read the
|
|
40 |
+ |
/// other way round. Those emit a stylesheet, so an override reaches the page
|
|
41 |
+ |
/// as generated CSS; egui loads faces itself and there is no stylesheet
|
|
42 |
+ |
/// anywhere in this path, so the declaration is read at runtime through
|
|
43 |
+ |
/// `Typography::faces` and handed to `ctx.set_fonts`. The point either way is
|
|
44 |
+ |
/// that the family name is stated once: [`setup_fonts`] registers the file
|
|
45 |
+ |
/// under it and the toolbar asks for it back, and neither spells it.
|
|
46 |
+ |
///
|
|
47 |
+ |
/// The weight is on the face because it is true of the file, not because
|
|
48 |
+ |
/// anything here reads it. Nothing does: this is a single static face, so
|
|
49 |
+ |
/// egui cannot synthesise the second bold that the same omission cost
|
|
50 |
+ |
/// goingson's Reglo in a browser.
|
|
51 |
+ |
static TYPOGRAPHY: LazyLock<makeover::Typography> = LazyLock::new(|| {
|
|
52 |
+ |
makeover::Typography::house("fonts").with_override(
|
|
53 |
+ |
makeover::FontOverride::new(makeover::FontSlot::Display, "\"RecursiveMono\", monospace")
|
|
54 |
+ |
.with_face(makeover::FontFace::new("RecursiveMono", [LOGO_FONT_FILE]).weight("700")),
|
|
55 |
+ |
)
|
|
56 |
+ |
});
|
|
57 |
+ |
|
|
58 |
+ |
/// The brand face declared over the display slot.
|
|
59 |
+ |
fn logo_face() -> &'static makeover::FontFace {
|
|
60 |
+ |
TYPOGRAPHY
|
|
61 |
+ |
.faces(makeover::FontSlot::Display)
|
|
62 |
+ |
.first()
|
|
63 |
+ |
.expect("the display slot is overridden with exactly one face")
|
|
64 |
+ |
}
|
|
65 |
+ |
|
|
66 |
+ |
/// The egui font family name for the logo font, off the override layer.
|
|
67 |
+ |
pub fn logo_font_family() -> &'static str {
|
|
68 |
+ |
logo_face().family()
|
|
69 |
+ |
}
|
| 34 |
70 |
|
|
| 35 |
71 |
|
// --- Spacing and stroke tokens ---
|
| 36 |
72 |
|
//
|
| 848 |
884 |
|
/// (e.g. from the eframe `CreationContext` or nih-plug init callback), because
|
| 849 |
885 |
|
/// `ctx.set_fonts()` only takes effect on the next frame.
|
| 850 |
886 |
|
pub fn setup_fonts(ctx: &egui::Context) {
|
|
887 |
+ |
let family = logo_font_family();
|
| 851 |
888 |
|
let mut fonts = egui::FontDefinitions::default();
|
| 852 |
889 |
|
fonts.font_data.insert(
|
| 853 |
|
- |
LOGO_FONT_FAMILY.to_owned(),
|
|
890 |
+ |
family.to_owned(),
|
| 854 |
891 |
|
egui::FontData::from_static(LOGO_FONT).into(),
|
| 855 |
892 |
|
);
|
| 856 |
893 |
|
fonts.families.insert(
|
| 857 |
|
- |
egui::FontFamily::Name(LOGO_FONT_FAMILY.into()),
|
| 858 |
|
- |
vec![LOGO_FONT_FAMILY.to_owned(), "Hack".to_owned()],
|
|
894 |
+ |
egui::FontFamily::Name(family.into()),
|
|
895 |
+ |
vec![family.to_owned(), "Hack".to_owned()],
|
| 859 |
896 |
|
);
|
| 860 |
897 |
|
ctx.set_fonts(fonts);
|
| 861 |
898 |
|
}
|
| 1537 |
1574 |
|
assert!(export_theme_content(DEFAULT_THEME_ID).is_some());
|
| 1538 |
1575 |
|
}
|
| 1539 |
1576 |
|
|
|
1577 |
+ |
#[test]
|
|
1578 |
+ |
fn the_declared_face_names_the_file_that_is_actually_embedded() {
|
|
1579 |
+ |
// The override layer is only worth having if it describes the face
|
|
1580 |
+ |
// that ships. `include_bytes!` needs a literal path, so the filename
|
|
1581 |
+ |
// is written twice by necessity; this is what stops the second copy
|
|
1582 |
+ |
// from drifting into a description of a font nobody loads.
|
|
1583 |
+ |
assert!(
|
|
1584 |
+ |
std::path::Path::new(concat!(
|
|
1585 |
+ |
env!("CARGO_MANIFEST_DIR"),
|
|
1586 |
+ |
"/fonts/RecursiveMonoLnrSt-Bold.ttf"
|
|
1587 |
+ |
))
|
|
1588 |
+ |
.ends_with(LOGO_FONT_FILE)
|
|
1589 |
+ |
);
|
|
1590 |
+ |
assert_eq!(logo_face().sources(), [LOGO_FONT_FILE]);
|
|
1591 |
+ |
assert!(!LOGO_FONT.is_empty());
|
|
1592 |
+ |
}
|
|
1593 |
+ |
|
|
1594 |
+ |
#[test]
|
|
1595 |
+ |
fn the_stack_the_display_slot_resolves_to_names_the_face_behind_it() {
|
|
1596 |
+ |
// egui registers a family by name and asks for it back by name, so a
|
|
1597 |
+ |
// stack that named something else would leave the face loaded and
|
|
1598 |
+ |
// unreachable.
|
|
1599 |
+ |
let stack = TYPOGRAPHY
|
|
1600 |
+ |
.resolve(makeover::FontSlot::Display)
|
|
1601 |
+ |
.expect("the display slot is overridden");
|
|
1602 |
+ |
assert!(stack.contains(logo_font_family()));
|
|
1603 |
+ |
assert_eq!(logo_font_family(), "RecursiveMono");
|
|
1604 |
+ |
}
|
|
1605 |
+ |
|
| 1540 |
1606 |
|
#[test]
|
| 1541 |
1607 |
|
fn bundled_theme_colors_are_not_all_black() {
|
| 1542 |
1608 |
|
// Sanity check: a properly parsed theme shouldn't have all-black fields
|