Created
August 29, 2021 13:13
-
-
Save bynect/cfd704d2125ba1d352e97d1b34f70d87 to your computer and use it in GitHub Desktop.
Mini svg library in Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub struct SVG { | |
text: String, | |
height: usize, | |
width: usize, | |
} | |
const INDENT: &str = " "; | |
const XMLNS: &str = "http://www.w3.org/2000/svg"; | |
const XLINK: &str = "http://www.w3.org/1999/xlink"; | |
impl SVG { | |
pub fn new(height: usize, width: usize) -> Self { | |
let text = format!( | |
"<svg height='{}px' width='{}px' version='1.1' xmlns='{}' xmlns:xlink='{}'>\n", | |
height, width, XMLNS, XLINK | |
); | |
Self { | |
text, | |
height, | |
width, | |
} | |
} | |
pub fn done(mut self) -> String { | |
self.text.push_str("</svg>"); | |
self.text | |
} | |
pub fn rectangle(&mut self, height: usize, width: usize, x: usize, y: usize, fill: &str, stroke: (&str, usize), rx: usize, ry: usize) { | |
self.text.push_str( | |
&format!( | |
"{}<rect fill='{}' stroke='{}' stroke-width='{}px' height='{}' width='{}' x='{}' y='{}' rx='{}' ry='{}' />\n", | |
INDENT, fill, stroke.0, stroke.1, height, width, x, y, rx, ry | |
) | |
); | |
} | |
pub fn fill(&mut self, fill: &str) { | |
self.rectangle(self.height, self.width, 0, 0, fill, (fill, 0), 0, 0); | |
} | |
pub fn line(&mut self, stroke: (&str, usize), x1: usize, y1: usize, x2: usize, y2: usize) { | |
self.text.push_str( | |
&format!( | |
"{}<line stroke='{}' stroke-width='{}px' x1='{}' y1='{}' x2='{}' y2='{}' />\n", | |
INDENT, stroke.0, stroke.1, x1, y1, x2, y2 | |
) | |
); | |
} | |
pub fn text(&mut self, font: (&str, usize), fill: &str, stroke: (&str, usize), x: usize, y: usize, text: &str) { | |
self.text.push_str( | |
&format!( | |
"{}<text font-family='{}' font-size='{}px' fill='{}' stroke='{}' stroke-width='{}px' x='{}' y='{}'>{}</text>\n", | |
INDENT, font.0, font.1, fill, stroke.0, stroke.1, x, y, text | |
) | |
); | |
} | |
pub fn circle(&mut self, fill: &str, stroke: (&str, usize), x: usize, y: usize, r: usize) { | |
self.text.push_str( | |
&format!( | |
"{}<circle fill='{}' stroke='{}' stroke-width='{}px' cx='{}' cy='{}' r='{}' />\n", | |
INDENT, fill, stroke.0, stroke.1, x, y, r | |
) | |
); | |
} | |
pub fn ellipse(&mut self, fill: &str, stroke: (&str, usize), x: usize, y: usize, rx: usize, ry: usize) { | |
self.text.push_str( | |
&format!( | |
"{}<ellipse fill='{}' stroke='{}' stroke-width='{}px' cx='{}' cy='{}' rx='{}' ry='{}' />\n", | |
INDENT, fill, stroke.0, stroke.1, x, y, rx, ry | |
) | |
); | |
} | |
fn points(&mut self, points: &[(usize, usize)]) { | |
let len = points.len(); | |
for i in 0..len { | |
self.text.push_str(&format!("{},{} ", points[i].0, points[i].1)); | |
} | |
} | |
pub fn polygon(&mut self, fill: &str, stroke: (&str, usize), points: &[(usize, usize)]) { | |
self.text.push_str( | |
&format!( | |
"{}<polygon fill='{}' stroke='{}' stroke-width='{}px' points='", | |
INDENT, fill, stroke.0, stroke.1 | |
) | |
); | |
self.points(points); | |
self.text.push_str("' />\n"); | |
} | |
pub fn polyline(&mut self, stroke: (&str, usize), points: &[(usize, usize)]) { | |
self.text.push_str( | |
&format!( | |
"{}<polyline stroke='{}' stroke-width='{}px' points='", | |
INDENT, stroke.0, stroke.1 | |
) | |
); | |
self.points(points); | |
self.text.push_str("' />\n"); | |
} | |
} | |
// Test it! | |
use std::{io, fs}; | |
pub fn main() -> io::Result<()> { | |
let mut svg = SVG::new(512, 512); | |
svg.fill("white"); | |
svg.rectangle(320, 100, 96, 96, "#FFFF00", ("#000000", 2), 8, 8); | |
svg.rectangle(100, 320, 128, 128, "#00FFFF", ("#000000", 2), 8, 8); | |
svg.rectangle(80, 80, 160, 160, "#FF00FF", ("#000000", 2), 8, 8); | |
let doc = svg.done(); | |
fs::write("test.svg", doc) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment