Siphon/examples/render_board.rs

82 lines
2.6 KiB
Rust

use std::path::PathBuf;
use std::time::Instant;
use siphon::geom::BBox;
use siphon::render::render as render_board;
use siphon::{render_to_svg, LibraryResolver, RenderOptions, SvgSink};
fn main() {
let path: PathBuf = std::env::args().nth(1)
.expect("usage: render_board <path/to/board.kicad_pcb> [out.svg]")
.into();
let out: PathBuf = std::env::args().nth(2)
.map(Into::into)
.unwrap_or_else(|| {
let stem = path.file_stem().unwrap_or_default().to_string_lossy().to_string();
PathBuf::from(format!("/tmp/siphon_{stem}.svg"))
});
let source = std::fs::read_to_string(&path).expect("read board");
let project_dir = path.parent().unwrap_or_else(|| std::path::Path::new("."));
let _ = LibraryResolver::from_global().and_then(|r| r.with_project(project_dir));
let t0 = Instant::now();
let svg = render_to_svg(&source, &RenderOptions::default()).expect("render");
let dt = t0.elapsed();
let board = siphon::parse::board::parse(&source).expect("parse");
let stats = count_items(&board);
println!(
"render {:?}{} bytes in {:?}\n items: {} tracks, {} arcs, {} vias, {} gr_*, {} footprints, {} zones ({} fills), {} dims, {} texts",
path.file_name().unwrap(),
svg.len(),
dt,
stats.tracks, stats.arcs, stats.vias, stats.gr, stats.footprints,
stats.zones, stats.zone_fills, stats.dims, stats.texts,
);
std::fs::write(&out, svg).expect("write");
println!("wrote {}", out.display());
let mut sink = SvgSink::new(BBox::empty());
let bb = render_board(&board, &mut sink, &RenderOptions::default());
sink.bounds = bb;
}
#[derive(Default)]
struct Stats {
tracks: usize,
arcs: usize,
vias: usize,
gr: usize,
footprints: usize,
zones: usize,
zone_fills: usize,
dims: usize,
texts: usize,
}
fn count_items(board: &siphon::Board) -> Stats {
use siphon::Item;
let mut s = Stats::default();
for item in &board.items {
match item {
Item::Segment(_) => s.tracks += 1,
Item::Arc(_) => s.arcs += 1,
Item::Via(_) => s.vias += 1,
Item::GrLine(_) | Item::GrArc(_) | Item::GrRect(_) | Item::GrCircle(_) | Item::GrPoly(_) => s.gr += 1,
Item::GrText(_) => s.texts += 1,
Item::Footprint(f) => {
s.footprints += 1;
s.texts += f.texts.len();
}
Item::Zone(z) => {
s.zones += 1;
s.zone_fills += z.filled_polygons.len();
}
Item::Dimension(_) => s.dims += 1,
}
}
s
}