mod helpers;
use helpers::{make_block, make_typesetter};
fn tall_doc() -> (helpers::Typesetter, f32) {
let mut ts = make_typesetter();
let blocks: Vec<_> = (1..=40)
.map(|i| make_block(i, "The quick brown fox"))
.collect();
ts.layout_blocks(blocks);
let line_h = ts.content_height() / 40.0;
ts.set_viewport(400.0, ts.content_height() + line_h);
(ts, line_h)
}
fn positions_are_a_subset(subset: &[[f32; 4]], superset: &[[f32; 4]]) {
for q in subset {
let found = superset
.iter()
.any(|s| (s[0] - q[0]).abs() < 0.01 && (s[1] - q[1]).abs() < 0.01);
assert!(
found,
"windowed glyph at ({:.2}, {:.2}) is missing (or moved) in the full frame — \
the window must cull, never shift",
q[0], q[1]
);
}
}
#[test]
fn a_window_culls_to_its_band_without_moving_glyphs() {
let (mut ts, line_h) = tall_doc();
let full: Vec<[f32; 4]> = ts.render().glyphs.iter().map(|g| g.screen).collect();
assert!(!full.is_empty());
let top = 10.0 * line_h;
let height = 5.0 * line_h;
ts.set_render_window(Some((top, height)));
let windowed: Vec<[f32; 4]> = ts.render().glyphs.iter().map(|g| g.screen).collect();
assert!(
windowed.len() < full.len(),
"a 5-line window over a 40-line document must cull most glyphs (got {} of {})",
windowed.len(),
full.len()
);
assert!(!windowed.is_empty(), "the visible band must still render");
positions_are_a_subset(&windowed, &full);
let min_y = windowed.iter().map(|g| g[1]).fold(f32::INFINITY, f32::min);
assert!(
min_y > top - 2.0 * line_h,
"windowed glyphs (min y = {min_y:.1}) should be near the band top {top:.1}, not the \
document top"
);
}
#[test]
fn none_restores_the_whole_document() {
let (mut ts, line_h) = tall_doc();
let full_count = ts.render().glyphs.len();
ts.set_render_window(Some((0.0, 3.0 * line_h)));
let windowed_count = ts.render().glyphs.len();
assert!(windowed_count < full_count);
ts.set_render_window(None);
let restored_count = ts.render().glyphs.len();
assert_eq!(
restored_count, full_count,
"clearing the window must render the whole document again"
);
}
#[test]
fn a_top_window_and_a_middle_window_render_different_bands() {
let (mut ts, line_h) = tall_doc();
ts.set_render_window(Some((0.0, 4.0 * line_h)));
let top_band: Vec<f32> = ts.render().glyphs.iter().map(|g| g.screen[1]).collect();
ts.set_render_window(Some((20.0 * line_h, 4.0 * line_h)));
let mid_band: Vec<f32> = ts.render().glyphs.iter().map(|g| g.screen[1]).collect();
let top_max = top_band.iter().cloned().fold(f32::NEG_INFINITY, f32::max);
let mid_min = mid_band.iter().cloned().fold(f32::INFINITY, f32::min);
assert!(
mid_min > top_max,
"the middle band (min y {mid_min:.1}) must sit entirely below the top band \
(max y {top_max:.1}) — the two windows select disjoint content"
);
}