mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-08 06:09:58 +00:00
LibWeb: Position absolute block-level boxes below previous siblings
Whether an absbox is positioned below or to the right of its previous sibling in an `InlineFormattingContext` is determined by the display-outside value before blockification, so we store the pre-blockification `display` value in `ComputedValues` to access it in `InlineFormattingContext` and position the box accordingly.
This commit is contained in:
parent
7867fef8d7
commit
5b1eba7ac8
Notes:
github-actions[bot]
2025-09-29 16:39:03 +00:00
Author: https://github.com/Pasi4K5 🔰
Commit: 5b1eba7ac8
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6133
Reviewed-by: https://github.com/Calme1709
Reviewed-by: https://github.com/awesomekling
9 changed files with 67 additions and 4 deletions
|
|
@ -132,6 +132,16 @@ void ComputedProperties::revert_property(PropertyID id, ComputedProperties const
|
|||
set_property_inherited(id, style_for_revert.is_property_inherited(id) ? Inherited::Yes : Inherited::No);
|
||||
}
|
||||
|
||||
Display ComputedProperties::display_before_box_type_transformation() const
|
||||
{
|
||||
return m_display_before_box_type_transformation;
|
||||
}
|
||||
|
||||
void ComputedProperties::set_display_before_box_type_transformation(Display value)
|
||||
{
|
||||
m_display_before_box_type_transformation = value;
|
||||
}
|
||||
|
||||
void ComputedProperties::set_animated_property(PropertyID id, NonnullRefPtr<StyleValue const> value, Inherited inherited)
|
||||
{
|
||||
m_animated_property_values.set(id, move(value));
|
||||
|
|
|
|||
|
|
@ -186,6 +186,9 @@ public:
|
|||
MixBlendMode mix_blend_mode() const;
|
||||
Optional<FlyString> view_transition_name() const;
|
||||
|
||||
Display display_before_box_type_transformation() const;
|
||||
void set_display_before_box_type_transformation(Display value);
|
||||
|
||||
static Vector<Transformation> transformations_for_style_value(StyleValue const& value);
|
||||
Vector<Transformation> transformations() const;
|
||||
TransformBox transform_box() const;
|
||||
|
|
@ -279,6 +282,8 @@ private:
|
|||
|
||||
HashMap<PropertyID, NonnullRefPtr<StyleValue const>> m_animated_property_values;
|
||||
|
||||
Display m_display_before_box_type_transformation { InitialValues::display() };
|
||||
|
||||
int m_math_depth { InitialValues::math_depth() };
|
||||
RefPtr<Gfx::FontCascadeList const> m_font_list;
|
||||
RefPtr<Gfx::Font const> m_first_available_computed_font;
|
||||
|
|
|
|||
|
|
@ -487,6 +487,7 @@ public:
|
|||
CSS::ContentData content() const { return m_noninherited.content; }
|
||||
CSS::PointerEvents pointer_events() const { return m_inherited.pointer_events; }
|
||||
CSS::Display display() const { return m_noninherited.display; }
|
||||
CSS::Display display_before_box_type_transformation() const { return m_noninherited.display_before_box_type_transformation; }
|
||||
Optional<int> const& z_index() const { return m_noninherited.z_index; }
|
||||
Variant<LengthOrCalculated, NumberOrCalculated> tab_size() const { return m_inherited.tab_size; }
|
||||
CSS::TextAlign text_align() const { return m_inherited.text_align; }
|
||||
|
|
@ -756,6 +757,7 @@ protected:
|
|||
CSS::Clear clear { InitialValues::clear() };
|
||||
CSS::Clip clip { InitialValues::clip() };
|
||||
CSS::Display display { InitialValues::display() };
|
||||
CSS::Display display_before_box_type_transformation { InitialValues::display() };
|
||||
Optional<int> z_index;
|
||||
// FIXME: Store this as flags in a u8.
|
||||
Vector<CSS::TextDecorationLine> text_decoration_line { InitialValues::text_decoration_line() };
|
||||
|
|
@ -955,6 +957,7 @@ public:
|
|||
void set_list_style_type(CSS::ListStyleType value) { m_inherited.list_style_type = move(value); }
|
||||
void set_list_style_position(CSS::ListStylePosition value) { m_inherited.list_style_position = move(value); }
|
||||
void set_display(CSS::Display value) { m_noninherited.display = value; }
|
||||
void set_display_before_box_type_transformation(CSS::Display value) { m_noninherited.display_before_box_type_transformation = value; }
|
||||
void set_backdrop_filter(CSS::Filter const& backdrop_filter) { m_noninherited.backdrop_filter = backdrop_filter; }
|
||||
void set_filter(CSS::Filter const& filter) { m_noninherited.filter = filter; }
|
||||
void set_border_bottom_left_radius(CSS::BorderRadiusData value)
|
||||
|
|
|
|||
|
|
@ -2154,6 +2154,8 @@ void StyleComputer::compute_property_values(ComputedProperties& style) const
|
|||
|
||||
style.set_property(property_id, absolutized_value, is_inherited);
|
||||
});
|
||||
|
||||
style.set_display_before_box_type_transformation(style.display());
|
||||
}
|
||||
|
||||
void StyleComputer::resolve_effective_overflow_values(ComputedProperties& style) const
|
||||
|
|
|
|||
|
|
@ -503,8 +503,10 @@ StaticPositionRect InlineFormattingContext::calculate_static_position_rect(Box c
|
|||
|
||||
CSSPixelPoint position;
|
||||
if (auto const* sibling = box.previous_sibling()) {
|
||||
// We're calculating the position for an absolutely positioned box with a previous sibling in an IFC. We need to
|
||||
// position the box at the top right corner of the last fragment of this sibling.
|
||||
// We're calculating the position for an absolutely positioned box with a previous sibling in an IFC.
|
||||
// We need to position the box...
|
||||
// ...below the last fragment of this sibling, if the display-outside value (before box type transformation) is block.
|
||||
// ...at the top right corner of the last fragment of this sibling otherwise.
|
||||
LineBoxFragment const* last_fragment = nullptr;
|
||||
auto const& cb_state = m_state.get(*sibling->containing_block());
|
||||
for (auto const& line_box : cb_state.line_boxes) {
|
||||
|
|
@ -514,8 +516,15 @@ StaticPositionRect InlineFormattingContext::calculate_static_position_rect(Box c
|
|||
}
|
||||
}
|
||||
if (last_fragment) {
|
||||
position.set_x(last_fragment->offset().x() + last_fragment->width());
|
||||
position.set_y(last_fragment->offset().y());
|
||||
if (box.display_before_box_type_transformation().is_block_outside()) {
|
||||
// Display-outside value is block => position below
|
||||
position.set_x(0);
|
||||
position.set_y(last_fragment->offset().y() + last_fragment->height());
|
||||
} else {
|
||||
// Display-outside value is not block => position to the right
|
||||
position.set_x(last_fragment->offset().x() + last_fragment->width());
|
||||
position.set_y(last_fragment->offset().y());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -571,6 +571,7 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
|
|||
border_top_right_radius.as_border_radius().vertical_radius() });
|
||||
}
|
||||
computed_values.set_display(computed_style.display());
|
||||
computed_values.set_display_before_box_type_transformation(computed_style.display_before_box_type_transformation());
|
||||
|
||||
computed_values.set_flex_direction(computed_style.flex_direction());
|
||||
computed_values.set_flex_wrap(computed_style.flex_wrap());
|
||||
|
|
@ -968,6 +969,15 @@ CSS::Display Node::display() const
|
|||
return computed_values().display();
|
||||
}
|
||||
|
||||
CSS::Display Node::display_before_box_type_transformation() const
|
||||
{
|
||||
if (!has_style()) {
|
||||
return CSS::Display(CSS::DisplayOutside::Inline, CSS::DisplayInside::Flow);
|
||||
}
|
||||
|
||||
return computed_values().display_before_box_type_transformation();
|
||||
}
|
||||
|
||||
bool Node::is_inline() const
|
||||
{
|
||||
return display().is_inline_outside();
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ public:
|
|||
virtual bool can_have_children() const { return true; }
|
||||
|
||||
CSS::Display display() const;
|
||||
CSS::Display display_before_box_type_transformation() const;
|
||||
|
||||
bool is_inline() const;
|
||||
bool is_inline_block() const;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue