use std::cell::RefCell;
use std::rc::Rc;
use egui_kittest::Harness;
use egui_kittest::wgpu::{WgpuTestRenderer, create_render_state, default_wgpu_setup};
use siplot::egui;
use siplot::{Colormap, ImageSpec, PlotWidget, YAxis};
const W: usize = 400;
const H: usize = 300;
const WD: u32 = 20;
const HD: u32 = 20;
fn is_teal(px: &[u8]) -> bool {
let (r, g, b) = (px[0] as i32, px[1] as i32, px[2] as i32);
let mx = r.max(g).max(b);
let mn = r.min(g).min(b);
g >= r && g >= b && (mx - mn) > 60
}
fn teal_left_right(raw: &[u8]) -> (u32, u32) {
let (mut left, mut right) = (0u32, 0u32);
for (i, px) in raw.chunks_exact(4).enumerate() {
if is_teal(px) {
let col = i % W;
if col < W / 3 {
left += 1;
} else if col >= 2 * W / 3 {
right += 1;
}
}
}
(left, right)
}
fn render(alpha_map: Option<Vec<f32>>) -> (u32, u32) {
render_after(alpha_map, None)
}
fn render_after(alpha_map: Option<Vec<f32>>, relevel: Option<(f64, f64)>) -> (u32, u32) {
let rs = create_render_state(default_wgpu_setup());
siplot::install(&rs);
let mut plot = PlotWidget::new(&rs, 0);
let data = vec![0.5f32; (WD * HD) as usize];
let colormap = Colormap::viridis(0.0, 1.0);
let mut spec = ImageSpec::scalar(WD, HD, &data, colormap);
if let Some(am) = alpha_map.as_ref() {
spec = spec.with_alpha_map(am);
}
plot.add_image_spec(spec);
if let Some((vmin, vmax)) = relevel {
assert!(
plot.set_active_image_levels(vmin, vmax),
"level edit must re-upload the active scalar image"
);
}
plot.set_show_colorbar(false);
plot.set_auto_reset_zoom(false);
plot.set_graph_x_limits(0.0, WD as f64);
plot.set_graph_y_limits(0.0, HD as f64, YAxis::Left);
let app = Rc::new(RefCell::new(plot));
let app_ui = app.clone();
let renderer = WgpuTestRenderer::from_render_state(rs);
let mut harness = Harness::builder()
.with_size(egui::vec2(W as f32, H as f32))
.with_pixels_per_point(1.0)
.renderer(renderer)
.build_ui(move |ui| {
app_ui.borrow_mut().show(ui);
});
harness.step();
harness.step();
let image = harness.render().expect("headless wgpu render");
teal_left_right(image.as_raw())
}
fn left_opaque_right_transparent() -> Vec<f32> {
(0..(WD * HD))
.map(|i| {
let col = i % WD;
if col < WD / 2 { 1.0 } else { 0.0 }
})
.collect()
}
#[test]
fn per_pixel_alpha_map_makes_only_the_masked_half_transparent() {
let (masked_left, masked_right) = render(Some(left_opaque_right_transparent()));
let (control_left, control_right) = render(None);
assert!(
control_left > 200 && control_right > 200,
"without an alpha map the uniform image must be teal on both halves: \
left={control_left} right={control_right}"
);
assert!(
masked_left > 200,
"the opaque (alpha=1) left half must stay teal: masked_left={masked_left}"
);
assert_eq!(
masked_right, 0,
"the transparent (alpha=0) right half must show no teal (was {control_right} \
when opaque): masked_right={masked_right}"
);
}
#[test]
fn per_pixel_alpha_map_survives_a_level_edit_reupload() {
let (masked_left, masked_right) =
render_after(Some(left_opaque_right_transparent()), Some((-1.0, 2.0)));
assert!(
masked_left > 200,
"after a re-upload the opaque left half must still be teal: masked_left={masked_left}"
);
assert_eq!(
masked_right, 0,
"after a re-upload the alpha map must still mask the right half: \
masked_right={masked_right}"
);
}