use crate::compare::*;
use crate::cpu::*;
use std::path::PathBuf;
use std::collections::HashMap;
use crate::render::testing::*;
use crate::render::*;
use crate::resolve::{self, Theme};
#[test]
fn the_examples_paint_as_their_references() {
let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("testdata");
let update = std::env::var_os("DEVPAGE_UPDATE_REFERENCES").is_some();
let mut renderer = Renderer::new();
for (theme, suffix) in [(Theme::Light, ""), (Theme::Dark, "-dark")] {
for name in ["button", "checkout", "confirmation", "details"] {
let path = format!("docs/designs/checkout/{name}.design");
let scene = crate::resolve(&repo(), &path).unwrap_or_else(|p| panic!("{p:?}"));
assert!(scene.themed, "{name}");
let png = crate::png(&mut renderer, &scene, theme).unwrap();
let name = format!("{name}{suffix}");
let reference = dir.join(format!("{name}.png"));
if update {
std::fs::write(&reference, &png).unwrap();
continue;
}
let expected = resolve::decode(&std::fs::read(&reference).unwrap()).unwrap();
let painted = resolve::decode(&png).unwrap();
assert_eq!(
(painted.width, painted.height),
(expected.width, expected.height),
"{name}"
);
if let Err(d) = matches(
painted.data.data(),
expected.data.data(),
painted.width as usize,
) {
panic!("{name}: {d:?}");
}
}
}
}
#[test]
fn tiles_paint_the_examples_as_the_whole_drawing() {
let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("testdata");
let mut renderer = Renderer::new();
for (theme, suffix) in [(Theme::Light, ""), (Theme::Dark, "-dark")] {
for name in ["button", "checkout", "confirmation", "details"] {
let path = format!("docs/designs/checkout/{name}.design");
let scene = crate::resolve(&repo(), &path).unwrap();
let tiled = crate::png(&mut renderer, &scene, theme).unwrap();
let whole = std::fs::read(dir.join(format!("{name}{suffix}.png"))).unwrap();
let (a, w, h) = pixels(&whole).unwrap();
let (b, tw, th) = pixels(&tiled).unwrap();
assert_eq!((w, h), (tw, th), "{name}");
let d = compare(&a, &b, w as usize).unwrap();
assert!(d.within_tolerance(), "{name} {theme:?}: {d:?}");
assert!(d.max <= 2, "{name} {theme:?}: {d:?}");
let drawing = renderer.drawing(&scene, theme, None).unwrap();
let one = paint_area(&drawing.list, frame_rect(drawing.area()), 1.0);
let mut tile = crate::cpu::tile(&drawing.list, 1.0, 0, 0);
let mut whole = one.data_as_u8_slice().to_vec();
crate::cpu::unpremultiply(&mut whole);
let side = crate::tiles::TILE as usize;
for y in 0..side.min(h as usize) {
let n = side.min(w as usize) * 4;
let row = &whole[y * w as usize * 4..][..n];
let tr = &mut tile[y * side * 4..][..n];
for (p, q) in row.iter().zip(tr.iter()) {
assert!(p.abs_diff(*q) <= 1, "{name} tile row {y}");
}
}
}
}
}
#[test]
fn a_design_100000_pixels_tall_has_a_png() {
let mut rows = String::new();
for i in 0..1000 {
rows.push_str(&format!(
"<Frame width={{400}} height={{100}} fill=\"#{:06x}\"><Text size={{20}}>Row {i}</Text></Frame>\n",
(i * 7919) % 0xffffff
));
}
let files: HashMap<String, String> = [(
"a.design".to_string(),
format!("<Frame layout=\"column\" fill=\"#ffffff\">{rows}</Frame>"),
)]
.into();
let s = resolve::resolve(&files, "a.design").unwrap();
let mut r = Renderer::new();
let t = std::time::Instant::now();
let drawing = r.drawing(&s, Theme::Light, None).unwrap();
let list = &drawing.list;
let built = t.elapsed();
assert_eq!((list.area.width, list.area.height), (400.0, 100_000.0));
let t = std::time::Instant::now();
let mut png = Vec::new();
crate::bands::png(list, &mut png).unwrap();
eprintln!(
"built {built:?}, png {:?}, {} bytes",
t.elapsed(),
png.len()
);
let (px, w, h) = pixels(&png).unwrap();
assert_eq!((w, h), (400, 100_000));
let c = 999 * 7919;
let at = ((99_950 * 400 + 390) * 4) as usize;
assert_eq!(&px[at..at + 3], &[(c >> 16) as u8, (c >> 8) as u8, c as u8]);
let t = std::time::Instant::now();
let found = list
.query(crate::tiles::tile_rect(list, 1.0, 0, 390), 1.0)
.len();
eprintln!("query {:?}, {found} commands", t.elapsed());
assert!(found < 12, "{found}");
}