//! `cargo run --release -p drawcraft-render --example bench` — render timing on synthetic documents. use drawcraft_color::{Color, Paint}; use drawcraft_doc::{Appearance, Document, Node}; use drawcraft_geom::{Affine, Point, Rect, shapes}; use drawcraft_render::{RenderOptions, Renderer}; fn rng(seed: &mut u64) -> f64 { *seed ^= *seed << 13; *seed ^= *seed >> 7; *seed ^= *seed << 17; (*seed % 1_000_000) as f64 / 1_000_000.0 } fn main() { let n: usize = std::env::args().nth(1).and_then(|s| s.parse().ok()).unwrap_or(20_000); let mut d = Document::new(1600.0, 1200.0); let l = d.layers[0].id; let mut seed = 42u64; for i in 0..n { let x = rng(&mut seed) * 1600.0; let y = rng(&mut seed) * 1200.0; let r = 3.0 + rng(&mut seed) * 22.0; let c = Color::rgb(rng(&mut seed) as f32, rng(&mut seed) as f32, rng(&mut seed) as f32); let id = d.alloc_id(); let mut node = match i % 3 { 0 => Node::path( id, shapes::ellipse(Rect::from_center_size(Point::new(x, y), (2.0 * r, 2.0 * r))), Appearance::basic(Paint::solid(c), Paint::solid(Color::BLACK), 0.5), ), 1 => Node::path(id, shapes::rectangle(Rect::new(x, y, x + 2.0 * r, y + r)), Appearance::basic(Paint::solid(c), Paint::None, 0.0)), _ => Node::path(id, shapes::star(Point::new(x, y), r, r / 2.0, 5, 0.0), Appearance::basic(Paint::None, Paint::solid(c), 2.0)), }; if i % 3 == 1 { node.opacity = 0.8; } d.insert(Some(l), usize::MAX, node).unwrap(); } // Text objects (1 per 20 shapes). for i in 0..n / 20 { let x = rng(&mut seed) * 1500.0; let y = rng(&mut seed) * 1150.0 + 20.0; let id = d.alloc_id(); let t = drawcraft_doc::TextObject::point(Point::new(x, y), &format!("Label {i} — DrawCraft"), drawcraft_doc::CharStyle { size: 10.0 + (i % 5) as f64 * 4.0, ..Default::default() }); d.insert(Some(l), usize::MAX, Node::new(id, drawcraft_doc::NodeKind::Text(Box::new(t)))).unwrap(); } let mut r = Renderer::new(); let opts = RenderOptions::default(); for (label, w, h, view) in [ ("fit 2880x1800", 2880u32, 1800u32, Affine::scale(1.6)), ("zoom 400% 2880x1800", 2880, 1800, Affine::scale(6.4) * Affine::translate((-600.0, -400.0))), ("thumb 400x300", 400, 300, Affine::scale(0.25)), ] { r.render(&d, w, h, view, &opts); // warm up let t = std::time::Instant::now(); let iters = 5; for _ in 0..iters { r.render(&d, w, h, view, &opts); } println!( "{n} objects, {label}: {:.1} ms/frame (drawn {}, culled {})", t.elapsed().as_secs_f64() * 1000.0 / iters as f64, r.stats.drawn, r.stats.culled ); } }