use rizzma::core::color::Rgba;
use rizzma::{Figure, RcParams, TickDirection};
fn pixel(r: &rizzma::skia::SkiaRenderer, x: u32, y: u32) -> [u8; 4] {
let p = r.pixmap().pixel(x, y).expect("pixel in bounds");
[p.red(), p.green(), p.blue(), p.alpha()]
}
fn count_in(
r: &rizzma::skia::SkiaRenderer,
x0: u32,
x1: u32,
y0: u32,
y1: u32,
pred: impl Fn([u8; 4]) -> bool,
) -> usize {
let mut n = 0;
for y in y0..y1 {
for x in x0..x1 {
if pred(pixel(r, x, y)) {
n += 1;
}
}
}
n
}
fn is_white(p: [u8; 4]) -> bool {
p == [255, 255, 255, 255]
}
#[test]
fn default_rcparams_matches_implicit_default() {
let build = |rc: Option<RcParams>| {
let mut fig = Figure::new(4.0, 3.0);
if let Some(rc) = rc {
fig.set_rcparams(rc);
}
let ax = fig.add_axes(0.15, 0.15, 0.7, 0.7);
ax.plot(&[0.0, 5.0, 10.0], &[0.0, 8.0, 3.0]);
ax.plot(&[0.0, 5.0, 10.0], &[2.0, 1.0, 9.0]);
ax.set_title("styled");
ax.legend(vec![
(Rgba::from_u8(31, 119, 180, 255), "a".to_string()),
(Rgba::from_u8(255, 127, 14, 255), "b".to_string()),
]);
ax.grid(true);
fig.encode_png().expect("encode")
};
assert_eq!(
build(None),
build(Some(RcParams::default())),
"explicit default rc must render identically to the implicit default"
);
}
#[test]
fn dark_preset_darkens_canvas_and_lightens_ink() {
let render = |rc: RcParams| {
let mut fig = Figure::new(4.0, 3.0).with_rcparams(rc);
let ax = fig.add_axes(0.15, 0.15, 0.7, 0.7);
ax.set_xlim(0.0, 10.0);
ax.set_ylim(0.0, 10.0);
fig.render()
};
let light = render(RcParams::default());
let dark = render(RcParams::dark());
let light_bg = pixel(&light, 3, 3);
let dark_bg = pixel(&dark, 3, 3);
assert!(is_white(light_bg), "default canvas white, got {light_bg:?}");
assert!(
dark_bg[0] < 60 && dark_bg[1] < 60 && dark_bg[2] < 60,
"dark canvas should be near-black, got {dark_bg:?}"
);
let light_spine = count_in(&light, 58, 61, 45, 255, |p| {
p[0] < 40 && p[1] < 40 && p[2] < 40
});
let dark_spine = count_in(&dark, 58, 61, 45, 255, |p| {
p[0] > 180 && p[1] > 180 && p[2] > 180
});
assert!(
light_spine > 20,
"default spine ink (dark), got {light_spine}"
);
assert!(
dark_spine > 20,
"dark-preset spine ink (light), got {dark_spine}"
);
}
#[test]
fn grid_toggle_and_custom_color() {
let interior_ink = |setup: &dyn Fn(&mut rizzma::Axes)| {
let mut fig = Figure::new(4.0, 3.0);
let ax = fig.add_axes(0.15, 0.15, 0.7, 0.7);
ax.set_xlim(0.0, 10.0);
ax.set_ylim(0.0, 10.0);
setup(ax);
let r = fig.render();
count_in(&r, 70, 330, 55, 245, |p| !is_white(p))
};
let off = interior_ink(&|_ax| {});
let on = interior_ink(&|ax| {
ax.grid(true);
});
assert_eq!(off, 0, "no grid, no data => clean interior, got {off}");
assert!(on > 100, "grid should add interior ink, got {on}");
let mut fig = Figure::new(4.0, 3.0);
let ax = fig.add_axes(0.15, 0.15, 0.7, 0.7);
ax.set_xlim(0.0, 10.0);
ax.set_ylim(0.0, 10.0);
ax.grid_with(Rgba::from_u8(220, 20, 20, 255), 1.5, 1.0);
let r = fig.render();
let red = count_in(&r, 70, 330, 55, 245, |p| {
p[0] > 150 && p[1] < 90 && p[2] < 90
});
assert!(red > 50, "custom red grid should show, got {red}");
}
#[test]
fn custom_prop_cycle_is_used() {
let mut fig = Figure::new(4.0, 3.0);
let ax = fig.add_axes(0.1, 0.1, 0.8, 0.8);
let red = Rgba::from_u8(200, 0, 0, 255);
let green = Rgba::from_u8(0, 160, 0, 255);
ax.set_prop_cycle(vec![red, green]);
assert_eq!(ax.cycle_color(0), red);
assert_eq!(ax.cycle_color(1), green);
assert_eq!(ax.cycle_color(2), red, "cycle wraps");
}
#[test]
fn tick_direction_changes_the_render() {
let render = |dir: TickDirection| {
let mut fig = Figure::new(4.0, 3.0);
let ax = fig.add_axes(0.2, 0.15, 0.65, 0.7);
ax.set_xlim(0.0, 10.0);
ax.set_ylim(0.0, 10.0);
ax.xaxis_mut().set_tick_direction(dir);
ax.yaxis_mut().set_tick_direction(dir);
fig.encode_png().expect("encode")
};
assert_ne!(
render(TickDirection::Out),
render(TickDirection::In),
"inward ticks must render differently from outward ticks"
);
}