Kaynağa Gözat

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.
Timothy Flynn 1 yıl önce
ebeveyn
işleme
4b1abcf61d

+ 19 - 0
Userland/Libraries/LibWeb/CSS/StyleComputer.cpp

@@ -68,6 +68,7 @@
 #include <LibWeb/DOM/ShadowRoot.h>
 #include <LibWeb/HTML/HTMLBRElement.h>
 #include <LibWeb/HTML/HTMLHtmlElement.h>
+#include <LibWeb/HTML/Parser/HTMLParser.h>
 #include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
 #include <LibWeb/HighResolutionTime/TimeOrigin.h>
 #include <LibWeb/Layout/Node.h>
@@ -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<CSS::Selector::PseudoElement::Type> 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.

+ 3 - 0
Userland/Libraries/LibWeb/DOM/Element.h

@@ -141,6 +141,9 @@ public:
     bool has_class(FlyString const&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
     Vector<FlyString> 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

+ 0 - 14
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)
 {

+ 3 - 2
Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.h

@@ -30,8 +30,6 @@ public:
     Optional<HighResolutionTime::DOMHighResTimeStamp> const& pending_resource_start_time() const { return m_pending_resource_start_time; }
     void set_pending_resource_start_time(Optional<HighResolutionTime::DOMHighResTimeStamp> 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<String> 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);
 

+ 1 - 7
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);

+ 3 - 0
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<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
 
     virtual void did_set_viewport_rect(CSSPixelRect const&) override;

+ 0 - 18
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
 {

+ 3 - 1
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;