Paintable.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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. }
  17. Paintable::~Paintable()
  18. {
  19. }
  20. void Paintable::visit_edges(Cell::Visitor& visitor)
  21. {
  22. Base::visit_edges(visitor);
  23. TreeNode::visit_edges(visitor);
  24. visitor.visit(m_dom_node);
  25. visitor.visit(m_layout_node);
  26. visitor.visit(m_browsing_context);
  27. if (m_containing_block.has_value())
  28. visitor.visit(m_containing_block.value());
  29. }
  30. bool Paintable::is_visible() const
  31. {
  32. return computed_values().visibility() == CSS::Visibility::Visible && computed_values().opacity() != 0;
  33. }
  34. bool Paintable::is_positioned() const
  35. {
  36. if (layout_node().is_grid_item() && computed_values().z_index().has_value()) {
  37. // https://www.w3.org/TR/css-grid-2/#z-order
  38. // grid items with z_index should behave as if position were "relative"
  39. return true;
  40. }
  41. return computed_values().position() != CSS::Positioning::Static;
  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. if (!containing_block->paintable_box())
  110. return;
  111. auto navigable = this->navigable();
  112. if (!navigable)
  113. return;
  114. if (is<Painting::InlinePaintable>(*this)) {
  115. auto const& fragments = static_cast<Painting::InlinePaintable const*>(this)->fragments();
  116. for (auto const& fragment : fragments)
  117. navigable->set_needs_display(fragment.absolute_rect());
  118. }
  119. if (!is<Painting::PaintableWithLines>(*containing_block->paintable_box()))
  120. return;
  121. static_cast<Painting::PaintableWithLines const&>(*containing_block->paintable_box()).for_each_fragment([&](auto& fragment) {
  122. navigable->set_needs_display(fragment.absolute_rect());
  123. return IterationDecision::Continue;
  124. });
  125. }
  126. CSSPixelPoint Paintable::box_type_agnostic_position() const
  127. {
  128. if (is_paintable_box())
  129. return static_cast<PaintableBox const*>(this)->absolute_position();
  130. VERIFY(is_inline());
  131. if (is_inline_paintable()) {
  132. auto const& inline_paintable = static_cast<Painting::InlinePaintable const&>(*this);
  133. if (!inline_paintable.fragments().is_empty())
  134. return inline_paintable.fragments().first().absolute_rect().location();
  135. return inline_paintable.bounding_rect().location();
  136. }
  137. CSSPixelPoint position;
  138. if (auto const* block = containing_block(); block && block->paintable() && is<Painting::PaintableWithLines>(*block->paintable())) {
  139. static_cast<Painting::PaintableWithLines const&>(*block->paintable_box()).for_each_fragment([&](auto& fragment) {
  140. position = fragment.absolute_rect().location();
  141. return IterationDecision::Break;
  142. });
  143. }
  144. return position;
  145. }
  146. }