Paintable.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (c) 2022-2023, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibWeb/DOM/Document.h>
  7. #include <LibWeb/Layout/BlockContainer.h>
  8. #include <LibWeb/Painting/Paintable.h>
  9. #include <LibWeb/Painting/PaintableBox.h>
  10. #include <LibWeb/Painting/StackingContext.h>
  11. namespace Web::Painting {
  12. Paintable::Paintable(Layout::Node const& layout_node)
  13. : m_layout_node(layout_node)
  14. , m_browsing_context(const_cast<HTML::BrowsingContext&>(layout_node.browsing_context()))
  15. {
  16. auto& computed_values = layout_node.computed_values();
  17. m_visible = computed_values.visibility() == CSS::Visibility::Visible && computed_values.opacity() != 0;
  18. if (layout_node.is_grid_item() && computed_values.z_index().has_value()) {
  19. // https://www.w3.org/TR/css-grid-2/#z-order
  20. // grid items with z_index should behave as if position were "relative"
  21. m_positioned = true;
  22. } else {
  23. m_positioned = computed_values.position() != CSS::Positioning::Static;
  24. }
  25. m_fixed_position = computed_values.position() == CSS::Positioning::Fixed;
  26. m_absolutely_positioned = computed_values.position() == CSS::Positioning::Absolute;
  27. m_floating = layout_node.is_floating();
  28. m_inline = layout_node.is_inline();
  29. }
  30. Paintable::~Paintable()
  31. {
  32. }
  33. void Paintable::visit_edges(Cell::Visitor& visitor)
  34. {
  35. Base::visit_edges(visitor);
  36. TreeNode::visit_edges(visitor);
  37. visitor.visit(m_dom_node);
  38. visitor.visit(m_layout_node);
  39. visitor.visit(m_browsing_context);
  40. if (m_containing_block.has_value())
  41. visitor.visit(m_containing_block.value());
  42. }
  43. void Paintable::set_dom_node(JS::GCPtr<DOM::Node> dom_node)
  44. {
  45. m_dom_node = dom_node;
  46. }
  47. JS::GCPtr<DOM::Node> Paintable::dom_node()
  48. {
  49. return m_dom_node;
  50. }
  51. JS::GCPtr<DOM::Node const> Paintable::dom_node() const
  52. {
  53. return m_dom_node;
  54. }
  55. HTML::BrowsingContext const& Paintable::browsing_context() const
  56. {
  57. return m_browsing_context;
  58. }
  59. HTML::BrowsingContext& Paintable::browsing_context()
  60. {
  61. return m_browsing_context;
  62. }
  63. JS::GCPtr<HTML::Navigable> Paintable::navigable() const
  64. {
  65. return document().navigable();
  66. }
  67. Paintable::DispatchEventOfSameName Paintable::handle_mousedown(Badge<EventHandler>, CSSPixelPoint, unsigned, unsigned)
  68. {
  69. return DispatchEventOfSameName::Yes;
  70. }
  71. Paintable::DispatchEventOfSameName Paintable::handle_mouseup(Badge<EventHandler>, CSSPixelPoint, unsigned, unsigned)
  72. {
  73. return DispatchEventOfSameName::Yes;
  74. }
  75. Paintable::DispatchEventOfSameName Paintable::handle_mousemove(Badge<EventHandler>, CSSPixelPoint, unsigned, unsigned)
  76. {
  77. return DispatchEventOfSameName::Yes;
  78. }
  79. bool Paintable::handle_mousewheel(Badge<EventHandler>, CSSPixelPoint, unsigned, unsigned, int, int)
  80. {
  81. return false;
  82. }
  83. TraversalDecision Paintable::hit_test(CSSPixelPoint, HitTestType, Function<TraversalDecision(HitTestResult)> const&) const
  84. {
  85. return TraversalDecision::Continue;
  86. }
  87. StackingContext* Paintable::enclosing_stacking_context()
  88. {
  89. for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
  90. if (auto* stacking_context = ancestor->stacking_context())
  91. return const_cast<StackingContext*>(stacking_context);
  92. }
  93. // We should always reach the viewport's stacking context.
  94. VERIFY_NOT_REACHED();
  95. }
  96. void Paintable::set_stacking_context(NonnullOwnPtr<StackingContext> stacking_context)
  97. {
  98. m_stacking_context = move(stacking_context);
  99. }
  100. void Paintable::invalidate_stacking_context()
  101. {
  102. m_stacking_context = nullptr;
  103. }
  104. void Paintable::set_needs_display() const
  105. {
  106. auto* containing_block = this->containing_block();
  107. if (!containing_block)
  108. return;
  109. auto navigable = this->navigable();
  110. if (!navigable)
  111. return;
  112. if (is<Painting::InlinePaintable>(*this)) {
  113. auto const& fragments = static_cast<Painting::InlinePaintable const*>(this)->fragments();
  114. for (auto const& fragment : fragments)
  115. navigable->set_needs_display(fragment.absolute_rect());
  116. }
  117. if (!is<Painting::PaintableWithLines>(*containing_block))
  118. return;
  119. static_cast<Painting::PaintableWithLines const&>(*containing_block).for_each_fragment([&](auto& fragment) {
  120. navigable->set_needs_display(fragment.absolute_rect());
  121. return IterationDecision::Continue;
  122. });
  123. }
  124. CSSPixelPoint Paintable::box_type_agnostic_position() const
  125. {
  126. if (is_paintable_box())
  127. return static_cast<PaintableBox const*>(this)->absolute_position();
  128. VERIFY(is_inline());
  129. if (is_inline_paintable()) {
  130. auto const& inline_paintable = static_cast<Painting::InlinePaintable const&>(*this);
  131. if (!inline_paintable.fragments().is_empty())
  132. return inline_paintable.fragments().first().absolute_rect().location();
  133. return inline_paintable.bounding_rect().location();
  134. }
  135. CSSPixelPoint position;
  136. if (auto const* block = containing_block(); block && is<Painting::PaintableWithLines>(*block)) {
  137. static_cast<Painting::PaintableWithLines const&>(*block).for_each_fragment([&](auto& fragment) {
  138. position = fragment.absolute_rect().location();
  139. return IterationDecision::Break;
  140. });
  141. }
  142. return position;
  143. }
  144. }