From 4b1abcf61d650e196bec2485bc61e6594654ec8d Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 10 Apr 2024 21:44:11 -0400 Subject: [PATCH] LibWeb: Generalize support for dimension attributes Rather than each element which supports dimension attributes needing to implement parsing the attributes and setting the appropriate style, we can generalize this functionality. This will also make each element more closely resemble the spec text, as we will be effectively declaring, for example, "The img element supports dimension attributes" in code. --- .../Libraries/LibWeb/CSS/StyleComputer.cpp | 19 +++++++++++++++++++ Userland/Libraries/LibWeb/DOM/Element.h | 3 +++ .../LibWeb/HTML/HTMLIFrameElement.cpp | 14 -------------- .../Libraries/LibWeb/HTML/HTMLIFrameElement.h | 5 +++-- .../LibWeb/HTML/HTMLImageElement.cpp | 8 +------- .../Libraries/LibWeb/HTML/HTMLImageElement.h | 3 +++ .../LibWeb/HTML/HTMLInputElement.cpp | 18 ------------------ .../Libraries/LibWeb/HTML/HTMLInputElement.h | 4 +++- 8 files changed, 32 insertions(+), 42 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 0f6ff4d6e80..048d2e9ddbb 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -1507,6 +1508,19 @@ static void apply_animation_properties(DOM::Document& document, StyleProperties& } } +static void apply_dimension_attribute(StyleProperties& style, DOM::Element const& element, FlyString const& attribute_name, CSS::PropertyID property_id) +{ + auto attribute = element.attribute(attribute_name); + if (!attribute.has_value()) + return; + + auto parsed_value = HTML::parse_dimension_value(*attribute); + if (!parsed_value) + return; + + style.set_property(property_id, parsed_value.release_nonnull()); +} + // https://www.w3.org/TR/css-cascade/#cascading void StyleComputer::compute_cascaded_values(StyleProperties& style, DOM::Element& element, Optional pseudo_element, bool& did_match_any_pseudo_element_rules, ComputeStyleMode mode) const { @@ -1543,6 +1557,11 @@ void StyleComputer::compute_cascaded_values(StyleProperties& style, DOM::Element if (!pseudo_element.has_value()) { element.apply_presentational_hints(style); + if (element.supports_dimension_attributes()) { + apply_dimension_attribute(style, element, HTML::AttributeNames::width, CSS::PropertyID::Width); + apply_dimension_attribute(style, element, HTML::AttributeNames::height, CSS::PropertyID::Height); + } + // SVG presentation attributes are parsed as CSS values, so we need to handle potential custom properties here. if (element.is_svg_element()) { // FIXME: This is not very efficient, we should only resolve the custom properties that are actually used. diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index 81526c0e957..8ccc83c0742 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -141,6 +141,9 @@ public: bool has_class(FlyString const&, CaseSensitivity = CaseSensitivity::CaseSensitive) const; Vector const& class_names() const { return m_classes; } + // https://html.spec.whatwg.org/multipage/embedded-content-other.html#dimension-attributes + virtual bool supports_dimension_attributes() const { return false; } + virtual void apply_presentational_hints(CSS::StyleProperties&) const { } // https://dom.spec.whatwg.org/#concept-element-attributes-change-ext diff --git a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp index 25fe51a80a0..cf0fbc18931 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp @@ -169,20 +169,6 @@ void HTMLIFrameElement::removed_from(DOM::Node* node) destroy_the_child_navigable(); } -// https://html.spec.whatwg.org/multipage/rendering.html#attributes-for-embedded-content-and-images -void HTMLIFrameElement::apply_presentational_hints(CSS::StyleProperties& style) const -{ - for_each_attribute([&](auto& name, auto& value) { - if (name == HTML::AttributeNames::width) { - if (auto parsed_value = parse_dimension_value(value)) - style.set_property(CSS::PropertyID::Width, parsed_value.release_nonnull()); - } else if (name == HTML::AttributeNames::height) { - if (auto parsed_value = parse_dimension_value(value)) - style.set_property(CSS::PropertyID::Height, parsed_value.release_nonnull()); - } - }); -} - // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#iframe-load-event-steps void run_iframe_load_event_steps(HTML::HTMLIFrameElement& element) { diff --git a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h index f1f0038a63e..237e87e7fa1 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h @@ -30,8 +30,6 @@ public: Optional const& pending_resource_start_time() const { return m_pending_resource_start_time; } void set_pending_resource_start_time(Optional time) { m_pending_resource_start_time = time; } - virtual void apply_presentational_hints(CSS::StyleProperties&) const override; - virtual void visit_edges(Cell::Visitor&) override; private: @@ -45,6 +43,9 @@ private: virtual void attribute_changed(FlyString const& name, Optional const& value) override; virtual i32 default_tab_index_value() const override; + // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:dimension-attributes + virtual bool supports_dimension_attributes() const override { return true; } + // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#process-the-iframe-attributes void process_the_iframe_attributes(bool initial_insertion = false); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp index 22409e1ebf5..5edb39b2260 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -77,13 +77,7 @@ void HTMLImageElement::visit_edges(Cell::Visitor& visitor) void HTMLImageElement::apply_presentational_hints(CSS::StyleProperties& style) const { for_each_attribute([&](auto& name, auto& value) { - if (name == HTML::AttributeNames::width) { - if (auto parsed_value = parse_dimension_value(value)) - style.set_property(CSS::PropertyID::Width, parsed_value.release_nonnull()); - } else if (name == HTML::AttributeNames::height) { - if (auto parsed_value = parse_dimension_value(value)) - style.set_property(CSS::PropertyID::Height, parsed_value.release_nonnull()); - } else if (name == HTML::AttributeNames::hspace) { + if (name == HTML::AttributeNames::hspace) { if (auto parsed_value = parse_dimension_value(value)) { style.set_property(CSS::PropertyID::MarginLeft, *parsed_value); style.set_property(CSS::PropertyID::MarginRight, *parsed_value); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h index cc86b848387..6f225357663 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h @@ -107,6 +107,9 @@ private: virtual void apply_presentational_hints(CSS::StyleProperties&) const override; + // https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element:dimension-attributes + virtual bool supports_dimension_attributes() const override { return true; } + virtual JS::GCPtr create_layout_node(NonnullRefPtr) override; virtual void did_set_viewport_rect(CSSPixelRect const&) override; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 8a6efeb7270..777fbb05871 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -1525,24 +1525,6 @@ i32 HTMLInputElement::default_tab_index_value() const return 0; } -// https://html.spec.whatwg.org/multipage/input.html#image-button-state-(type=image):the-input-element-11 -void HTMLInputElement::apply_presentational_hints(CSS::StyleProperties& style) const -{ - // The input element supports dimension attributes. - if (type_state() != TypeAttributeState::ImageButton) - return; - - for_each_attribute([&](auto& name, auto& value) { - if (name == HTML::AttributeNames::width) { - if (auto parsed_value = parse_dimension_value(value)) - style.set_property(CSS::PropertyID::Width, parsed_value.release_nonnull()); - } else if (name == HTML::AttributeNames::height) { - if (auto parsed_value = parse_dimension_value(value)) - style.set_property(CSS::PropertyID::Height, parsed_value.release_nonnull()); - } - }); -} - // https://html.spec.whatwg.org/multipage/input.html#dom-input-maxlength WebIDL::Long HTMLInputElement::max_length() const { diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h index eb9e5c13a7f..47dd7131748 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -208,7 +208,9 @@ private: // ^DOM::Element virtual i32 default_tab_index_value() const override; - virtual void apply_presentational_hints(CSS::StyleProperties&) const override; + + // https://html.spec.whatwg.org/multipage/input.html#image-button-state-(type=image):dimension-attributes + virtual bool supports_dimension_attributes() const override { return type_state() == TypeAttributeState::ImageButton; } // ^Layout::ImageProvider virtual bool is_image_available() const override;