Browse Source

Precalculate structural volatility

Michael Ragazzon 6 years ago
parent
commit
94a40245c6
3 changed files with 38 additions and 37 deletions
  1. 1 0
      Source/Core/StyleSheet.cpp
  2. 28 35
      Source/Core/StyleSheetNode.cpp
  3. 9 2
      Source/Core/StyleSheetNode.h

+ 1 - 0
Source/Core/StyleSheet.cpp

@@ -120,6 +120,7 @@ void StyleSheet::BuildNodeIndexAndOptimizeProperties()
 		complete_node_index.clear();
 		complete_node_index.clear();
 
 
 		root->BuildIndexAndOptimizeProperties(styled_node_index, complete_node_index, *this);
 		root->BuildIndexAndOptimizeProperties(styled_node_index, complete_node_index, *this);
+		root->SetStructurallyVolatileRecursive(false);
 	}
 	}
 }
 }
 
 

+ 28 - 35
Source/Core/StyleSheetNode.cpp

@@ -45,6 +45,8 @@ StyleSheetNode::StyleSheetNode(const String& name, NodeType _type, StyleSheetNod
 	selector = NULL;
 	selector = NULL;
 	a = 0;
 	a = 0;
 	b = 0;
 	b = 0;
+
+	is_structurally_volatile = true;
 }
 }
 
 
 // Constructs a structural style-sheet node.
 // Constructs a structural style-sheet node.
@@ -208,6 +210,29 @@ void StyleSheetNode::BuildIndexAndOptimizeProperties(StyleSheet::NodeIndex& styl
 	}
 	}
 }
 }
 
 
+
+bool StyleSheetNode::SetStructurallyVolatileRecursive(bool ancestor_is_structural_pseudo_class)
+{
+	// If any ancestor or descendant is a structural pseudo class, then we are structurally volatile.
+	bool self_is_structural_pseudo_class = (type == STRUCTURAL_PSEUDO_CLASS);
+
+	// Check our children for structural pseudo-classes.
+	bool descendant_is_structural_pseudo_class = false;
+	for (int i = 0; i < NUM_NODE_TYPES; ++i)
+	{
+		for (auto& child_name_node : children[i])
+		{
+			if (child_name_node.second->SetStructurallyVolatileRecursive(self_is_structural_pseudo_class || ancestor_is_structural_pseudo_class))
+				descendant_is_structural_pseudo_class = true;
+		}
+	}
+
+	is_structurally_volatile = (self_is_structural_pseudo_class || ancestor_is_structural_pseudo_class || descendant_is_structural_pseudo_class);
+
+	return (self_is_structural_pseudo_class || descendant_is_structural_pseudo_class);
+}
+
+
 // Returns the name of this node.
 // Returns the name of this node.
 const String& StyleSheetNode::GetName() const
 const String& StyleSheetNode::GetName() const
 {
 {
@@ -475,44 +500,12 @@ void StyleSheetNode::GetApplicableDescendants(std::vector< const StyleSheetNode*
 	}
 	}
 }
 }
 
 
-// Returns true if this node employs a structural selector, and therefore generates element definitions that are
-// sensitive to sibling changes.
-bool StyleSheetNode::IsStructurallyVolatile(bool check_ancestors) const
+bool StyleSheetNode::IsStructurallyVolatile() const
 {
 {
-	if (type == STRUCTURAL_PSEUDO_CLASS)
-		return true;
-
-	if (!children[STRUCTURAL_PSEUDO_CLASS].empty())
-		return true;
-
-	// Check our children for structural pseudo-classes.
-	for (int i = 0; i < NUM_NODE_TYPES; ++i)
-	{
-		if (i == STRUCTURAL_PSEUDO_CLASS)
-			continue;
-
-		for (NodeMap::const_iterator j = children[i].begin(); j != children[i].end(); ++j)
-		{
-			if ((*j).second->IsStructurallyVolatile(false))
-				return true;
-		}
-	}
-
-	if (check_ancestors)
-	{
-		StyleSheetNode* ancestor = parent;
-		while (ancestor != NULL)
-		{
-			if (ancestor->type == STRUCTURAL_PSEUDO_CLASS)
-				return true;
-
-			ancestor = ancestor->parent;
-		}
-	}
-
-	return false;
+	return is_structurally_volatile;
 }
 }
 
 
+
 // Constructs a structural pseudo-class child node.
 // Constructs a structural pseudo-class child node.
 StyleSheetNode* StyleSheetNode::CreateStructuralChild(const String& child_name)
 StyleSheetNode* StyleSheetNode::CreateStructuralChild(const String& child_name)
 {
 {

+ 9 - 2
Source/Core/StyleSheetNode.h

@@ -72,6 +72,8 @@ public:
 	bool MergeHierarchy(StyleSheetNode* node, int specificity_offset = 0);
 	bool MergeHierarchy(StyleSheetNode* node, int specificity_offset = 0);
 	/// Builds up a style sheet's index recursively and optimizes some properties for faster retrieval.
 	/// Builds up a style sheet's index recursively and optimizes some properties for faster retrieval.
 	void BuildIndexAndOptimizeProperties(StyleSheet::NodeIndex& styled_index, StyleSheet::NodeIndex& complete_index, const StyleSheet& style_sheet);
 	void BuildIndexAndOptimizeProperties(StyleSheet::NodeIndex& styled_index, StyleSheet::NodeIndex& complete_index, const StyleSheet& style_sheet);
+	/// Recursively set structural volatility
+	bool SetStructurallyVolatileRecursive(bool ancestor_is_structurally_volatile);
 
 
 	/// Returns the name of this node.
 	/// Returns the name of this node.
 	const String& GetName() const;
 	const String& GetName() const;
@@ -113,9 +115,11 @@ public:
 	void GetApplicableDescendants(std::vector< const StyleSheetNode* >& applicable_nodes, const Element* element) const;
 	void GetApplicableDescendants(std::vector< const StyleSheetNode* >& applicable_nodes, const Element* element) const;
 
 
 	/// Returns true if this node employs a structural selector, and therefore generates element definitions that are
 	/// Returns true if this node employs a structural selector, and therefore generates element definitions that are
-	/// sensitive to sibling changes.
+	/// sensitive to sibling changes. 
+	/// @warning Result is only valid if structural volatility is set since any changes to the node tree.
 	/// @return True if this node uses a structural selector.
 	/// @return True if this node uses a structural selector.
-	bool IsStructurallyVolatile(bool check_ancestors = true) const;
+	bool IsStructurallyVolatile() const;
+
 
 
 private:
 private:
 	// Constructs a structural pseudo-class child node.
 	// Constructs a structural pseudo-class child node.
@@ -137,6 +141,9 @@ private:
 	int a;
 	int a;
 	int b;
 	int b;
 
 
+	// True if any ancestor, descendent, or self is a structural pseudo class.
+	bool is_structurally_volatile;
+
 	// A measure of specificity of this node; the attribute in a node with a higher value will override those of a
 	// A measure of specificity of this node; the attribute in a node with a higher value will override those of a
 	// node with a lower value.
 	// node with a lower value.
 	int specificity;
 	int specificity;