Sfoglia il codice sorgente

Inline block performance issue fix.

Michael 7 anni fa
parent
commit
4d667faaec

+ 12 - 14
Source/Core/LayoutBlockBox.cpp

@@ -528,19 +528,17 @@ void LayoutBlockBox::PositionLineBox(Vector2f& box_position, float& box_width, b
 }
 
 
-// Calculate the dimensions of the box's internal content; i.e. the size of the largest line, plus this element's padding.
-Vector2f LayoutBlockBox::InternalContentSize() const
+// Calculate the dimensions of the box's internal width; i.e. the size of the largest line, plus this element's padding.
+float LayoutBlockBox::InternalContentWidth() const
 {
-	Vector2f content_box(0, 0);
+	float content_width = 0.0f;
 
 	if (context == BLOCK)
 	{
-		content_box.y = box_cursor;
-		content_box.y += (box.GetEdge(Box::PADDING, Box::TOP) + box.GetEdge(Box::PADDING, Box::BOTTOM));
 
 		for (size_t i = 0; i < block_boxes.size(); i++)
 		{
-			content_box.x = Math::Max(content_box.x, block_boxes[i]->InternalContentSize().x);
+			content_width = Math::Max(content_width, block_boxes[i]->InternalContentWidth());
 		}
 
 		// Work-around for supporting 'width' specification of 'display:block' elements inside 'display:inline-block'.
@@ -554,23 +552,23 @@ Vector2f LayoutBlockBox::InternalContentSize() const
 			if(width)
 			{
 				float w_value = element->ResolveProperty(width, box.GetSize(Box::CONTENT).x);
-				content_box.x = Math::Max(content_box.x, w_value);
+				content_width = Math::Max(content_width, w_value);
 			}
 			float block_width = box.GetSize(Box::CONTENT).x;
 			if (min_width)
 			{
 				float value = element->ResolveProperty(min_width, block_width);
-				content_box.x = Math::Max(content_box.x, value);
+				content_width = Math::Max(content_width, value);
 			}
 			if (max_width)
 			{
 				float value = element->ResolveProperty(max_width, block_width);
-				content_box.x = Math::Min(content_box.x, value);
+				content_width = Math::Min(content_width, value);
 			}
 		}
 
-		content_box.x += (box.GetEdge(Box::PADDING, Box::LEFT) + box.GetEdge(Box::PADDING, Box::RIGHT));
-		content_box.x += (box.GetEdge(Box::MARGIN, Box::LEFT) + box.GetEdge(Box::MARGIN, Box::RIGHT));
+		content_width += (box.GetEdge(Box::PADDING, Box::LEFT) + box.GetEdge(Box::PADDING, Box::RIGHT));
+		content_width += (box.GetEdge(Box::MARGIN, Box::LEFT) + box.GetEdge(Box::MARGIN, Box::RIGHT));
 	}
 	else
 	{
@@ -580,12 +578,12 @@ Vector2f LayoutBlockBox::InternalContentSize() const
 			// Perhaps a more robust solution is to modify how we set the line box dimension on 'line_box->close()'
 			// and use that, or add another value in the line_box ... but seems to work for now.
 			LayoutLineBox* line_box = line_boxes[i];
-			content_box.x = Math::Max(content_box.x, line_box->GetBoxCursor());
+			content_width = Math::Max(content_width, line_box->GetBoxCursor());
 		}
-		content_box.x = Math::Min(content_box.x, box.GetSize(Box::CONTENT).x);
+		content_width = Math::Min(content_width, box.GetSize(Box::CONTENT).x);
 	}
 
-	return content_box;
+	return content_width;
 }
 
 

+ 1 - 1
Source/Core/LayoutBlockBox.h

@@ -129,7 +129,7 @@ public:
 	/// @param dimensions[in] The minimum dimensions of the line.
 	void PositionLineBox(Vector2f& box_position, float& box_width, bool& wrap_content, const Vector2f& dimensions) const;
 
-	Vector2f InternalContentSize() const;
+	float InternalContentWidth() const;
 
 	/// Returns the block box's element.
 	/// @return The block box's element.

+ 27 - 19
Source/Core/LayoutEngine.cpp

@@ -68,7 +68,7 @@ LayoutEngine::~LayoutEngine()
 }
 
 // Formats the contents for a root-level element (usually a document or floating element).
-bool LayoutEngine::FormatElement(Element* element, const Vector2f& containing_block, Vector2f* internal_content_size)
+bool LayoutEngine::FormatElement(Element* element, const Vector2f& containing_block, bool shrink_to_fit)
 {
 	block_box = new LayoutBlockBox(this, NULL, NULL);
 	block_box->GetBox().SetContent(containing_block);
@@ -81,15 +81,33 @@ bool LayoutEngine::FormatElement(Element* element, const Vector2f& containing_bl
 			i = -1;
 	}
 
-	block_context_box->Close();
-	block_context_box->CloseAbsoluteElements();
-
-	if (internal_content_size)
+	if (shrink_to_fit)
 	{
-		Vector2f content_size = block_box->InternalContentSize();
-		*internal_content_size = content_size;
+		// For inline blocks, we want to shrink the box back to its inner content width, recreating the LayoutBlockBox.
+		// There is an issue where resize events are not propagated correctly, which affects e.g. DataGridCells.
+		float content_width = block_box->InternalContentWidth();
+
+		if (content_width < containing_block.x)
+		{
+			Vector2f shrinked_block_size(content_width, containing_block.y);
+			
+			delete block_box;
+			block_box = new LayoutBlockBox(this, NULL, NULL);
+			block_box->GetBox().SetContent(shrinked_block_size);
+
+			block_context_box = block_box->AddBlockElement(element);
+
+			for (int i = 0; i < element->GetNumChildren(); i++)
+			{
+				if (!FormatElement(element->GetChild(i)))
+					i = -1;
+			}
+		}
 	}
 
+	block_context_box->Close();
+	block_context_box->CloseAbsoluteElements();
+
 	element->OnLayout();
 
 	delete block_box;
@@ -432,19 +450,9 @@ bool LayoutEngine::FormatElementReplaced(Element* element)
 {
 	// Format the element separately as a block element, then position it inside our own layout as an inline element.
 	Vector2f containing_block_size = GetContainingBlock(block_context_box);
-	Vector2f internal_content_size(0, 0);
-	
-	{
-		LayoutEngine layout_engine;
-		layout_engine.FormatElement(element, containing_block_size, &internal_content_size);
-	}
 
-	if (internal_content_size.x < containing_block_size.x)
-	{
-		Vector2f shrinked_block_size(internal_content_size.x, containing_block_size.y);
-		LayoutEngine layout_engine;
-		layout_engine.FormatElement(element, shrinked_block_size);
-	}
+	LayoutEngine layout_engine;
+	layout_engine.FormatElement(element, containing_block_size, true);
 
 	block_context_box->AddInlineElement(element, element->GetBox())->Close();
 

+ 1 - 1
Source/Core/LayoutEngine.h

@@ -49,7 +49,7 @@ public:
 	/// Formats the contents for a root-level element (usually a document, floating or replaced element).
 	/// @param element[in] The element to lay out.
 	/// @param containing_block[in] The size of the containing block.
-	bool FormatElement(Element* element, const Vector2f& containing_block, Vector2f* internal_content_size = nullptr);
+	bool FormatElement(Element* element, const Vector2f& containing_block, bool shrink_to_fit = false);
 
 	/// Generates the box for an element.
 	/// @param[out] box The box to be built.