mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-04-18 09:50:27 +00:00
Instead, compute them on demand. This affects ReplacedBox and its subclasses. This commit is centered around a new Box::auto_content_box_size method. It returns a SizeWithAspectRatio representing the natural size of a replaced element, or the size derived from attributes for text input and textarea. These values are used when the corresponding axis is auto or indefinite. Although introducing this API choke-point for sizing replaced and replaced-like elements was the main goal, it's notable that layout becomes more robust in the face of dynamic changes due to reduced potential for stale size values (at the cost of extra calculations and allocations).
91 lines
2.6 KiB
C++
91 lines
2.6 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <andreas@ladybird.org>
|
|
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibWeb/DOM/Document.h>
|
|
#include <LibWeb/HTML/HTMLHtmlElement.h>
|
|
#include <LibWeb/Layout/BlockContainer.h>
|
|
#include <LibWeb/Layout/Box.h>
|
|
#include <LibWeb/Layout/FormattingContext.h>
|
|
#include <LibWeb/Layout/TableWrapper.h>
|
|
#include <LibWeb/Painting/PaintableBox.h>
|
|
|
|
namespace Web::Layout {
|
|
|
|
GC_DEFINE_ALLOCATOR(Box);
|
|
|
|
Box::Box(DOM::Document& document, DOM::Node* node, GC::Ref<CSS::ComputedProperties> style)
|
|
: NodeWithStyleAndBoxModelMetrics(document, node, move(style))
|
|
{
|
|
}
|
|
|
|
Box::Box(DOM::Document& document, DOM::Node* node, NonnullOwnPtr<CSS::ComputedValues> computed_values)
|
|
: NodeWithStyleAndBoxModelMetrics(document, node, move(computed_values))
|
|
{
|
|
}
|
|
|
|
Box::~Box()
|
|
{
|
|
}
|
|
|
|
CSS::SizeWithAspectRatio Box::auto_content_box_size() const
|
|
{
|
|
// https://drafts.csswg.org/css-contain-2/#containment-size
|
|
// Replaced elements must be treated as having a natural width and height of 0 and no natural aspect
|
|
// ratio.
|
|
if (has_size_containment())
|
|
return { 0, 0, {} };
|
|
|
|
return compute_auto_content_box_size();
|
|
}
|
|
|
|
void Box::visit_edges(Cell::Visitor& visitor)
|
|
{
|
|
Base::visit_edges(visitor);
|
|
visitor.visit(m_contained_abspos_children);
|
|
}
|
|
|
|
GC::Ptr<Painting::Paintable> Box::create_paintable() const
|
|
{
|
|
return Painting::PaintableBox::create(*this);
|
|
}
|
|
|
|
Painting::PaintableBox* Box::paintable_box()
|
|
{
|
|
return static_cast<Painting::PaintableBox*>(Node::first_paintable());
|
|
}
|
|
|
|
Painting::PaintableBox const* Box::paintable_box() const
|
|
{
|
|
return static_cast<Painting::PaintableBox const*>(Node::first_paintable());
|
|
}
|
|
|
|
Optional<CSSPixelFraction> Box::preferred_aspect_ratio() const
|
|
{
|
|
auto const& computed_aspect_ratio = computed_values().aspect_ratio();
|
|
|
|
// https://www.w3.org/TR/css-contain-2/#containment-size
|
|
if (!has_size_containment() && computed_aspect_ratio.use_natural_aspect_ratio_if_available) {
|
|
if (auto auto_size = auto_content_box_size(); auto_size.has_aspect_ratio())
|
|
return auto_size.aspect_ratio;
|
|
}
|
|
|
|
if (!computed_aspect_ratio.preferred_ratio.has_value())
|
|
return {};
|
|
|
|
auto ratio = computed_aspect_ratio.preferred_ratio.value();
|
|
if (ratio.is_degenerate())
|
|
return {};
|
|
|
|
auto fraction = CSSPixelFraction(ratio.numerator(), ratio.denominator());
|
|
// ratio.is_degenerate() operates on doubles while CSSPixelFraction uses CSSPixels, so we need to check again here.
|
|
if (fraction == 0)
|
|
return {};
|
|
|
|
return fraction;
|
|
}
|
|
|
|
}
|