mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-08 17:19:13 +00:00
LibWeb: Avoid many style invalidations on DOM attribute mutation
Many times, attribute mutation doesn't necessitate a full style invalidation on the element. However, the conditions are pretty elaborate, so this first version has a lot of false positives. We only need to invalidate style when any of these things apply: 1. The change may affect the match state of a selector somewhere. 2. The change may affect presentational hints applied to the element. For (1) in this first version, we have a fixed list of attribute names that may affect selectors. We also collect all names referenced by attribute selectors anywhere in the document. For (2), we add a new Element::is_presentational_hint() virtual that tells us whether a given attribute name is a presentational hint. This drastically reduces style work on many websites. As an example, https://cnn.com/ is once again browseable.
This commit is contained in:
parent
b11bdd4022
commit
b981e6f7bc
Notes:
github-actions[bot]
2024-12-24 16:18:00 +00:00
Author: https://github.com/awesomekling
Commit: b981e6f7bc
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3034
56 changed files with 377 additions and 37 deletions
|
@ -2047,8 +2047,14 @@ void StyleComputer::compute_font(ComputedProperties& style, DOM::Element const*
|
||||||
|
|
||||||
RefPtr<Gfx::Font const> const found_font = font_list->first();
|
RefPtr<Gfx::Font const> 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(
|
||||||
style.set_property(CSS::PropertyID::FontWeight, NumberStyleValue::create(font_weight.to_font_weight()));
|
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);
|
style.set_computed_font_list(*font_list);
|
||||||
|
|
||||||
|
|
|
@ -177,6 +177,7 @@ public:
|
||||||
[[nodiscard]] GC::Ref<ComputedProperties> compute_properties(DOM::Element&, Optional<Selector::PseudoElement::Type>, CascadedProperties&) const;
|
[[nodiscard]] GC::Ref<ComputedProperties> compute_properties(DOM::Element&, Optional<Selector::PseudoElement::Type>, CascadedProperties&) const;
|
||||||
|
|
||||||
void absolutize_values(ComputedProperties&) const;
|
void absolutize_values(ComputedProperties&) const;
|
||||||
|
void compute_font(ComputedProperties&, DOM::Element const*, Optional<CSS::Selector::PseudoElement::Type>) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class ComputeStyleMode {
|
enum class ComputeStyleMode {
|
||||||
|
@ -193,7 +194,6 @@ private:
|
||||||
static RefPtr<Gfx::FontCascadeList const> find_matching_font_weight_ascending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive);
|
static RefPtr<Gfx::FontCascadeList const> find_matching_font_weight_ascending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive);
|
||||||
static RefPtr<Gfx::FontCascadeList const> find_matching_font_weight_descending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive);
|
static RefPtr<Gfx::FontCascadeList const> find_matching_font_weight_descending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive);
|
||||||
RefPtr<Gfx::FontCascadeList const> font_matching_algorithm(FlyString const& family_name, int weight, int slope, float font_size_in_pt) const;
|
RefPtr<Gfx::FontCascadeList const> 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<CSS::Selector::PseudoElement::Type>) const;
|
|
||||||
void compute_math_depth(ComputedProperties&, DOM::Element const*, Optional<CSS::Selector::PseudoElement::Type>) const;
|
void compute_math_depth(ComputedProperties&, DOM::Element const*, Optional<CSS::Selector::PseudoElement::Type>) const;
|
||||||
void compute_defaulted_values(ComputedProperties&, DOM::Element const*, Optional<CSS::Selector::PseudoElement::Type>) const;
|
void compute_defaulted_values(ComputedProperties&, DOM::Element const*, Optional<CSS::Selector::PseudoElement::Type>) const;
|
||||||
void start_needed_transitions(ComputedProperties const& old_style, ComputedProperties& new_style, DOM::Element&, Optional<Selector::PseudoElement::Type>) const;
|
void start_needed_transitions(ComputedProperties const& old_style, ComputedProperties& new_style, DOM::Element&, Optional<Selector::PseudoElement::Type>) const;
|
||||||
|
|
|
@ -573,6 +573,7 @@ CSS::RequiredInvalidationAfterStyleChange Element::recompute_inherited_style()
|
||||||
invalidation |= CSS::compute_property_invalidation(property_id, old_value, new_value);
|
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);
|
document().style_computer().absolutize_values(*computed_properties);
|
||||||
|
|
||||||
layout_node()->apply_style(*computed_properties);
|
layout_node()->apply_style(*computed_properties);
|
||||||
|
@ -1899,26 +1900,53 @@ ErrorOr<void> Element::scroll_into_view(Optional<Variant<bool, ScrollIntoViewOpt
|
||||||
// FIXME: 8. Optionally perform some other action that brings the element to the user’s attention.
|
// FIXME: 8. Optionally perform some other action that brings the element to the user’s attention.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool attribute_name_may_affect_selectors(Element const& element, FlyString const& attribute_name)
|
||||||
|
{
|
||||||
|
// FIXME: We could make these cases more narrow by making the conditions more elaborate.
|
||||||
|
if (attribute_name == HTML::AttributeNames::id
|
||||||
|
|| attribute_name == HTML::AttributeNames::class_
|
||||||
|
|| attribute_name == HTML::AttributeNames::dir
|
||||||
|
|| attribute_name == HTML::AttributeNames::lang
|
||||||
|
|| attribute_name == HTML::AttributeNames::checked
|
||||||
|
|| attribute_name == HTML::AttributeNames::disabled
|
||||||
|
|| attribute_name == HTML::AttributeNames::readonly
|
||||||
|
|| attribute_name == HTML::AttributeNames::switch_
|
||||||
|
|| attribute_name == HTML::AttributeNames::href
|
||||||
|
|| attribute_name == HTML::AttributeNames::open
|
||||||
|
|| attribute_name == HTML::AttributeNames::placeholder) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return element.document().style_computer().has_attribute_selector(attribute_name);
|
||||||
|
}
|
||||||
|
|
||||||
void Element::invalidate_style_after_attribute_change(FlyString const& attribute_name)
|
void Element::invalidate_style_after_attribute_change(FlyString const& attribute_name)
|
||||||
{
|
{
|
||||||
// FIXME: Only invalidate if the attribute can actually affect style.
|
// FIXME: Only invalidate if the attribute can actually affect style.
|
||||||
|
|
||||||
// OPTIMIZATION: For the `style` attribute, unless it's referenced by an attribute selector,
|
// OPTIMIZATION: For the `style` attribute, unless it's referenced by an attribute selector,
|
||||||
// only invalidate the element itself, then let inheritance propagate to descendants.
|
// only invalidate the element itself, then let inheritance propagate to descendants.
|
||||||
if (attribute_name == HTML::AttributeNames::style
|
if (attribute_name == HTML::AttributeNames::style) {
|
||||||
&& !document().style_computer().has_attribute_selector(HTML::AttributeNames::style)) {
|
if (!document().style_computer().has_attribute_selector(HTML::AttributeNames::style)) {
|
||||||
set_needs_style_update(true);
|
set_needs_style_update(true);
|
||||||
for_each_shadow_including_descendant([](Node& node) {
|
for_each_shadow_including_descendant([](Node& node) {
|
||||||
if (!node.is_element())
|
if (!node.is_element())
|
||||||
|
return TraversalDecision::Continue;
|
||||||
|
auto& element = static_cast<Element&>(node);
|
||||||
|
element.set_needs_inherited_style_update(true);
|
||||||
return TraversalDecision::Continue;
|
return TraversalDecision::Continue;
|
||||||
auto& element = static_cast<Element&>(node);
|
});
|
||||||
element.set_needs_inherited_style_update(true);
|
} else {
|
||||||
return TraversalDecision::Continue;
|
invalidate_style(StyleInvalidationReason::ElementAttributeChange);
|
||||||
});
|
}
|
||||||
return;
|
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
|
bool Element::is_hidden() const
|
||||||
|
|
|
@ -173,6 +173,7 @@ public:
|
||||||
// https://html.spec.whatwg.org/multipage/embedded-content-other.html#dimension-attributes
|
// https://html.spec.whatwg.org/multipage/embedded-content-other.html#dimension-attributes
|
||||||
virtual bool supports_dimension_attributes() const { return false; }
|
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<CSS::CascadedProperties>) const { }
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const { }
|
||||||
|
|
||||||
void run_attribute_change_steps(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_);
|
void run_attribute_change_steps(FlyString const& local_name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_);
|
||||||
|
|
|
@ -71,6 +71,7 @@ enum class IsDescendant {
|
||||||
X(ElementSetShadowRoot) \
|
X(ElementSetShadowRoot) \
|
||||||
X(FocusedElementChange) \
|
X(FocusedElementChange) \
|
||||||
X(HTMLHyperlinkElementHrefChange) \
|
X(HTMLHyperlinkElementHrefChange) \
|
||||||
|
X(HTMLIFrameElementGeometryChange) \
|
||||||
X(HTMLInputElementSetChecked) \
|
X(HTMLInputElementSetChecked) \
|
||||||
X(HTMLObjectElementUpdateLayoutAndChildObjects) \
|
X(HTMLObjectElementUpdateLayoutAndChildObjects) \
|
||||||
X(HTMLSelectElementSetIsOpen) \
|
X(HTMLSelectElementSetIsOpen) \
|
||||||
|
|
|
@ -41,6 +41,17 @@ void HTMLBodyElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLBodyElement);
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLBodyElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
for_each_attribute([&](auto& name, auto& value) {
|
for_each_attribute([&](auto& name, auto& value) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ public:
|
||||||
virtual ~HTMLBodyElement() override;
|
virtual ~HTMLBodyElement() override;
|
||||||
|
|
||||||
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
|
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
// https://www.w3.org/TR/html-aria/#el-body
|
// https://www.w3.org/TR/html-aria/#el-body
|
||||||
|
|
|
@ -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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLCanvasElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
// https://html.spec.whatwg.org/multipage/rendering.html#attributes-for-embedded-content-and-images
|
// https://html.spec.whatwg.org/multipage/rendering.html#attributes-for-embedded-content-and-images
|
||||||
|
|
|
@ -52,6 +52,7 @@ private:
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
virtual void visit_edges(Cell::Visitor&) override;
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
virtual GC::Ptr<Layout::Node> create_layout_node(GC::Ref<CSS::ComputedProperties>) override;
|
virtual GC::Ptr<Layout::Node> create_layout_node(GC::Ref<CSS::ComputedProperties>) override;
|
||||||
|
|
|
@ -21,6 +21,14 @@ HTMLDivElement::HTMLDivElement(DOM::Document& document, DOM::QualifiedName quali
|
||||||
|
|
||||||
HTMLDivElement::~HTMLDivElement() = default;
|
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
|
// https://html.spec.whatwg.org/multipage/rendering.html#flow-content-3
|
||||||
void HTMLDivElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLDivElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,19 @@ void HTMLEmbedElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLEmbedElement);
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLEmbedElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
for_each_attribute([&](auto& name, auto& value) {
|
for_each_attribute([&](auto& name, auto& value) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ private:
|
||||||
|
|
||||||
virtual bool is_html_embed_element() const override { return true; }
|
virtual bool is_html_embed_element() const override { return true; }
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
virtual void adjust_computed_style(CSS::ComputedProperties&) override;
|
virtual void adjust_computed_style(CSS::ComputedProperties&) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -112,6 +112,17 @@ void HTMLFontElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLFontElement);
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLFontElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
for_each_attribute([&](auto& name, auto& value) {
|
for_each_attribute([&](auto& name, auto& value) {
|
||||||
|
|
|
@ -17,6 +17,7 @@ class HTMLFontElement final : public HTMLElement {
|
||||||
public:
|
public:
|
||||||
virtual ~HTMLFontElement() override;
|
virtual ~HTMLFontElement() override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -28,6 +28,14 @@ void HTMLHRElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLHRElement);
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLHRElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
for_each_attribute([&](auto& name, auto& value) {
|
for_each_attribute([&](auto& name, auto& value) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ private:
|
||||||
|
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,14 @@ void HTMLHeadingElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLHeadingElement);
|
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
|
// https://html.spec.whatwg.org/multipage/rendering.html#tables-2
|
||||||
void HTMLHeadingElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLHeadingElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@ class HTMLHeadingElement final : public HTMLElement {
|
||||||
public:
|
public:
|
||||||
virtual ~HTMLHeadingElement() override;
|
virtual ~HTMLHeadingElement() override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
// https://www.w3.org/TR/html-aria/#el-h1-h6
|
// https://www.w3.org/TR/html-aria/#el-h1-h6
|
||||||
|
|
|
@ -60,6 +60,11 @@ void HTMLIFrameElement::attribute_changed(FlyString const& name, Optional<String
|
||||||
if (name == AttributeNames::srcdoc || (name == AttributeNames::src && !has_attribute(AttributeNames::srcdoc)))
|
if (name == AttributeNames::srcdoc || (name == AttributeNames::src && !has_attribute(AttributeNames::srcdoc)))
|
||||||
process_the_iframe_attributes();
|
process_the_iframe_attributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name == HTML::AttributeNames::width || name == HTML::AttributeNames::height) {
|
||||||
|
// FIXME: This should only invalidate the layout, not the style.
|
||||||
|
invalidate_style(DOM::StyleInvalidationReason::ElementAttributeChange);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:html-element-post-connection-steps
|
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:html-element-post-connection-steps
|
||||||
|
|
|
@ -82,6 +82,17 @@ void HTMLImageElement::visit_edges(Cell::Visitor& visitor)
|
||||||
visit_lazy_loading_element(visitor);
|
visit_lazy_loading_element(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HTMLImageElement::is_presentational_hint(FlyString const& name) const
|
||||||
|
{
|
||||||
|
if (Base::is_presentational_hint(name))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return first_is_one_of(name,
|
||||||
|
HTML::AttributeNames::hspace,
|
||||||
|
HTML::AttributeNames::vspace,
|
||||||
|
HTML::AttributeNames::border);
|
||||||
|
}
|
||||||
|
|
||||||
void HTMLImageElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLImageElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
for_each_attribute([&](auto& name, auto& value) {
|
for_each_attribute([&](auto& name, auto& value) {
|
||||||
|
|
|
@ -121,6 +121,7 @@ private:
|
||||||
|
|
||||||
virtual void adopted_from(DOM::Document&) override;
|
virtual void adopted_from(DOM::Document&) override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element:dimension-attributes
|
// https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element:dimension-attributes
|
||||||
|
|
|
@ -1593,6 +1593,23 @@ void HTMLInputElement::form_associated_element_was_removed(DOM::Node*)
|
||||||
set_shadow_root(nullptr);
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLInputElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
if (type_state() != TypeAttributeState::ImageButton)
|
if (type_state() != TypeAttributeState::ImageButton)
|
||||||
|
|
|
@ -227,6 +227,7 @@ private:
|
||||||
|
|
||||||
void type_attribute_changed(TypeAttributeState old_state, TypeAttributeState new_state);
|
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<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
// ^DOM::Node
|
// ^DOM::Node
|
||||||
|
|
|
@ -30,6 +30,19 @@ void HTMLMarqueeElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLMarqueeElement);
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLMarqueeElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
HTMLElement::apply_presentational_hints(cascaded_properties);
|
HTMLElement::apply_presentational_hints(cascaded_properties);
|
||||||
|
|
|
@ -30,6 +30,7 @@ private:
|
||||||
HTMLMarqueeElement(DOM::Document&, DOM::QualifiedName);
|
HTMLMarqueeElement(DOM::Document&, DOM::QualifiedName);
|
||||||
|
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,20 @@ void HTMLObjectElement::form_associated_element_was_removed(DOM::Node*)
|
||||||
destroy_the_child_navigable();
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLObjectElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
for_each_attribute([&](auto& name, auto& value) {
|
for_each_attribute([&](auto& name, auto& value) {
|
||||||
|
|
|
@ -54,6 +54,7 @@ private:
|
||||||
|
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
virtual GC::Ptr<Layout::Node> create_layout_node(GC::Ref<CSS::ComputedProperties>) override;
|
virtual GC::Ptr<Layout::Node> create_layout_node(GC::Ref<CSS::ComputedProperties>) override;
|
||||||
|
|
|
@ -27,6 +27,14 @@ void HTMLParagraphElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLParagraphElement);
|
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
|
// https://html.spec.whatwg.org/multipage/rendering.html#tables-2
|
||||||
void HTMLParagraphElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLParagraphElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@ class HTMLParagraphElement final : public HTMLElement {
|
||||||
public:
|
public:
|
||||||
virtual ~HTMLParagraphElement() override;
|
virtual ~HTMLParagraphElement() override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
// https://www.w3.org/TR/html-aria/#el-p
|
// https://www.w3.org/TR/html-aria/#el-p
|
||||||
|
|
|
@ -28,6 +28,14 @@ void HTMLPreElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLPreElement);
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLPreElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
HTMLElement::apply_presentational_hints(cascaded_properties);
|
HTMLElement::apply_presentational_hints(cascaded_properties);
|
||||||
|
|
|
@ -26,6 +26,7 @@ private:
|
||||||
HTMLPreElement(DOM::Document&, DOM::QualifiedName);
|
HTMLPreElement(DOM::Document&, DOM::QualifiedName);
|
||||||
|
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,14 @@ void HTMLTableCaptionElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLTableCaptionElement);
|
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
|
// https://html.spec.whatwg.org/multipage/rendering.html#tables-2
|
||||||
void HTMLTableCaptionElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLTableCaptionElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@ class HTMLTableCaptionElement final : public HTMLElement {
|
||||||
public:
|
public:
|
||||||
virtual ~HTMLTableCaptionElement() override;
|
virtual ~HTMLTableCaptionElement() override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
// https://www.w3.org/TR/html-aria/#el-caption
|
// https://www.w3.org/TR/html-aria/#el-caption
|
||||||
|
|
|
@ -37,6 +37,20 @@ void HTMLTableCellElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLTableCellElement);
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLTableCellElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
for_each_attribute([&](auto& name, auto& value) {
|
for_each_attribute([&](auto& name, auto& value) {
|
||||||
|
|
|
@ -34,6 +34,7 @@ private:
|
||||||
virtual bool is_html_table_cell_element() const override { return true; }
|
virtual bool is_html_table_cell_element() const override { return true; }
|
||||||
|
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,14 @@ WebIDL::ExceptionOr<void> HTMLTableColElement::set_span(unsigned int value)
|
||||||
return set_attribute(HTML::AttributeNames::span, String::number(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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLTableColElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
for_each_attribute([&](auto& name, auto& value) {
|
for_each_attribute([&](auto& name, auto& value) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ private:
|
||||||
|
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,22 @@ static unsigned parse_border(StringView value)
|
||||||
return value.to_number<unsigned>().value_or(0);
|
return value.to_number<unsigned>().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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLTableElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
for_each_attribute([&](auto& name, auto& value) {
|
for_each_attribute([&](auto& name, auto& value) {
|
||||||
|
|
|
@ -58,6 +58,7 @@ private:
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
virtual void visit_edges(Cell::Visitor&) override;
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
|
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,18 @@ void HTMLTableRowElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLTableRowElement);
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLTableRowElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
Base::apply_presentational_hints(cascaded_properties);
|
Base::apply_presentational_hints(cascaded_properties);
|
||||||
|
|
|
@ -35,6 +35,7 @@ private:
|
||||||
|
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
virtual void visit_edges(Cell::Visitor&) override;
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
GC::Ptr<DOM::HTMLCollection> mutable m_cells;
|
GC::Ptr<DOM::HTMLCollection> mutable m_cells;
|
||||||
|
|
|
@ -100,6 +100,16 @@ WebIDL::ExceptionOr<void> HTMLTableSectionElement::delete_row(WebIDL::Long index
|
||||||
return {};
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void HTMLTableSectionElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
for_each_attribute([&](auto& name, auto& value) {
|
for_each_attribute([&](auto& name, auto& value) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ private:
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
virtual void visit_edges(Cell::Visitor&) override;
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
GC::Ptr<DOM::HTMLCollection> mutable m_rows;
|
GC::Ptr<DOM::HTMLCollection> mutable m_rows;
|
||||||
|
|
|
@ -29,6 +29,17 @@ void SVGCircleElement::initialize(JS::Realm& realm)
|
||||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(SVGCircleElement);
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void SVGCircleElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
Base::apply_presentational_hints(cascaded_properties);
|
Base::apply_presentational_hints(cascaded_properties);
|
||||||
|
|
|
@ -18,6 +18,7 @@ class SVGCircleElement final : public SVGGeometryElement {
|
||||||
public:
|
public:
|
||||||
virtual ~SVGCircleElement() override = default;
|
virtual ~SVGCircleElement() override = default;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
virtual Gfx::Path get_path(CSSPixelSize viewport_size) override;
|
virtual Gfx::Path get_path(CSSPixelSize viewport_size) override;
|
||||||
|
|
|
@ -52,6 +52,16 @@ GC::Ptr<Layout::Node> SVGForeignObjectElement::create_layout_node(GC::Ref<CSS::C
|
||||||
return heap().allocate<Layout::SVGForeignObjectBox>(document(), *this, move(style));
|
return heap().allocate<Layout::SVGForeignObjectBox>(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<CSS::CascadedProperties> cascaded_properties) const
|
void SVGForeignObjectElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
Base::apply_presentational_hints(cascaded_properties);
|
Base::apply_presentational_hints(cascaded_properties);
|
||||||
|
|
|
@ -31,6 +31,7 @@ private:
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
virtual void visit_edges(Cell::Visitor&) override;
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
GC::Ptr<SVG::SVGAnimatedLength> m_x;
|
GC::Ptr<SVG::SVGAnimatedLength> m_x;
|
||||||
|
|
|
@ -143,32 +143,40 @@ struct NamedPropertyID {
|
||||||
StringView name;
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void SVGGraphicsElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> 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 };
|
CSS::Parser::ParsingContext parsing_context { document(), CSS::Parser::ParsingContext::Mode::SVGPresentationAttribute };
|
||||||
for_each_attribute([&](auto& name, auto& value) {
|
for_each_attribute([&](auto& name, auto& value) {
|
||||||
for (auto property : attribute_style_properties) {
|
for (auto property : attribute_style_properties) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ class SVGGraphicsElement : public SVGElement {
|
||||||
WEB_PLATFORM_OBJECT(SVGGraphicsElement, SVGElement);
|
WEB_PLATFORM_OBJECT(SVGGraphicsElement, SVGElement);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
|
virtual void attribute_changed(FlyString const& name, Optional<String> const& old_value, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
|
||||||
|
|
|
@ -79,6 +79,20 @@ RefPtr<CSS::CSSStyleValue> SVGSVGElement::height_style_value_from_attribute() co
|
||||||
return nullptr;
|
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<CSS::CascadedProperties> cascaded_properties) const
|
void SVGSVGElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
Base::apply_presentational_hints(cascaded_properties);
|
Base::apply_presentational_hints(cascaded_properties);
|
||||||
|
|
|
@ -31,6 +31,7 @@ class SVGSVGElement final : public SVGGraphicsElement
|
||||||
public:
|
public:
|
||||||
virtual GC::Ptr<Layout::Node> create_layout_node(GC::Ref<CSS::ComputedProperties>) override;
|
virtual GC::Ptr<Layout::Node> create_layout_node(GC::Ref<CSS::ComputedProperties>) override;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
virtual bool requires_svg_container() const override { return false; }
|
virtual bool requires_svg_container() const override { return false; }
|
||||||
|
|
|
@ -30,6 +30,16 @@ void SVGStopElement::attribute_changed(FlyString const& name, Optional<String> 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<CSS::CascadedProperties> cascaded_properties) const
|
void SVGStopElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
CSS::Parser::ParsingContext parsing_context { document() };
|
CSS::Parser::ParsingContext parsing_context { document() };
|
||||||
|
|
|
@ -25,6 +25,7 @@ public:
|
||||||
|
|
||||||
GC::Ref<SVGAnimatedNumber> offset() const;
|
GC::Ref<SVGAnimatedNumber> offset() const;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
NumberPercentage stop_offset() const { return m_offset.value_or(NumberPercentage::create_number(0)); }
|
NumberPercentage stop_offset() const { return m_offset.value_or(NumberPercentage::create_number(0)); }
|
||||||
|
|
|
@ -39,11 +39,24 @@ void SVGSymbolElement::visit_edges(Cell::Visitor& visitor)
|
||||||
visitor.visit(m_view_box_for_bindings);
|
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
|
// https://svgwg.org/svg2-draft/struct.html#SymbolNotes
|
||||||
void SVGSymbolElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
void SVGSymbolElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties> cascaded_properties) const
|
||||||
{
|
{
|
||||||
Base::apply_presentational_hints(cascaded_properties);
|
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()) {
|
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.
|
// 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)));
|
cascaded_properties->set_property_from_presentational_hint(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::Inline)));
|
||||||
|
|
|
@ -19,6 +19,7 @@ class SVGSymbolElement final : public SVGGraphicsElement
|
||||||
public:
|
public:
|
||||||
virtual ~SVGSymbolElement() override = default;
|
virtual ~SVGSymbolElement() override = default;
|
||||||
|
|
||||||
|
virtual bool is_presentational_hint(FlyString const&) const override;
|
||||||
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
|
||||||
|
|
||||||
virtual Optional<ViewBox> view_box() const override { return m_view_box; }
|
virtual Optional<ViewBox> view_box() const override { return m_view_box; }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue