Paintable.cpp 5.2 KB

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