| 
									
										
										
										
											2019-10-03 15:20:13 +02:00
										 |  |  | #include <AK/Utf8View.h>
 | 
					
						
							| 
									
										
										
										
											2019-06-21 20:54:13 +02:00
										 |  |  | #include <LibHTML/CSS/StyleSheet.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-12 23:26:47 +02:00
										 |  |  | #include <LibHTML/DOM/Comment.h>
 | 
					
						
							| 
									
										
										
										
											2019-06-15 23:41:15 +02:00
										 |  |  | #include <LibHTML/DOM/Document.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-09 20:17:01 +02:00
										 |  |  | #include <LibHTML/DOM/DocumentType.h>
 | 
					
						
							| 
									
										
										
										
											2019-06-15 23:41:15 +02:00
										 |  |  | #include <LibHTML/DOM/Element.h>
 | 
					
						
							|  |  |  | #include <LibHTML/DOM/Text.h>
 | 
					
						
							| 
									
										
										
										
											2019-06-15 18:55:47 +02:00
										 |  |  | #include <LibHTML/Dump.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-03 15:20:13 +02:00
										 |  |  | #include <LibHTML/Layout/LayoutBlock.h>
 | 
					
						
							| 
									
										
										
										
											2019-06-15 23:41:15 +02:00
										 |  |  | #include <LibHTML/Layout/LayoutNode.h>
 | 
					
						
							|  |  |  | #include <LibHTML/Layout/LayoutText.h>
 | 
					
						
							| 
									
										
										
										
											2019-06-15 18:55:47 +02:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | void dump_tree(const Node& node) | 
					
						
							| 
									
										
										
										
											2019-06-15 18:55:47 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     static int indent = 0; | 
					
						
							|  |  |  |     for (int i = 0; i < indent; ++i) | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |         dbgprintf("  "); | 
					
						
							| 
									
										
										
										
											2019-10-06 20:37:39 +02:00
										 |  |  |     if (is<Document>(node)) { | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |         dbgprintf("*Document*\n"); | 
					
						
							| 
									
										
										
										
											2019-10-06 20:37:39 +02:00
										 |  |  |     } else if (is<Element>(node)) { | 
					
						
							|  |  |  |         dbgprintf("<%s", to<Element>(node).tag_name().characters()); | 
					
						
							|  |  |  |         to<Element>(node).for_each_attribute([](auto& name, auto& value) { | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |             dbgprintf(" %s=%s", name.characters(), value.characters()); | 
					
						
							| 
									
										
										
										
											2019-06-15 21:08:36 +02:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |         dbgprintf(">\n"); | 
					
						
							| 
									
										
										
										
											2019-10-06 20:37:39 +02:00
										 |  |  |     } else if (is<Text>(node)) { | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |         dbgprintf("\"%s\"\n", static_cast<const Text&>(node).data().characters()); | 
					
						
							| 
									
										
										
										
											2019-10-09 20:17:01 +02:00
										 |  |  |     } else if (is<DocumentType>(node)) { | 
					
						
							|  |  |  |         dbgprintf("<!DOCTYPE>\n"); | 
					
						
							| 
									
										
										
										
											2019-10-12 23:26:47 +02:00
										 |  |  |     } else if (is<Comment>(node)) { | 
					
						
							|  |  |  |         dbgprintf("<!--%s-->\n", to<Comment>(node).data().characters()); | 
					
						
							| 
									
										
										
										
											2019-06-15 18:55:47 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     ++indent; | 
					
						
							| 
									
										
										
										
											2019-10-06 20:37:39 +02:00
										 |  |  |     if (is<ParentNode>(node)) { | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  |         static_cast<const ParentNode&>(node).for_each_child([](auto& child) { | 
					
						
							| 
									
										
										
										
											2019-06-15 18:55:47 +02:00
										 |  |  |             dump_tree(child); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     --indent; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-16 11:28:47 +02:00
										 |  |  | void dump_tree(const LayoutNode& layout_node) | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     static int indent = 0; | 
					
						
							|  |  |  |     for (int i = 0; i < indent; ++i) | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |         dbgprintf("    "); | 
					
						
							| 
									
										
										
										
											2019-06-16 11:28:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     String tag_name; | 
					
						
							|  |  |  |     if (layout_node.is_anonymous()) | 
					
						
							|  |  |  |         tag_name = "(anonymous)"; | 
					
						
							| 
									
										
										
										
											2019-10-06 20:37:39 +02:00
										 |  |  |     else if (is<Text>(layout_node.node())) | 
					
						
							| 
									
										
										
										
											2019-06-16 11:28:47 +02:00
										 |  |  |         tag_name = "#text"; | 
					
						
							| 
									
										
										
										
											2019-10-06 20:37:39 +02:00
										 |  |  |     else if (is<Document>(layout_node.node())) | 
					
						
							| 
									
										
										
										
											2019-06-16 11:28:47 +02:00
										 |  |  |         tag_name = "#document"; | 
					
						
							| 
									
										
										
										
											2019-10-06 20:37:39 +02:00
										 |  |  |     else if (is<Element>(layout_node.node())) | 
					
						
							|  |  |  |         tag_name = to<Element>(*layout_node.node()).tag_name(); | 
					
						
							| 
									
										
										
										
											2019-06-16 11:28:47 +02:00
										 |  |  |     else | 
					
						
							|  |  |  |         tag_name = "???"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |     dbgprintf("%s {%s} at (%d,%d) size %dx%d", | 
					
						
							| 
									
										
										
										
											2019-06-16 11:28:47 +02:00
										 |  |  |         layout_node.class_name(), | 
					
						
							|  |  |  |         tag_name.characters(), | 
					
						
							| 
									
										
										
										
											2019-10-13 17:31:58 +02:00
										 |  |  |         layout_node.x(), | 
					
						
							|  |  |  |         layout_node.y(), | 
					
						
							|  |  |  |         layout_node.width(), | 
					
						
							|  |  |  |         layout_node.height()); | 
					
						
							| 
									
										
										
										
											2019-08-18 08:09:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Dump the horizontal box properties
 | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |     dbgprintf(" [%d+%d+%d %d %d+%d+%d]", | 
					
						
							| 
									
										
										
										
											2019-10-04 15:50:50 +02:00
										 |  |  |         layout_node.box_model().margin().left.to_px(), | 
					
						
							|  |  |  |         layout_node.box_model().border().left.to_px(), | 
					
						
							|  |  |  |         layout_node.box_model().padding().left.to_px(), | 
					
						
							| 
									
										
										
										
											2019-10-13 17:31:58 +02:00
										 |  |  |         layout_node.width(), | 
					
						
							| 
									
										
										
										
											2019-10-04 15:50:50 +02:00
										 |  |  |         layout_node.box_model().padding().right.to_px(), | 
					
						
							|  |  |  |         layout_node.box_model().border().right.to_px(), | 
					
						
							|  |  |  |         layout_node.box_model().margin().right.to_px()); | 
					
						
							| 
									
										
										
										
											2019-08-18 08:37:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // And the vertical box properties
 | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |     dbgprintf(" [%d+%d+%d %d %d+%d+%d]", | 
					
						
							| 
									
										
										
										
											2019-10-04 15:50:50 +02:00
										 |  |  |         layout_node.box_model().margin().top.to_px(), | 
					
						
							|  |  |  |         layout_node.box_model().border().top.to_px(), | 
					
						
							|  |  |  |         layout_node.box_model().padding().top.to_px(), | 
					
						
							| 
									
										
										
										
											2019-10-13 17:31:58 +02:00
										 |  |  |         layout_node.height(), | 
					
						
							| 
									
										
										
										
											2019-10-04 15:50:50 +02:00
										 |  |  |         layout_node.box_model().padding().bottom.to_px(), | 
					
						
							|  |  |  |         layout_node.box_model().border().bottom.to_px(), | 
					
						
							|  |  |  |         layout_node.box_model().margin().bottom.to_px()); | 
					
						
							| 
									
										
										
										
											2019-08-18 08:09:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |     dbgprintf("\n"); | 
					
						
							| 
									
										
										
										
											2019-06-21 20:54:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-03 15:20:13 +02:00
										 |  |  |     if (layout_node.is_block() && static_cast<const LayoutBlock&>(layout_node).children_are_inline()) { | 
					
						
							|  |  |  |         auto& block = static_cast<const LayoutBlock&>(layout_node); | 
					
						
							|  |  |  |         for (int i = 0; i < indent; ++i) | 
					
						
							|  |  |  |             dbgprintf("    "); | 
					
						
							|  |  |  |         dbgprintf("  Line boxes (%d):\n", block.line_boxes().size()); | 
					
						
							|  |  |  |         for (int line_box_index = 0; line_box_index < block.line_boxes().size(); ++line_box_index) { | 
					
						
							|  |  |  |             auto& line_box = block.line_boxes()[line_box_index]; | 
					
						
							|  |  |  |             for (int i = 0; i < indent; ++i) | 
					
						
							|  |  |  |                 dbgprintf("    "); | 
					
						
							|  |  |  |             dbgprintf("    [%d] width: %d\n", line_box_index, line_box.width()); | 
					
						
							|  |  |  |             for (int fragment_index = 0; fragment_index < line_box.fragments().size(); ++fragment_index) { | 
					
						
							|  |  |  |                 auto& fragment = line_box.fragments()[fragment_index]; | 
					
						
							|  |  |  |                 for (int i = 0; i < indent; ++i) | 
					
						
							|  |  |  |                     dbgprintf("    "); | 
					
						
							|  |  |  |                 dbgprintf("      [%d] layout_node: %s{%p}, start: %d, length: %d, rect: %s\n", | 
					
						
							|  |  |  |                     fragment_index, | 
					
						
							|  |  |  |                     fragment.layout_node().class_name(), | 
					
						
							|  |  |  |                     &fragment.layout_node(), | 
					
						
							|  |  |  |                     fragment.start(), | 
					
						
							|  |  |  |                     fragment.length(), | 
					
						
							|  |  |  |                     fragment.rect().to_string().characters()); | 
					
						
							|  |  |  |                 if (fragment.layout_node().is_text()) { | 
					
						
							|  |  |  |                     for (int i = 0; i < indent; ++i) | 
					
						
							|  |  |  |                         dbgprintf("    "); | 
					
						
							|  |  |  |                     auto& layout_text = static_cast<const LayoutText&>(fragment.layout_node()); | 
					
						
							|  |  |  |                     dbgprintf("        text: \"%s\"\n", | 
					
						
							|  |  |  |                         String(Utf8View(layout_text.node().data()).substring_view(fragment.start(), fragment.length()).as_string()).characters()); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-08 15:34:19 +02:00
										 |  |  |     layout_node.style().for_each_property([&](auto property_id, auto& value) { | 
					
						
							| 
									
										
										
										
											2019-06-28 21:17:34 +02:00
										 |  |  |         for (int i = 0; i < indent; ++i) | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |             dbgprintf("    "); | 
					
						
							| 
									
										
										
										
											2019-10-08 15:34:19 +02:00
										 |  |  |         dbgprintf("  (CSS::PropertyID(%u): %s)\n", (unsigned)property_id, value.to_string().characters()); | 
					
						
							| 
									
										
										
										
											2019-06-28 21:17:34 +02:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-09-21 15:32:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-28 21:17:34 +02:00
										 |  |  |     ++indent; | 
					
						
							| 
									
										
										
										
											2019-09-21 15:32:17 +03:00
										 |  |  |     layout_node.for_each_child([](auto& child) { | 
					
						
							| 
									
										
										
										
											2019-06-28 21:17:34 +02:00
										 |  |  |         dump_tree(child); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     --indent; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  | void dump_rule(const StyleRule& rule) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |     dbgprintf("Rule:\n"); | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  |     for (auto& selector : rule.selectors()) { | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |         dbgprintf("  Selector:\n"); | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  |         for (auto& component : selector.components()) { | 
					
						
							|  |  |  |             const char* type_description = "Unknown"; | 
					
						
							|  |  |  |             switch (component.type) { | 
					
						
							|  |  |  |             case Selector::Component::Type::Invalid: | 
					
						
							|  |  |  |                 type_description = "Invalid"; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case Selector::Component::Type::Id: | 
					
						
							|  |  |  |                 type_description = "Id"; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case Selector::Component::Type::Class: | 
					
						
							|  |  |  |                 type_description = "Class"; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case Selector::Component::Type::TagName: | 
					
						
							|  |  |  |                 type_description = "TagName"; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-10-06 09:28:10 +02:00
										 |  |  |             const char* relation_description = ""; | 
					
						
							|  |  |  |             switch (component.relation) { | 
					
						
							|  |  |  |             case Selector::Component::Relation::None: | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case Selector::Component::Relation::ImmediateChild: | 
					
						
							|  |  |  |                 relation_description = "{ImmediateChild}"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2019-10-06 11:05:57 +02:00
										 |  |  |             case Selector::Component::Relation::Descendant: | 
					
						
							|  |  |  |                 relation_description = "{Descendant}"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2019-10-06 19:59:07 +02:00
										 |  |  |             case Selector::Component::Relation::AdjacentSibling: | 
					
						
							|  |  |  |                 relation_description = "{AdjacentSibling}"; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case Selector::Component::Relation::GeneralSibling: | 
					
						
							|  |  |  |                 relation_description = "{GeneralSibling}"; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2019-10-06 09:28:10 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |             dbgprintf("    %s:%s %s\n", type_description, component.value.characters(), relation_description); | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |     dbgprintf("  Declarations:\n"); | 
					
						
							| 
									
										
										
										
											2019-09-30 20:06:17 +02:00
										 |  |  |     for (auto& property : rule.declaration().properties()) { | 
					
						
							| 
									
										
										
										
											2019-10-08 15:34:19 +02:00
										 |  |  |         dbgprintf("    CSS::PropertyID(%u): '%s'\n", (unsigned)property.property_id, property.value->to_string().characters()); | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-21 20:54:13 +02:00
										 |  |  | void dump_sheet(const StyleSheet& sheet) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-03 10:25:00 +02:00
										 |  |  |     dbgprintf("StyleSheet{%p}: %d rule(s)\n", &sheet, sheet.rules().size()); | 
					
						
							| 
									
										
										
										
											2019-06-25 06:31:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (auto& rule : sheet.rules()) { | 
					
						
							| 
									
										
										
										
											2019-06-27 20:40:21 +02:00
										 |  |  |         dump_rule(rule); | 
					
						
							| 
									
										
										
										
											2019-06-25 06:31:47 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-21 20:54:13 +02:00
										 |  |  | } |