ResizeObserverEntry.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/Heap/Heap.h>
  7. #include <LibWeb/Bindings/ExceptionOrUtils.h>
  8. #include <LibWeb/Bindings/Intrinsics.h>
  9. #include <LibWeb/Bindings/ResizeObserverEntryPrototype.h>
  10. #include <LibWeb/Painting/PaintableBox.h>
  11. #include <LibWeb/ResizeObserver/ResizeObserverEntry.h>
  12. namespace Web::ResizeObserver {
  13. JS_DEFINE_ALLOCATOR(ResizeObserverEntry);
  14. // https://drafts.csswg.org/resize-observer-1/#create-and-populate-resizeobserverentry-h
  15. WebIDL::ExceptionOr<JS::NonnullGCPtr<ResizeObserverEntry>> ResizeObserverEntry::create_and_populate(JS::Realm& realm, DOM::Element& target)
  16. {
  17. // 1. Let this be a new ResizeObserverEntry.
  18. // 2. Set this.target slot to target.
  19. auto resize_observer_entry = realm.heap().allocate<ResizeObserverEntry>(realm, realm, target);
  20. // 3. Set this.borderBoxSize slot to result of calculating box size given target and observedBox of "border-box".
  21. auto border_box_size = ResizeObserverSize::calculate_box_size(realm, target, Bindings::ResizeObserverBoxOptions::BorderBox);
  22. resize_observer_entry->m_border_box_size.append(border_box_size);
  23. // 4. Set this.contentBoxSize slot to result of calculating box size given target and observedBox of "content-box".
  24. auto content_box_size = ResizeObserverSize::calculate_box_size(realm, target, Bindings::ResizeObserverBoxOptions::ContentBox);
  25. resize_observer_entry->m_content_box_size.append(content_box_size);
  26. // 5. Set this.devicePixelContentBoxSize slot to result of calculating box size given target and observedBox of "device-pixel-content-box".
  27. auto device_pixel_content_box_size = ResizeObserverSize::calculate_box_size(realm, target, Bindings::ResizeObserverBoxOptions::DevicePixelContentBox);
  28. resize_observer_entry->m_device_pixel_content_box_size.append(device_pixel_content_box_size);
  29. // 6. Set this.contentRect to logical this.contentBoxSize given target and observedBox of "content-box".
  30. double x = 0;
  31. double y = 0;
  32. double width = content_box_size->inline_size();
  33. double height = content_box_size->block_size();
  34. // 7. If target is not an SVG element or target is an SVG element with an associated CSS layout box do these steps:
  35. if (!target.is_svg_element() && target.paintable_box()) {
  36. auto const& paintable_box = *target.paintable_box();
  37. auto absolute_padding_rect = paintable_box.absolute_padding_box_rect();
  38. // Set this.contentRect.top to target.padding top.
  39. y = absolute_padding_rect.y().to_double();
  40. // Set this.contentRect.left to target.padding left.
  41. x = absolute_padding_rect.x().to_double();
  42. } else if (target.is_svg_element() && target.paintable_box()) {
  43. // 8. If target is an SVG element without an associated CSS layout box do these steps:
  44. // Set this.contentRect.top and this.contentRect.left to 0.
  45. // NOTE: This is already done by the default constructor.
  46. }
  47. resize_observer_entry->m_content_rect = MUST(Geometry::DOMRectReadOnly::construct_impl(realm, x, y, width, height));
  48. return resize_observer_entry;
  49. }
  50. void ResizeObserverEntry::initialize(JS::Realm& realm)
  51. {
  52. Base::initialize(realm);
  53. WEB_SET_PROTOTYPE_FOR_INTERFACE(ResizeObserverEntry);
  54. }
  55. void ResizeObserverEntry::visit_edges(JS::Cell::Visitor& visitor)
  56. {
  57. Base::visit_edges(visitor);
  58. visitor.visit(m_target);
  59. visitor.visit(m_content_box_size);
  60. visitor.visit(m_border_box_size);
  61. visitor.visit(m_device_pixel_content_box_size);
  62. visitor.visit(m_content_rect);
  63. }
  64. static JS::NonnullGCPtr<JS::Object> to_js_array(JS::Realm& realm, Vector<JS::NonnullGCPtr<ResizeObserverSize>> const& sizes)
  65. {
  66. Vector<JS::Value> vector;
  67. for (auto const& size : sizes)
  68. vector.append(JS::Value(size.ptr()));
  69. auto array = JS::Array::create_from(realm, vector);
  70. MUST(array->set_integrity_level(JS::Object::IntegrityLevel::Frozen));
  71. return array;
  72. }
  73. JS::NonnullGCPtr<JS::Object> ResizeObserverEntry::border_box_size_js_array() const
  74. {
  75. return to_js_array(realm(), m_border_box_size);
  76. }
  77. JS::NonnullGCPtr<JS::Object> ResizeObserverEntry::content_box_size_js_array() const
  78. {
  79. return to_js_array(realm(), m_content_box_size);
  80. }
  81. JS::NonnullGCPtr<JS::Object> ResizeObserverEntry::device_pixel_content_box_size_js_array() const
  82. {
  83. return to_js_array(realm(), m_device_pixel_content_box_size);
  84. }
  85. }