use std::fmt::Write as FmtWrite;
use crate::gerber::apertures::ApertureDictionary;
use crate::gerber::coordinates::Coord;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FilePolarity {
Positive,
Negative,
}
impl FilePolarity {
fn as_str(self) -> &'static str {
match self {
Self::Positive => "Positive",
Self::Negative => "Negative",
}
}
}
pub struct GerberWriter {
buffer: String,
current_aperture: Option<u32>,
}
impl GerberWriter {
pub fn new(
title: &str,
file_function: &str,
polarity: FilePolarity,
apertures: &ApertureDictionary,
) -> Self {
let mut buffer = String::with_capacity(8192);
let _ = writeln!(buffer, "G04 =========================================*");
let _ = writeln!(buffer, "G04 Fusible Pure-Rust Gerber Generator *");
let _ = writeln!(buffer, "G04 Layer: {title:<33} *");
let _ = writeln!(buffer, "G04 =========================================*");
let _ = writeln!(buffer, "%FSLAX46Y46*%");
let _ = writeln!(buffer, "%MOMM*%");
let _ = writeln!(
buffer,
"%TF.GenerationSoftware,Fusible,Fusible,{}*%",
env!("CARGO_PKG_VERSION")
);
let _ = writeln!(buffer, "%TF.FileFunction,{file_function}*%");
let _ = writeln!(buffer, "%TF.FilePolarity,{}*%", polarity.as_str());
apertures.write_definitions(&mut buffer);
let _ = writeln!(buffer, "%LPD*%");
let _ = writeln!(buffer, "G01*");
Self {
buffer,
current_aperture: None,
}
}
pub fn select_aperture(&mut self, id: u32) {
if self.current_aperture != Some(id) {
let _ = writeln!(self.buffer, "D{id}*");
self.current_aperture = Some(id);
}
}
pub fn move_to(&mut self, x: Coord, y: Coord) {
let _ = writeln!(
self.buffer,
"X{}Y{}D02*",
x.format_gerber(),
y.format_gerber()
);
}
pub fn draw_to(&mut self, x: Coord, y: Coord) {
let _ = writeln!(
self.buffer,
"X{}Y{}D01*",
x.format_gerber(),
y.format_gerber()
);
}
pub fn flash(&mut self, x: Coord, y: Coord) {
let _ = writeln!(
self.buffer,
"X{}Y{}D03*",
x.format_gerber(),
y.format_gerber()
);
}
pub fn region(&mut self, points: &[[Coord; 2]]) {
let Some(&[fx, fy]) = points.first() else {
return;
};
let _ = writeln!(self.buffer, "G36*");
self.move_to(fx, fy);
for &[x, y] in &points[1..] {
self.draw_to(x, y);
}
self.draw_to(fx, fy);
let _ = writeln!(self.buffer, "G37*");
}
pub fn finish(mut self) -> String {
let _ = writeln!(self.buffer, "M02*");
self.buffer
}
}