Skip to content

Commit

Permalink
Simplify svgtree a bit.
Browse files Browse the repository at this point in the history
  • Loading branch information
RazrFalcon committed Oct 23, 2022
1 parent d9c9fd9 commit 312f90d
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 43 deletions.
50 changes: 11 additions & 39 deletions usvg/src/svgtree/mod.rs
Expand Up @@ -120,6 +120,7 @@ impl std::fmt::Debug for Document {
}
}

// TODO: use u32
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct NodeId(usize);

Expand All @@ -138,7 +139,6 @@ enum NodeKind {

struct NodeData {
parent: Option<NodeId>,
prev_sibling: Option<NodeId>,
next_sibling: Option<NodeId>,
children: Option<(NodeId, NodeId)>,
kind: NodeKind,
Expand Down Expand Up @@ -363,10 +363,6 @@ impl<'a> Node<'a> {
self.ancestors().skip(1).find(|n| n.is_element())
}

pub fn prev_sibling(&self) -> Option<Self> {
self.d.prev_sibling.map(|id| self.gen_node(id))
}

pub fn next_sibling(&self) -> Option<Self> {
self.d.next_sibling.map(|id| self.gen_node(id))
}
Expand Down Expand Up @@ -510,30 +506,18 @@ impl std::fmt::Debug for Node<'_> {
}
}

macro_rules! axis_iterators {
($($i:ident($f:path);)*) => {
$(
#[derive(Clone)]
pub struct $i<'a>(Option<Node<'a>>);

impl<'a> Iterator for $i<'a> {
type Item = Node<'a>;
#[derive(Clone)]
pub struct Ancestors<'a>(Option<Node<'a>>);

#[inline]
fn next(&mut self) -> Option<Self::Item> {
let node = self.0.take();
self.0 = node.as_ref().and_then($f);
node
}
}
)*
};
}
impl<'a> Iterator for Ancestors<'a> {
type Item = Node<'a>;

axis_iterators! {
Ancestors(Node::parent);
PrevSiblings(Node::prev_sibling);
NextSiblings(Node::next_sibling);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let node = self.0.take();
self.0 = node.as_ref().and_then(Node::parent);
node
}
}

#[derive(Clone)]
Expand All @@ -556,18 +540,6 @@ impl<'a> Iterator for Children<'a> {
}
}

impl<'a> DoubleEndedIterator for Children<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
let node = self.back.take();
if self.back == self.front {
self.front = None;
} else {
self.back = node.as_ref().and_then(Node::prev_sibling);
}
node
}
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Edge<'a> {
Open(Node<'a>),
Expand Down
8 changes: 4 additions & 4 deletions usvg/src/svgtree/parse.rs
Expand Up @@ -22,14 +22,12 @@ impl Document {
let new_child_id = NodeId(self.nodes.len());
self.nodes.push(NodeData {
parent: Some(parent_id),
prev_sibling: None,
next_sibling: None,
children: None,
kind,
});

let last_child_id = self.nodes[parent_id.0].children.map(|(_, id)| id);
self.nodes[new_child_id.0].prev_sibling = last_child_id;

if let Some(id) = last_child_id {
self.nodes[id.0].next_sibling = Some(new_child_id);
Expand Down Expand Up @@ -71,7 +69,6 @@ fn parse(xml: &roxmltree::Document) -> Result<Document, Error> {
// Add a root node.
doc.nodes.push(NodeData {
parent: None,
prev_sibling: None,
next_sibling: None,
children: None,
kind: NodeKind::Root,
Expand Down Expand Up @@ -251,10 +248,11 @@ pub(super) fn parse_svg_element(
for rule in &style_sheet.rules {
if rule.selector.matches(&XmlNode(xml_node)) {
for declaration in &rule.declarations {
// TODO: preform XML attribute normalization
// TODO: perform XML attribute normalization
if let Some(aid) = AId::from_str(declaration.name) {
// Parse only the presentation attributes.
// `transform` isn't a presentation attribute, but should be parsed anyway.
// TODO: `transform` is presentation in SVG 2?
if aid.is_presentation() || aid == AId::Transform {
insert_attribute(aid, declaration.value);
}
Expand Down Expand Up @@ -331,6 +329,7 @@ fn parse_svg_attribute(tag_name: EId, aid: AId, value: &str) -> Option<Attribute
// `href` can contain base64 data and we do store it as is.
match svgtypes::IRI::from_str(value) {
Ok(link) => AttributeValue::Link(link.0.to_string()),
// TODO: avoid string allocation
Err(_) => AttributeValue::String(value.to_string()),
}
}
Expand Down Expand Up @@ -551,6 +550,7 @@ fn parse_svg_attribute(tag_name: EId, aid: AId, value: &str) -> Option<Attribute
})
}

// TODO: move to svgtypes
#[inline(never)]
fn parse_path(text: &str) -> crate::PathData {
// Previous MoveTo coordinates.
Expand Down

0 comments on commit 312f90d

Please sign in to comment.