//! 1. The `layout_document` function takes the `viewport` as an argument. The `LayoutCache` stores
//! percentage-based sizes and repositions all elements according to the new viewport dimensions.
//! 4. The intrinsic size calculation (bottom-up) can often be skipped, as it's independent of the
get_overflow_y, get_scrollbar_gutter_property, get_text_align, get_white_space_property, get_wrap, get_writing_mode,
get_display_type, is_block_level, AnonymousBoxType, DirtyFlag, LayoutNode, LayoutNodeHot, LayoutTreeBuilder, SubtreeHash,
pub fn get_size(&self, slot: usize, known_dims: LogicalSize) -> Option<&SizingCacheEntry> {
pub fn to_overflow_behavior(overflow: MultiValue<LayoutOverflow>) -> fc::OverflowBehavior {
// +spec:text-alignment-spacing:43ea0a - text-align-all shorthand: aligns all lines except last (overridden by text-align-last)
pub fn collect_children_dom_ids(styled_dom: &StyledDom, parent_dom_id: NodeId) -> Vec<NodeId> {
let writing_mode = get_writing_mode(styled_dom, dom_id, &styled_node_state).unwrap_or_default();
/// Recursively traverses the new DOM and old tree, building a new tree and marking dirty nodes.
let new_layout_relevant_count = layout_relevant_child_count(styled_dom, &new_children_dom_ids, new_dom_id);
// +spec:display-property:42f9c0 - anonymous block boxes wrap inline runs when block container has mixed block/inline children
// +spec:display-property:bef3fc - anonymous blocks of only collapsible whitespace removed from rendering tree
"[reconcile_recursive] Skipping whitespace-only inline run ({} nodes) between blocks in node {}",
"[reconcile_recursive] Created anonymous IFC wrapper (layout_idx={}) for {} inline children: {:?}",
"[reconcile_recursive] Created trailing anonymous IFC wrapper (layout_idx={}) for {} inline children: {:?}",
// +spec:overflow:08b60d - non-interactive media: UA may show scroll indicators but we skip them for print
// +spec:overflow:3c44cc - scrollbar-gutter: stable reserves gutter even when no scrollbar is shown
// +spec:overflow:3a6966 - classic scrollbar gutter width == scrollbar width; overlay scrollbars have no gutter
let scrollbar_gutter = get_scrollbar_gutter_property(ctx.styled_dom, dom_id, styled_node_state)
let is_scroll_container = matches!(ob_y, fc::OverflowBehavior::Scroll | fc::OverflowBehavior::Auto);
compute_scrollbar_info_core(ctx, dom_id, styled_node_state, content_size, container_size)
// self_content_box_pos is [CoordinateSpace::Window] - absolute position of parent's content-box
position_bfc_child_descendants(tree, child_index, child_content_box_pos, calculated_positions);
// +spec:overflow:44ef3b - scroll container detection: overflow scroll/auto makes box a scroll container
matches!(ov_x, MultiValue::Exact(LayoutOverflow::Scroll) | MultiValue::Exact(LayoutOverflow::Auto))
|| matches!(ov_y, MultiValue::Exact(LayoutOverflow::Scroll) | MultiValue::Exact(LayoutOverflow::Auto))
// +spec:overflow:f28d6a - hanging glyphs should be ink overflow, not scrollable overflow (not yet subtracted from content_size)
// self_content_box_pos is [CoordinateSpace::Window] - the absolute position of this node's content-box
// Positions in layout_result.output.positions are [CoordinateSpace::Parent] - relative to this node's content-box