use std::{fs::File, io::{BufWriter, Write}}; use crate::font::{GlyphHeader, GlyphPoint, SplineElement}; use super::Visitor; pub struct SvgWriter { first_point: bool, writer: BufWriter, points: Vec<(i32, i32)>, control_points: Vec<(i32, i32)>, virtual_points: Vec<(i32, i32)> } impl SvgWriter { pub fn new(file: File) -> Self { SvgWriter { first_point: true, writer: BufWriter::new(file), points: vec![], control_points: vec![], virtual_points: vec![] } } } impl SvgWriter { fn handle_start_point(&mut self, point: &GlyphPoint) { if self.first_point { write!(self.writer, "M{} {} ", point.x, -point.y); self.first_point = false; } } fn handle_end_point(&mut self, point: &GlyphPoint) { if point.is_endpoint { self.first_point = true; } } fn write_points(writer: &mut BufWriter, points: &Vec<(i32, i32)>, color: &'static str) { for (x, y) in points { write!(writer, ""); } } } impl Visitor for SvgWriter { fn write_prefix(&mut self, header: &GlyphHeader) { write!( self.writer, " { self.handle_start_point(start); write!(self.writer, "L{} {} ", end.x, -end.y); self.points.push((start.x, -start.y)); self.handle_end_point(start); }, SplineElement::Bezier(start, control, end) => { self.handle_start_point(start); write!(self.writer, "Q{} {} {} {} ", control.x, -control.y, end.x, -end.y); if start.is_virtual { self.virtual_points.push((start.x, -start.y)); } else { self.points.push((start.x, -start.y)); } self.control_points.push((control.x, -control.y)); self.handle_end_point(start); } } } fn write_suffix(&mut self) { write!( self.writer, "\" style=\"fill:none; stroke:black; stroke-width:3;\" />" ); SvgWriter::write_points(&mut self.writer, &self.points, "red"); SvgWriter::write_points(&mut self.writer, &self.control_points, "blue"); SvgWriter::write_points(&mut self.writer, &self.virtual_points, "green"); write!(self.writer, ""); } }