Skip to content

Instantly share code, notes, and snippets.

@bynect
Created August 29, 2021 13:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bynect/cfd704d2125ba1d352e97d1b34f70d87 to your computer and use it in GitHub Desktop.
Save bynect/cfd704d2125ba1d352e97d1b34f70d87 to your computer and use it in GitHub Desktop.
Mini svg library in Rust
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