Michael Ragazzon 7 mesi fa
parent
commit
2238b6a9c1

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

@@ -141,6 +141,9 @@ public:
 	/// has already been called after the change. This has a performance penalty, only call when necessary.
 	/// has already been called after the change. This has a performance penalty, only call when necessary.
 	void UpdateDocument();
 	void UpdateDocument();
 
 
+	// TODO: Remove
+	void UpdatePropertiesForDebug();
+
 protected:
 protected:
 	/// Repositions the document if necessary.
 	/// Repositions the document if necessary.
 	void OnPropertyChange(const PropertyIdSet& changed_properties) override;
 	void OnPropertyChange(const PropertyIdSet& changed_properties) override;

+ 7 - 9
Source/Core/ElementDocument.cpp

@@ -516,6 +516,13 @@ void ElementDocument::UpdateDocument()
 	UpdatePosition();
 	UpdatePosition();
 }
 }
 
 
+void ElementDocument::UpdatePropertiesForDebug()
+{
+	const float dp_ratio = (context ? context->GetDensityIndependentPixelRatio() : 1.0f);
+	const Vector2f vp_dimensions = (context ? Vector2f(context->GetDimensions()) : Vector2f(1.0f));
+	Update(dp_ratio, vp_dimensions);
+}
+
 void ElementDocument::UpdateLayout()
 void ElementDocument::UpdateLayout()
 {
 {
 	// Note: Carefully consider when to call this function for performance reasons.
 	// Note: Carefully consider when to call this function for performance reasons.
@@ -525,15 +532,6 @@ void ElementDocument::UpdateLayout()
 		RMLUI_ZoneScoped;
 		RMLUI_ZoneScoped;
 		RMLUI_ZoneText(source_url.c_str(), source_url.size());
 		RMLUI_ZoneText(source_url.c_str(), source_url.size());
 
 
-		String tree_dirty_state;
-		ElementUtilities::VisitElementsDepthOrder(this, [&](Element* element, int tree_depth) {
-			tree_dirty_state += '\n' + String(size_t(4 * tree_depth), ' ');
-			tree_dirty_state += CreateString("%s: Dirty: %d  Dirty Self: %d", element->GetAddress().c_str(), element->GetLayoutNode()->IsDirty(),
-				element->GetLayoutNode()->IsSelfDirty());
-		});
-
-		Log::Message(Log::LT_INFO, "ElementDocument::UpdateLayout - Tree dirty state:\n%s\n\n", tree_dirty_state.c_str());
-
 		bool force_full_document_layout = false;
 		bool force_full_document_layout = false;
 		bool any_layout_updates = false;
 		bool any_layout_updates = false;
 
 

+ 10 - 0
Source/Core/Layout/FormattingContextDebug.cpp

@@ -138,6 +138,16 @@ void FormatIndependentDebugTracker::LogMessage() const
 	Log::Message(Log::LT_INFO, "%s", ToString().c_str());
 	Log::Message(Log::LT_INFO, "%s", ToString().c_str());
 }
 }
 
 
+int FormatIndependentDebugTracker::CountCachedEntries() const
+{
+	return (int)std::count_if(entries.begin(), entries.end(), [](const auto& entry) { return entry.layout.has_value() && entry.layout->from_cache; });
+}
+
+int FormatIndependentDebugTracker::CountFormattedEntries() const
+{
+	return (int)entries.size() - CountCachedEntries();
+}
+
 int FormatIndependentDebugTracker::CountEntries() const
 int FormatIndependentDebugTracker::CountEntries() const
 {
 {
 	return (int)entries.size();
 	return (int)entries.size();

+ 2 - 0
Source/Core/Layout/FormattingContextDebug.h

@@ -67,6 +67,8 @@ public:
 	String ToString() const;
 	String ToString() const;
 	void LogMessage() const;
 	void LogMessage() const;
 	int CountEntries() const;
 	int CountEntries() const;
+	int CountCachedEntries() const;
+	int CountFormattedEntries() const;
 };
 };
 
 
 #endif // RMLUI_DEBUG
 #endif // RMLUI_DEBUG

+ 74 - 7
Tests/Source/UnitTests/LayoutIsolation.cpp

@@ -27,6 +27,7 @@
  */
  */
 
 
 #include "../../../Source/Core/Layout/FormattingContextDebug.h"
 #include "../../../Source/Core/Layout/FormattingContextDebug.h"
+#include "../../../Source/Core/Layout/LayoutNode.h"
 #include "../Common/TestsShell.h"
 #include "../Common/TestsShell.h"
 #include "../Common/TypesToString.h"
 #include "../Common/TypesToString.h"
 #include <RmlUi/Core/Context.h>
 #include <RmlUi/Core/Context.h>
@@ -34,10 +35,67 @@
 #include <RmlUi/Core/Element.h>
 #include <RmlUi/Core/Element.h>
 #include <RmlUi/Core/ElementDocument.h>
 #include <RmlUi/Core/ElementDocument.h>
 #include <RmlUi/Core/ElementText.h>
 #include <RmlUi/Core/ElementText.h>
+#include <RmlUi/Core/ElementUtilities.h>
 #include <doctest.h>
 #include <doctest.h>
 
 
 using namespace Rml;
 using namespace Rml;
 
 
+struct ElementLayoutInfo {
+	ElementLayoutInfo(int tree_depth, const String& address, const Box& box, Vector2f absolute_offset) :
+		tree_depth(tree_depth), address(address), box(box), absolute_offset(absolute_offset)
+	{}
+
+	int tree_depth;
+	String address;
+	Box box;
+	Vector2f absolute_offset;
+
+	bool operator==(const ElementLayoutInfo& other) const
+	{
+		return tree_depth == other.tree_depth && address == other.address && box == other.box && absolute_offset == other.absolute_offset;
+	}
+	bool operator!=(const ElementLayoutInfo& other) const { return !(*this == other); }
+
+	String ToString() const
+	{
+		return String(size_t(4 * tree_depth), ' ') +
+			CreateString("%s :: box = %g x %g (outer %g x %g) :: absolute_offset = %g x %g", address.c_str(), box.GetSize().x, box.GetSize().y,
+				box.GetSizeAcross(BoxDirection::Horizontal, BoxArea::Margin), box.GetSizeAcross(BoxDirection::Vertical, BoxArea::Margin),
+				absolute_offset.x, absolute_offset.y);
+	}
+};
+
+static Vector<ElementLayoutInfo> CaptureLayoutTree(Element* root_element)
+{
+	Vector<ElementLayoutInfo> layout_info_list;
+	ElementUtilities::VisitElementsDepthOrder(root_element, [&](Element* element, int tree_depth) {
+		layout_info_list.emplace_back(tree_depth, element->GetAddress(false, false), element->GetBox(), element->GetAbsoluteOffset());
+	});
+	return layout_info_list;
+}
+
+static void LogLayoutTree(const Vector<ElementLayoutInfo>& layout_info_list)
+{
+	String message = "Element layout tree:\n";
+	for (const auto& layout_info : layout_info_list)
+		message += layout_info.ToString() + "\n";
+
+	Rml::Log::Message(Rml::Log::LT_DEBUG, "%s", message.c_str());
+}
+
+static void LogDirtyLayoutTree(Element* root_element)
+{
+	String tree_dirty_state;
+	ElementUtilities::VisitElementsDepthOrder(root_element, [&](Element* element, int tree_depth) {
+		tree_dirty_state += String(size_t(4 * tree_depth), ' ');
+		tree_dirty_state += CreateString("%s: Dirty: %d  Dirty Self: %d", element->GetAddress(false, tree_depth == 0).c_str(),
+			element->GetLayoutNode()->IsDirty(), element->GetLayoutNode()->IsSelfDirty());
+		tree_dirty_state += '\n';
+	});
+
+	Log::Message(Log::LT_INFO, "Dirty layout tree:\n%s\n", tree_dirty_state.c_str());
+}
+
 static const String document_isolation_rml = R"(
 static const String document_isolation_rml = R"(
 <rml>
 <rml>
 <head>
 <head>
@@ -209,7 +267,7 @@ TEST_CASE("LayoutIsolation.FullLayoutFormatIndependentCount")
 	document->Show();
 	document->Show();
 	TestsShell::RenderLoop();
 	TestsShell::RenderLoop();
 
 
-	Log::Message(Log::LT_INFO, "%s", format_independent_tracker.ToString().c_str());
+	format_independent_tracker.LogMessage();
 
 
 	const auto count_level_1 = std::count_if(format_independent_tracker.entries.begin(), format_independent_tracker.entries.end(),
 	const auto count_level_1 = std::count_if(format_independent_tracker.entries.begin(), format_independent_tracker.entries.end(),
 		[](const auto& entry) { return entry.level == 1; });
 		[](const auto& entry) { return entry.level == 1; });
@@ -217,7 +275,8 @@ TEST_CASE("LayoutIsolation.FullLayoutFormatIndependentCount")
 
 
 	// There are quite a few flex item format occurrences being performed currently. We might reduce the following
 	// There are quite a few flex item format occurrences being performed currently. We might reduce the following
 	// number while working on the flex formatting engine. If this fails for any other reason, it is likely a bug.
 	// number while working on the flex formatting engine. If this fails for any other reason, it is likely a bug.
-	CHECK(format_independent_tracker.entries.size() == 10);
+	CHECK(format_independent_tracker.CountEntries() == 10);
+	CHECK(format_independent_tracker.CountFormattedEntries() == 10);
 
 
 	document->Close();
 	document->Close();
 	TestsShell::ShutdownShell();
 	TestsShell::ShutdownShell();
@@ -297,7 +356,7 @@ TEST_CASE("LayoutIsolation.Absolute")
 		TestsShell::RenderLoop();
 		TestsShell::RenderLoop();
 
 
 		CHECK(element->GetOffsetHeight() != initial_height);
 		CHECK(element->GetOffsetHeight() != initial_height);
-		CHECK(format_independent_tracker.entries.size() == 1);
+		CHECK(format_independent_tracker.CountFormattedEntries() == 1);
 	}
 	}
 
 
 	SUBCASE("Modify absolute width")
 	SUBCASE("Modify absolute width")
@@ -308,11 +367,17 @@ TEST_CASE("LayoutIsolation.Absolute")
 		const float element_initial_width = element->GetOffsetWidth();
 		const float element_initial_width = element->GetOffsetWidth();
 
 
 		container->SetProperty("width", "300px");
 		container->SetProperty("width", "300px");
+
+		LogDirtyLayoutTree(document);
+		document->UpdatePropertiesForDebug();
+		LogDirtyLayoutTree(document);
+
 		TestsShell::RenderLoop();
 		TestsShell::RenderLoop();
 
 
 		CHECK(container->GetOffsetWidth() != container_initial_width);
 		CHECK(container->GetOffsetWidth() != container_initial_width);
 		CHECK(element->GetOffsetWidth() != element_initial_width);
 		CHECK(element->GetOffsetWidth() != element_initial_width);
-		CHECK(format_independent_tracker.entries.size() == 1);
+		CHECK(format_independent_tracker.CountEntries() == 1);
+		CHECK(format_independent_tracker.CountFormattedEntries() == 1);
 	}
 	}
 
 
 	SUBCASE("Modify document width")
 	SUBCASE("Modify document width")
@@ -337,12 +402,14 @@ TEST_CASE("LayoutIsolation.Absolute")
 		Element* element = document->GetElementById("normal-item");
 		Element* element = document->GetElementById("normal-item");
 		const float initial_height = element->GetOffsetHeight();
 		const float initial_height = element->GetOffsetHeight();
 
 
+		LogLayoutTree(CaptureLayoutTree(document));
+
 		rmlui_dynamic_cast<ElementText*>(element->GetFirstChild())->SetText("Modified text that is long enough to cause line break");
 		rmlui_dynamic_cast<ElementText*>(element->GetFirstChild())->SetText("Modified text that is long enough to cause line break");
 
 
 		TestsShell::RenderLoop();
 		TestsShell::RenderLoop();
 		CHECK(element->GetOffsetHeight() != initial_height);
 		CHECK(element->GetOffsetHeight() != initial_height);
 
 
-		CHECK(format_independent_tracker.entries.size() == 1);
+		CHECK(format_independent_tracker.CountFormattedEntries() == 1);
 	}
 	}
 
 
 	SUBCASE("Modify normal content and absolute content")
 	SUBCASE("Modify normal content and absolute content")
@@ -359,10 +426,10 @@ TEST_CASE("LayoutIsolation.Absolute")
 		CHECK(absolute_element->GetOffsetHeight() != absolute_initial_height);
 		CHECK(absolute_element->GetOffsetHeight() != absolute_initial_height);
 		CHECK(normal_element->GetOffsetHeight() != normal_initial_height);
 		CHECK(normal_element->GetOffsetHeight() != normal_initial_height);
 
 
-		CHECK(format_independent_tracker.entries.size() == 2);
+		CHECK(format_independent_tracker.CountFormattedEntries() == 2);
 	}
 	}
 
 
-	Log::Message(Log::LT_INFO, "%s", format_independent_tracker.ToString().c_str());
+	format_independent_tracker.LogMessage();
 
 
 	document->Close();
 	document->Close();
 	TestsShell::ShutdownShell();
 	TestsShell::ShutdownShell();