#![allow(dead_code)]
pub struct SmilAnimElement {
pub attribute_name: String,
pub from: String,
pub to: String,
pub duration_ms: u32,
pub repeat_count: String,
}
pub struct SvgAnimDocument {
pub elements: Vec<SmilAnimElement>,
pub width: u32,
pub height: u32,
}
pub fn new_svg_anim_document(width: u32, height: u32) -> SvgAnimDocument {
SvgAnimDocument {
elements: Vec::new(),
width,
height,
}
}
pub fn add_smil_element(
doc: &mut SvgAnimDocument,
attr: &str,
from: &str,
to: &str,
duration_ms: u32,
repeat: &str,
) {
doc.elements.push(SmilAnimElement {
attribute_name: attr.to_string(),
from: from.to_string(),
to: to.to_string(),
duration_ms,
repeat_count: repeat.to_string(),
});
}
pub fn total_anim_duration_ms(doc: &SvgAnimDocument) -> u32 {
doc.elements
.iter()
.map(|e| e.duration_ms)
.max()
.unwrap_or(0)
}
pub fn anim_element_count(doc: &SvgAnimDocument) -> usize {
doc.elements.len()
}
pub fn render_svg_anim(doc: &SvgAnimDocument) -> String {
format!(
r#"<svg xmlns="http://www.w3.org/2000/svg" width="{}" height="{}">{} elements</svg>"#,
doc.width,
doc.height,
doc.elements.len()
)
}
pub fn validate_svg_anim(doc: &SvgAnimDocument) -> bool {
doc.width > 0 && doc.height > 0
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_doc_empty() {
let doc = new_svg_anim_document(800, 600);
assert_eq!(anim_element_count(&doc), 0 );
}
#[test]
fn add_element_increments_count() {
let mut doc = new_svg_anim_document(100, 100);
add_smil_element(&mut doc, "opacity", "0", "1", 1000, "indefinite");
assert_eq!(anim_element_count(&doc), 1 );
}
#[test]
fn total_duration_zero_when_empty() {
let doc = new_svg_anim_document(100, 100);
assert_eq!(total_anim_duration_ms(&doc), 0 );
}
#[test]
fn total_duration_max_of_elements() {
let mut doc = new_svg_anim_document(100, 100);
add_smil_element(&mut doc, "x", "0", "100", 500, "1");
add_smil_element(&mut doc, "y", "0", "50", 1000, "1");
assert_eq!(total_anim_duration_ms(&doc), 1000 );
}
#[test]
fn validate_valid_doc() {
let doc = new_svg_anim_document(800, 600);
assert!(validate_svg_anim(&doc) );
}
#[test]
fn validate_zero_width_fails() {
let doc = new_svg_anim_document(0, 600);
assert!(!validate_svg_anim(&doc) );
}
#[test]
fn render_contains_dimensions() {
let doc = new_svg_anim_document(200, 150);
let svg = render_svg_anim(&doc);
assert!(svg.contains("200") );
assert!(svg.contains("150") );
}
#[test]
fn element_fields_stored() {
let mut doc = new_svg_anim_document(100, 100);
add_smil_element(&mut doc, "fill", "red", "blue", 2000, "3");
let e = &doc.elements[0];
assert_eq!(e.attribute_name, "fill" );
assert_eq!(e.duration_ms, 2000 );
}
#[test]
fn multiple_elements_independent() {
let mut doc = new_svg_anim_document(500, 500);
for i in 0..5 {
add_smil_element(&mut doc, "x", "0", &i.to_string(), i * 100, "1");
}
assert_eq!(anim_element_count(&doc), 5 );
}
}