82 lines
2.6 KiB
Rust
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
|
|
}
|