LibWeb: Add debug tracing for FormattingContext::run() calls
Add optional tracing that prints a tree visualization of formatting context `run()` invocations. This is useful for debugging layout issues where you need to understand the nesting and order of layout passes, or why a box receives unexpected available space. Example output: ``` ├─ BFC <Viewport<#document>> run(definite(800) x definite(600)) │ ├─ BFC <BlockContainer<HTML>> run(definite(800) x indefinite) │ │ ├─ IFC <BlockContainer(anonymous)> run(definite(800) x indefinite) │ │ ├─ GFC <Box<DIV.grid>> run(definite(800) x indefinite) │ │ │ ├─ BFC <BlockContainer<DIV.item>> run(definite(400) x indefinite) ```
This commit is contained in:
parent
a6360a9792
commit
ccffc42d6a
10 changed files with 66 additions and 9 deletions
|
|
@ -82,6 +82,10 @@
|
|||
# cmakedefine01 FLAC_ENCODER_DEBUG
|
||||
#endif
|
||||
|
||||
#ifndef FORMATTING_CONTEXT_TRACE_DEBUG
|
||||
# cmakedefine01 FORMATTING_CONTEXT_TRACE_DEBUG
|
||||
#endif
|
||||
|
||||
#ifndef GENERATE_DEBUG
|
||||
# cmakedefine01 GENERATE_DEBUG
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -313,19 +313,11 @@ void dump_tree(StringBuilder& builder, Layout::Node const& layout_node, bool sho
|
|||
if (auto formatting_context_type = Layout::FormattingContext::formatting_context_type_created_by_box(box); formatting_context_type.has_value()) {
|
||||
switch (formatting_context_type.value()) {
|
||||
case Layout::FormattingContext::Type::Block:
|
||||
builder.appendff(" [{}BFC{}]", formatting_context_color_on, color_off);
|
||||
break;
|
||||
case Layout::FormattingContext::Type::Flex:
|
||||
builder.appendff(" [{}FFC{}]", formatting_context_color_on, color_off);
|
||||
break;
|
||||
case Layout::FormattingContext::Type::Grid:
|
||||
builder.appendff(" [{}GFC{}]", formatting_context_color_on, color_off);
|
||||
break;
|
||||
case Layout::FormattingContext::Type::Table:
|
||||
builder.appendff(" [{}TFC{}]", formatting_context_color_on, color_off);
|
||||
break;
|
||||
case Layout::FormattingContext::Type::SVG:
|
||||
builder.appendff(" [{}SVG{}]", formatting_context_color_on, color_off);
|
||||
builder.appendff(" [{}{}{}]", formatting_context_color_on, Layout::FormattingContext::type_name(formatting_context_type.value()), color_off);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ static bool margins_collapse_through(Box const& box, LayoutState& state)
|
|||
|
||||
void BlockFormattingContext::run(AvailableSpace const& available_space)
|
||||
{
|
||||
FORMATTING_CONTEXT_TRACE();
|
||||
// https://drafts.csswg.org/css-multicol-2/#the-multi-column-model
|
||||
auto root_state = m_state.get(root());
|
||||
auto column_count = determine_used_value_for_column_count(root_state.content_width());
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ void FlexFormattingContext::run(AvailableSpace const& available_space)
|
|||
return;
|
||||
}
|
||||
|
||||
FORMATTING_CONTEXT_TRACE();
|
||||
m_available_space = available_space;
|
||||
|
||||
// 1. Generate anonymous flex items
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ template<typename T>
|
|||
}
|
||||
|
||||
class FormattingContext {
|
||||
#if FORMATTING_CONTEXT_TRACE_DEBUG
|
||||
friend class FormattingContextTracer;
|
||||
#endif
|
||||
|
||||
public:
|
||||
virtual ~FormattingContext();
|
||||
|
||||
|
|
@ -36,6 +40,29 @@ public:
|
|||
InternalDummy, // Internal hack formatting context for unimplemented things. FIXME: Get rid of this.
|
||||
};
|
||||
|
||||
static constexpr StringView type_name(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Type::Block:
|
||||
return "BFC"sv;
|
||||
case Type::Inline:
|
||||
return "IFC"sv;
|
||||
case Type::Flex:
|
||||
return "FFC"sv;
|
||||
case Type::Grid:
|
||||
return "GFC"sv;
|
||||
case Type::Table:
|
||||
return "TFC"sv;
|
||||
case Type::SVG:
|
||||
return "SVG"sv;
|
||||
case Type::InternalReplaced:
|
||||
return "Replaced"sv;
|
||||
case Type::InternalDummy:
|
||||
return "Dummy"sv;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
virtual void run(AvailableSpace const&) = 0;
|
||||
|
||||
// These functions return the automatic content dimensions of the context's root box.
|
||||
|
|
@ -166,4 +193,31 @@ protected:
|
|||
LayoutState& m_state;
|
||||
};
|
||||
|
||||
#if FORMATTING_CONTEXT_TRACE_DEBUG
|
||||
class FormattingContextTracer {
|
||||
public:
|
||||
FormattingContextTracer(FormattingContext const& fc, AvailableSpace const& available_space)
|
||||
{
|
||||
StringBuilder indent_builder;
|
||||
for (int i = 0; i < s_depth; ++i)
|
||||
indent_builder.append("| "sv);
|
||||
auto intrinsic_marker = fc.m_layout_mode == LayoutMode::IntrinsicSizing ? " [intrinsic]"sv : ""sv;
|
||||
dbgln("{}|- {} <{}> run({}){}", indent_builder.string_view(), FormattingContext::type_name(fc.m_type), fc.m_context_box->debug_description(), available_space, intrinsic_marker);
|
||||
++s_depth;
|
||||
}
|
||||
|
||||
~FormattingContextTracer()
|
||||
{
|
||||
--s_depth;
|
||||
}
|
||||
|
||||
private:
|
||||
inline static int s_depth = 0;
|
||||
};
|
||||
|
||||
# define FORMATTING_CONTEXT_TRACE() FormattingContextTracer _formatting_context_tracer(*this, available_space)
|
||||
#else
|
||||
# define FORMATTING_CONTEXT_TRACE()
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2044,6 +2044,7 @@ void GridFormattingContext::run(AvailableSpace const& available_space)
|
|||
return;
|
||||
}
|
||||
|
||||
FORMATTING_CONTEXT_TRACE();
|
||||
m_available_space = available_space;
|
||||
|
||||
init_grid_lines(GridDimension::Column);
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ CSSPixels InlineFormattingContext::automatic_content_height() const
|
|||
|
||||
void InlineFormattingContext::run(AvailableSpace const& available_space)
|
||||
{
|
||||
FORMATTING_CONTEXT_TRACE();
|
||||
VERIFY(containing_block().children_are_inline());
|
||||
m_available_space = available_space;
|
||||
generate_line_boxes();
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ static bool is_container_element(Node const& node)
|
|||
|
||||
void SVGFormattingContext::run(AvailableSpace const& available_space)
|
||||
{
|
||||
FORMATTING_CONTEXT_TRACE();
|
||||
// NOTE: SVG doesn't have a "formatting context" in the spec, but this is the most
|
||||
// obvious way to drive SVG layout in our engine at the moment.
|
||||
|
||||
|
|
|
|||
|
|
@ -1672,6 +1672,7 @@ void TableFormattingContext::parent_context_did_dimension_child_root_box()
|
|||
|
||||
void TableFormattingContext::run(AvailableSpace const& available_space)
|
||||
{
|
||||
FORMATTING_CONTEXT_TRACE();
|
||||
m_available_space = available_space;
|
||||
|
||||
auto total_captions_height = run_caption_layout(CSS::CaptionSide::Top);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ set(EDITOR_DEBUG ON)
|
|||
set(EMOJI_DEBUG ON)
|
||||
set(FILE_WATCHER_DEBUG ON)
|
||||
set(FLAC_ENCODER_DEBUG ON)
|
||||
set(FORMATTING_CONTEXT_TRACE_DEBUG ON)
|
||||
set(GENERATE_DEBUG ON)
|
||||
set(GHASH_PROCESS_DEBUG ON)
|
||||
set(GIF_DEBUG ON)
|
||||
|
|
|
|||
Loading…
Reference in a new issue