mod bounds;
mod copper;
mod legend;
use super::writer::SvgWriter;
use crate::gerber::layers::PcbModel;
pub struct PcbPalette {
pub substrate: &'static str,
pub board_edge: &'static str,
pub top_copper: &'static str,
pub bottom_copper: &'static str,
pub pad_gold: &'static str,
pub drill_hole: &'static str,
pub silkscreen: &'static str,
}
pub const DEFAULT_PALETTE: PcbPalette = PcbPalette {
substrate: "#182a1d",
board_edge: "#2d5a37",
top_copper: "#cf8a3c",
bottom_copper: "#3b5284",
pad_gold: "#e6c35c",
drill_hole: "#0a0a0f",
silkscreen: "#f7fafc",
};
const CANVAS_MARGIN_MM: f64 = 5.0;
pub fn render_pcb(model: &PcbModel) -> String {
let mut writer = SvgWriter::new();
let bounds = bounds::calculate_bounds(model);
let margin = CANVAS_MARGIN_MM;
let view_w = (bounds.max_x - bounds.min_x) + (margin * 2.0);
let view_h = (bounds.max_y - bounds.min_y) + (margin * 2.0);
writer.start_svg(
[view_w, view_h],
[bounds.min_x - margin, bounds.min_y - margin, view_w, view_h],
);
group(&mut writer, "substrate", None, |w| {
legend::render_substrate(w, &model.boards, &bounds)
});
group(&mut writer, "bottom_copper", Some(0.6), |w| {
copper::render_copper_traces(w, model, "bottom", DEFAULT_PALETTE.bottom_copper)
});
group(&mut writer, "top_copper", None, |w| {
copper::render_copper_traces(w, model, "top", DEFAULT_PALETTE.top_copper)
});
group(&mut writer, "pads", None, |w| copper::render_pads(w, model));
group(&mut writer, "holes_and_vias", None, |w| {
copper::render_holes_and_vias(w, model)
});
group(&mut writer, "silkscreen", None, |w| {
legend::render_silkscreen(w, model)
});
writer.end_svg();
writer.finish()
}
fn group(
writer: &mut SvgWriter,
id: &str,
opacity: Option<f64>,
draw: impl FnOnce(&mut SvgWriter),
) {
writer.start_group(id, opacity);
draw(writer);
writer.end_group();
}
fn polyline<'a>(points: impl IntoIterator<Item = &'a crate::gerber::layers::PcbPoint>) -> String {
let mut d = String::new();
for (i, pt) in points.into_iter().enumerate() {
let cmd = if i == 0 { "M" } else { "L" };
d.push_str(&format!("{cmd} {:.3} {:.3} ", pt.x, -pt.y));
}
d
}