Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions crates/rendering/src/layers/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,85 @@ mod gpu_tests {
assert_eq!(after_edit, fresh(&frame));
}

#[test]
#[ignore = "requires a working wgpu adapter"]
fn reused_layouts_follow_each_shaping_input() {
type Edit = (&'static str, fn(&mut PreparedText));
let (device, queue) = device().expect("A working wgpu adapter is required for this test");
let base = PreparedText {
color: [0.0, 0.0, 0.0, 1.0],
background_color: None,
content: "Hi yo\ngq".to_string(),
font_size: 16.0,
line_height: 1.25,
..text([4.0, 4.0, 60.0, 60.0], [0.0; 4])
};
// Family, weight, and italic only change pixels when the host has a
// distinct face. The cache key still has to include them: a miss leaves
// the previous buffer unused.
let face_edits: [Edit; 3] = [
("font family", |text| {
text.font_family = "monospace".to_string()
}),
("font weight", |text| text.font_weight = 800.0),
("italic", |text| text.italic = true),
];
let layout_edits: [Edit; 5] = [
("font size", |text| {
text.font_size = 20.0;
text.line_height = 1.0;
}),
("letter spacing", |text| text.letter_spacing = 3.0),
("alignment", |text| text.align = TextAlign::Right),
("line height", |text| text.line_height = 2.0),
("wrap width", |text| text.bounds[2] = 24.0),
];
let render_fresh = |text: &PreparedText| {
let mut layer = TextLayer::new(&device, &queue);
layer.prepare(
&device,
&queue,
(OUTPUT, OUTPUT),
std::slice::from_ref(text),
);
render_pixels(&device, &queue, &layer)
};
let base_pixels = render_fresh(&base);
assert!(base_pixels.chunks_exact(4).any(|pixel| pixel != [255; 4]));

let check = |name: &str, edit: fn(&mut PreparedText), require_pixel_change: bool| {
let mut edited = base.clone();
edit(&mut edited);
let expected = render_fresh(&edited);
if require_pixel_change {
assert!(
expected != base_pixels,
"{name} edit should change the output"
);
}

let mut reused = TextLayer::new(&device, &queue);
reused.prepare(&device, &queue, (OUTPUT, OUTPUT), &[base.clone()]);
reused.prepare(&device, &queue, (OUTPUT, OUTPUT), &[edited]);
assert_eq!(
reused.previous_buffers.len(),
1,
"{name} edit reused the previous layout"
);
assert_eq!(
render_pixels(&device, &queue, &reused),
expected,
"{name} edit drew a stale layout"
);
};
for (name, edit) in face_edits {
check(name, edit, false);
}
for (name, edit) in layout_edits {
check(name, edit, true);
}
}

#[test]
#[ignore = "requires a working wgpu adapter"]
fn text_background_timeline_preserves_order_and_shrinks_without_stale_layers() {
Expand Down
Loading