extern crate rctree;
use std::cell::Ref;
use std::path;
use svgdom;
pub use self::node::*;
pub use self::attribute::*;
pub use self::io::load_svg_file;
use {
Error,
Options,
};
mod attribute;
mod convert;
mod node;
mod io;
pub mod prelude {
pub use tree::FuzzyEq;
pub use tree::FuzzyZero;
pub use super::NodeExt;
}
pub type Node = rctree::Node<NodeKind>;
pub struct Tree {
root: Node,
}
impl Tree {
pub fn from_data(data: &[u8], opt: &Options) -> Result<Self, Error> {
if data.starts_with(&[0x1f, 0x8b]) {
let text = io::deflate(data, data.len())?;
Ok(Self::from_str(&text, opt))
} else {
let text = ::std::str::from_utf8(data).map_err(|_| Error::NotAnUtf8Str)?;
Ok(Self::from_str(text, opt))
}
}
pub fn from_str(text: &str, opt: &Options) -> Self {
let doc = io::parse_dom(text);
Self::from_dom(doc, opt)
}
pub fn from_dom(mut doc: svgdom::Document, opt: &Options) -> Self {
super::preproc::prepare_doc(&mut doc, opt);
super::convert::convert_doc(&doc, opt)
}
pub fn from_file<P: AsRef<path::Path>>(
path: P,
opt: &Options,
) -> Result<Self, Error> {
let text = io::load_svg_file(path.as_ref())?;
Ok(Self::from_str(&text, opt))
}
pub fn create(svg: Svg) -> Self {
let mut root_node = Node::new(NodeKind::Svg(svg));
let defs_node = Node::new(NodeKind::Defs);
root_node.append(defs_node);
Tree {
root: root_node,
}
}
pub fn root(&self) -> Node {
self.root.clone()
}
pub fn svg_node(&self) -> Ref<Svg> {
Ref::map(self.root.borrow(), |v| {
match *v {
NodeKind::Svg(ref svg) => svg,
_ => unreachable!(),
}
})
}
pub fn defs(&self) -> Node {
self.root.first_child().unwrap()
}
pub fn is_in_defs(&self, node: &Node) -> bool {
let defs = self.defs();
node.ancestors().any(|n| n == defs)
}
pub fn append_to_defs(&mut self, kind: NodeKind) -> Node {
let new_node = Node::new(kind);
self.defs().append(new_node.clone());
new_node
}
pub fn defs_by_id(&self, id: &str) -> Option<Node> {
for n in self.defs().children() {
if &*n.id() == id {
return Some(n);
}
}
None
}
pub fn node_by_id(&self, id: &str) -> Option<Node> {
if id.is_empty() {
return None;
}
for node in self.root().descendants() {
if !self.is_in_defs(&node) {
if &*node.id() == id {
return Some(node);
}
}
}
None
}
pub fn to_svgdom(&self) -> svgdom::Document {
convert::conv_doc(self)
}
}
pub trait NodeExt {
fn id(&self) -> Ref<str>;
fn transform(&self) -> Transform;
fn append_kind(&mut self, kind: NodeKind) -> Node;
fn tree(&self) -> Tree;
}
impl NodeExt for Node {
fn id(&self) -> Ref<str> {
Ref::map(self.borrow(), |v| v.id())
}
fn transform(&self) -> Transform {
self.borrow().transform()
}
fn append_kind(&mut self, kind: NodeKind) -> Node {
let new_node = Node::new(kind);
self.append(new_node.clone());
new_node
}
fn tree(&self) -> Tree {
Tree { root: self.root() }
}
}