LibWeb: Allow Layout::ImageBox to be anonymous

This is prep work for CSS content:image, which means pseudo-elements can
be used to generate images without a corresponding DOM node.
This commit is contained in:
Andreas Kling 2025-07-26 14:22:50 +02:00 committed by Andreas Kling
commit 9603aa0745
Notes: github-actions[bot] 2025-07-28 20:48:21 +00:00
11 changed files with 26 additions and 22 deletions

View file

@ -21,12 +21,12 @@ AudioBox::AudioBox(DOM::Document& document, DOM::Element& element, GC::Ref<CSS::
HTML::HTMLAudioElement& AudioBox::dom_node()
{
return static_cast<HTML::HTMLAudioElement&>(ReplacedBox::dom_node());
return static_cast<HTML::HTMLAudioElement&>(*ReplacedBox::dom_node());
}
HTML::HTMLAudioElement const& AudioBox::dom_node() const
{
return static_cast<HTML::HTMLAudioElement const&>(ReplacedBox::dom_node());
return static_cast<HTML::HTMLAudioElement const&>(*ReplacedBox::dom_node());
}
GC::Ptr<Painting::Paintable> AudioBox::create_paintable() const

View file

@ -21,7 +21,7 @@ public:
virtual void prepare_for_replaced_layout() override;
const HTML::HTMLCanvasElement& dom_node() const { return static_cast<const HTML::HTMLCanvasElement&>(ReplacedBox::dom_node()); }
HTML::HTMLCanvasElement const& dom_node() const { return static_cast<HTML::HTMLCanvasElement const&>(*ReplacedBox::dom_node()); }
virtual GC::Ptr<Painting::Paintable> create_paintable() const override;
};

View file

@ -15,7 +15,7 @@ namespace Web::Layout {
GC_DEFINE_ALLOCATOR(ImageBox);
ImageBox::ImageBox(DOM::Document& document, DOM::Element& element, GC::Ref<CSS::ComputedProperties> style, ImageProvider const& image_provider)
ImageBox::ImageBox(DOM::Document& document, GC::Ptr<DOM::Element> element, GC::Ref<CSS::ComputedProperties> style, ImageProvider const& image_provider)
: ReplacedBox(document, element, move(style))
, m_image_provider(image_provider)
{
@ -36,8 +36,9 @@ void ImageBox::prepare_for_replaced_layout()
set_natural_aspect_ratio(m_image_provider.intrinsic_aspect_ratio());
if (renders_as_alt_text()) {
auto const& element = as<HTML::HTMLElement>(dom_node());
auto alt = element.get_attribute_value(HTML::AttributeNames::alt);
String alt;
if (auto element = dom_node())
alt = element->get_attribute_value(HTML::AttributeNames::alt);
if (alt.is_empty()) {
set_natural_width(0);
@ -66,7 +67,7 @@ void ImageBox::dom_node_did_update_alt_text(Badge<ImageProvider>)
bool ImageBox::renders_as_alt_text() const
{
if (auto const* image_provider = dynamic_cast<ImageProvider const*>(&dom_node()))
if (auto const* image_provider = dynamic_cast<ImageProvider const*>(dom_node().ptr()))
return !image_provider->is_image_available();
return false;
}

View file

@ -16,13 +16,11 @@ class ImageBox final : public ReplacedBox {
GC_DECLARE_ALLOCATOR(ImageBox);
public:
ImageBox(DOM::Document&, DOM::Element&, GC::Ref<CSS::ComputedProperties>, ImageProvider const&);
ImageBox(DOM::Document&, GC::Ptr<DOM::Element>, GC::Ref<CSS::ComputedProperties>, ImageProvider const&);
virtual ~ImageBox() override;
virtual void prepare_for_replaced_layout() override;
const DOM::Element& dom_node() const { return static_cast<const DOM::Element&>(ReplacedBox::dom_node()); }
bool renders_as_alt_text() const;
virtual GC::Ptr<Painting::Paintable> create_paintable() const override;

View file

@ -18,6 +18,9 @@ public:
Painting::LabelablePaintable* paintable();
Painting::LabelablePaintable const* paintable() const;
DOM::Element const& dom_node() const { return *ReplacedBox::dom_node(); }
DOM::Element& dom_node() { return *ReplacedBox::dom_node(); }
protected:
LabelableNode(DOM::Document& document, DOM::Element& element, GC::Ref<CSS::ComputedProperties> style)
: ReplacedBox(document, element, move(style))

View file

@ -21,8 +21,8 @@ public:
virtual void prepare_for_replaced_layout() override;
[[nodiscard]] HTML::NavigableContainer const& dom_node() const { return as<HTML::NavigableContainer>(ReplacedBox::dom_node()); }
[[nodiscard]] HTML::NavigableContainer& dom_node() { return as<HTML::NavigableContainer>(ReplacedBox::dom_node()); }
[[nodiscard]] HTML::NavigableContainer const& dom_node() const { return as<HTML::NavigableContainer>(*ReplacedBox::dom_node()); }
[[nodiscard]] HTML::NavigableContainer& dom_node() { return as<HTML::NavigableContainer>(*ReplacedBox::dom_node()); }
virtual GC::Ptr<Painting::Paintable> create_paintable() const override;

View file

@ -11,8 +11,8 @@
namespace Web::Layout {
ReplacedBox::ReplacedBox(DOM::Document& document, DOM::Element& element, GC::Ref<CSS::ComputedProperties> style)
: Box(document, &element, move(style))
ReplacedBox::ReplacedBox(DOM::Document& document, GC::Ptr<DOM::Element> element, GC::Ref<CSS::ComputedProperties> style)
: Box(document, element, move(style))
{
}

View file

@ -15,11 +15,11 @@ class ReplacedBox : public Box {
GC_CELL(ReplacedBox, Box);
public:
ReplacedBox(DOM::Document&, DOM::Element&, GC::Ref<CSS::ComputedProperties>);
ReplacedBox(DOM::Document&, GC::Ptr<DOM::Element>, GC::Ref<CSS::ComputedProperties>);
virtual ~ReplacedBox() override;
DOM::Element const& dom_node() const { return as<DOM::Element>(*Node::dom_node()); }
DOM::Element& dom_node() { return as<DOM::Element>(*Node::dom_node()); }
GC::Ptr<DOM::Element const> dom_node() const { return as<DOM::Element>(Node::dom_node()); }
GC::Ptr<DOM::Element> dom_node() { return as<DOM::Element>(Node::dom_node()); }
virtual void prepare_for_replaced_layout() { }

View file

@ -19,8 +19,8 @@ public:
SVGSVGBox(DOM::Document&, SVG::SVGSVGElement&, GC::Ref<CSS::ComputedProperties>);
virtual ~SVGSVGBox() override = default;
SVG::SVGSVGElement& dom_node() { return as<SVG::SVGSVGElement>(ReplacedBox::dom_node()); }
SVG::SVGSVGElement const& dom_node() const { return as<SVG::SVGSVGElement>(ReplacedBox::dom_node()); }
SVG::SVGSVGElement& dom_node() { return as<SVG::SVGSVGElement>(*ReplacedBox::dom_node()); }
SVG::SVGSVGElement const& dom_node() const { return as<SVG::SVGSVGElement>(*ReplacedBox::dom_node()); }
virtual bool can_have_children() const override { return true; }

View file

@ -29,12 +29,12 @@ void VideoBox::finalize()
HTML::HTMLVideoElement& VideoBox::dom_node()
{
return static_cast<HTML::HTMLVideoElement&>(ReplacedBox::dom_node());
return static_cast<HTML::HTMLVideoElement&>(*ReplacedBox::dom_node());
}
HTML::HTMLVideoElement const& VideoBox::dom_node() const
{
return static_cast<HTML::HTMLVideoElement const&>(ReplacedBox::dom_node());
return static_cast<HTML::HTMLVideoElement const&>(*ReplacedBox::dom_node());
}
void VideoBox::prepare_for_replaced_layout()

View file

@ -26,7 +26,9 @@ GC::Ref<ImagePaintable> ImagePaintable::create(Layout::SVGImageBox const& layout
GC::Ref<ImagePaintable> ImagePaintable::create(Layout::ImageBox const& layout_box)
{
auto alt = layout_box.dom_node().get_attribute_value(HTML::AttributeNames::alt);
String alt;
if (auto element = layout_box.dom_node())
alt = element->get_attribute_value(HTML::AttributeNames::alt);
return layout_box.heap().allocate<ImagePaintable>(layout_box, layout_box.image_provider(), layout_box.renders_as_alt_text(), move(alt), false);
}