Browse Source

Move stylesheet property optimization into the stylesheet factory so that decorators are cached. This should make loading documents with shared stylesheets faster.

Michael Ragazzon 5 years ago
parent
commit
81a0d0671c

+ 5 - 3
Include/RmlUi/Core/StyleSheet.h

@@ -84,9 +84,11 @@ public:
 
 	/// Combines this style sheet with another one, producing a new sheet.
 	SharedPtr<StyleSheet> CombineStyleSheet(const StyleSheet& sheet) const;
-	/// Builds the node index for a combined style sheet, and optimizes some properties for faster retrieval.
-	/// Specifically, converts all decorator properties from strings to instanced decorator lists.
-	void BuildNodeIndexAndOptimizeProperties();
+	/// Builds the node index for a combined style sheet.
+	void BuildNodeIndex();
+	/// Optimizes some properties for faster retrieval.
+	/// Specifically, converts all decorator and font-effect properties from strings to instanced decorator and font effect lists.
+	void OptimizeNodeProperties();
 
 	/// Returns the Keyframes of the given name, or null if it does not exist.
 	Keyframes* GetKeyframes(const String& name);

+ 5 - 2
Source/Core/ElementDocument.cpp

@@ -181,10 +181,13 @@ void ElementDocument::SetStyleSheet(SharedPtr<StyleSheet> _style_sheet)
 	if (style_sheet == _style_sheet)
 		return;
 
-	style_sheet = _style_sheet;
+	style_sheet = std::move(_style_sheet);
 	
 	if (style_sheet)
-		style_sheet->BuildNodeIndexAndOptimizeProperties();
+	{
+		style_sheet->BuildNodeIndex();
+		style_sheet->OptimizeNodeProperties();
+	}
 
 	GetStyle()->DirtyDefinition();
 }

+ 10 - 8
Source/Core/PropertyDictionary.cpp

@@ -72,22 +72,24 @@ const PropertyMap& PropertyDictionary::GetProperties() const
 }
 
 // Imports potentially un-specified properties into the dictionary.
-void PropertyDictionary::Import(const PropertyDictionary& property_dictionary, int property_specificity)
+void PropertyDictionary::Import(const PropertyDictionary& other, int property_specificity)
 {
-	for (PropertyMap::const_iterator iterator = property_dictionary.properties.begin(); iterator != property_dictionary.properties.end(); ++iterator)
+	for (const auto& pair : other.properties)
 	{
-		const Property& property = iterator->second;
-		SetProperty(iterator->first, property, property_specificity > 0 ? property_specificity : property.specificity);
+		const PropertyId id = pair.first;
+		const Property& property = pair.second;
+		SetProperty(id, property, property_specificity > 0 ? property_specificity : property.specificity);
 	}
 }
 
 // Merges the contents of another fully-specified property dictionary with this one.
-void PropertyDictionary::Merge(const PropertyDictionary& property_dictionary, int specificity_offset)
+void PropertyDictionary::Merge(const PropertyDictionary& other, int specificity_offset)
 {
-	for (PropertyMap::const_iterator iterator = property_dictionary.properties.begin(); iterator != property_dictionary.properties.end(); ++iterator)
+	for (const auto& pair : other.properties)
 	{
-		const Property& property = iterator->second;
-		SetProperty(iterator->first, property, property.specificity + specificity_offset);
+		const PropertyId id = pair.first;
+		const Property& property = pair.second;
+		SetProperty(id, property, property.specificity + specificity_offset);
 	}
 }
 

+ 9 - 2
Source/Core/StyleSheet.cpp

@@ -107,14 +107,21 @@ SharedPtr<StyleSheet> StyleSheet::CombineStyleSheet(const StyleSheet& other_shee
 }
 
 // Builds the node index for a combined style sheet.
-void StyleSheet::BuildNodeIndexAndOptimizeProperties()
+void StyleSheet::BuildNodeIndex()
 {
 	RMLUI_ZoneScoped;
 	styled_node_index.clear();
-	root->BuildIndexAndOptimizeProperties(styled_node_index, *this);
+	root->BuildIndex(styled_node_index);
 	root->SetStructurallyVolatileRecursive(false);
 }
 
+// Builds the node index for a combined style sheet.
+void StyleSheet::OptimizeNodeProperties()
+{
+	RMLUI_ZoneScoped;
+	root->OptimizeProperties(*this);
+}
+
 // Returns the Keyframes of the given name, or null if it does not exist.
 Keyframes * StyleSheet::GetKeyframes(const String & name)
 {

+ 3 - 1
Source/Core/StyleSheetFactory.cpp

@@ -137,7 +137,7 @@ SharedPtr<StyleSheet> StyleSheetFactory::GetStyleSheet(const StringList& sheets)
 			if (sheet)
 			{
 				SharedPtr<StyleSheet> new_sheet = sheet->CombineStyleSheet(*sub_sheet);
-				sheet = new_sheet;
+				sheet = std::move(new_sheet);
 			}
 			else
 				sheet = sub_sheet;
@@ -149,6 +149,8 @@ SharedPtr<StyleSheet> StyleSheetFactory::GetStyleSheet(const StringList& sheets)
 	if (!sheet)
 		return nullptr;
 
+	sheet->OptimizeNodeProperties();
+
 	// Add to cache, and a reference to the sheet to hold it in the cache.
 	instance->stylesheet_cache[combined_key] = sheet;
 	return sheet;

+ 15 - 10
Source/Core/StyleSheetNode.cpp

@@ -104,10 +104,8 @@ bool StyleSheetNode::MergeHierarchy(StyleSheetNode* node, int specificity_offset
 }
 
 // Builds up a style sheet's index recursively.
-void StyleSheetNode::BuildIndexAndOptimizeProperties(StyleSheet::NodeIndex& styled_node_index, const StyleSheet& style_sheet)
+void StyleSheetNode::BuildIndex(StyleSheet::NodeIndex& styled_node_index)
 {
-	RMLUI_ZoneScoped;
-
 	// If this has properties defined, then we insert it into the styled node index.
 	if(properties.GetNumProperties() > 0)
 	{
@@ -119,10 +117,18 @@ void StyleSheetNode::BuildIndexAndOptimizeProperties(StyleSheet::NodeIndex& styl
 			nodes.push_back(this);
 	}
 
+	for (auto& child : children)
+	{
+		child->BuildIndex(styled_node_index);
+	}
+}
+
+// Builds up a style sheet's index recursively.
+void StyleSheetNode::OptimizeProperties(const StyleSheet& style_sheet)
+{
 	// Turn any decorator and font-effect properties from String to DecoratorList / FontEffectList.
 	// This is essentially an optimization, it will work fine to skip this step and let ElementStyle::ComputeValues() do all the work.
 	// However, when we do it here, we only need to do it once.
-	// Note, since the user may set a new decorator through its style, we still do the conversion as necessary again in ComputeValues.
 	if (properties.GetNumProperties() > 0)
 	{
 		// Decorators
@@ -131,8 +137,8 @@ void StyleSheetNode::BuildIndexAndOptimizeProperties(StyleSheet::NodeIndex& styl
 			if (property->unit == Property::STRING)
 			{
 				const String string_value = property->Get<String>();
-				
-				if(DecoratorsPtr decorators = style_sheet.InstanceDecoratorsFromString(string_value, property->source))
+
+				if (DecoratorsPtr decorators = style_sheet.InstanceDecoratorsFromString(string_value, property->source))
 				{
 					Property new_property = *property;
 					new_property.value = std::move(decorators);
@@ -143,7 +149,7 @@ void StyleSheetNode::BuildIndexAndOptimizeProperties(StyleSheet::NodeIndex& styl
 		}
 
 		// Font-effects
-		if (const Property * property = properties.GetProperty(PropertyId::FontEffect))
+		if (const Property* property = properties.GetProperty(PropertyId::FontEffect))
 		{
 			if (property->unit == Property::STRING)
 			{
@@ -158,13 +164,12 @@ void StyleSheetNode::BuildIndexAndOptimizeProperties(StyleSheet::NodeIndex& styl
 		}
 	}
 
-	for (auto& child : children)
+	for (const auto& child : children)
 	{
-		child->BuildIndexAndOptimizeProperties(styled_node_index, style_sheet);
+		child->OptimizeProperties(style_sheet);
 	}
 }
 
-
 bool StyleSheetNode::SetStructurallyVolatileRecursive(bool ancestor_is_structural_pseudo_class)
 {
 	// If any ancestor or descendant is a structural pseudo class, then we are structurally volatile.

+ 4 - 2
Source/Core/StyleSheetNode.h

@@ -73,8 +73,10 @@ public:
 	bool MergeHierarchy(StyleSheetNode* node, int specificity_offset = 0);
 	/// Recursively set structural volatility.
 	bool SetStructurallyVolatileRecursive(bool ancestor_is_structurally_volatile);
-	/// Builds up a style sheet's index recursively and optimizes some properties for faster retrieval.
-	void BuildIndexAndOptimizeProperties(StyleSheet::NodeIndex& styled_node_index, const StyleSheet& style_sheet);
+	/// Builds up a style sheet's index recursively.
+	void BuildIndex(StyleSheet::NodeIndex& styled_node_index);
+	/// Optimizes some properties recursively for faster retrieval. In particular, decorators and font effects.
+	void OptimizeProperties(const StyleSheet& style_sheet);
 
 	/// Imports properties from a single rule definition into the node's properties and sets the
 	/// appropriate specificity on them. Any existing attributes sharing a key with a new attribute