diff --git a/crates/benilla-ui/src/script/simplehtml/mod.rs b/crates/benilla-ui/src/script/simplehtml/mod.rs index 1a6513cf..1e3772d0 100644 --- a/crates/benilla-ui/src/script/simplehtml/mod.rs +++ b/crates/benilla-ui/src/script/simplehtml/mod.rs @@ -288,6 +288,11 @@ fn build(model: &mut Model, fh: FrameHandle, blocks: &[Block]) { let anchors = point .map(|p| vec![anchor_for(prev_block, frame_id, p, next_y)]) .unwrap_or_default(); + // `src=""` names no file, as `""` does on every texture setter (`0x770200`). + // Kept, it was the one path left in the UI that could put an empty string where a + // texture path goes, and the renderer then searched the patch chain for a nameless + // file and warned about a miss it could name neither the file nor the asker of. + let src = src.clone().filter(|p| !p.is_empty()); model.region_data.insert( rh, RegionData { diff --git a/crates/benilla-ui/src/script/tests/simplehtml.rs b/crates/benilla-ui/src/script/tests/simplehtml.rs index 0da4387e..ed8f49b4 100644 --- a/crates/benilla-ui/src/script/tests/simplehtml.rs +++ b/crates/benilla-ui/src/script/tests/simplehtml.rs @@ -552,6 +552,54 @@ fn the_books_unsized_crest_is_its_arts_texel_square_not_the_whole_page() { ); } +/// `` names no file. `""` clears on every texture setter here, as the reference's path +/// arm treats it like nil (`0x770200`), but the SimpleHTML image path stored the empty string: the +/// region then carried `texture: Some("")`, the resolve asked the size probe for a nameless file, +/// and the renderer searched the patch chain and logged `texture miss: ''` — a defect-shaped +/// warning naming neither a file nor an asker. It was the last unguarded route in the UI. +#[test] +fn an_img_with_an_empty_src_names_no_file() { + use std::cell::RefCell; + use std::rc::Rc; + + let asked: Rc>> = Rc::new(RefCell::new(Vec::new())); + let seen = Rc::clone(&asked); + let mut s = script(); + s.set_texture_size_probe(Box::new(move |path| { + seen.borrow_mut().push(path.to_string()); + Some((64, 48)) + })); + page(&s); + s.run( + r#"Page:SetText("

a

" .. + "" .. + "

b

")"#, + ) + .unwrap(); + + let b = blocks(&s, "Page"); + assert_eq!( + b.len(), + 3, + "the image block is still made, art or none: {b:?}" + ); + assert!( + b.iter().all(|x| x.texture.as_deref() != Some("")), + "a nameless file was stored as this image's texture: {b:?}" + ); + assert!( + !asked.borrow().iter().any(|p| p.is_empty()), + "the patch chain was searched for a nameless file: {:?}", + asked.borrow() + ); + // And nothing is reserved in the flow for art that does not exist. + assert_eq!( + b[2].anchor.unwrap(), + (Point::TopLeft, Point::BottomLeft, 0.0, 0.0, Rel::Block(0)), + "an image with no art reserved height anyway" + ); +} + /// An unfloated image reserves `GetHeight()` in the flow (`0x78ad07`), its art's texel height when /// it has no `height=`; a floated one reserves nothing, so text runs over it in the reference too. #[test]