|
@@ -180,6 +180,63 @@ static Gfx::FloatSize solve_replaced_size_constraint(float w, float h, const Rep
|
|
|
return { w, h };
|
|
|
}
|
|
|
|
|
|
+float FormattingContext::compute_auto_height_for_block_level_element(const Box& box)
|
|
|
+{
|
|
|
+ Optional<float> top;
|
|
|
+ Optional<float> bottom;
|
|
|
+
|
|
|
+ if (box.children_are_inline()) {
|
|
|
+ // If it only has inline-level children, the height is the distance between
|
|
|
+ // the top of the topmost line box and the bottom of the bottommost line box.
|
|
|
+ if (!box.line_boxes().is_empty()) {
|
|
|
+ for (auto& fragment : box.line_boxes().first().fragments()) {
|
|
|
+ if (!top.has_value() || fragment.offset().y() < top.value())
|
|
|
+ top = fragment.offset().y();
|
|
|
+ }
|
|
|
+ for (auto& fragment : box.line_boxes().last().fragments()) {
|
|
|
+ if (!bottom.has_value() || (fragment.offset().y() + fragment.height()) > bottom.value())
|
|
|
+ bottom = fragment.offset().y() + fragment.height();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // If it has block-level children, the height is the distance between
|
|
|
+ // the top margin-edge of the topmost block-level child box
|
|
|
+ // and the bottom margin-edge of the bottommost block-level child box.
|
|
|
+ box.for_each_child_of_type<Box>([&](Layout::Box& child_box) {
|
|
|
+ if (child_box.is_absolutely_positioned())
|
|
|
+ return IterationDecision::Continue;
|
|
|
+ if ((box.computed_values().overflow_y() == CSS::Overflow::Visible) && child_box.is_floating())
|
|
|
+ return IterationDecision::Continue;
|
|
|
+
|
|
|
+ float child_box_top = child_box.effective_offset().y() - child_box.box_model().margin_box().top;
|
|
|
+ float child_box_bottom = child_box.effective_offset().y() + child_box.height() + child_box.box_model().margin_box().bottom;
|
|
|
+
|
|
|
+ if (!top.has_value() || child_box_top < top.value())
|
|
|
+ top = child_box_top;
|
|
|
+
|
|
|
+ if (!bottom.has_value() || child_box_bottom > bottom.value())
|
|
|
+ bottom = child_box_bottom;
|
|
|
+
|
|
|
+ return IterationDecision::Continue;
|
|
|
+ });
|
|
|
+ // In addition, if the element has any floating descendants
|
|
|
+ // whose bottom margin edge is below the element's bottom content edge,
|
|
|
+ // then the height is increased to include those edges.
|
|
|
+ box.for_each_child_of_type<Box>([&](Layout::Box& child_box) {
|
|
|
+ if (!child_box.is_floating())
|
|
|
+ return IterationDecision::Continue;
|
|
|
+
|
|
|
+ float child_box_bottom = child_box.effective_offset().y() + child_box.height();
|
|
|
+
|
|
|
+ if (!bottom.has_value() || child_box_bottom > bottom.value())
|
|
|
+ bottom = child_box_bottom;
|
|
|
+
|
|
|
+ return IterationDecision::Continue;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return bottom.value_or(0) - top.value_or(0);
|
|
|
+}
|
|
|
+
|
|
|
float FormattingContext::tentative_width_for_replaced_element(const ReplacedBox& box, const CSS::Length& width)
|
|
|
{
|
|
|
auto& containing_block = *box.containing_block();
|
|
@@ -487,7 +544,16 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
|
|
|
box.box_model().padding.top = computed_values.padding().top.resolved_or_zero(box, containing_block.width()).to_px(box);
|
|
|
box.box_model().padding.bottom = computed_values.padding().bottom.resolved_or_zero(box, containing_block.width()).to_px(box);
|
|
|
|
|
|
- if (specified_height.is_auto() && !specified_top.is_auto() && !specified_bottom.is_auto()) {
|
|
|
+ if (specified_height.is_auto() && !specified_top.is_auto() && specified_bottom.is_auto()) {
|
|
|
+ const auto& margin = box.box_model().margin;
|
|
|
+ const auto& padding = box.box_model().padding;
|
|
|
+ const auto& border = box.box_model().border;
|
|
|
+
|
|
|
+ specified_height = CSS::Length(compute_auto_height_for_block_level_element(box), CSS::Length::Type::Px);
|
|
|
+ box.box_model().offset.bottom = containing_block.height() - specified_height.to_px(box) - specified_top.to_px(box) - margin.top - padding.top - border.top - margin.bottom - padding.bottom - border.bottom;
|
|
|
+ }
|
|
|
+
|
|
|
+ else if (specified_height.is_auto() && !specified_top.is_auto() && !specified_bottom.is_auto()) {
|
|
|
const auto& margin = box.box_model().margin;
|
|
|
const auto& padding = box.box_model().padding;
|
|
|
const auto& border = box.box_model().border;
|