diff --git a/Libraries/LibWeb/CSS/StyleComputer.cpp b/Libraries/LibWeb/CSS/StyleComputer.cpp index 638c89da668..7e678e0f7de 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -2047,8 +2047,14 @@ void StyleComputer::compute_font(ComputedProperties& style, DOM::Element const* RefPtr const found_font = font_list->first(); - style.set_property(CSS::PropertyID::FontSize, LengthStyleValue::create(CSS::Length::make_px(CSSPixels::nearest_value_for(found_font->pixel_size())))); - style.set_property(CSS::PropertyID::FontWeight, NumberStyleValue::create(font_weight.to_font_weight())); + style.set_property( + CSS::PropertyID::FontSize, + LengthStyleValue::create(CSS::Length::make_px(CSSPixels::nearest_value_for(found_font->pixel_size()))), + style.is_property_inherited(CSS::PropertyID::FontSize) ? ComputedProperties::Inherited::Yes : ComputedProperties::Inherited::No); + style.set_property( + CSS::PropertyID::FontWeight, + NumberStyleValue::create(font_weight.to_font_weight()), + style.is_property_inherited(CSS::PropertyID::FontWeight) ? ComputedProperties::Inherited::Yes : ComputedProperties::Inherited::No); style.set_computed_font_list(*font_list); diff --git a/Libraries/LibWeb/CSS/StyleComputer.h b/Libraries/LibWeb/CSS/StyleComputer.h index 718dd12ef50..8ceef16a23c 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.h +++ b/Libraries/LibWeb/CSS/StyleComputer.h @@ -177,6 +177,7 @@ public: [[nodiscard]] GC::Ref compute_properties(DOM::Element&, Optional, CascadedProperties&) const; void absolutize_values(ComputedProperties&) const; + void compute_font(ComputedProperties&, DOM::Element const*, Optional) const; private: enum class ComputeStyleMode { @@ -193,7 +194,6 @@ private: static RefPtr find_matching_font_weight_ascending(Vector const& candidates, int target_weight, float font_size_in_pt, bool inclusive); static RefPtr find_matching_font_weight_descending(Vector const& candidates, int target_weight, float font_size_in_pt, bool inclusive); RefPtr font_matching_algorithm(FlyString const& family_name, int weight, int slope, float font_size_in_pt) const; - void compute_font(ComputedProperties&, DOM::Element const*, Optional) const; void compute_math_depth(ComputedProperties&, DOM::Element const*, Optional) const; void compute_defaulted_values(ComputedProperties&, DOM::Element const*, Optional) const; void start_needed_transitions(ComputedProperties const& old_style, ComputedProperties& new_style, DOM::Element&, Optional) const; diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 2569f340f68..d836bfb1040 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -573,6 +573,7 @@ CSS::RequiredInvalidationAfterStyleChange Element::recompute_inherited_style() invalidation |= CSS::compute_property_invalidation(property_id, old_value, new_value); } + document().style_computer().compute_font(*computed_properties, this, {}); document().style_computer().absolutize_values(*computed_properties); layout_node()->apply_style(*computed_properties); @@ -1899,26 +1900,53 @@ ErrorOr Element::scroll_into_view(Optional(node); + element.set_needs_inherited_style_update(true); return TraversalDecision::Continue; - auto& element = static_cast(node); - element.set_needs_inherited_style_update(true); - return TraversalDecision::Continue; - }); + }); + } else { + invalidate_style(StyleInvalidationReason::ElementAttributeChange); + } return; } - invalidate_style(StyleInvalidationReason::ElementAttributeChange); + if (is_presentational_hint(attribute_name) + || attribute_name_may_affect_selectors(*this, attribute_name)) { + invalidate_style(StyleInvalidationReason::ElementAttributeChange); + return; + } } bool Element::is_hidden() const diff --git a/Libraries/LibWeb/DOM/Element.h b/Libraries/LibWeb/DOM/Element.h index 216bfa6f24a..7b20d286950 100644 --- a/Libraries/LibWeb/DOM/Element.h +++ b/Libraries/LibWeb/DOM/Element.h @@ -173,6 +173,7 @@ public: // https://html.spec.whatwg.org/multipage/embedded-content-other.html#dimension-attributes virtual bool supports_dimension_attributes() const { return false; } + virtual bool is_presentational_hint(FlyString const&) const { return false; } virtual void apply_presentational_hints(GC::Ref) const { } void run_attribute_change_steps(FlyString const& local_name, Optional const& old_value, Optional const& value, Optional const& namespace_); diff --git a/Libraries/LibWeb/DOM/Node.h b/Libraries/LibWeb/DOM/Node.h index dfe51be8a49..dc62b35a9d4 100644 --- a/Libraries/LibWeb/DOM/Node.h +++ b/Libraries/LibWeb/DOM/Node.h @@ -71,6 +71,7 @@ enum class IsDescendant { X(ElementSetShadowRoot) \ X(FocusedElementChange) \ X(HTMLHyperlinkElementHrefChange) \ + X(HTMLIFrameElementGeometryChange) \ X(HTMLInputElementSetChecked) \ X(HTMLObjectElementUpdateLayoutAndChildObjects) \ X(HTMLSelectElementSetIsOpen) \ diff --git a/Libraries/LibWeb/HTML/HTMLBodyElement.cpp b/Libraries/LibWeb/HTML/HTMLBodyElement.cpp index e655234c82a..e490a5afb02 100644 --- a/Libraries/LibWeb/HTML/HTMLBodyElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLBodyElement.cpp @@ -41,6 +41,17 @@ void HTMLBodyElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLBodyElement); } +bool HTMLBodyElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + HTML::AttributeNames::bgcolor, + HTML::AttributeNames::text, + HTML::AttributeNames::background); +} + void HTMLBodyElement::apply_presentational_hints(GC::Ref cascaded_properties) const { for_each_attribute([&](auto& name, auto& value) { diff --git a/Libraries/LibWeb/HTML/HTMLBodyElement.h b/Libraries/LibWeb/HTML/HTMLBodyElement.h index 3d39a6c5663..24888808c0a 100644 --- a/Libraries/LibWeb/HTML/HTMLBodyElement.h +++ b/Libraries/LibWeb/HTML/HTMLBodyElement.h @@ -22,6 +22,7 @@ public: virtual ~HTMLBodyElement() override; virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value, Optional const& namespace_) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; // https://www.w3.org/TR/html-aria/#el-body diff --git a/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp b/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp index f6eb984fb4d..d98e34dd07d 100644 --- a/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp @@ -65,6 +65,16 @@ void HTMLCanvasElement::visit_edges(Cell::Visitor& visitor) }); } +bool HTMLCanvasElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + HTML::AttributeNames::width, + HTML::AttributeNames::height); +} + void HTMLCanvasElement::apply_presentational_hints(GC::Ref cascaded_properties) const { // https://html.spec.whatwg.org/multipage/rendering.html#attributes-for-embedded-content-and-images diff --git a/Libraries/LibWeb/HTML/HTMLCanvasElement.h b/Libraries/LibWeb/HTML/HTMLCanvasElement.h index 639b47de3b7..887b4bda7e0 100644 --- a/Libraries/LibWeb/HTML/HTMLCanvasElement.h +++ b/Libraries/LibWeb/HTML/HTMLCanvasElement.h @@ -52,6 +52,7 @@ private: virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; virtual GC::Ptr create_layout_node(GC::Ref) override; diff --git a/Libraries/LibWeb/HTML/HTMLDivElement.cpp b/Libraries/LibWeb/HTML/HTMLDivElement.cpp index bada0519200..f68683a08c2 100644 --- a/Libraries/LibWeb/HTML/HTMLDivElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLDivElement.cpp @@ -21,6 +21,14 @@ HTMLDivElement::HTMLDivElement(DOM::Document& document, DOM::QualifiedName quali HTMLDivElement::~HTMLDivElement() = default; +bool HTMLDivElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return name == HTML::AttributeNames::align; +} + // https://html.spec.whatwg.org/multipage/rendering.html#flow-content-3 void HTMLDivElement::apply_presentational_hints(GC::Ref cascaded_properties) const { diff --git a/Libraries/LibWeb/HTML/HTMLDivElement.h b/Libraries/LibWeb/HTML/HTMLDivElement.h index 4e6b6f269e3..ddfd0349df1 100644 --- a/Libraries/LibWeb/HTML/HTMLDivElement.h +++ b/Libraries/LibWeb/HTML/HTMLDivElement.h @@ -26,6 +26,7 @@ protected: private: virtual void initialize(JS::Realm&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; }; diff --git a/Libraries/LibWeb/HTML/HTMLEmbedElement.cpp b/Libraries/LibWeb/HTML/HTMLEmbedElement.cpp index 367d40ee7fb..6539f9d000f 100644 --- a/Libraries/LibWeb/HTML/HTMLEmbedElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLEmbedElement.cpp @@ -29,6 +29,19 @@ void HTMLEmbedElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLEmbedElement); } +bool HTMLEmbedElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + HTML::AttributeNames::align, + HTML::AttributeNames::height, + HTML::AttributeNames::hspace, + HTML::AttributeNames::vspace, + HTML::AttributeNames::width); +} + void HTMLEmbedElement::apply_presentational_hints(GC::Ref cascaded_properties) const { for_each_attribute([&](auto& name, auto& value) { diff --git a/Libraries/LibWeb/HTML/HTMLEmbedElement.h b/Libraries/LibWeb/HTML/HTMLEmbedElement.h index bf0de680246..8b539d0d6e9 100644 --- a/Libraries/LibWeb/HTML/HTMLEmbedElement.h +++ b/Libraries/LibWeb/HTML/HTMLEmbedElement.h @@ -22,6 +22,7 @@ private: virtual bool is_html_embed_element() const override { return true; } virtual void initialize(JS::Realm&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; virtual void adjust_computed_style(CSS::ComputedProperties&) override; }; diff --git a/Libraries/LibWeb/HTML/HTMLFontElement.cpp b/Libraries/LibWeb/HTML/HTMLFontElement.cpp index ccd091da95f..e3f3dcc1efe 100644 --- a/Libraries/LibWeb/HTML/HTMLFontElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLFontElement.cpp @@ -112,6 +112,17 @@ void HTMLFontElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLFontElement); } +bool HTMLFontElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + HTML::AttributeNames::color, + HTML::AttributeNames::face, + HTML::AttributeNames::size); +} + void HTMLFontElement::apply_presentational_hints(GC::Ref cascaded_properties) const { for_each_attribute([&](auto& name, auto& value) { diff --git a/Libraries/LibWeb/HTML/HTMLFontElement.h b/Libraries/LibWeb/HTML/HTMLFontElement.h index 6dabdac0374..7d2f57b16a0 100644 --- a/Libraries/LibWeb/HTML/HTMLFontElement.h +++ b/Libraries/LibWeb/HTML/HTMLFontElement.h @@ -17,6 +17,7 @@ class HTMLFontElement final : public HTMLElement { public: virtual ~HTMLFontElement() override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; private: diff --git a/Libraries/LibWeb/HTML/HTMLHRElement.cpp b/Libraries/LibWeb/HTML/HTMLHRElement.cpp index b516dfaad59..bf1ddc6cd7d 100644 --- a/Libraries/LibWeb/HTML/HTMLHRElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLHRElement.cpp @@ -28,6 +28,14 @@ void HTMLHRElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLHRElement); } +bool HTMLHRElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, HTML::AttributeNames::width); +} + void HTMLHRElement::apply_presentational_hints(GC::Ref cascaded_properties) const { for_each_attribute([&](auto& name, auto& value) { diff --git a/Libraries/LibWeb/HTML/HTMLHRElement.h b/Libraries/LibWeb/HTML/HTMLHRElement.h index 3a6805d4ffc..f5343e484a4 100644 --- a/Libraries/LibWeb/HTML/HTMLHRElement.h +++ b/Libraries/LibWeb/HTML/HTMLHRElement.h @@ -26,6 +26,7 @@ private: virtual void initialize(JS::Realm&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; }; diff --git a/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp b/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp index 405512e905e..50cdd0fc438 100644 --- a/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLHeadingElement.cpp @@ -27,6 +27,14 @@ void HTMLHeadingElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLHeadingElement); } +bool HTMLHeadingElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return name == HTML::AttributeNames::align; +} + // https://html.spec.whatwg.org/multipage/rendering.html#tables-2 void HTMLHeadingElement::apply_presentational_hints(GC::Ref cascaded_properties) const { diff --git a/Libraries/LibWeb/HTML/HTMLHeadingElement.h b/Libraries/LibWeb/HTML/HTMLHeadingElement.h index 285288e121c..778fd399938 100644 --- a/Libraries/LibWeb/HTML/HTMLHeadingElement.h +++ b/Libraries/LibWeb/HTML/HTMLHeadingElement.h @@ -18,6 +18,7 @@ class HTMLHeadingElement final : public HTMLElement { public: virtual ~HTMLHeadingElement() override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; // https://www.w3.org/TR/html-aria/#el-h1-h6 diff --git a/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp b/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp index f0db6c9996b..bc7295d0580 100644 --- a/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp @@ -60,6 +60,11 @@ void HTMLIFrameElement::attribute_changed(FlyString const& name, Optional cascaded_properties) const { for_each_attribute([&](auto& name, auto& value) { diff --git a/Libraries/LibWeb/HTML/HTMLImageElement.h b/Libraries/LibWeb/HTML/HTMLImageElement.h index 0cd5a86d46e..380de2758d1 100644 --- a/Libraries/LibWeb/HTML/HTMLImageElement.h +++ b/Libraries/LibWeb/HTML/HTMLImageElement.h @@ -121,6 +121,7 @@ private: virtual void adopted_from(DOM::Document&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; // https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element:dimension-attributes diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp index a1dfa695d49..39ba2b6fcfa 100644 --- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -1593,6 +1593,23 @@ void HTMLInputElement::form_associated_element_was_removed(DOM::Node*) set_shadow_root(nullptr); } +bool HTMLInputElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + if (type_state() != TypeAttributeState::ImageButton) + return false; + + return first_is_one_of(name, + HTML::AttributeNames::align, + HTML::AttributeNames::border, + HTML::AttributeNames::height, + HTML::AttributeNames::hspace, + HTML::AttributeNames::vspace, + HTML::AttributeNames::width); +} + void HTMLInputElement::apply_presentational_hints(GC::Ref cascaded_properties) const { if (type_state() != TypeAttributeState::ImageButton) diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.h b/Libraries/LibWeb/HTML/HTMLInputElement.h index 6f6d20f4c73..d02dabf9bc3 100644 --- a/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -227,6 +227,7 @@ private: void type_attribute_changed(TypeAttributeState old_state, TypeAttributeState new_state); + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; // ^DOM::Node diff --git a/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp b/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp index a35b1265c4a..8fd62fb03a5 100644 --- a/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLMarqueeElement.cpp @@ -30,6 +30,19 @@ void HTMLMarqueeElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLMarqueeElement); } +bool HTMLMarqueeElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + HTML::AttributeNames::bgcolor, + HTML::AttributeNames::height, + HTML::AttributeNames::hspace, + HTML::AttributeNames::vspace, + HTML::AttributeNames::width); +} + void HTMLMarqueeElement::apply_presentational_hints(GC::Ref cascaded_properties) const { HTMLElement::apply_presentational_hints(cascaded_properties); diff --git a/Libraries/LibWeb/HTML/HTMLMarqueeElement.h b/Libraries/LibWeb/HTML/HTMLMarqueeElement.h index 9ad94012deb..95a0f5635ee 100644 --- a/Libraries/LibWeb/HTML/HTMLMarqueeElement.h +++ b/Libraries/LibWeb/HTML/HTMLMarqueeElement.h @@ -30,6 +30,7 @@ private: HTMLMarqueeElement(DOM::Document&, DOM::QualifiedName); virtual void initialize(JS::Realm&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; }; diff --git a/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Libraries/LibWeb/HTML/HTMLObjectElement.cpp index d29e6cd88cd..9d288232739 100644 --- a/Libraries/LibWeb/HTML/HTMLObjectElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLObjectElement.cpp @@ -100,6 +100,20 @@ void HTMLObjectElement::form_associated_element_was_removed(DOM::Node*) destroy_the_child_navigable(); } +bool HTMLObjectElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + HTML::AttributeNames::align, + HTML::AttributeNames::border, + HTML::AttributeNames::height, + HTML::AttributeNames::hspace, + HTML::AttributeNames::vspace, + HTML::AttributeNames::width); +} + void HTMLObjectElement::apply_presentational_hints(GC::Ref cascaded_properties) const { for_each_attribute([&](auto& name, auto& value) { diff --git a/Libraries/LibWeb/HTML/HTMLObjectElement.h b/Libraries/LibWeb/HTML/HTMLObjectElement.h index 3d07dcce970..c165a10a700 100644 --- a/Libraries/LibWeb/HTML/HTMLObjectElement.h +++ b/Libraries/LibWeb/HTML/HTMLObjectElement.h @@ -54,6 +54,7 @@ private: virtual void initialize(JS::Realm&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; virtual GC::Ptr create_layout_node(GC::Ref) override; diff --git a/Libraries/LibWeb/HTML/HTMLParagraphElement.cpp b/Libraries/LibWeb/HTML/HTMLParagraphElement.cpp index eee22eeaa5f..d30a5fdc988 100644 --- a/Libraries/LibWeb/HTML/HTMLParagraphElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLParagraphElement.cpp @@ -27,6 +27,14 @@ void HTMLParagraphElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLParagraphElement); } +bool HTMLParagraphElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return name == HTML::AttributeNames::align; +} + // https://html.spec.whatwg.org/multipage/rendering.html#tables-2 void HTMLParagraphElement::apply_presentational_hints(GC::Ref cascaded_properties) const { diff --git a/Libraries/LibWeb/HTML/HTMLParagraphElement.h b/Libraries/LibWeb/HTML/HTMLParagraphElement.h index b431d354ee2..102964b8cb3 100644 --- a/Libraries/LibWeb/HTML/HTMLParagraphElement.h +++ b/Libraries/LibWeb/HTML/HTMLParagraphElement.h @@ -18,6 +18,7 @@ class HTMLParagraphElement final : public HTMLElement { public: virtual ~HTMLParagraphElement() override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; // https://www.w3.org/TR/html-aria/#el-p diff --git a/Libraries/LibWeb/HTML/HTMLPreElement.cpp b/Libraries/LibWeb/HTML/HTMLPreElement.cpp index a591243d2d5..0aef62ea0e1 100644 --- a/Libraries/LibWeb/HTML/HTMLPreElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLPreElement.cpp @@ -28,6 +28,14 @@ void HTMLPreElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLPreElement); } +bool HTMLPreElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return name == HTML::AttributeNames::wrap; +} + void HTMLPreElement::apply_presentational_hints(GC::Ref cascaded_properties) const { HTMLElement::apply_presentational_hints(cascaded_properties); diff --git a/Libraries/LibWeb/HTML/HTMLPreElement.h b/Libraries/LibWeb/HTML/HTMLPreElement.h index 6de15dd44a0..eac0b83ac08 100644 --- a/Libraries/LibWeb/HTML/HTMLPreElement.h +++ b/Libraries/LibWeb/HTML/HTMLPreElement.h @@ -26,6 +26,7 @@ private: HTMLPreElement(DOM::Document&, DOM::QualifiedName); virtual void initialize(JS::Realm&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; }; diff --git a/Libraries/LibWeb/HTML/HTMLTableCaptionElement.cpp b/Libraries/LibWeb/HTML/HTMLTableCaptionElement.cpp index 8de35a79ef6..a4db81f0991 100644 --- a/Libraries/LibWeb/HTML/HTMLTableCaptionElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLTableCaptionElement.cpp @@ -27,6 +27,14 @@ void HTMLTableCaptionElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLTableCaptionElement); } +bool HTMLTableCaptionElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return name == HTML::AttributeNames::align; +} + // https://html.spec.whatwg.org/multipage/rendering.html#tables-2 void HTMLTableCaptionElement::apply_presentational_hints(GC::Ref cascaded_properties) const { diff --git a/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h b/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h index 91eafaa86a8..8a3eb7bfa1c 100644 --- a/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h +++ b/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h @@ -18,6 +18,7 @@ class HTMLTableCaptionElement final : public HTMLElement { public: virtual ~HTMLTableCaptionElement() override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; // https://www.w3.org/TR/html-aria/#el-caption diff --git a/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp b/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp index 328e47bd8f8..4cf419f0f2e 100644 --- a/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp @@ -37,6 +37,20 @@ void HTMLTableCellElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLTableCellElement); } +bool HTMLTableCellElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + HTML::AttributeNames::align, + HTML::AttributeNames::background, + HTML::AttributeNames::bgcolor, + HTML::AttributeNames::height, + HTML::AttributeNames::valign, + HTML::AttributeNames::width); +} + void HTMLTableCellElement::apply_presentational_hints(GC::Ref cascaded_properties) const { for_each_attribute([&](auto& name, auto& value) { diff --git a/Libraries/LibWeb/HTML/HTMLTableCellElement.h b/Libraries/LibWeb/HTML/HTMLTableCellElement.h index 9d8beff1f49..8ff23b8751e 100644 --- a/Libraries/LibWeb/HTML/HTMLTableCellElement.h +++ b/Libraries/LibWeb/HTML/HTMLTableCellElement.h @@ -34,6 +34,7 @@ private: virtual bool is_html_table_cell_element() const override { return true; } virtual void initialize(JS::Realm&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; }; diff --git a/Libraries/LibWeb/HTML/HTMLTableColElement.cpp b/Libraries/LibWeb/HTML/HTMLTableColElement.cpp index c39ee4c0b1f..6d6cfb7f1ea 100644 --- a/Libraries/LibWeb/HTML/HTMLTableColElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLTableColElement.cpp @@ -51,6 +51,14 @@ WebIDL::ExceptionOr HTMLTableColElement::set_span(unsigned int value) return set_attribute(HTML::AttributeNames::span, String::number(value)); } +bool HTMLTableColElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return name == HTML::AttributeNames::width; +} + void HTMLTableColElement::apply_presentational_hints(GC::Ref cascaded_properties) const { for_each_attribute([&](auto& name, auto& value) { diff --git a/Libraries/LibWeb/HTML/HTMLTableColElement.h b/Libraries/LibWeb/HTML/HTMLTableColElement.h index 64411bed3b3..47932c3aa7b 100644 --- a/Libraries/LibWeb/HTML/HTMLTableColElement.h +++ b/Libraries/LibWeb/HTML/HTMLTableColElement.h @@ -26,6 +26,7 @@ private: virtual void initialize(JS::Realm&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; }; diff --git a/Libraries/LibWeb/HTML/HTMLTableElement.cpp b/Libraries/LibWeb/HTML/HTMLTableElement.cpp index 53361defaec..8fbffcad5d7 100644 --- a/Libraries/LibWeb/HTML/HTMLTableElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLTableElement.cpp @@ -51,6 +51,22 @@ static unsigned parse_border(StringView value) return value.to_number().value_or(0); } +bool HTMLTableElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + HTML::AttributeNames::align, + HTML::AttributeNames::background, + HTML::AttributeNames::bgcolor, + HTML::AttributeNames::border, + HTML::AttributeNames::cellpadding, + HTML::AttributeNames::cellspacing, + HTML::AttributeNames::height, + HTML::AttributeNames::width); +} + void HTMLTableElement::apply_presentational_hints(GC::Ref cascaded_properties) const { for_each_attribute([&](auto& name, auto& value) { diff --git a/Libraries/LibWeb/HTML/HTMLTableElement.h b/Libraries/LibWeb/HTML/HTMLTableElement.h index 73eb5d73bd6..b5926d1b7d8 100644 --- a/Libraries/LibWeb/HTML/HTMLTableElement.h +++ b/Libraries/LibWeb/HTML/HTMLTableElement.h @@ -58,6 +58,7 @@ private: virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value, Optional const& namespace_) override; diff --git a/Libraries/LibWeb/HTML/HTMLTableRowElement.cpp b/Libraries/LibWeb/HTML/HTMLTableRowElement.cpp index b717cce45ad..6887e8e7e28 100644 --- a/Libraries/LibWeb/HTML/HTMLTableRowElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLTableRowElement.cpp @@ -39,6 +39,18 @@ void HTMLTableRowElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLTableRowElement); } +bool HTMLTableRowElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + HTML::AttributeNames::bgcolor, + HTML::AttributeNames::background, + HTML::AttributeNames::height, + HTML::AttributeNames::valign); +} + void HTMLTableRowElement::apply_presentational_hints(GC::Ref cascaded_properties) const { Base::apply_presentational_hints(cascaded_properties); diff --git a/Libraries/LibWeb/HTML/HTMLTableRowElement.h b/Libraries/LibWeb/HTML/HTMLTableRowElement.h index 47aeba89285..a9d20536693 100644 --- a/Libraries/LibWeb/HTML/HTMLTableRowElement.h +++ b/Libraries/LibWeb/HTML/HTMLTableRowElement.h @@ -35,6 +35,7 @@ private: virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; GC::Ptr mutable m_cells; diff --git a/Libraries/LibWeb/HTML/HTMLTableSectionElement.cpp b/Libraries/LibWeb/HTML/HTMLTableSectionElement.cpp index 6ae57ec7627..e92c94eb799 100644 --- a/Libraries/LibWeb/HTML/HTMLTableSectionElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLTableSectionElement.cpp @@ -100,6 +100,16 @@ WebIDL::ExceptionOr HTMLTableSectionElement::delete_row(WebIDL::Long index return {}; } +bool HTMLTableSectionElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + HTML::AttributeNames::background, + HTML::AttributeNames::bgcolor); +} + void HTMLTableSectionElement::apply_presentational_hints(GC::Ref cascaded_properties) const { for_each_attribute([&](auto& name, auto& value) { diff --git a/Libraries/LibWeb/HTML/HTMLTableSectionElement.h b/Libraries/LibWeb/HTML/HTMLTableSectionElement.h index 83b1554bb9f..836534c1a15 100644 --- a/Libraries/LibWeb/HTML/HTMLTableSectionElement.h +++ b/Libraries/LibWeb/HTML/HTMLTableSectionElement.h @@ -37,6 +37,7 @@ private: virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; GC::Ptr mutable m_rows; diff --git a/Libraries/LibWeb/SVG/SVGCircleElement.cpp b/Libraries/LibWeb/SVG/SVGCircleElement.cpp index ce75225e98d..daeccaafc58 100644 --- a/Libraries/LibWeb/SVG/SVGCircleElement.cpp +++ b/Libraries/LibWeb/SVG/SVGCircleElement.cpp @@ -29,6 +29,17 @@ void SVGCircleElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(SVGCircleElement); } +bool SVGCircleElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + SVG::AttributeNames::cx, + SVG::AttributeNames::cy, + SVG::AttributeNames::r); +} + void SVGCircleElement::apply_presentational_hints(GC::Ref cascaded_properties) const { Base::apply_presentational_hints(cascaded_properties); diff --git a/Libraries/LibWeb/SVG/SVGCircleElement.h b/Libraries/LibWeb/SVG/SVGCircleElement.h index c4b841784fc..131b08c790e 100644 --- a/Libraries/LibWeb/SVG/SVGCircleElement.h +++ b/Libraries/LibWeb/SVG/SVGCircleElement.h @@ -18,6 +18,7 @@ class SVGCircleElement final : public SVGGeometryElement { public: virtual ~SVGCircleElement() override = default; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; virtual Gfx::Path get_path(CSSPixelSize viewport_size) override; diff --git a/Libraries/LibWeb/SVG/SVGForeignObjectElement.cpp b/Libraries/LibWeb/SVG/SVGForeignObjectElement.cpp index 2fdb2dacfaf..80e7b5449e8 100644 --- a/Libraries/LibWeb/SVG/SVGForeignObjectElement.cpp +++ b/Libraries/LibWeb/SVG/SVGForeignObjectElement.cpp @@ -52,6 +52,16 @@ GC::Ptr SVGForeignObjectElement::create_layout_node(GC::Ref(document(), *this, move(style)); } +bool SVGForeignObjectElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + SVG::AttributeNames::width, + SVG::AttributeNames::height); +} + void SVGForeignObjectElement::apply_presentational_hints(GC::Ref cascaded_properties) const { Base::apply_presentational_hints(cascaded_properties); diff --git a/Libraries/LibWeb/SVG/SVGForeignObjectElement.h b/Libraries/LibWeb/SVG/SVGForeignObjectElement.h index c0338bc1e47..c0330dd7415 100644 --- a/Libraries/LibWeb/SVG/SVGForeignObjectElement.h +++ b/Libraries/LibWeb/SVG/SVGForeignObjectElement.h @@ -31,6 +31,7 @@ private: virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; GC::Ptr m_x; diff --git a/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp b/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp index f824508517d..4e031e13ecd 100644 --- a/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp +++ b/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp @@ -143,32 +143,40 @@ struct NamedPropertyID { StringView name; }; +static Array const attribute_style_properties { + // FIXME: The `fill` attribute and CSS `fill` property are not the same! But our support is limited enough that they are equivalent for now. + NamedPropertyID(CSS::PropertyID::Fill), + // FIXME: The `stroke` attribute and CSS `stroke` property are not the same! But our support is limited enough that they are equivalent for now. + NamedPropertyID(CSS::PropertyID::Stroke), + NamedPropertyID(CSS::PropertyID::StrokeDasharray), + NamedPropertyID(CSS::PropertyID::StrokeDashoffset), + NamedPropertyID(CSS::PropertyID::StrokeLinecap), + NamedPropertyID(CSS::PropertyID::StrokeLinejoin), + NamedPropertyID(CSS::PropertyID::StrokeMiterlimit), + NamedPropertyID(CSS::PropertyID::StrokeWidth), + NamedPropertyID(CSS::PropertyID::FillRule), + NamedPropertyID(CSS::PropertyID::FillOpacity), + NamedPropertyID(CSS::PropertyID::StrokeOpacity), + NamedPropertyID(CSS::PropertyID::Opacity), + NamedPropertyID(CSS::PropertyID::TextAnchor), + NamedPropertyID(CSS::PropertyID::FontSize), + NamedPropertyID(CSS::PropertyID::Mask), + NamedPropertyID(CSS::PropertyID::MaskType), + NamedPropertyID(CSS::PropertyID::ClipPath), + NamedPropertyID(CSS::PropertyID::ClipRule), + NamedPropertyID(CSS::PropertyID::Display), +}; + +bool SVGGraphicsElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return any_of(attribute_style_properties, [&](auto& property) { return name.equals_ignoring_ascii_case(property.name); }); +} + void SVGGraphicsElement::apply_presentational_hints(GC::Ref cascaded_properties) const { - static Array const attribute_style_properties { - // FIXME: The `fill` attribute and CSS `fill` property are not the same! But our support is limited enough that they are equivalent for now. - NamedPropertyID(CSS::PropertyID::Fill), - // FIXME: The `stroke` attribute and CSS `stroke` property are not the same! But our support is limited enough that they are equivalent for now. - NamedPropertyID(CSS::PropertyID::Stroke), - NamedPropertyID(CSS::PropertyID::StrokeDasharray), - NamedPropertyID(CSS::PropertyID::StrokeDashoffset), - NamedPropertyID(CSS::PropertyID::StrokeLinecap), - NamedPropertyID(CSS::PropertyID::StrokeLinejoin), - NamedPropertyID(CSS::PropertyID::StrokeMiterlimit), - NamedPropertyID(CSS::PropertyID::StrokeWidth), - NamedPropertyID(CSS::PropertyID::FillRule), - NamedPropertyID(CSS::PropertyID::FillOpacity), - NamedPropertyID(CSS::PropertyID::StrokeOpacity), - NamedPropertyID(CSS::PropertyID::Opacity), - NamedPropertyID(CSS::PropertyID::TextAnchor), - NamedPropertyID(CSS::PropertyID::FontSize), - NamedPropertyID(CSS::PropertyID::Mask), - NamedPropertyID(CSS::PropertyID::MaskType), - NamedPropertyID(CSS::PropertyID::ClipPath), - NamedPropertyID(CSS::PropertyID::ClipRule), - NamedPropertyID(CSS::PropertyID::Display), - }; - CSS::Parser::ParsingContext parsing_context { document(), CSS::Parser::ParsingContext::Mode::SVGPresentationAttribute }; for_each_attribute([&](auto& name, auto& value) { for (auto property : attribute_style_properties) { diff --git a/Libraries/LibWeb/SVG/SVGGraphicsElement.h b/Libraries/LibWeb/SVG/SVGGraphicsElement.h index 3fd2bf1675a..f54084335a9 100644 --- a/Libraries/LibWeb/SVG/SVGGraphicsElement.h +++ b/Libraries/LibWeb/SVG/SVGGraphicsElement.h @@ -29,6 +29,7 @@ class SVGGraphicsElement : public SVGElement { WEB_PLATFORM_OBJECT(SVGGraphicsElement, SVGElement); public: + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value, Optional const& namespace_) override; diff --git a/Libraries/LibWeb/SVG/SVGSVGElement.cpp b/Libraries/LibWeb/SVG/SVGSVGElement.cpp index 30fb6c26f0c..d66bfd2255e 100644 --- a/Libraries/LibWeb/SVG/SVGSVGElement.cpp +++ b/Libraries/LibWeb/SVG/SVGSVGElement.cpp @@ -79,6 +79,20 @@ RefPtr SVGSVGElement::height_style_value_from_attribute() co return nullptr; } +bool SVGSVGElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + SVG::AttributeNames::x, + SVG::AttributeNames::y, + SVG::AttributeNames::width, + SVG::AttributeNames::height, + SVG::AttributeNames::viewBox, + SVG::AttributeNames::preserveAspectRatio); +} + void SVGSVGElement::apply_presentational_hints(GC::Ref cascaded_properties) const { Base::apply_presentational_hints(cascaded_properties); diff --git a/Libraries/LibWeb/SVG/SVGSVGElement.h b/Libraries/LibWeb/SVG/SVGSVGElement.h index ead9d4ef374..05ca00f8057 100644 --- a/Libraries/LibWeb/SVG/SVGSVGElement.h +++ b/Libraries/LibWeb/SVG/SVGSVGElement.h @@ -31,6 +31,7 @@ class SVGSVGElement final : public SVGGraphicsElement public: virtual GC::Ptr create_layout_node(GC::Ref) override; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; virtual bool requires_svg_container() const override { return false; } diff --git a/Libraries/LibWeb/SVG/SVGStopElement.cpp b/Libraries/LibWeb/SVG/SVGStopElement.cpp index 5fe260b48b0..52d5cc48b0b 100644 --- a/Libraries/LibWeb/SVG/SVGStopElement.cpp +++ b/Libraries/LibWeb/SVG/SVGStopElement.cpp @@ -30,6 +30,16 @@ void SVGStopElement::attribute_changed(FlyString const& name, Optional c } } +bool SVGStopElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + return first_is_one_of(name, + "stop-color"sv, + "stop-opacity"sv); +} + void SVGStopElement::apply_presentational_hints(GC::Ref cascaded_properties) const { CSS::Parser::ParsingContext parsing_context { document() }; diff --git a/Libraries/LibWeb/SVG/SVGStopElement.h b/Libraries/LibWeb/SVG/SVGStopElement.h index 20a625a63e9..1560b0868eb 100644 --- a/Libraries/LibWeb/SVG/SVGStopElement.h +++ b/Libraries/LibWeb/SVG/SVGStopElement.h @@ -25,6 +25,7 @@ public: GC::Ref offset() const; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; NumberPercentage stop_offset() const { return m_offset.value_or(NumberPercentage::create_number(0)); } diff --git a/Libraries/LibWeb/SVG/SVGSymbolElement.cpp b/Libraries/LibWeb/SVG/SVGSymbolElement.cpp index ce07a9dea68..c797eaf2ec4 100644 --- a/Libraries/LibWeb/SVG/SVGSymbolElement.cpp +++ b/Libraries/LibWeb/SVG/SVGSymbolElement.cpp @@ -39,11 +39,24 @@ void SVGSymbolElement::visit_edges(Cell::Visitor& visitor) visitor.visit(m_view_box_for_bindings); } +bool SVGSymbolElement::is_presentational_hint(FlyString const& name) const +{ + if (Base::is_presentational_hint(name)) + return true; + + // FIXME: This is not a correct use of the presentational hint mechanism. + if (is_direct_child_of_use_shadow_tree()) + return true; + + return false; +} + // https://svgwg.org/svg2-draft/struct.html#SymbolNotes void SVGSymbolElement::apply_presentational_hints(GC::Ref cascaded_properties) const { Base::apply_presentational_hints(cascaded_properties); + // FIXME: This is not a correct use of the presentational hint mechanism. if (is_direct_child_of_use_shadow_tree()) { // The generated instance of a ‘symbol’ that is the direct referenced element of a ‘use’ element must always have a computed value of inline for the display property. cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::Inline))); diff --git a/Libraries/LibWeb/SVG/SVGSymbolElement.h b/Libraries/LibWeb/SVG/SVGSymbolElement.h index eb3b2c3565a..e78321c612b 100644 --- a/Libraries/LibWeb/SVG/SVGSymbolElement.h +++ b/Libraries/LibWeb/SVG/SVGSymbolElement.h @@ -19,6 +19,7 @@ class SVGSymbolElement final : public SVGGraphicsElement public: virtual ~SVGSymbolElement() override = default; + virtual bool is_presentational_hint(FlyString const&) const override; virtual void apply_presentational_hints(GC::Ref) const override; virtual Optional view_box() const override { return m_view_box; }