diff --git a/components/layout/flow/inline/mod.rs b/components/layout/flow/inline/mod.rs index da77a4ea840..7034144a79d 100644 --- a/components/layout/flow/inline/mod.rs +++ b/components/layout/flow/inline/mod.rs @@ -333,6 +333,10 @@ struct LineUnderConstruction { /// indicates that the next run that exceeds the line length can cause a line break. has_content: bool, + /// Whether any active linebox has added some inline-axis padding, border or margin + /// to this line. + has_inline_pbm: bool, + /// Whether or not there are floats that did not fit on the current line. Before /// the [`LineItem`]s of this line are laid out, these floats will need to be /// placed directly below this line, but still as children of this line's Fragments. @@ -356,6 +360,7 @@ impl LineUnderConstruction { start_position, max_block_size: LineBlockSizes::zero(), has_content: false, + has_inline_pbm: false, has_floats_waiting_to_be_placed: false, placement_among_floats: OnceCell::new(), line_items: Vec::new(), @@ -558,6 +563,10 @@ struct UnbreakableSegmentUnderConstruction { /// a line break. has_content: bool, + /// Whether any active linebox has added some inline-axis padding, border or margin + /// to this line segment. + has_inline_pbm: bool, + /// The inline size of any trailing whitespace in this segment. trailing_whitespace_size: Au, } @@ -574,6 +583,7 @@ impl UnbreakableSegmentUnderConstruction { line_items: Vec::new(), inline_box_hierarchy_depth: None, has_content: false, + has_inline_pbm: false, trailing_whitespace_size: Au::zero(), } } @@ -732,8 +742,9 @@ pub(super) struct InlineFormattingContextLayout<'layout_data> { /// is encountered. pub have_deferred_soft_wrap_opportunity: bool, - /// Whether or not this InlineFormattingContext has processed any in flow content at all. - had_inflow_content: bool, + /// Whether or not this InlineFormattingContext contains line boxes, excluding + /// [phantom line boxes](https://drafts.csswg.org/css-inline-3/#phantom-line-box). + has_line_boxes: bool, /// Whether or not the layout of this InlineFormattingContext depends on the block size /// of its container for the purposes of flexbox layout. @@ -837,9 +848,15 @@ impl InlineFormattingContextLayout<'_> { } if inline_box.is_first_split { - self.current_line_segment.inline_size += inline_box_state.pbm.padding.inline_start + - inline_box_state.pbm.border.inline_start + - inline_box_state.pbm.margin.inline_start.auto_is(Au::zero); + let padding = inline_box_state.pbm.padding.inline_start; + let border = inline_box_state.pbm.border.inline_start; + let margin = inline_box_state.pbm.margin.inline_start.auto_is(Au::zero); + // We can't just check if the sum is zero because the margin can be negative, + // we need to check the values separately. + if !padding.is_zero() || !border.is_zero() || !margin.is_zero() { + self.current_line_segment.has_inline_pbm = true; + } + self.current_line_segment.inline_size += padding + border + margin; self.current_line_segment .line_items .push(LineItem::InlineStartBoxPaddingBorderMargin( @@ -881,10 +898,15 @@ impl InlineFormattingContextLayout<'_> { } if inline_box_state.is_last_fragment { - let pbm_end = inline_box_state.pbm.padding.inline_end + - inline_box_state.pbm.border.inline_end + - inline_box_state.pbm.margin.inline_end.auto_is(Au::zero); - self.current_line_segment.inline_size += pbm_end; + let padding = inline_box_state.pbm.padding.inline_end; + let border = inline_box_state.pbm.border.inline_end; + let margin = inline_box_state.pbm.margin.inline_end.auto_is(Au::zero); + // We can't just check if the sum is zero because the margin can be negative, + // we need to check the values separately. + if !padding.is_zero() || !border.is_zero() || !margin.is_zero() { + self.current_line_segment.has_inline_pbm = true; + } + self.current_line_segment.inline_size += padding + border + margin; self.current_line_segment .line_items .push(LineItem::InlineEndBoxPaddingBorderMargin( @@ -984,10 +1006,16 @@ impl InlineFormattingContextLayout<'_> { justification_adjustment, ); - if line_to_layout.has_content { + // https://drafts.csswg.org/css-inline-3/#invisible-line-boxes + // > Line boxes that contain no text, no preserved white space, no inline boxes with non-zero + // > inline-axis margins, padding, or borders, and no other in-flow content (such as atomic + // > inlines or ruby annotations), and do not end with a forced line break are phantom line boxes. + // > Such boxes [...] must be treated as not existing for any other layout or rendering purpose. + if line_to_layout.has_content || line_to_layout.has_inline_pbm { let baseline = baseline_offset + block_start_position; self.baselines.first.get_or_insert(baseline); self.baselines.last = Some(baseline); + self.has_line_boxes = true; } // If the line doesn't have any fragments, we don't need to add a containing fragment for it. @@ -1350,8 +1378,6 @@ impl InlineFormattingContextLayout<'_> { SegmentContentFlags::empty(), ); } - - self.had_inflow_content = true; } pub(super) fn possibly_flush_deferred_forced_line_break(&mut self) { @@ -1486,7 +1512,6 @@ impl InlineFormattingContextLayout<'_> { } if !flags.is_collapsible_whitespace() { self.current_line_segment.has_content = true; - self.had_inflow_content = true; } // This may or may not include the size of the strut depending on the quirks mode setting. @@ -1601,6 +1626,7 @@ impl InlineFormattingContextLayout<'_> { self.current_line.line_items.extend(segment_items); self.current_line.has_content |= self.current_line_segment.has_content; + self.current_line.has_inline_pbm |= self.current_line_segment.has_inline_pbm; self.current_line_segment.reset(); } @@ -1792,7 +1818,7 @@ impl InlineFormattingContext { linebreak_before_new_content: false, deferred_br_clear: Clear::None, have_deferred_soft_wrap_opportunity: false, - had_inflow_content: false, + has_line_boxes: false, depends_on_block_constraints: false, white_space_collapse: style_text.white_space_collapse, text_wrap_mode: style_text.text_wrap_mode, @@ -1846,7 +1872,7 @@ impl InlineFormattingContext { let mut collapsible_margins_in_children = CollapsedBlockMargins::zero(); let content_block_size = layout.current_line.start_position.block; - collapsible_margins_in_children.collapsed_through = !layout.had_inflow_content && + collapsible_margins_in_children.collapsed_through = !layout.has_line_boxes && content_block_size.is_zero() && collapsible_with_parent_start_margin.0; diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index b5f49a7e567..f4a5a871ff8 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -210635,6 +210635,86 @@ ] ] }, + "model": { + "phantom-line-boxes-001.html": [ + "da0e9095b7a37e6b4a897269e753175c68039a34", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], + "phantom-line-boxes-002.html": [ + "c180a9bf3b5c4cda3e281d84bb36b6d8b2bae91c", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], + "phantom-line-boxes-003.html": [ + "633aa9dfba8d81d515c807c66074b77c73dbfee4", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], + "phantom-line-boxes-004.html": [ + "0b4f7737ee21b4490e951ce1677772b9d1ae2d71", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], + "phantom-line-boxes-005.html": [ + "dd2620294412fab68af218f30e470a3003255dd4", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], + "phantom-line-boxes-006.html": [ + "7b5a43cbf811680087429abe5b0236d1221f28d4", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ] + }, "text-box-trim": { "border-padding-001.html": [ "9c25c42a1def684b364e98dc9d6233cd5c700519", diff --git a/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-001.html b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-001.html new file mode 100644 index 00000000000..da0e9095b7a --- /dev/null +++ b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-001.html @@ -0,0 +1,49 @@ + +CSS Inline Layout Model: Phantom Line Boxes + + + + + + + + + +

Test passes if there is a filled green square and no red.

+ +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-002.html b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-002.html new file mode 100644 index 00000000000..c180a9bf3b5 --- /dev/null +++ b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-002.html @@ -0,0 +1,49 @@ + +CSS Inline Layout Model: Phantom Line Boxes + + + + + + + + + +

Test passes if there is a filled green square and no red.

+ +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-003.html b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-003.html new file mode 100644 index 00000000000..633aa9dfba8 --- /dev/null +++ b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-003.html @@ -0,0 +1,49 @@ + +CSS Inline Layout Model: Phantom Line Boxes + + + + + + + + + +

Test passes if there is a filled green square and no red.

+ +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-004.html b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-004.html new file mode 100644 index 00000000000..0b4f7737ee2 --- /dev/null +++ b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-004.html @@ -0,0 +1,49 @@ + +CSS Inline Layout Model: Phantom Line Boxes + + + + + + + + + +

Test passes if there is a filled green square and no red.

+ +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-005.html b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-005.html new file mode 100644 index 00000000000..dd262029441 --- /dev/null +++ b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-005.html @@ -0,0 +1,49 @@ + +CSS Inline Layout Model: Phantom Line Boxes + + + + + + + + + +

Test passes if there is a filled green square and no red.

+ +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-006.html b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-006.html new file mode 100644 index 00000000000..7b5a43cbf81 --- /dev/null +++ b/tests/wpt/tests/css/css-inline/model/phantom-line-boxes-006.html @@ -0,0 +1,50 @@ + +CSS Inline Layout Model: Phantom Line Boxes + + + + + + + + + +

Test passes if there is a filled green square and no red.

+ +
+
+
+
+
+
+
+
+
+
+
+