use std::sync::Arc;
use super::*;
use crate::egui::{FontId, Galley};
struct Measurer {
asked: Vec<(String, FontId)>,
laid_out: Vec<Arc<Galley>>,
}
impl Game for Measurer {
type Meshes = CubeSet;
type Sounds = NoSounds;
type InputActions = NoInputActions;
type Skyboxes = NoSkyboxes;
type SurfaceStyles = NoSurfaceStyles;
type PostEffects = NoPostEffects;
fn tick(&mut self, _ctx: &mut TickContext<'_, Self>) {}
fn frame(&mut self, ctx: &mut FrameContext<'_, Self>) {
self.laid_out = self
.asked
.iter()
.map(|(text, font)| ctx.text_layout(text, font.clone()))
.collect();
}
}
fn measured(asked: &[(&str, FontId)]) -> Option<Vec<Arc<Galley>>> {
let asked = asked
.iter()
.map(|(text, font)| ((*text).to_owned(), font.clone()))
.collect();
let mut session = started(
Config::new("headless text"),
UVec2::splat(SIDE),
|_ctx: &mut InitContext<'_, Measurer>| {
Ok(Measurer {
asked,
laid_out: Vec::new(),
})
},
)?;
session.step();
Some(session.game().laid_out.clone())
}
#[test]
fn a_longer_text_is_wider_and_of_the_same_height() {
let font = FontId::proportional(14.0);
let Some(laid_out) = measured(&[("score", font.clone()), ("score: 1200", font)]) else {
eprintln!("skipped: this machine has no usable graphics adapter");
return;
};
let [short, long] = &laid_out[..] else {
panic!("one layout per text");
};
assert!(
long.size().x > short.size().x,
"{} points over {}",
long.size().x,
short.size().x
);
assert_eq!(long.size().y, short.size().y, "one line either way");
}
#[test]
fn text_at_a_larger_size_is_wider_and_taller() {
let Some(laid_out) = measured(&[
("score", FontId::proportional(12.0)),
("score", FontId::proportional(24.0)),
]) else {
eprintln!("skipped: this machine has no usable graphics adapter");
return;
};
let [small, large] = &laid_out[..] else {
panic!("one layout per text");
};
assert!(large.size().x > small.size().x);
assert!(large.size().y > small.size().y);
}
#[test]
fn the_one_width_family_lays_every_glyph_out_at_one_width() {
let one_width = FontId::monospace(14.0);
let own_widths = FontId::proportional(14.0);
let Some(laid_out) = measured(&[
("0", one_width.clone()),
("1", one_width.clone()),
("11", one_width.clone()),
("i", one_width.clone()),
("m", one_width),
("i", own_widths.clone()),
("m", own_widths),
]) else {
eprintln!("skipped: this machine has no usable graphics adapter");
return;
};
let [
zero,
one,
eleven,
thin,
broad,
thin_of_its_own,
broad_of_its_own,
] = &laid_out[..]
else {
panic!("one layout per text");
};
assert_eq!(zero.size().x, one.size().x, "whichever digit it is");
assert!(
eleven.size().x > one.size().x,
"and a second digit is wider still"
);
assert_eq!(thin.size().x, broad.size().x, "whichever glyph it is");
assert!(
thin_of_its_own.size().x < broad_of_its_own.size().x,
"where the other family gives each glyph its own width"
);
}
#[test]
fn a_text_has_height_and_the_empty_text_has_no_width() {
let font = FontId::proportional(14.0);
let Some(laid_out) = measured(&[("score", font.clone()), ("", font)]) else {
eprintln!("skipped: this machine has no usable graphics adapter");
return;
};
let [text, empty] = &laid_out[..] else {
panic!("one layout per text");
};
assert!(text.size().y > 0.0, "got {}", text.size().y);
assert_eq!(empty.size().x, 0.0);
}
#[test]
fn a_row_ends_where_a_newline_starts_the_next_one() {
let font = FontId::proportional(14.0);
let Some(laid_out) = measured(&[("a", font.clone()), ("bb", font.clone()), ("a\nbb", font)])
else {
eprintln!("skipped: this machine has no usable graphics adapter");
return;
};
let [one, other, both] = &laid_out[..] else {
panic!("one layout per text");
};
assert!(
both.size().y > one.size().y,
"two rows are taller than one, got {} over {}",
both.size().y,
one.size().y
);
assert_eq!(
both.size().x,
other.size().x,
"and as wide as the wider row alone"
);
}
#[test]
fn a_space_at_the_end_of_a_text_widens_it() {
let font = FontId::proportional(14.0);
let Some(laid_out) = measured(&[("score", font.clone()), ("score ", font)]) else {
eprintln!("skipped: this machine has no usable graphics adapter");
return;
};
let [tight, spaced] = &laid_out[..] else {
panic!("one layout per text");
};
assert!(
spaced.size().x > tight.size().x,
"the width a text takes holds the spaces at its end, got {} over {}",
spaced.size().x,
tight.size().x
);
}