//! Constellation rendering (docs/06): deterministic layout, SVG sky, PNG card. pub mod layout; pub mod svg; /// OG/badge image: the same renderer at card dimensions (docs/06 — the /// shareable-badge requirement solved by reuse). pub fn render_card_png(l: &layout::Layout, title: &str) -> anyhow::Result> { let svg_str = svg::render_sky( l, &svg::SvgOptions { width: 1200, height: 630, focus: None, card: true, title: title.to_string(), }, ); let mut opts = resvg::usvg::Options::default(); // Text nodes are dropped without fonts; load the system set once per render // (cards are cold-path, cost is acceptable). opts.fontdb_mut().load_system_fonts(); let tree = resvg::usvg::Tree::from_str(&svg_str, &opts)?; let mut pixmap = resvg::tiny_skia::Pixmap::new(1200, 630) .ok_or_else(|| anyhow::anyhow!("pixmap alloc failed"))?; // Letterbox in sky color, not transparency. pixmap.fill(resvg::tiny_skia::Color::from_rgba8(5, 6, 15, 255)); // usvg already fits the 1000×1000 viewBox into the svg's declared // 1200×630 canvas (xMidYMid meet), so render with identity. resvg::render(&tree, resvg::tiny_skia::Transform::identity(), &mut pixmap.as_mut()); Ok(pixmap.encode_png()?) }