2025-03-03 12:18:52 +00:00
|
|
|
use std::{fs::File, io::{BufWriter, Write}};
|
|
|
|
|
|
|
|
use crate::font::{GlyphHeader, GlyphPoint};
|
|
|
|
|
|
|
|
use super::Visitor;
|
|
|
|
|
|
|
|
pub struct SvgWriter {
|
|
|
|
first_point: bool,
|
2025-03-03 16:21:55 +00:00
|
|
|
last_on_curve: bool,
|
|
|
|
final_point: Option<(i32, i32)>,
|
|
|
|
final_control: Option<(i32, i32)>,
|
2025-03-03 12:18:52 +00:00
|
|
|
writer: BufWriter<File>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SvgWriter {
|
|
|
|
pub fn new(file: File) -> Self {
|
|
|
|
SvgWriter {
|
|
|
|
first_point: true,
|
2025-03-03 16:21:55 +00:00
|
|
|
last_on_curve: false,
|
|
|
|
final_control: None,
|
|
|
|
final_point: None,
|
2025-03-03 12:18:52 +00:00
|
|
|
writer: BufWriter::new(file)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Visitor for SvgWriter {
|
|
|
|
fn write_prefix(&mut self, header: &GlyphHeader) {
|
|
|
|
write!(
|
|
|
|
self.writer,
|
|
|
|
"<svg width=\"1000\" height=\"1000\" viewBox=\"{} {} {} {}\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"",
|
2025-03-03 16:21:55 +00:00
|
|
|
header.xmin, -header.ymax,
|
2025-03-03 12:18:52 +00:00
|
|
|
header.xmax - header.xmin,
|
|
|
|
header.ymax - header.ymin
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_point(&mut self, point: &GlyphPoint) {
|
2025-03-03 16:21:55 +00:00
|
|
|
if self.final_point.is_none() && point.on_curve {
|
|
|
|
self.final_point = Some((point.x, point.y));
|
2025-03-03 12:18:52 +00:00
|
|
|
}
|
|
|
|
|
2025-03-03 16:21:55 +00:00
|
|
|
if self.first_point && self.final_control.is_none() && !point.on_curve {
|
|
|
|
self.final_control = Some((point.x, point.y));
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.first_point {
|
|
|
|
if !point.on_curve {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(self.writer, "M{} {} ", point.x, -point.y);
|
|
|
|
self.first_point = false;
|
|
|
|
self.last_on_curve = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let prefix = if point.on_curve { if self.last_on_curve { "L" } else { "" } } else { "Q" };
|
|
|
|
self.last_on_curve = point.on_curve;
|
2025-03-03 12:18:52 +00:00
|
|
|
|
|
|
|
write!(
|
|
|
|
self.writer,
|
|
|
|
"{prefix}{} {} ",
|
2025-03-03 16:21:55 +00:00
|
|
|
point.x, -point.y
|
2025-03-03 12:18:52 +00:00
|
|
|
);
|
|
|
|
|
2025-03-03 16:21:55 +00:00
|
|
|
if point.is_endpoint {
|
|
|
|
if let Some(final_control) = self.final_control {
|
|
|
|
if let Some(final_point) = self.final_point {
|
|
|
|
write!(self.writer, "Q{} {} {} {} ", final_control.0, -final_control.1, final_point.0, -final_point.1);
|
|
|
|
} else {
|
|
|
|
write!(self.writer, "Z ");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
write!(self.writer, "Z ");
|
|
|
|
}
|
|
|
|
|
|
|
|
self.final_point = None;
|
|
|
|
self.final_control = None;
|
|
|
|
}
|
|
|
|
self.first_point = point.is_endpoint;
|
2025-03-03 12:18:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn write_suffix(&mut self) {
|
|
|
|
write!(
|
|
|
|
self.writer,
|
|
|
|
"\" style=\"fill:none; stroke:black; stroke-width:3;\" /></svg>"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|