SVGElement.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
  3. * Copyright (c) 2023, Preston Taylor <95388976+PrestonLTaylor@users.noreply.github.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <LibWeb/Bindings/ExceptionOrUtils.h>
  8. #include <LibWeb/Bindings/Intrinsics.h>
  9. #include <LibWeb/CSS/StyleProperties.h>
  10. #include <LibWeb/DOM/Document.h>
  11. #include <LibWeb/DOM/ShadowRoot.h>
  12. #include <LibWeb/HTML/DOMStringMap.h>
  13. #include <LibWeb/SVG/SVGElement.h>
  14. #include <LibWeb/SVG/SVGUseElement.h>
  15. namespace Web::SVG {
  16. SVGElement::SVGElement(DOM::Document& document, DOM::QualifiedName qualified_name)
  17. : Element(document, move(qualified_name))
  18. {
  19. }
  20. void SVGElement::initialize(JS::Realm& realm)
  21. {
  22. Base::initialize(realm);
  23. WEB_SET_PROTOTYPE_FOR_INTERFACE(SVGElement);
  24. m_dataset = HTML::DOMStringMap::create(*this);
  25. }
  26. void SVGElement::visit_edges(Cell::Visitor& visitor)
  27. {
  28. Base::visit_edges(visitor);
  29. visitor.visit(m_dataset);
  30. }
  31. void SVGElement::attribute_changed(FlyString const& name, Optional<String> const& value)
  32. {
  33. Base::attribute_changed(name, value);
  34. update_use_elements_that_reference_this();
  35. }
  36. void SVGElement::inserted()
  37. {
  38. Base::inserted();
  39. update_use_elements_that_reference_this();
  40. }
  41. void SVGElement::children_changed()
  42. {
  43. Base::children_changed();
  44. update_use_elements_that_reference_this();
  45. }
  46. void SVGElement::update_use_elements_that_reference_this()
  47. {
  48. if (is<SVGUseElement>(this)
  49. // If this element is in a shadow root, it already represents a clone and is not itself referenced.
  50. || is<DOM::ShadowRoot>(this->root())
  51. // If this does not have an id it cannot be referenced, no point in searching the entire DOM tree.
  52. || !id().has_value()
  53. // An unconnected node cannot have valid references.
  54. // This also prevents searches for elements that are in the process of being constructed - as clones.
  55. || !this->is_connected()
  56. // Each use element already listens for the completely_loaded event and then clones its referece,
  57. // we do not have to also clone it in the process of initial DOM building.
  58. || !document().is_completely_loaded()) {
  59. return;
  60. }
  61. document().for_each_in_subtree_of_type<SVGUseElement>([this](SVGUseElement& use_element) {
  62. use_element.svg_element_changed(*this);
  63. return IterationDecision::Continue;
  64. });
  65. }
  66. void SVGElement::removed_from(Node* parent)
  67. {
  68. Base::removed_from(parent);
  69. remove_from_use_element_that_reference_this();
  70. }
  71. void SVGElement::remove_from_use_element_that_reference_this()
  72. {
  73. if (is<SVGUseElement>(this) || !id().has_value()) {
  74. return;
  75. }
  76. document().for_each_in_subtree_of_type<SVGUseElement>([this](SVGUseElement& use_element) {
  77. use_element.svg_element_removed(*this);
  78. return IterationDecision::Continue;
  79. });
  80. }
  81. void SVGElement::focus()
  82. {
  83. dbgln("(STUBBED) SVGElement::focus()");
  84. }
  85. void SVGElement::blur()
  86. {
  87. dbgln("(STUBBED) SVGElement::blur()");
  88. }
  89. JS::NonnullGCPtr<SVGAnimatedLength> SVGElement::svg_animated_length_for_property(CSS::PropertyID property) const
  90. {
  91. // FIXME: Create a proper animated value when animations are supported.
  92. auto make_length = [&] {
  93. if (auto const* style = computed_css_values(); style) {
  94. if (auto length = style->length_percentage(property); length.has_value())
  95. return SVGLength::from_length_percentage(realm(), *length);
  96. }
  97. return SVGLength::create(realm(), 0, 0.0f);
  98. };
  99. return SVGAnimatedLength::create(realm(), make_length(), make_length());
  100. }
  101. }