Browse Source

Merge pull request #78 from viciious/optimizations_p1

Part1 of various optimizations
Lloyd Weehuizen 13 years ago
parent
commit
3a433977ba

+ 3 - 0
Include/Rocket/Core/Element.h

@@ -571,6 +571,9 @@ protected:
 	/// Forces a re-layout of this element, and any other elements required.
 	virtual void DirtyLayout();
 
+	/// Returns true if the element has been marked as needing a re-layout.
+	virtual bool IsLayoutDirty();
+
 	/// Forces a reevaluation of applicable font effects.
 	virtual void DirtyFont();
 

+ 3 - 0
Include/Rocket/Core/ElementDocument.h

@@ -144,6 +144,9 @@ protected:
 	/// Sets the dirty flag on the layout so the document will format its children before the next render.
 	virtual void DirtyLayout();
 
+	/// Returns true if the document has been marked as needing a re-layout.
+	virtual bool IsLayoutDirty();
+
 	/// Processes the 'onpropertychange' event, checking for a change in position or size.
 	virtual void ProcessEvent(Event& event);
 

+ 9 - 3
Include/Rocket/Core/PropertySpecification.h

@@ -75,9 +75,13 @@ public:
 	/// @return The appropriate property definition if it could be found, NULL otherwise.
 	const PropertyDefinition* GetProperty(const String& property_name) const;
 
-	/// Fetches a list of the names of all registered property definitions.
-	/// @param properties[in] The list to store the property names.
-	void GetRegisteredProperties(PropertyNameList& properties) const;
+	/// Returns the list of the names of all registered property definitions.
+	/// @return The list with stored property names.
+	const PropertyNameList& GetRegisteredProperties() const;
+
+	/// Returns the list of the names of all registered inherited property definitions.
+	/// @return The list with stored property names.
+	const PropertyNameList& GetRegisteredInheritedProperties() const;
 
 	/// Registers a shorthand property definition.
 	/// @param[in] shorthand_name The name to register the new shorthand property under.
@@ -106,6 +110,8 @@ private:
 
 	PropertyMap properties;
 	ShorthandMap shorthands;
+	PropertyNameList property_names;
+	PropertyNameList inherited_property_names;
 
 	bool ParsePropertyValues(StringList& values_list, const String& values, bool split_values) const;
 };

+ 7 - 3
Include/Rocket/Core/StyleSheetSpecification.h

@@ -72,9 +72,13 @@ public:
 	/// @return The appropriate property definition if it could be found, NULL otherwise.
 	static const PropertyDefinition* GetProperty(const String& property_name);
 
-	/// Fetches a list of the names of all registered property definitions.
-	/// @param properties[in] The list to store the property names.
-	static void GetRegisteredProperties(PropertyNameList& properties);
+	/// Returns the list of the names of all registered property definitions.
+	/// @return The list with stored property names.
+	static const PropertyNameList & GetRegisteredProperties();
+
+	/// Returns the list of the names of all registered inherited property definitions.
+	/// @return The list with stored property names.
+	static const PropertyNameList & GetRegisteredInheritedProperties();
 
 	/// Registers a shorthand property definition.
 	/// @param[in] shorthand_name The name to register the new shorthand property under.

+ 12 - 0
Source/Controls/ElementDataGridRow.cpp

@@ -362,6 +362,10 @@ void ElementDataGridRow::AddChildren(int first_row_added, int num_rows_added)
 		first_row_added = (int)children.size();
 	}
 
+	// prevent relayout of the document while adding rows
+	Core::ElementDocument* document = parent_grid->GetOwnerDocument();
+	document->LockLayout(true);
+
 	// We need to make a row for each new child, then pass through the cell
 	// information and the child's data source (if one exists.)
 	if (data_source)
@@ -392,6 +396,8 @@ void ElementDataGridRow::AddChildren(int first_row_added, int num_rows_added)
 		}
 	}
 
+	document->LockLayout(false);
+
 	RefreshChildDependentCells();
 	DirtyRow();
 
@@ -408,6 +414,10 @@ void ElementDataGridRow::RemoveChildren(int first_row_removed, int num_rows_remo
 		num_rows_removed = (int)children.size() - first_row_removed;
 	}
 
+	// prevent relayout of the document while removing rows
+	Core::ElementDocument* document = parent_grid->GetOwnerDocument();
+	document->LockLayout(true);
+
 	for (int i = num_rows_removed - 1; i >= 0; i--)
 	{
 		children[first_row_removed + i]->RemoveChildren();
@@ -421,6 +431,8 @@ void ElementDataGridRow::RemoveChildren(int first_row_removed, int num_rows_remo
 		children[i]->DirtyTableRelativeIndex();
 	}
 
+	document->LockLayout(false);
+
 	Rocket::Core::Dictionary parameters;
 	parameters.Set("first_row_removed", GetChildTableRelativeIndex(first_row_removed));
 	parameters.Set("num_rows_removed", num_rows_removed);

+ 43 - 15
Source/Core/Element.cpp

@@ -1348,22 +1348,34 @@ void Element::OnAttributeChange(const AttributeNameList& changed_attributes)
 // Called when properties on the element are changed.
 void Element::OnPropertyChange(const PropertyNameList& changed_properties)
 {
-	// Force a relayout if any of the changed properties require it.
-	for (PropertyNameList::const_iterator i = changed_properties.begin(); i != changed_properties.end(); ++i)
+	bool all_dirty = StyleSheetSpecification::GetRegisteredProperties() == changed_properties;
+
+	if (!IsLayoutDirty())
 	{
-		const PropertyDefinition* property_definition = StyleSheetSpecification::GetProperty(*i);
-		if (property_definition)
+		if (all_dirty)
+		{
+			DirtyLayout();
+		}
+		else
 		{
-			if (property_definition->IsLayoutForced())
+			// Force a relayout if any of the changed properties require it.
+			for (PropertyNameList::const_iterator i = changed_properties.begin(); i != changed_properties.end(); ++i)
 			{
-				DirtyLayout();
-				break;
+				const PropertyDefinition* property_definition = StyleSheetSpecification::GetProperty(*i);
+				if (property_definition)
+				{
+					if (property_definition->IsLayoutForced())
+					{
+						DirtyLayout();
+						break;
+					}
+				}
 			}
 		}
 	}
 
 	// Update the visibility.
-	if (changed_properties.find(VISIBILITY) != changed_properties.end() ||
+	if (all_dirty || changed_properties.find(VISIBILITY) != changed_properties.end() ||
 		changed_properties.find(DISPLAY) != changed_properties.end())
 	{
 		bool new_visibility = GetProperty< int >(VISIBILITY) == VISIBILITY_VISIBLE &&
@@ -1377,7 +1389,8 @@ void Element::OnPropertyChange(const PropertyNameList& changed_properties)
 				parent->DirtyStackingContext();
 		}
 
-		if (changed_properties.find(DISPLAY) != changed_properties.end())
+		if (all_dirty || 
+			changed_properties.find(DISPLAY) != changed_properties.end())
 		{
 			if (parent != NULL)
 				parent->DirtyStructure();
@@ -1385,7 +1398,8 @@ void Element::OnPropertyChange(const PropertyNameList& changed_properties)
 	}
 
 	// Update the position.
-	if (changed_properties.find(LEFT) != changed_properties.end() ||
+	if (all_dirty ||
+		changed_properties.find(LEFT) != changed_properties.end() ||
 		changed_properties.find(RIGHT) != changed_properties.end() ||
 		changed_properties.find(TOP) != changed_properties.end() ||
 		changed_properties.find(BOTTOM) != changed_properties.end())
@@ -1395,7 +1409,8 @@ void Element::OnPropertyChange(const PropertyNameList& changed_properties)
 	}
 
 	// Update the z-index.
-	if (changed_properties.find(Z_INDEX) != changed_properties.end())
+	if (all_dirty || 
+		changed_properties.find(Z_INDEX) != changed_properties.end())
 	{
 		const Property* z_index_property = GetProperty(Z_INDEX);
 
@@ -1449,11 +1464,13 @@ void Element::OnPropertyChange(const PropertyNameList& changed_properties)
 	}
 
 	// Dirty the background if it's changed.
-	if (changed_properties.find(BACKGROUND_COLOR) != changed_properties.end())
+	if (all_dirty ||
+		changed_properties.find(BACKGROUND_COLOR) != changed_properties.end())
 		background->DirtyBackground();
 
 	// Dirty the border if it's changed.
-	if (changed_properties.find(BORDER_TOP_WIDTH) != changed_properties.end() ||
+	if (all_dirty || 
+		changed_properties.find(BORDER_TOP_WIDTH) != changed_properties.end() ||
 		changed_properties.find(BORDER_RIGHT_WIDTH) != changed_properties.end() ||
 		changed_properties.find(BORDER_BOTTOM_WIDTH) != changed_properties.end() ||
 		changed_properties.find(BORDER_LEFT_WIDTH) != changed_properties.end() ||
@@ -1464,7 +1481,8 @@ void Element::OnPropertyChange(const PropertyNameList& changed_properties)
 		border->DirtyBorder();
 
 	// Fetch a new font face if it has been changed.
-	if (changed_properties.find(FONT_FAMILY) != changed_properties.end() ||
+	if (all_dirty ||
+		changed_properties.find(FONT_FAMILY) != changed_properties.end() ||
 		changed_properties.find(FONT_CHARSET) != changed_properties.end() ||
 		changed_properties.find(FONT_WEIGHT) != changed_properties.end() ||
 		changed_properties.find(FONT_STYLE) != changed_properties.end() ||
@@ -1503,7 +1521,8 @@ void Element::OnPropertyChange(const PropertyNameList& changed_properties)
 	}
 	
 	// Check for clipping state changes
-	if (changed_properties.find(CLIP) != changed_properties.end() ||
+	if (all_dirty ||
+		changed_properties.find(CLIP) != changed_properties.end() ||
 		changed_properties.find(OVERFLOW_X) != changed_properties.end() ||
 		changed_properties.find(OVERFLOW_Y) != changed_properties.end())
 	{
@@ -1541,6 +1560,15 @@ void Element::DirtyLayout()
 		document->DirtyLayout();
 }
 
+// Forces a re-layout of this element, and any other children required.
+bool Element::IsLayoutDirty()
+{
+	Element* document = GetOwnerDocument();
+	if (document != NULL)
+		return document->IsLayoutDirty();
+	return false;
+}
+
 // Forces a reevaluation of applicable font effects.
 void Element::DirtyFont()
 {

+ 5 - 0
Source/Core/ElementDocument.cpp

@@ -354,6 +354,11 @@ void ElementDocument::DirtyLayout()
 	layout_dirty = true;
 }
 
+bool ElementDocument::IsLayoutDirty()
+{
+	return layout_dirty;
+}
+
 // Refreshes the document layout if required.
 void ElementDocument::OnUpdate()
 {

+ 30 - 19
Source/Core/ElementStyle.cpp

@@ -469,27 +469,24 @@ void ElementStyle::DirtyChildDefinitions()
 // Dirties every property.
 void ElementStyle::DirtyProperties()
 {
-	PropertyNameList properties;
-	StyleSheetSpecification::GetRegisteredProperties(properties);
-
+	const PropertyNameList &properties = StyleSheetSpecification::GetRegisteredProperties();
 	DirtyProperties(properties);
 }
 
 // Dirties em-relative properties.
 void ElementStyle::DirtyEmProperties()
 {
-	PropertyNameList properties;
-	StyleSheetSpecification::GetRegisteredProperties(properties);
+	const PropertyNameList &properties = StyleSheetSpecification::GetRegisteredProperties();
 
 	// Check if any of these are currently em-relative. If so, dirty them.
 	PropertyNameList em_properties;
-	for (PropertyNameList::iterator list_iterator = properties.begin(); list_iterator != properties.end(); ++list_iterator)
+	for (PropertyNameList::const_iterator list_iterator = properties.begin(); list_iterator != properties.end(); ++list_iterator)
 	{
 		// Skip font-size; this is relative to our parent's em, not ours.
 		if (*list_iterator == FONT_SIZE)
 			continue;
 
-		// Get this element from this element. If this is em-relative, then add it to the list to
+		// Get this property from this element. If this is em-relative, then add it to the list to
 		// dirty.
 		if (element->GetProperty(*list_iterator)->unit == Property::EM)
 			em_properties.insert(*list_iterator);
@@ -536,21 +533,35 @@ void ElementStyle::DirtyProperties(const PropertyNameList& properties)
 	if (properties.empty())
 		return;
 
-	PropertyNameList inherited_properties;
-	for (PropertyNameList::const_iterator i = properties.begin(); i != properties.end(); ++i)
-	{
-		// If this property is an inherited property, then push it into the list to be passed onto our children.
-		const PropertyDefinition* property = StyleSheetSpecification::GetProperty(*i);
-		if (property != NULL &&
-			property->IsInherited())
-			inherited_properties.insert(*i);
-	}
+	bool all_inherited_dirty = 
+		StyleSheetSpecification::GetRegisteredProperties() == properties ||
+		StyleSheetSpecification::GetRegisteredInheritedProperties() == properties;
 
-	// Pass the list of those properties that are inherited onto our children.
-	if (!inherited_properties.empty())
+	if (all_inherited_dirty)
 	{
+		const PropertyNameList &all_inherited_properties = StyleSheetSpecification::GetRegisteredInheritedProperties();
 		for (int i = 0; i < element->GetNumChildren(true); i++)
-			element->GetChild(i)->GetStyle()->DirtyInheritedProperties(inherited_properties);
+			element->GetChild(i)->GetStyle()->DirtyInheritedProperties(all_inherited_properties);
+	}
+	else
+	{
+		PropertyNameList inherited_properties;
+
+		for (PropertyNameList::const_iterator i = properties.begin(); i != properties.end(); ++i)
+		{
+			// If this property is an inherited property, then push it into the list to be passed onto our children.
+			const PropertyDefinition* property = StyleSheetSpecification::GetProperty(*i);
+			if (property != NULL &&
+				property->IsInherited())
+				inherited_properties.insert(*i);
+		}
+
+		// Pass the list of those properties that are inherited onto our children.
+		if (!inherited_properties.empty())
+		{
+			for (int i = 0; i < element->GetNumChildren(true); i++)
+				element->GetChild(i)->GetStyle()->DirtyInheritedProperties(inherited_properties);
+		}
 	}
 
 	// And send the event.

+ 1 - 1
Source/Core/LayoutEngine.cpp

@@ -201,7 +201,7 @@ void LayoutEngine::BuildBox(Box& box, const Vector2f& containing_block, Element*
 void LayoutEngine::BuildBox(Box& box, float& min_height, float& max_height, LayoutBlockBox* containing_box, Element* element, bool inline_element)
 {
 	Vector2f containing_block = GetContainingBlock(containing_box);
-	BuildBox(box, GetContainingBlock(containing_box), element, inline_element);
+	BuildBox(box, containing_block, element, inline_element);
 
 	float box_height = box.GetSize().y;
 	if (box_height < 0)

+ 18 - 3
Source/Core/PropertySpecification.cpp

@@ -60,7 +60,17 @@ PropertyDefinition& PropertySpecification::RegisterProperty(const String& proper
 	// Delete any existing property.
 	PropertyMap::iterator iterator = properties.find(lower_case_name);
 	if (iterator != properties.end())
+	{
 		delete (*iterator).second;
+	}
+	else
+	{
+		property_names.insert(lower_case_name);
+		if (inherited)
+		{
+			inherited_property_names.insert(lower_case_name);
+		}
+	}
 
 	properties[lower_case_name] = property_definition;
 	return *property_definition;
@@ -77,10 +87,15 @@ const PropertyDefinition* PropertySpecification::GetProperty(const String& prope
 }
 
 // Fetches a list of the names of all registered property definitions.
-void PropertySpecification::GetRegisteredProperties(PropertyNameList& _properties) const
+const PropertyNameList& PropertySpecification::GetRegisteredProperties(void) const
 {
-	for (PropertyMap::const_iterator i = properties.begin(); i != properties.end(); ++i)
-		_properties.insert((*i).first);
+	return property_names;
+}
+
+// Fetches a list of the names of all registered property definitions.
+const PropertyNameList& PropertySpecification::GetRegisteredInheritedProperties(void) const
+{
+	return inherited_property_names;
 }
 
 // Registers a shorthand property definition.

+ 7 - 2
Source/Core/StyleSheetSpecification.cpp

@@ -107,9 +107,14 @@ const PropertyDefinition* StyleSheetSpecification::GetProperty(const String& pro
 }
 
 // Fetches a list of the names of all registered property definitions.
-void StyleSheetSpecification::GetRegisteredProperties(PropertyNameList& properties)
+const PropertyNameList& StyleSheetSpecification::GetRegisteredProperties()
 {
-	instance->properties.GetRegisteredProperties(properties);
+	return instance->properties.GetRegisteredProperties();
+}
+
+const PropertyNameList & StyleSheetSpecification::GetRegisteredInheritedProperties()
+{
+	return instance->properties.GetRegisteredInheritedProperties();
 }
 
 // Registers a shorthand property definition.