[librsvg/librsvg-2.46] AcquiredNodes: Only push nodes which are accessed by reference



commit cfb84808e783954f281fde51a62d27e5ecde8db7
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Oct 15 08:46:05 2019 -0500

    AcquiredNodes: Only push nodes which are accessed by reference
    
    "Indirect" nodes like pattern, linearGradient, etc. are the ones
    normally only used through a reference from a fill="url(#...)",
    filter="url(#...)", etc.  These indirect nodes, can cause "direct"
    nodes to be referenced, which can in turn reference other indirect
    nodes, thus causing a potential reference cycle.
    
    We now only push indirect nodes into the stack of acquired nodes -
    that is, only nodes that are only used by reference.
    
    Direct nodes like <use> which always cause other nodes to be
    referenced will have to add themselves to the stack, as in upcoming
    commits.

 rsvg_internals/src/drawing_ctx.rs | 41 +++++++++++++++++++++++++++++++--------
 1 file changed, 33 insertions(+), 8 deletions(-)
---
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index cc22d43e..589ed501 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -1138,19 +1138,44 @@ impl AcquiredNodes {
     ) -> Result<AcquiredNode, AcquireError> {
         let node = self.lookup_node(fragment, node_types)?;
 
-        if self.node_stack.borrow().contains(&node) {
-            Err(AcquireError::CircularReference(fragment.clone()))
+        if node_is_accessed_by_reference(&node) {
+            if self.node_stack.borrow().contains(&node) {
+                Err(AcquireError::CircularReference(fragment.clone()))
+            } else {
+                self.node_stack.borrow_mut().push(&node);
+                Ok(AcquiredNode {
+                    stack: Some(self.node_stack.clone()),
+                    node: node.clone()
+                })
+            }
         } else {
-            self.node_stack.borrow_mut().push(&node);
-            let acquired = AcquiredNode {
-                stack: Some(self.node_stack.clone()),
-                node: node.clone()
-            };
-            Ok(acquired)
+            Ok(AcquiredNode {
+                stack: None,
+                node: node.clone(),
+            })
         }
     }
 }
 
+// Returns whether a node of a particular type is only accessed by reference
+// from other nodes' atributes.  The node could in turn cause other nodes
+// to get referenced, potentially causing reference cycles.
+fn node_is_accessed_by_reference(node: &RsvgNode) -> bool {
+    use NodeType::*;
+
+    match node.borrow().get_type() {
+        ClipPath |
+        Filter |
+        LinearGradient |
+        Marker |
+        Mask |
+        Pattern |
+        RadialGradient => true,
+
+        _ => false,
+    }
+}
+
 /// Keeps a stack of nodes and can check if a certain node is contained in the stack
 ///
 /// Sometimes parts of the code cannot plainly use the implicit stack of acquired


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]