///|
/// `ParamPair` represents an X,Y absolute coordinate pair of parameters.
pub(all) struct ParamPair {
x : Double
y : Double
} derive(Eq)
///|
pub fn ParamPair::to_string(self : ParamPair) -> String {
"(\{svg_num(self.x)},\{svg_num(self.y)})"
}
///|
impl Show for ParamPair with output(self, logger) {
logger.write_string(self.to_string())
}
///|
/// `Cmd` represents an individual absolute SVG command.
pub(all) struct PathCmd {
cmd : AbsoluteCmd
gerber_lp : GerberLP
params : Array[ParamPair]
} derive(Show, Eq)
///|
pub fn PathCmd::from_svg_cmd(
svg_cmd : Cmd,
gerber_lp : GerberLP,
) -> PathCmd raise FontError {
let cmd = match svg_cmd.c {
"M" => M
"L" => L
"C" => C
"Q" => Q
"Z" => Z
c =>
raise FontError("PathCmd::from_svg_cmd: unsupported SVG command '\{c}'")
}
if svg_cmd.p.inner().length() % 2 != 0 {
raise FontError(
"PathCmd::from_svg_cmd: unexpected odd params length in svg_cmd: \{svg_cmd}",
)
}
//
let params : Array[ParamPair] = Array::new(
capacity=svg_cmd.p.inner().length() / 2,
)
let mut x = 0.0
for index, param in svg_cmd.p.inner() {
if index % 2 == 0 {
x = param
} else {
params.push({ x, y: param })
}
}
//
{ cmd, gerber_lp, params }
}
///|
pub fn PathCmd::to_svg_cmd(self : PathCmd) -> (Cmd, String) {
let gerber_lp = match self.cmd {
M =>
match self.gerber_lp {
Dark => "d"
Clear => "c"
}
_ => ""
}
let p : Array[Double] = Array::new(capacity=self.params.length() * 2)
for pp in self.params {
p.push(pp.x)
p.push(pp.y)
}
let c = "\{self.cmd}"
let cmd = { c, p }
(cmd, gerber_lp)
}
///|
/// `bbox` returns the minimum bounding box of a PathCmd.
pub fn bbox(self : PathCmd) -> Rectangle {
let r = Rectangle::new()
for index, pp in self.params {
if index == 0 {
r.min.x = pp.x
r.min.y = pp.y
r.max.x = pp.x
r.max.y = pp.y
} else {
r.extend(pt(pp.x, pp.y))
}
}
r
}
///|
/// `PathCmdFn` represents a function that processes or transforms individual commands.
/// The first argument is the index within the command.
pub(all) struct PathCmdFn((Int, PathCmd) -> PathCmd)
///|
/// `clone` makes a deep copy of a PatchCmd.
pub fn PathCmd::clone(self : PathCmd) -> PathCmd {
let params = Array::new(capacity=self.params.length())
for param in self.params {
let pp : ParamPair = { x: param.x, y: param.y }
params.push(pp)
}
{ cmd: self.cmd, gerber_lp: self.gerber_lp, params }
}