use hephaestus::backend::vello::VelloRenderer;
use hephaestus::color::rgb8;
use hephaestus::geometry::Point;
use hephaestus::{Affine, Brush, FillRule, PickId, Rect, Renderer, SceneBuilder};
use kurbo::Shape;
const W: u32 = 200;
const H: u32 = 200;
fn fresh_buf() -> Vec<u8> {
vec![0u8; (W * H * 4) as usize]
}
#[test]
fn pick_at_returns_none_when_picking_disabled() {
let mut r = VelloRenderer::new().expect("vello renderer init");
let mut buf = fresh_buf();
r.render_to_buffer(W, H, rgb8(0, 0, 0), &mut buf)
.expect("render");
assert_eq!(r.pick_at(50, 50), None);
assert!(r.hitmap().is_none());
}
#[test]
fn pick_at_returns_id_at_known_positions() {
let mut r = VelloRenderer::with_picking().expect("vello renderer init");
{
let scene = r.scene();
let red: Brush = rgb8(220, 60, 60).into();
let green: Brush = rgb8(60, 220, 60).into();
let blue: Brush = rgb8(60, 60, 220).into();
let a = Rect::new(10.0, 10.0, 60.0, 60.0).to_path(0.1);
let b = Rect::new(80.0, 10.0, 130.0, 60.0).to_path(0.1);
let c = Rect::new(150.0, 10.0, 195.0, 60.0).to_path(0.1);
scene.fill(
FillRule::NonZero,
Affine::IDENTITY,
&red,
None,
&a,
PickId::Id(7),
);
scene.fill(
FillRule::NonZero,
Affine::IDENTITY,
&green,
None,
&b,
PickId::Id(42),
);
scene.fill(
FillRule::NonZero,
Affine::IDENTITY,
&blue,
None,
&c,
PickId::Id(0xAA_BBCC),
);
}
let mut buf = fresh_buf();
r.render_to_buffer(W, H, rgb8(0, 0, 0), &mut buf)
.expect("render");
assert_eq!(r.pick_at(35, 35), Some(7));
assert_eq!(r.pick_at(105, 35), Some(42));
assert_eq!(r.pick_at(170, 35), Some(0xAA_BBCC));
assert_eq!(r.pick_at(70, 35), None);
assert_eq!(r.pick_at(35, 100), None);
assert_eq!(r.pick_at(W, 0), None);
assert_eq!(r.pick_at(0, H), None);
let map = r.hitmap().expect("hitmap populated");
assert_eq!(map.len() as u32, W * H);
}
#[test]
fn block_occludes_underneath_pick() {
let mut r = VelloRenderer::with_picking().expect("vello renderer init");
{
let scene = r.scene();
let red: Brush = rgb8(220, 60, 60).into();
let yellow: Brush = rgb8(220, 220, 60).into();
let big = Rect::new(0.0, 0.0, W as f64, H as f64).to_path(0.1);
let block = Rect::new(80.0, 80.0, 120.0, 120.0).to_path(0.1);
scene.fill(
FillRule::NonZero,
Affine::IDENTITY,
&red,
None,
&big,
PickId::Id(7),
);
scene.fill(
FillRule::NonZero,
Affine::IDENTITY,
&yellow,
None,
&block,
PickId::Block,
);
}
let mut buf = fresh_buf();
r.render_to_buffer(W, H, rgb8(0, 0, 0), &mut buf)
.expect("render");
assert_eq!(r.pick_at(20, 20), Some(7));
assert_eq!(r.pick_at(100, 100), None);
}
#[test]
fn skip_does_not_disturb_underlying_pick() {
let mut r = VelloRenderer::with_picking().expect("vello renderer init");
{
let scene = r.scene();
let red: Brush = rgb8(220, 60, 60).into();
let yellow: Brush = rgb8(220, 220, 60).into();
let big = Rect::new(0.0, 0.0, W as f64, H as f64).to_path(0.1);
let overlay = Rect::new(80.0, 80.0, 120.0, 120.0).to_path(0.1);
scene.fill(
FillRule::NonZero,
Affine::IDENTITY,
&red,
None,
&big,
PickId::Id(7),
);
scene.fill(
FillRule::NonZero,
Affine::IDENTITY,
&yellow,
None,
&overlay,
PickId::Skip,
);
}
let mut buf = fresh_buf();
r.render_to_buffer(W, H, rgb8(0, 0, 0), &mut buf)
.expect("render");
assert_eq!(r.pick_at(20, 20), Some(7));
assert_eq!(r.pick_at(100, 100), Some(7));
}
#[test]
fn empty_space_around_a_mark_reports_no_id() {
let mut r = VelloRenderer::with_picking().expect("vello renderer init");
let (w, h) = (128u32, 128u32);
let id = 200u32;
{
let scene = r.scene();
scene.clear();
let brush: Brush = rgb8(200, 90, 40).into();
let circle = kurbo::Circle::new(Point::new(64.0, 64.0), 30.0).to_path(0.1);
scene.fill(
FillRule::NonZero,
Affine::IDENTITY,
&brush,
None,
&circle,
PickId::Id(id),
);
}
let mut pixels = vec![0u8; (w * h * 4) as usize];
r.render_to_buffer(w, h, rgb8(20, 22, 28), &mut pixels)
.expect("render");
let hitmap = r.hitmap().expect("picking enabled");
let mut phantom = Vec::new();
for (i, &px) in hitmap.iter().enumerate() {
if let Some(found) = hephaestus::pick::decode(px) {
if found != id {
phantom.push((i % w as usize, i / w as usize, found));
}
}
}
assert!(
phantom.is_empty(),
"{} pixels reported an id other than {id}; first few: {:?}",
phantom.len(),
&phantom[..phantom.len().min(5)]
);
assert_eq!(r.pick_at(64, 64), Some(id));
assert_eq!(r.pick_at(64, 100), None);
}