diff --git a/Libraries/LibWeb/Animations/ScrollTimeline.cpp b/Libraries/LibWeb/Animations/ScrollTimeline.cpp index c8dfc1d90f..79779db993 100644 --- a/Libraries/LibWeb/Animations/ScrollTimeline.cpp +++ b/Libraries/LibWeb/Animations/ScrollTimeline.cpp @@ -145,7 +145,7 @@ void ScrollTimeline::update_current_time(double) if (!layout_node || !layout_node->is_scroll_container()) return; - auto const& paintable_box = propagated_source.visit([](auto const& source) -> Painting::PaintableBox const* { return source->unsafe_paintable_box(); }); + auto paintable_box = propagated_source.visit([](auto const& source) -> RefPtr { return source->unsafe_paintable_box(); }); if (!paintable_box || !paintable_box->has_scrollable_overflow()) return; diff --git a/Libraries/LibWeb/CSS/CSSStyleProperties.cpp b/Libraries/LibWeb/CSS/CSSStyleProperties.cpp index 3b77455cad..843713088b 100644 --- a/Libraries/LibWeb/CSS/CSSStyleProperties.cpp +++ b/Libraries/LibWeb/CSS/CSSStyleProperties.cpp @@ -662,10 +662,12 @@ RefPtr CSSStyleProperties::style_value_for_computed_property(L auto used_value_for_property = [&layout_node, property_id](Function&& used_value_getter) -> Optional { auto const& display = layout_node.computed_values().display(); - if (!display.is_none() && !display.is_contents() && layout_node.first_paintable()) { - if (auto const* paintable_box = as_if(layout_node.first_paintable())) + if (!display.is_none() && !display.is_contents()) { + auto first_paintable = layout_node.first_paintable(); + if (auto const* paintable_box = as_if(first_paintable.ptr())) return used_value_getter(*paintable_box); - dbgln("FIXME: Support getting used value for property `{}` on {}", string_from_property_id(property_id), layout_node.debug_description()); + if (first_paintable) + dbgln("FIXME: Support getting used value for property `{}` on {}", string_from_property_id(property_id), layout_node.debug_description()); } return {}; }; @@ -889,8 +891,9 @@ RefPtr CSSStyleProperties::style_value_for_computed_property(L auto transform = FloatMatrix4x4::identity(); // 2. Post-multiply all s in to transform. - VERIFY(layout_node.first_paintable()); - auto const& paintable_box = as(*layout_node.first_paintable()); + auto first_paintable = layout_node.first_paintable(); + VERIFY(first_paintable); + auto const& paintable_box = as(*first_paintable); for (auto const& transformation : transformations) { transform = transform * transformation->to_matrix(paintable_box).release_value(); } @@ -1023,16 +1026,14 @@ RefPtr CSSStyleProperties::style_value_for_computed_property(L // For grid-template-columns and grid-template-rows the resolved value is the used value. // https://www.w3.org/TR/css-grid-2/#resolved-track-list-standalone if (property_id == PropertyID::GridTemplateColumns) { - if (layout_node.first_paintable() && layout_node.first_paintable()->is_paintable_box()) { - auto const& paintable_box = as(*layout_node.first_paintable()); - if (auto used_values_for_grid_template_columns = paintable_box.used_values_for_grid_template_columns()) { + if (auto first_paintable = layout_node.first_paintable(); auto const* paintable_box = as_if(first_paintable.ptr())) { + if (auto used_values_for_grid_template_columns = paintable_box->used_values_for_grid_template_columns()) { return used_values_for_grid_template_columns; } } } else if (property_id == PropertyID::GridTemplateRows) { - if (layout_node.first_paintable() && layout_node.first_paintable()->is_paintable_box()) { - auto const& paintable_box = as(*layout_node.first_paintable()); - if (auto used_values_for_grid_template_rows = paintable_box.used_values_for_grid_template_rows()) { + if (auto first_paintable = layout_node.first_paintable(); auto const* paintable_box = as_if(first_paintable.ptr())) { + if (auto used_values_for_grid_template_rows = paintable_box->used_values_for_grid_template_rows()) { return used_values_for_grid_template_rows; } } diff --git a/Libraries/LibWeb/CSS/Interpolation.cpp b/Libraries/LibWeb/CSS/Interpolation.cpp index e8e65b4237..428fab4855 100644 --- a/Libraries/LibWeb/CSS/Interpolation.cpp +++ b/Libraries/LibWeb/CSS/Interpolation.cpp @@ -1240,7 +1240,7 @@ RefPtr interpolate_transform(DOM::Element& element, Calculatio generic_function = TransformFunction::Matrix3d; // NB: Called during animation interpolation. auto paintable_box = [&] -> Optional { - if (auto* box = element.unsafe_paintable_box()) + if (auto box = element.unsafe_paintable_box()) return *box; return {}; }(); @@ -1343,8 +1343,9 @@ RefPtr interpolate_transform(DOM::Element& element, Calculatio // iterating over Va and Vb. // NB: Called during animation interpolation. Optional paintable_box; - if (auto* paintable = as_if(element.unsafe_paintable())) - paintable_box = *paintable; + auto paintable = element.unsafe_paintable(); + if (auto const* box = as_if(paintable.ptr())) + paintable_box = *box; auto post_multiply_remaining_transformations = [&paintable_box](size_t start_index, Vector> const& transformations) -> Optional { FloatMatrix4x4 result = FloatMatrix4x4::identity(); diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 3598306632..470a426db4 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -1458,13 +1458,13 @@ static void relayout_svg_root(Layout::SVGSVGBox& svg_root) Layout::LayoutState layout_state(svg_root); // Pre-populate the svg_root itself. - if (auto const* paintable = svg_root.paintable_box()) + if (auto paintable = svg_root.paintable_box()) layout_state.populate_from_paintable(svg_root, *paintable); // Pre-populate SVGGraphicsBox ancestors (up to outer SVG) for get_parent_svg_transform(). for (auto* ancestor = svg_root.parent(); ancestor; ancestor = ancestor->parent()) { if (auto const* svg_graphics_ancestor = as_if(*ancestor)) { - if (auto const* paintable = svg_graphics_ancestor->paintable_box()) + if (auto paintable = svg_graphics_ancestor->paintable_box()) layout_state.populate_from_paintable(*svg_graphics_ancestor, *paintable); } if (is(*ancestor)) @@ -1473,7 +1473,7 @@ static void relayout_svg_root(Layout::SVGSVGBox& svg_root) // Pre-populate the viewport for position:fixed elements inside . auto& viewport = svg_root.root(); - if (auto const* paintable = viewport.paintable_box()) + if (auto paintable = viewport.paintable_box()) layout_state.populate_from_paintable(viewport, *paintable); auto const& svg_state = layout_state.get(svg_root); @@ -1713,7 +1713,7 @@ void Document::update_layout(UpdateLayoutReason reason) } // Collect elements with content-visibility: auto. This is used in the HTML event loop to avoid traversing the whole tree every time. - Vector> paintable_boxes_with_auto_content_visibility; + Vector> paintable_boxes_with_auto_content_visibility; unsafe_paintable()->for_each_in_subtree_of_type([&](auto& paintable_box) { if (paintable_box.dom_node() && paintable_box.dom_node()->is_element() @@ -1964,13 +1964,13 @@ void Document::set_needs_animated_style_update() void Document::update_paint_and_hit_testing_properties_if_needed() { // NB: Called during paint property resolution. - if (auto* paintable = this->unsafe_paintable()) { + if (auto paintable = this->unsafe_paintable()) { paintable->refresh_scroll_state(); } if (m_needs_accumulated_visual_contexts_update) { m_needs_accumulated_visual_contexts_update = false; - if (auto* paintable = this->unsafe_paintable()) { + if (auto paintable = this->unsafe_paintable()) { paintable->assign_accumulated_visual_contexts(); } } @@ -4249,7 +4249,7 @@ void Document::set_page_showing(bool page_showing) void Document::invalidate_stacking_context_tree() { // NB: Called during stacking context invalidation. - if (auto* paintable_box = this->unsafe_paintable_box()) + if (auto paintable_box = this->unsafe_paintable_box()) paintable_box->invalidate_stacking_context(); } @@ -5381,15 +5381,15 @@ void Document::queue_an_intersection_observer_entry(IntersectionObserver::Inters } // https://www.w3.org/TR/intersection-observer/#compute-the-intersection -static CSSPixelRect compute_intersection(GC::Ref target, CSSPixelRect target_rect, IntersectionObserver::IntersectionObserver const& observer, Painting::PaintableBox const* root_paintable, CSSPixelRect const& root_bounds) +static CSSPixelRect compute_intersection(GC::Ref target, CSSPixelRect target_rect, IntersectionObserver::IntersectionObserver const& observer, RefPtr root_paintable, CSSPixelRect const& root_bounds) { // 1. Let intersectionRect be the result of getting the bounding box for target. auto intersection_rect = target_rect; // 2. Let container be the containing block of target. // 3. While container is not root: - if (auto const* target_paintable = target->paintable_box()) { - for (auto const* container = target_paintable->containing_block(); container; container = container->containing_block()) { + if (auto target_paintable = target->paintable_box()) { + for (auto container = target_paintable->containing_block(); container; container = container->containing_block()) { // Stop when we reach the intersection root. if (container == root_paintable) break; @@ -5460,7 +5460,7 @@ void Document::run_the_update_intersection_observations_steps(HighResolutionTime // Pre-compute per-observer values to avoid repeated work in the per-target loop. auto intersection_root_node = observer->intersection_root_node(); - auto* root_paintable = intersection_root_node->paintable_box(); + auto root_paintable = intersection_root_node->paintable_box(); bool is_implicit_root = observer->is_implicit_root(); bool root_is_element = intersection_root_node->is_element(); @@ -5807,24 +5807,36 @@ void Document::shared_declarative_refresh_steps(StringView input, GC::Ptr Document::paintable() const { - return static_cast(Node::paintable()); + auto paintable = Node::paintable(); + if (!paintable) + return nullptr; + return as(*paintable); } -Painting::ViewportPaintable* Document::paintable() +RefPtr Document::paintable() { - return static_cast(Node::paintable()); + auto paintable = Node::paintable(); + if (!paintable) + return nullptr; + return as(*paintable); } -Painting::ViewportPaintable const* Document::unsafe_paintable() const +RefPtr Document::unsafe_paintable() const { - return static_cast(Node::unsafe_paintable()); + auto paintable = Node::unsafe_paintable(); + if (!paintable) + return nullptr; + return as(*paintable); } -Painting::ViewportPaintable* Document::unsafe_paintable() +RefPtr Document::unsafe_paintable() { - return static_cast(Node::unsafe_paintable()); + auto paintable = Node::unsafe_paintable(); + if (!paintable) + return nullptr; + return as(*paintable); } // https://html.spec.whatwg.org/multipage/browsing-the-web.html#restore-the-history-object-state @@ -6399,7 +6411,7 @@ Element const* Document::element_from_point(double x, double y) // 2. If there is a box in the viewport that would be a target for hit testing at coordinates x,y, when applying the transforms // that apply to the descendants of the viewport, return the associated element and terminate these steps. GC::Ptr hit_element; - if (auto const* paintable_box = this->paintable_box()) { + if (auto paintable_box = this->paintable_box()) { (void)paintable_box->hit_test(position, Painting::HitTestType::Exact, [&](Painting::HitTestResult result) { if (auto* element = as_if(result.dom_node())) { hit_element = element; @@ -6442,7 +6454,7 @@ GC::RootVector> Document::elements_from_point(double x, double // 3. For each box in the viewport, in paint order, starting with the topmost box, that would be a target for // hit testing at coordinates x,y even if nothing would be overlapping it, when applying the transforms that // apply to the descendants of the viewport, append the associated element to sequence. - if (auto const* paintable_box = this->paintable_box()) { + if (auto paintable_box = this->paintable_box()) { (void)paintable_box->hit_test(position, Painting::HitTestType::Exact, [&](Painting::HitTestResult result) { if (auto* element = as_if(result.dom_node())) { // AD-HOC: If element is inside a UA internal shadow root, retarget to the host. @@ -6976,7 +6988,7 @@ GC::Ptr Document::topmost_auto_or_hint_popover() void Document::set_needs_to_refresh_scroll_state(bool b) { // NB: Propagating scroll state invalidation. - if (auto* paintable = this->unsafe_paintable()) + if (auto paintable = this->unsafe_paintable()) paintable->set_needs_to_refresh_scroll_state(b); } @@ -7917,7 +7929,7 @@ String Document::dump_display_list() { update_layout(UpdateLayoutReason::DumpDisplayList); - auto* viewport_paintable = paintable(); + auto viewport_paintable = paintable(); if (!viewport_paintable) return "No paintable"_string; @@ -7925,11 +7937,11 @@ String Document::dump_display_list() if (!display_list) return "No display list"_string; - HashMap context_id_to_paintable; + HashMap> context_id_to_paintable; viewport_paintable->for_each_in_inclusive_subtree_of_type([&](auto const& paintable_box) { auto visual_context_index = paintable_box.accumulated_visual_context_index(); if (visual_context_index.value()) - (void)context_id_to_paintable.try_set(visual_context_index.value(), &paintable_box); + (void)context_id_to_paintable.try_set(visual_context_index.value(), paintable_box); return TraversalDecision::Continue; }); @@ -8009,13 +8021,13 @@ String Document::dump_stacking_context_tree() { update_layout(UpdateLayoutReason::DumpDisplayList); - auto* viewport_paintable = paintable(); + auto viewport_paintable = paintable(); if (!viewport_paintable) return "No paintable"_string; viewport_paintable->build_stacking_context_tree_if_needed(); - auto* stacking_context = viewport_paintable->stacking_context(); + auto stacking_context = viewport_paintable->stacking_context(); if (!stacking_context) return "No stacking context"_string; diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index 57ddc10a3e..e87ad8e2ca 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -399,11 +400,11 @@ public: Layout::Viewport const* unsafe_layout_node() const; Layout::Viewport* unsafe_layout_node(); - Painting::ViewportPaintable const* paintable() const; - Painting::ViewportPaintable* paintable(); + RefPtr paintable() const; + RefPtr paintable(); - Painting::ViewportPaintable const* unsafe_paintable() const; - Painting::ViewportPaintable* unsafe_paintable(); + RefPtr unsafe_paintable() const; + RefPtr unsafe_paintable(); GC::Ref get_elements_by_name(FlyString const&); diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index e56da30aa9..11118353ed 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -1543,7 +1543,7 @@ static Vector compute_client_rects_assuming_layout_clean(Element c // are left in the final list. Vector rects; - if (auto const* paintable_box = element.paintable_box()) { + if (auto paintable_box = element.paintable_box()) { auto absolute_rect = paintable_box->absolute_border_box_rect(); rects.append(paintable_box->transform_rect_to_viewport(absolute_rect)); } else if (element.paintable()) { diff --git a/Libraries/LibWeb/DOM/Node.cpp b/Libraries/LibWeb/DOM/Node.cpp index 33920ab37e..7c5ad80dca 100644 --- a/Libraries/LibWeb/DOM/Node.cpp +++ b/Libraries/LibWeb/DOM/Node.cpp @@ -133,8 +133,6 @@ void Node::visit_edges(Cell::Visitor& visitor) visitor.visit(m_child_nodes); visitor.visit(m_layout_node); - visitor.visit(m_paintable); - if (m_registered_observer_list) { visitor.visit(*m_registered_observer_list); } @@ -2656,7 +2654,7 @@ Layout::Node* Node::layout_node() return m_layout_node; } -void Node::set_paintable(GC::Ptr paintable) +void Node::set_paintable(WeakPtr paintable) { m_paintable = paintable; } @@ -2670,7 +2668,7 @@ void Node::set_needs_repaint(InvalidateDisplayList should_invalidate_display_lis { if (auto* layout_node = unsafe_layout_node()) { for (auto& paintable : layout_node->paintables()) - paintable.set_needs_repaint(should_invalidate_display_list); + paintable->set_needs_repaint(should_invalidate_display_list); } } @@ -2682,45 +2680,55 @@ void Node::set_needs_layout_update(SetNeedsLayoutReason reason) } } -Painting::Paintable const* Node::paintable() const +RefPtr Node::paintable() const { if (m_paintable) VERIFY(document().layout_is_up_to_date()); - return m_paintable; + return m_paintable.strong_ref(); } -Painting::Paintable* Node::paintable() +RefPtr Node::paintable() { if (m_paintable) VERIFY(document().layout_is_up_to_date()); - return m_paintable; + return m_paintable.strong_ref(); } -Painting::PaintableBox const* Node::paintable_box() const +RefPtr Node::unsafe_paintable() const { - if (auto* p = paintable(); p && p->is_paintable_box()) - return static_cast(p); + return m_paintable.strong_ref(); +} + +RefPtr Node::unsafe_paintable() +{ + return m_paintable.strong_ref(); +} + +RefPtr Node::paintable_box() const +{ + if (auto p = paintable(); p && p->is_paintable_box()) + return static_cast(*p); return nullptr; } -Painting::PaintableBox* Node::paintable_box() +RefPtr Node::paintable_box() { - if (auto* p = paintable(); p && p->is_paintable_box()) - return static_cast(p); + if (auto p = paintable(); p && p->is_paintable_box()) + return static_cast(*p); return nullptr; } -Painting::PaintableBox const* Node::unsafe_paintable_box() const +RefPtr Node::unsafe_paintable_box() const { - if (m_paintable && m_paintable->is_paintable_box()) - return static_cast(m_paintable.ptr()); + if (auto paintable = m_paintable.strong_ref(); paintable && paintable->is_paintable_box()) + return static_cast(*paintable); return nullptr; } -Painting::PaintableBox* Node::unsafe_paintable_box() +RefPtr Node::unsafe_paintable_box() { - if (m_paintable && m_paintable->is_paintable_box()) - return static_cast(m_paintable.ptr()); + if (auto paintable = m_paintable.strong_ref(); paintable && paintable->is_paintable_box()) + return static_cast(*paintable); return nullptr; } diff --git a/Libraries/LibWeb/DOM/Node.h b/Libraries/LibWeb/DOM/Node.h index ef61c501d8..09327c8c34 100644 --- a/Libraries/LibWeb/DOM/Node.h +++ b/Libraries/LibWeb/DOM/Node.h @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -329,17 +331,17 @@ public: Layout::Node const* unsafe_layout_node() const { return m_layout_node; } Layout::Node* unsafe_layout_node() { return m_layout_node; } - Painting::PaintableBox const* paintable_box() const; - Painting::PaintableBox* paintable_box(); - Painting::Paintable const* paintable() const; - Painting::Paintable* paintable(); + RefPtr paintable_box() const; + RefPtr paintable_box(); + RefPtr paintable() const; + RefPtr paintable(); - Painting::PaintableBox const* unsafe_paintable_box() const; - Painting::PaintableBox* unsafe_paintable_box(); - Painting::Paintable const* unsafe_paintable() const { return m_paintable; } - Painting::Paintable* unsafe_paintable() { return m_paintable; } + RefPtr unsafe_paintable_box() const; + RefPtr unsafe_paintable_box(); + RefPtr unsafe_paintable() const; + RefPtr unsafe_paintable(); - void set_paintable(GC::Ptr); + void set_paintable(WeakPtr); void clear_paintable(); void set_needs_repaint(InvalidateDisplayList = InvalidateDisplayList::Yes); @@ -498,7 +500,7 @@ protected: GC::Ptr m_document; GC::Ptr m_layout_node; - GC::Ptr m_paintable; + WeakPtr m_paintable; NodeType m_type { NodeType::INVALID }; bool m_needs_layout_tree_update { false }; bool m_child_needs_layout_tree_update { false }; diff --git a/Libraries/LibWeb/DOM/Range.cpp b/Libraries/LibWeb/DOM/Range.cpp index bb510d5efe..d28eb93b91 100644 --- a/Libraries/LibWeb/DOM/Range.cpp +++ b/Libraries/LibWeb/DOM/Range.cpp @@ -113,7 +113,7 @@ void Range::update_associated_selection() document.reset_cursor_blink_cycle(); // NB: Called during selection update after range change. - if (auto* viewport = document.unsafe_paintable()) { + if (auto viewport = document.unsafe_paintable()) { viewport->recompute_selection_states(*this); viewport->set_needs_repaint(); } @@ -1210,9 +1210,10 @@ GC::Ref Range::get_client_rects() // 2. For each Text node selected or partially selected by the range (including when the boundary-points // are identical), include scaled DOMRect object (for the part that is selected, not the whole line box). auto const& text = static_cast(*node); - auto const* paintable = text.paintable(); + auto paintable = text.paintable(); if (paintable && selection_state != Painting::Paintable::SelectionState::None) { - if (auto const* paintable_lines = as_if(paintable->containing_block())) { + auto containing_block = paintable->containing_block(); + if (auto const* paintable_lines = as_if(containing_block.ptr())) { auto fragments = paintable_lines->fragments(); for (auto frag = fragments.begin(); frag != fragments.end(); frag++) { auto rect = frag->range_rect(selection_state, start_offset(), end_offset()); diff --git a/Libraries/LibWeb/Dump.cpp b/Libraries/LibWeb/Dump.cpp index 432118a417..a4bcd57f00 100644 --- a/Libraries/LibWeb/Dump.cpp +++ b/Libraries/LibWeb/Dump.cpp @@ -208,13 +208,13 @@ void dump_tree(StringBuilder& builder, Layout::Node const& layout_node, bool sho } auto dump_position = [&] { - if (auto* paintable_box = as_if(layout_node.first_paintable())) + if (auto first_paintable = layout_node.first_paintable(); auto const* paintable_box = as_if(first_paintable.ptr())) builder.appendff("at {}", paintable_box->absolute_rect().location()); else builder.appendff("(not painted)"); }; auto dump_box_model = [&] { - if (auto const* paintable_box = as_if(layout_node.first_paintable())) { + if (auto first_paintable = layout_node.first_paintable(); auto const* paintable_box = as_if(first_paintable.ptr())) { auto const& box_model = paintable_box->box_model(); // Dump the horizontal box properties builder.appendff(" [{}+{}+{} {} {}+{}+{}]", @@ -385,14 +385,15 @@ void dump_tree(StringBuilder& builder, Layout::Node const& layout_node, bool sho if (auto const* block_container = as_if(layout_node); block_container && block_container->children_are_inline() && block_container->paintable_with_lines()) { size_t fragment_index = 0; - for (auto const& fragment : block_container->paintable_with_lines()->fragments()) + auto paintable_with_lines = block_container->paintable_with_lines(); + for (auto const& fragment : paintable_with_lines->fragments()) dump_fragment(fragment, fragment_index++); } if (is(layout_node) && layout_node.first_paintable()) { auto const& inline_node = static_cast(layout_node); for (auto const& paintable : inline_node.paintables()) { - auto const& paintable_with_lines = static_cast(paintable); + auto const& paintable_with_lines = static_cast(*paintable); auto const& fragments = paintable_with_lines.fragments(); for (size_t fragment_index = 0; fragment_index < fragments.size(); ++fragment_index) { auto const& fragment = fragments[fragment_index]; @@ -748,9 +749,9 @@ void dump_tree(StringBuilder& builder, Painting::Paintable const& paintable, boo else builder.append(paintable_color_on); - builder.appendff("{}{} ({})", node_paintable.class_name(), color_off, node_paintable.layout_node().debug_description()); + builder.appendff("{}{} ({})", node_paintable->class_name(), color_off, node_paintable->layout_node().debug_description()); - if (auto const* paintable_box = as_if(node_paintable)) { + if (auto const* paintable_box = as_if(*node_paintable)) { builder.appendff(" {}", paintable_box->absolute_border_box_rect()); if (paintable_box->has_scrollable_overflow()) @@ -761,7 +762,7 @@ void dump_tree(StringBuilder& builder, Painting::Paintable const& paintable, boo } builder.append("\n"sv); - for (auto const* child = node_paintable.first_child(); child; child = child->next_sibling()) + for (auto child = node_paintable->first_child(); child; child = child->next_sibling()) dump_tree(builder, *child, colorize, indent + 1); dumped_any = true; } diff --git a/Libraries/LibWeb/HTML/FormAssociatedElement.cpp b/Libraries/LibWeb/HTML/FormAssociatedElement.cpp index 10d6f6b737..e4731b1549 100644 --- a/Libraries/LibWeb/HTML/FormAssociatedElement.cpp +++ b/Libraries/LibWeb/HTML/FormAssociatedElement.cpp @@ -1118,7 +1118,7 @@ void FormAssociatedTextControlElement::scroll_cursor_into_view() if (!text_node) return; - auto* paintable = text_node->paintable(); + auto paintable = text_node->paintable(); if (!paintable) return; @@ -1140,7 +1140,7 @@ void FormAssociatedTextControlElement::selection_was_changed(SelectionSource sou if (!text_node) return; // NB: Called during selection change handling, layout may be stale. - auto* text_paintable = text_node->unsafe_paintable(); + auto text_paintable = text_node->unsafe_paintable(); if (!text_paintable) return; diff --git a/Libraries/LibWeb/HTML/HTMLElement.cpp b/Libraries/LibWeb/HTML/HTMLElement.cpp index 16fd5408fb..7aae7b5ebd 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -676,7 +676,7 @@ int HTMLElement::offset_width() const const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLElementOffsetWidth); // 1. If the element does not have any associated box return zero and terminate this algorithm. - auto const* box = paintable_box(); + auto box = paintable_box(); if (!box) return 0; @@ -695,7 +695,7 @@ int HTMLElement::offset_height() const const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLElementOffsetHeight); // 1. If the element does not have any associated box return zero and terminate this algorithm. - auto const* box = paintable_box(); + auto box = paintable_box(); if (!box) return 0; diff --git a/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Libraries/LibWeb/HTML/HTMLImageElement.cpp index 50a8a555a7..3a02e3c978 100644 --- a/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -292,7 +292,7 @@ WebIDL::UnsignedLong HTMLImageElement::width() const const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLImageElementWidth); // Return the rendered width of the image, in CSS pixels, if the image is being rendered. - if (auto* paintable_box = this->paintable_box()) + if (auto paintable_box = this->paintable_box()) return paintable_box->content_width().to_int(); // On setting [the width or height IDL attribute], they must act as if they reflected the respective content attributes of the same name. @@ -323,7 +323,7 @@ WebIDL::UnsignedLong HTMLImageElement::height() const const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLImageElementHeight); // Return the rendered height of the image, in CSS pixels, if the image is being rendered. - if (auto* paintable_box = this->paintable_box()) + if (auto paintable_box = this->paintable_box()) return paintable_box->content_height().to_int(); // On setting [the width or height IDL attribute], they must act as if they reflected the respective content attributes of the same name. @@ -380,7 +380,7 @@ int HTMLImageElement::x() const // to the element and its ancestors, or zero if there is no box. const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLImageElementX); - auto const* paintable_box = this->paintable_box(); + auto paintable_box = this->paintable_box(); if (!paintable_box) return 0; @@ -399,7 +399,7 @@ int HTMLImageElement::y() const // to the element and its ancestors, or zero if there is no box. const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLImageElementY); - auto const* paintable_box = this->paintable_box(); + auto paintable_box = this->paintable_box(); if (!paintable_box) return 0; diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 54361297bb..515996a445 100644 --- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -2376,7 +2376,7 @@ WebIDL::UnsignedLong HTMLInputElement::height() const return 0; // Return the rendered height of the image, in CSS pixels, if the image is being rendered. - if (auto* paintable_box = this->paintable_box()) + if (auto paintable_box = this->paintable_box()) return paintable_box->content_height().to_int(); // On setting [the width or height IDL attribute], they must act as if they reflected the respective content attributes of the same name. @@ -2411,7 +2411,7 @@ WebIDL::UnsignedLong HTMLInputElement::width() const return 0; // Return the rendered width of the image, in CSS pixels, if the image is being rendered. - if (auto* paintable_box = this->paintable_box()) + if (auto paintable_box = this->paintable_box()) return paintable_box->content_width().to_int(); // On setting [the width or height IDL attribute], they must act as if they reflected the respective content attributes of the same name. diff --git a/Libraries/LibWeb/HTML/HTMLLabelElement.cpp b/Libraries/LibWeb/HTML/HTMLLabelElement.cpp index 9abd8d9236..9c3caf1b98 100644 --- a/Libraries/LibWeb/HTML/HTMLLabelElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLLabelElement.cpp @@ -86,7 +86,7 @@ void HTMLLabelElement::activation_behavior(DOM::Event const& event) document().update_layout(DOM::UpdateLayoutReason::HTMLLabelElementActivationBehavior); // Recompute offsetX/offsetY relative to the control element, since the original values are relative to the label. - if (auto const* paintable = control_element->paintable(); paintable && document().navigable()) { + if (auto paintable = control_element->paintable(); paintable && document().navigable()) { auto scroll_offset = document().navigable()->viewport_scroll_offset(); auto page_position = CSSPixelPoint { CSSPixels(mouse_event.client_x()) + scroll_offset.x(), CSSPixels(mouse_event.client_y()) + scroll_offset.y() }; auto box_position = paintable->box_type_agnostic_position(); diff --git a/Libraries/LibWeb/HTML/Navigable.cpp b/Libraries/LibWeb/HTML/Navigable.cpp index 46b1a6d5d0..84e1c83bf7 100644 --- a/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Libraries/LibWeb/HTML/Navigable.cpp @@ -2813,7 +2813,7 @@ CSSPixelPoint Navigable::to_top_level_position(CSSPixelPoint a_position) break; if (!ancestor->container()) return {}; - auto const* paintable = ancestor->container()->paintable(); + auto paintable = ancestor->container()->paintable(); if (!paintable) return {}; diff --git a/Libraries/LibWeb/Internals/Internals.cpp b/Libraries/LibWeb/Internals/Internals.cpp index 1b24677894..d45c36c3f3 100644 --- a/Libraries/LibWeb/Internals/Internals.cpp +++ b/Libraries/LibWeb/Internals/Internals.cpp @@ -489,7 +489,7 @@ String Internals::dump_paintable_tree(GC::Ref node) { node->document().update_layout(DOM::UpdateLayoutReason::Debugging); - auto* paintable = node->paintable(); + auto paintable = node->paintable(); if (!paintable) return "(no paintable)"_string; diff --git a/Libraries/LibWeb/Layout/AudioBox.cpp b/Libraries/LibWeb/Layout/AudioBox.cpp index aa26fec379..bfdd9d63c8 100644 --- a/Libraries/LibWeb/Layout/AudioBox.cpp +++ b/Libraries/LibWeb/Layout/AudioBox.cpp @@ -33,7 +33,7 @@ bool AudioBox::can_have_children() const return dom_node().shadow_root() != nullptr; } -GC::Ptr AudioBox::create_paintable() const +RefPtr AudioBox::create_paintable() const { return Painting::PaintableBox::create(*this); } diff --git a/Libraries/LibWeb/Layout/AudioBox.h b/Libraries/LibWeb/Layout/AudioBox.h index 14193fe642..bc7c3d3ee7 100644 --- a/Libraries/LibWeb/Layout/AudioBox.h +++ b/Libraries/LibWeb/Layout/AudioBox.h @@ -22,7 +22,7 @@ public: virtual bool can_have_children() const override; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: // Treat the audio element as if it was not a replaced element, sizing based on its content. diff --git a/Libraries/LibWeb/Layout/BlockContainer.cpp b/Libraries/LibWeb/Layout/BlockContainer.cpp index fdd8545b85..6e1663c19b 100644 --- a/Libraries/LibWeb/Layout/BlockContainer.cpp +++ b/Libraries/LibWeb/Layout/BlockContainer.cpp @@ -23,12 +23,13 @@ BlockContainer::BlockContainer(DOM::Document& document, DOM::Node* node, Nonnull BlockContainer::~BlockContainer() = default; -Painting::PaintableWithLines const* BlockContainer::paintable_with_lines() const +RefPtr BlockContainer::paintable_with_lines() const { - return as_if(Box::paintable_box()); + auto paintable_box = Box::paintable_box(); + return as_if(paintable_box.ptr()); } -GC::Ptr BlockContainer::create_paintable() const +RefPtr BlockContainer::create_paintable() const { return Painting::PaintableWithLines::create(*this); } diff --git a/Libraries/LibWeb/Layout/BlockContainer.h b/Libraries/LibWeb/Layout/BlockContainer.h index a816e630fb..cba3753593 100644 --- a/Libraries/LibWeb/Layout/BlockContainer.h +++ b/Libraries/LibWeb/Layout/BlockContainer.h @@ -21,9 +21,9 @@ public: BlockContainer(DOM::Document&, DOM::Node*, NonnullOwnPtr); virtual ~BlockContainer() override; - Painting::PaintableWithLines const* paintable_with_lines() const; + RefPtr paintable_with_lines() const; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_block_container() const final { return true; } diff --git a/Libraries/LibWeb/Layout/Box.cpp b/Libraries/LibWeb/Layout/Box.cpp index 36520c6c14..0509a91858 100644 --- a/Libraries/LibWeb/Layout/Box.cpp +++ b/Libraries/LibWeb/Layout/Box.cpp @@ -48,19 +48,23 @@ void Box::visit_edges(Cell::Visitor& visitor) visitor.visit(m_contained_abspos_children); } -GC::Ptr Box::create_paintable() const +RefPtr Box::create_paintable() const { return Painting::PaintableBox::create(*this); } -Painting::PaintableBox* Box::paintable_box() +RefPtr Box::paintable_box() { - return static_cast(Node::first_paintable()); + if (auto paintable = Node::first_paintable()) + return static_cast(*paintable); + return nullptr; } -Painting::PaintableBox const* Box::paintable_box() const +RefPtr Box::paintable_box() const { - return static_cast(Node::first_paintable()); + if (auto paintable = Node::first_paintable()) + return static_cast(*paintable); + return nullptr; } Optional Box::preferred_aspect_ratio() const diff --git a/Libraries/LibWeb/Layout/Box.h b/Libraries/LibWeb/Layout/Box.h index 99434ee626..aa6ca6eb4e 100644 --- a/Libraries/LibWeb/Layout/Box.h +++ b/Libraries/LibWeb/Layout/Box.h @@ -31,8 +31,8 @@ class WEB_API Box : public NodeWithStyleAndBoxModelMetrics { GC_DECLARE_ALLOCATOR(Box); public: - Painting::PaintableBox const* paintable_box() const; - Painting::PaintableBox* paintable_box(); + RefPtr paintable_box() const; + RefPtr paintable_box(); // https://www.w3.org/TR/css-images-3/#natural-dimensions virtual CSS::SizeWithAspectRatio natural_size() const { return {}; } @@ -53,7 +53,7 @@ public: virtual void did_set_content_size() { } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; void add_contained_abspos_child(GC::Ref child) { m_contained_abspos_children.append(child); } void clear_contained_abspos_children() { m_contained_abspos_children.clear(); } diff --git a/Libraries/LibWeb/Layout/CanvasBox.cpp b/Libraries/LibWeb/Layout/CanvasBox.cpp index 72f1bde0b3..5079fe8131 100644 --- a/Libraries/LibWeb/Layout/CanvasBox.cpp +++ b/Libraries/LibWeb/Layout/CanvasBox.cpp @@ -27,7 +27,7 @@ CSS::SizeWithAspectRatio CanvasBox::compute_auto_content_box_size() const return { width, height, CSSPixelFraction(width, height) }; } -GC::Ptr CanvasBox::create_paintable() const +RefPtr CanvasBox::create_paintable() const { return Painting::CanvasPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/CanvasBox.h b/Libraries/LibWeb/Layout/CanvasBox.h index a2c1271dbe..027bb8c873 100644 --- a/Libraries/LibWeb/Layout/CanvasBox.h +++ b/Libraries/LibWeb/Layout/CanvasBox.h @@ -21,7 +21,7 @@ public: HTML::HTMLCanvasElement const& dom_node() const { return static_cast(*ReplacedBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual CSS::SizeWithAspectRatio compute_auto_content_box_size() const override; diff --git a/Libraries/LibWeb/Layout/CheckBox.cpp b/Libraries/LibWeb/Layout/CheckBox.cpp index d41ed2ceba..4a017d87a9 100644 --- a/Libraries/LibWeb/Layout/CheckBox.cpp +++ b/Libraries/LibWeb/Layout/CheckBox.cpp @@ -20,7 +20,7 @@ CheckBox::CheckBox(DOM::Document& document, HTML::HTMLInputElement& element, GC: CheckBox::~CheckBox() = default; -GC::Ptr CheckBox::create_paintable() const +RefPtr CheckBox::create_paintable() const { return Painting::CheckBoxPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/CheckBox.h b/Libraries/LibWeb/Layout/CheckBox.h index d7f406606a..561d3a3f31 100644 --- a/Libraries/LibWeb/Layout/CheckBox.h +++ b/Libraries/LibWeb/Layout/CheckBox.h @@ -21,7 +21,7 @@ public: private: virtual CSS::SizeWithAspectRatio compute_auto_content_box_size() const override { return { 13, 13, {} }; } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; }; } diff --git a/Libraries/LibWeb/Layout/FieldSetBox.cpp b/Libraries/LibWeb/Layout/FieldSetBox.cpp index d1a938f5bd..4953a7b5ee 100644 --- a/Libraries/LibWeb/Layout/FieldSetBox.cpp +++ b/Libraries/LibWeb/Layout/FieldSetBox.cpp @@ -37,7 +37,7 @@ GC::Ptr FieldSetBox::rendered_legend() const return legend; } -GC::Ptr FieldSetBox::create_paintable() const +RefPtr FieldSetBox::create_paintable() const { return Painting::FieldSetPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/FieldSetBox.h b/Libraries/LibWeb/Layout/FieldSetBox.h index da0ca4b23b..85e81d3933 100644 --- a/Libraries/LibWeb/Layout/FieldSetBox.h +++ b/Libraries/LibWeb/Layout/FieldSetBox.h @@ -25,7 +25,7 @@ public: DOM::Element const& dom_node() const { return static_cast(*BlockContainer::dom_node()); } GC::Ptr rendered_legend() const; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_fieldset_box() const final diff --git a/Libraries/LibWeb/Layout/ImageBox.cpp b/Libraries/LibWeb/Layout/ImageBox.cpp index 1a3f60ef6d..8d1c176a66 100644 --- a/Libraries/LibWeb/Layout/ImageBox.cpp +++ b/Libraries/LibWeb/Layout/ImageBox.cpp @@ -69,7 +69,7 @@ bool ImageBox::renders_as_alt_text() const return !m_image_provider.is_image_available(); } -GC::Ptr ImageBox::create_paintable() const +RefPtr ImageBox::create_paintable() const { return Painting::ImagePaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/ImageBox.h b/Libraries/LibWeb/Layout/ImageBox.h index 7efbb22159..371e700894 100644 --- a/Libraries/LibWeb/Layout/ImageBox.h +++ b/Libraries/LibWeb/Layout/ImageBox.h @@ -21,7 +21,7 @@ public: bool renders_as_alt_text() const; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; auto const& image_provider() const { return m_image_provider; } auto& image_provider() { return m_image_provider; } diff --git a/Libraries/LibWeb/Layout/InlineNode.cpp b/Libraries/LibWeb/Layout/InlineNode.cpp index fc23e9f784..bf76422d3b 100644 --- a/Libraries/LibWeb/Layout/InlineNode.cpp +++ b/Libraries/LibWeb/Layout/InlineNode.cpp @@ -23,11 +23,11 @@ InlineNode::InlineNode(DOM::Document& document, DOM::Element* element, GC::Ref InlineNode::create_paintable_for_line_with_index(size_t line_index) const +NonnullRefPtr InlineNode::create_paintable_for_line_with_index(size_t line_index) const { for (auto const& paintable : paintables()) { - if (is(paintable)) { - auto const& paintable_with_lines = static_cast(paintable); + if (is(*paintable)) { + auto const& paintable_with_lines = static_cast(*paintable); if (paintable_with_lines.line_index() == line_index) { return const_cast(paintable_with_lines); } diff --git a/Libraries/LibWeb/Layout/InlineNode.h b/Libraries/LibWeb/Layout/InlineNode.h index a443468a81..705917bf4d 100644 --- a/Libraries/LibWeb/Layout/InlineNode.h +++ b/Libraries/LibWeb/Layout/InlineNode.h @@ -18,7 +18,7 @@ public: InlineNode(DOM::Document&, DOM::Element*, GC::Ref); virtual ~InlineNode() override; - GC::Ptr create_paintable_for_line_with_index(size_t line_index) const; + NonnullRefPtr create_paintable_for_line_with_index(size_t line_index) const; private: virtual bool is_inline_node() const override { return true; } diff --git a/Libraries/LibWeb/Layout/LayoutState.cpp b/Libraries/LibWeb/Layout/LayoutState.cpp index 9575eed8c8..f424c4ff9c 100644 --- a/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Libraries/LibWeb/Layout/LayoutState.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -189,7 +188,7 @@ static CSSPixelRect measure_scrollable_overflow(Box const& box, ContainedBoxesMa auto overflow_directions = physical_overflow_directions(box); // - All line boxes directly contained by the scroll container. - if (auto const* paintable_with_lines = as_if(box.first_paintable())) { + if (auto first_paintable = box.first_paintable(); auto const* paintable_with_lines = as_if(first_paintable.ptr())) { for (auto const& fragment : paintable_with_lines->fragments()) scrollable_overflow_rect.unite(fragment.absolute_rect()); } @@ -315,11 +314,11 @@ void LayoutState::resolve_relative_positions() auto& node = const_cast(used_values.node()); for (auto& paintable : node.paintables()) { - if (!(is(paintable) && is(paintable.layout_node()))) + auto* inline_paintable = as_if(paintable.ptr()); + if (!inline_paintable || !is(inline_paintable->layout_node())) continue; - auto const& inline_paintable = static_cast(paintable); - for (auto& fragment : inline_paintable.fragments()) { + for (auto& fragment : inline_paintable->fragments()) { auto const& fragment_node = fragment.layout_node(); if (!is(*fragment_node.parent())) continue; @@ -332,7 +331,8 @@ void LayoutState::resolve_relative_positions() break; if (ancestor->computed_values().position() == CSS::Positioning::Relative) { VERIFY(ancestor->first_paintable()); - auto const& ancestor_node = as(*ancestor->first_paintable()); + auto ancestor_paintable = ancestor->first_paintable(); + auto const& ancestor_node = as(*ancestor_paintable); auto const& inset = ancestor_node.box_model().inset; offset.translate_by(inset.left, inset.top); } @@ -343,14 +343,14 @@ void LayoutState::resolve_relative_positions() }); } -static void build_paint_tree(Node& node, Painting::Paintable* parent_paintable = nullptr) +static void build_paint_tree(Node& node, RefPtr parent_paintable = nullptr) { for (auto& paintable : node.paintables()) { - if (parent_paintable && !paintable.forms_unconnected_subtree()) { - VERIFY(!paintable.parent()); + if (parent_paintable && !paintable->forms_unconnected_subtree()) { + VERIFY(!paintable->parent()); parent_paintable->append_child(paintable); } - paintable.set_dom_node(node.dom_node()); + paintable->set_dom_node(node.dom_node()); if (node.dom_node()) node.dom_node()->set_paintable(paintable); } @@ -361,19 +361,19 @@ static void build_paint_tree(Node& node, Painting::Paintable* parent_paintable = void LayoutState::commit(Box& root) { - Painting::Paintable* parent_paintable = nullptr; + RefPtr parent_paintable; if (!root.is_viewport()) { - if (auto* existing = as_if(root.first_paintable())) { - parent_paintable = existing->parent(); + if (auto existing = root.first_paintable(); auto* existing_box = as_if(existing.ptr())) { + parent_paintable = existing_box->parent(); if (parent_paintable) - parent_paintable->remove_child(*existing); + parent_paintable->remove_child(*existing_box); } } // Cache existing paintables before clearing. - GC::RootHashMap> paintable_cache(root.document().heap()); + HashMap> paintable_cache; root.for_each_in_inclusive_subtree([&](Node& node) { - if (auto* paintable_box = as_if(node.first_paintable())) { + if (auto paintable = node.first_paintable(); auto* paintable_box = as_if(paintable.ptr())) { // InlineNodes are excluded because they can span multiple lines, with a separate // InlinePaintable created for each line via create_paintable_for_line_with_index(). // This 1:N relationship between layout node and paintables, combined with the @@ -410,7 +410,7 @@ void LayoutState::commit(Box& root) }); HashTable text_nodes; - HashTable inline_node_paintables; + HashTable> inline_node_paintables; auto transfer_box_model_metrics = [](Painting::BoxModelMetrics& box_model, UsedValues const& used_values) { box_model.inset = { used_values.inset_top, used_values.inset_right, used_values.inset_bottom, used_values.inset_left }; @@ -430,7 +430,7 @@ void LayoutState::commit(Box& root) if (auto const* used_values = try_get(inline_node)) transfer_box_model_metrics(line_paintable->box_model(), *used_values); if (!inline_node_paintables.contains(line_paintable.ptr())) { - inline_node_paintables.set(line_paintable.ptr()); + inline_node_paintables.set(line_paintable); inline_node.add_paintable(line_paintable); } return true; @@ -445,7 +445,7 @@ void LayoutState::commit(Box& root) if (m_subtree_root && !m_subtree_root->is_inclusive_ancestor_of(node)) return; - GC::Ptr paintable; + RefPtr paintable; // Try to reuse cached paintable for Box nodes if (auto cached = paintable_cache.get(&node); cached.has_value()) { @@ -524,7 +524,8 @@ void LayoutState::commit(Box& root) if (!node.is_box()) return; - auto& paintable = as(*node.first_paintable()); + auto paintable_ref = node.first_paintable(); + auto& paintable = as(*paintable_ref); CSSPixelPoint offset; if (used_values.containing_line_box_fragment.has_value()) { @@ -559,7 +560,10 @@ void LayoutState::commit(Box& root) resolve_relative_positions(); // Measure size of paintables created for inline nodes. - for (auto* paintable_with_lines : inline_node_paintables) { + for (auto const& weak_paintable_with_lines : inline_node_paintables) { + auto paintable_with_lines = weak_paintable_with_lines.strong_ref(); + if (!paintable_with_lines) + continue; if (!is(paintable_with_lines->layout_node())) continue; @@ -636,7 +640,7 @@ void LayoutState::commit(Box& root) m_used_values_store.for_each([&](UsedValues& used_values) { auto& node = used_values.node(); for (auto& paintable : node.paintables()) { - auto* paintable_box = as_if(paintable); + auto* paintable_box = as_if(paintable.ptr()); if (!paintable_box) continue; @@ -648,7 +652,7 @@ void LayoutState::commit(Box& root) auto sticky_insets = make(); auto const& inset = node.computed_values().inset(); - auto const* nearest_scrollable_ancestor = paintable_box->nearest_scrollable_ancestor(); + auto nearest_scrollable_ancestor = paintable_box->nearest_scrollable_ancestor(); CSSPixelSize scrollport_size; if (nearest_scrollable_ancestor) scrollport_size = nearest_scrollable_ancestor->absolute_rect().size(); diff --git a/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp b/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp index 9b59cc8f0c..cfb9323345 100644 --- a/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp +++ b/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp @@ -75,7 +75,7 @@ Optional ListItemMarkerBox::text() const }); } -GC::Ptr ListItemMarkerBox::create_paintable() const +RefPtr ListItemMarkerBox::create_paintable() const { return Painting::MarkerPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/ListItemMarkerBox.h b/Libraries/LibWeb/Layout/ListItemMarkerBox.h index 8fa14bb2ba..89de9ca2e3 100644 --- a/Libraries/LibWeb/Layout/ListItemMarkerBox.h +++ b/Libraries/LibWeb/Layout/ListItemMarkerBox.h @@ -24,7 +24,7 @@ public: Optional text() const; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; CSS::ListStyleType const& list_style_type() const { return m_list_style_type; } CSS::ListStylePosition list_style_position() const { return m_list_style_position; } diff --git a/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp b/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp index 3b763a4b1f..0cced7128d 100644 --- a/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp +++ b/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp @@ -48,7 +48,7 @@ void NavigableContainerViewport::did_set_content_size() dom_node().content_navigable()->set_viewport_size(paintable_box()->content_size()); } -GC::Ptr NavigableContainerViewport::create_paintable() const +RefPtr NavigableContainerViewport::create_paintable() const { return Painting::NavigableContainerViewportPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/NavigableContainerViewport.h b/Libraries/LibWeb/Layout/NavigableContainerViewport.h index cefa91cbed..b55bf54cf8 100644 --- a/Libraries/LibWeb/Layout/NavigableContainerViewport.h +++ b/Libraries/LibWeb/Layout/NavigableContainerViewport.h @@ -22,7 +22,7 @@ public: [[nodiscard]] HTML::NavigableContainer const& dom_node() const { return as(*ReplacedBox::dom_node()); } [[nodiscard]] HTML::NavigableContainer& dom_node() { return as(*ReplacedBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual CSS::SizeWithAspectRatio natural_size() const override; diff --git a/Libraries/LibWeb/Layout/Node.cpp b/Libraries/LibWeb/Layout/Node.cpp index 7daecfa145..d9db6c4bed 100644 --- a/Libraries/LibWeb/Layout/Node.cpp +++ b/Libraries/LibWeb/Layout/Node.cpp @@ -59,9 +59,6 @@ void Node::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); visitor.visit(m_dom_node); - for (auto const& paintable : m_paintable) { - visitor.visit(GC::Ptr { &paintable }); - } visitor.visit(m_containing_block); visitor.visit(m_inline_containing_block_if_applicable); visitor.visit(m_pseudo_element_generator); @@ -610,7 +607,7 @@ void NodeWithStyle::ImageObserver::image_style_value_did_update(CSS::ImageStyleV VERIFY(m_owner); for (auto& paintable : m_owner->paintables()) - paintable.set_needs_repaint(); + paintable->set_needs_repaint(); // The body's background propagates to the root element's paintable, which holds the cached draw commands. if (m_owner->is_body()) { @@ -619,7 +616,7 @@ void NodeWithStyle::ImageObserver::image_style_value_did_update(CSS::ImageStyleV if (auto html_layout_node = html_element->unsafe_layout_node()) { if (html_element->should_use_body_background_properties()) { for (auto& paintable : html_layout_node->paintables()) - paintable.set_needs_repaint(); + paintable->set_needs_repaint(); } } } @@ -1256,7 +1253,7 @@ bool NodeWithStyle::is_scroll_container() const || overflow_value_makes_box_a_scroll_container(computed_values().overflow_y()); } -void Node::add_paintable(GC::Ptr paintable) +void Node::add_paintable(RefPtr paintable) { if (!paintable) return; @@ -1265,10 +1262,14 @@ void Node::add_paintable(GC::Ptr paintable) void Node::clear_paintables() { + for (auto& paintable : m_paintable) { + if (paintable->parent()) + paintable->remove(); + } m_paintable.clear(); } -GC::Ptr Node::create_paintable() const +RefPtr Node::create_paintable() const { return nullptr; } diff --git a/Libraries/LibWeb/Layout/Node.h b/Libraries/LibWeb/Layout/Node.h index 9166a569ad..4418706919 100644 --- a/Libraries/LibWeb/Layout/Node.h +++ b/Libraries/LibWeb/Layout/Node.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -65,16 +66,26 @@ public: m_pseudo_element_generator = &element; } - using PaintableList = IntrusiveList<&Painting::Paintable::m_list_node>; + using PaintableList = DoublyLinkedList>; - Painting::Paintable* first_paintable() { return m_paintable.first(); } - Painting::Paintable const* first_paintable() const { return m_paintable.first(); } + RefPtr first_paintable() + { + if (m_paintable.is_empty()) + return nullptr; + return m_paintable.first(); + } + RefPtr first_paintable() const + { + if (m_paintable.is_empty()) + return nullptr; + return m_paintable.first(); + } PaintableList& paintables() { return m_paintable; } PaintableList const& paintables() const { return m_paintable; } - void add_paintable(GC::Ptr); + void add_paintable(RefPtr); void clear_paintables(); - virtual GC::Ptr create_paintable() const; + virtual RefPtr create_paintable() const; DOM::Document& document(); DOM::Document const& document() const; diff --git a/Libraries/LibWeb/Layout/RadioButton.cpp b/Libraries/LibWeb/Layout/RadioButton.cpp index 53b3c60956..57fa36d904 100644 --- a/Libraries/LibWeb/Layout/RadioButton.cpp +++ b/Libraries/LibWeb/Layout/RadioButton.cpp @@ -21,7 +21,7 @@ RadioButton::RadioButton(DOM::Document& document, HTML::HTMLInputElement& elemen RadioButton::~RadioButton() = default; -GC::Ptr RadioButton::create_paintable() const +RefPtr RadioButton::create_paintable() const { return Painting::RadioButtonPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/RadioButton.h b/Libraries/LibWeb/Layout/RadioButton.h index 6db6d4c9a1..482397b597 100644 --- a/Libraries/LibWeb/Layout/RadioButton.h +++ b/Libraries/LibWeb/Layout/RadioButton.h @@ -21,7 +21,7 @@ public: private: CSS::SizeWithAspectRatio compute_auto_content_box_size() const override { return { 12, 12, {} }; } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; }; } diff --git a/Libraries/LibWeb/Layout/SVGClipBox.cpp b/Libraries/LibWeb/Layout/SVGClipBox.cpp index 6896b309f2..5d0c8e1d29 100644 --- a/Libraries/LibWeb/Layout/SVGClipBox.cpp +++ b/Libraries/LibWeb/Layout/SVGClipBox.cpp @@ -17,7 +17,7 @@ SVGClipBox::SVGClipBox(DOM::Document& document, SVG::SVGClipPathElement& element { } -GC::Ptr SVGClipBox::create_paintable() const +RefPtr SVGClipBox::create_paintable() const { return Painting::SVGClipPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGClipBox.h b/Libraries/LibWeb/Layout/SVGClipBox.h index 407892162f..e30f872f7f 100644 --- a/Libraries/LibWeb/Layout/SVGClipBox.h +++ b/Libraries/LibWeb/Layout/SVGClipBox.h @@ -23,7 +23,7 @@ public: SVG::SVGClipPathElement& dom_node() { return as(SVGBox::dom_node()); } SVG::SVGClipPathElement const& dom_node() const { return as(SVGBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_svg_clip_box() const final { return true; } diff --git a/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp b/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp index 6eb8ac9b08..b458ef52df 100644 --- a/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp +++ b/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp @@ -17,7 +17,7 @@ SVGForeignObjectBox::SVGForeignObjectBox(DOM::Document& document, SVG::SVGForeig { } -GC::Ptr SVGForeignObjectBox::create_paintable() const +RefPtr SVGForeignObjectBox::create_paintable() const { return Painting::SVGForeignObjectPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGForeignObjectBox.h b/Libraries/LibWeb/Layout/SVGForeignObjectBox.h index c462c891d3..c8efcb2f91 100644 --- a/Libraries/LibWeb/Layout/SVGForeignObjectBox.h +++ b/Libraries/LibWeb/Layout/SVGForeignObjectBox.h @@ -24,7 +24,7 @@ public: SVG::SVGForeignObjectElement& dom_node() { return static_cast(*BlockContainer::dom_node()); } SVG::SVGForeignObjectElement const& dom_node() const { return static_cast(*BlockContainer::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_svg_foreign_object_box() const override { return true; } diff --git a/Libraries/LibWeb/Layout/SVGGeometryBox.cpp b/Libraries/LibWeb/Layout/SVGGeometryBox.cpp index 1290097058..c3a7c551da 100644 --- a/Libraries/LibWeb/Layout/SVGGeometryBox.cpp +++ b/Libraries/LibWeb/Layout/SVGGeometryBox.cpp @@ -19,7 +19,7 @@ SVGGeometryBox::SVGGeometryBox(DOM::Document& document, SVG::SVGGeometryElement& { } -GC::Ptr SVGGeometryBox::create_paintable() const +RefPtr SVGGeometryBox::create_paintable() const { return Painting::SVGPathPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGGeometryBox.h b/Libraries/LibWeb/Layout/SVGGeometryBox.h index 848a706210..10410772cd 100644 --- a/Libraries/LibWeb/Layout/SVGGeometryBox.h +++ b/Libraries/LibWeb/Layout/SVGGeometryBox.h @@ -23,7 +23,7 @@ public: SVG::SVGGeometryElement& dom_node() { return static_cast(SVGGraphicsBox::dom_node()); } SVG::SVGGeometryElement const& dom_node() const { return static_cast(SVGGraphicsBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_svg_geometry_box() const final { return true; } diff --git a/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp b/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp index fca4156049..0b1af66300 100644 --- a/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp +++ b/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp @@ -17,7 +17,7 @@ SVGGraphicsBox::SVGGraphicsBox(DOM::Document& document, SVG::SVGGraphicsElement& { } -GC::Ptr SVGGraphicsBox::create_paintable() const +RefPtr SVGGraphicsBox::create_paintable() const { return Painting::SVGGraphicsPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGGraphicsBox.h b/Libraries/LibWeb/Layout/SVGGraphicsBox.h index 98e05e0423..539803269f 100644 --- a/Libraries/LibWeb/Layout/SVGGraphicsBox.h +++ b/Libraries/LibWeb/Layout/SVGGraphicsBox.h @@ -24,7 +24,7 @@ public: SVG::SVGGraphicsElement& dom_node() { return as(SVGBox::dom_node()); } SVG::SVGGraphicsElement const& dom_node() const { return as(SVGBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_svg_graphics_box() const override { return true; } diff --git a/Libraries/LibWeb/Layout/SVGImageBox.cpp b/Libraries/LibWeb/Layout/SVGImageBox.cpp index f2c24636d5..18fb066188 100644 --- a/Libraries/LibWeb/Layout/SVGImageBox.cpp +++ b/Libraries/LibWeb/Layout/SVGImageBox.cpp @@ -18,7 +18,7 @@ SVGImageBox::SVGImageBox(DOM::Document& document, SVG::SVGGraphicsElement& eleme { } -GC::Ptr SVGImageBox::create_paintable() const +RefPtr SVGImageBox::create_paintable() const { return Painting::ImagePaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGImageBox.h b/Libraries/LibWeb/Layout/SVGImageBox.h index a4f5b9c5ee..efbca46f3e 100644 --- a/Libraries/LibWeb/Layout/SVGImageBox.h +++ b/Libraries/LibWeb/Layout/SVGImageBox.h @@ -23,7 +23,7 @@ public: SVG::SVGImageElement& dom_node() { return static_cast(SVGGraphicsBox::dom_node()); } SVG::SVGImageElement const& dom_node() const { return static_cast(SVGGraphicsBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; }; } diff --git a/Libraries/LibWeb/Layout/SVGMaskBox.cpp b/Libraries/LibWeb/Layout/SVGMaskBox.cpp index f1ec31d91c..1d96018412 100644 --- a/Libraries/LibWeb/Layout/SVGMaskBox.cpp +++ b/Libraries/LibWeb/Layout/SVGMaskBox.cpp @@ -17,7 +17,7 @@ SVGMaskBox::SVGMaskBox(DOM::Document& document, SVG::SVGMaskElement& element, GC { } -GC::Ptr SVGMaskBox::create_paintable() const +RefPtr SVGMaskBox::create_paintable() const { return Painting::SVGMaskPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGMaskBox.h b/Libraries/LibWeb/Layout/SVGMaskBox.h index fe0ad02728..88cf4e1947 100644 --- a/Libraries/LibWeb/Layout/SVGMaskBox.h +++ b/Libraries/LibWeb/Layout/SVGMaskBox.h @@ -25,7 +25,7 @@ public: SVG::SVGMaskElement& dom_node() { return as(SVGGraphicsBox::dom_node()); } SVG::SVGMaskElement const& dom_node() const { return as(SVGGraphicsBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; }; template<> diff --git a/Libraries/LibWeb/Layout/SVGPatternBox.cpp b/Libraries/LibWeb/Layout/SVGPatternBox.cpp index b163b72e01..662325f3bc 100644 --- a/Libraries/LibWeb/Layout/SVGPatternBox.cpp +++ b/Libraries/LibWeb/Layout/SVGPatternBox.cpp @@ -16,7 +16,7 @@ SVGPatternBox::SVGPatternBox(DOM::Document& document, SVG::SVGPatternElement& el { } -GC::Ptr SVGPatternBox::create_paintable() const +RefPtr SVGPatternBox::create_paintable() const { return Painting::SVGPatternPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGPatternBox.h b/Libraries/LibWeb/Layout/SVGPatternBox.h index 393dba50b1..8921a97d16 100644 --- a/Libraries/LibWeb/Layout/SVGPatternBox.h +++ b/Libraries/LibWeb/Layout/SVGPatternBox.h @@ -22,7 +22,7 @@ public: SVG::SVGPatternElement& dom_node() { return as(SVGBox::dom_node()); } SVG::SVGPatternElement const& dom_node() const { return as(SVGBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_svg_pattern_box() const final { return true; } diff --git a/Libraries/LibWeb/Layout/SVGSVGBox.cpp b/Libraries/LibWeb/Layout/SVGSVGBox.cpp index 6cdabf30e3..d3805ee646 100644 --- a/Libraries/LibWeb/Layout/SVGSVGBox.cpp +++ b/Libraries/LibWeb/Layout/SVGSVGBox.cpp @@ -20,7 +20,7 @@ SVGSVGBox::SVGSVGBox(DOM::Document& document, SVG::SVGSVGElement& element, GC::R { } -GC::Ptr SVGSVGBox::create_paintable() const +RefPtr SVGSVGBox::create_paintable() const { return Painting::SVGSVGPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGSVGBox.h b/Libraries/LibWeb/Layout/SVGSVGBox.h index 300574d579..3eb1525d0c 100644 --- a/Libraries/LibWeb/Layout/SVGSVGBox.h +++ b/Libraries/LibWeb/Layout/SVGSVGBox.h @@ -24,7 +24,7 @@ public: virtual bool can_have_children() const override { return true; } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual CSS::SizeWithAspectRatio natural_size() const override; diff --git a/Libraries/LibWeb/Layout/SVGTextBox.cpp b/Libraries/LibWeb/Layout/SVGTextBox.cpp index c4a77530e2..2a3dcfb0d4 100644 --- a/Libraries/LibWeb/Layout/SVGTextBox.cpp +++ b/Libraries/LibWeb/Layout/SVGTextBox.cpp @@ -17,7 +17,7 @@ SVGTextBox::SVGTextBox(DOM::Document& document, SVG::SVGTextPositioningElement& { } -GC::Ptr SVGTextBox::create_paintable() const +RefPtr SVGTextBox::create_paintable() const { return Painting::SVGPathPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGTextBox.h b/Libraries/LibWeb/Layout/SVGTextBox.h index 0ca7e4c085..79a967372d 100644 --- a/Libraries/LibWeb/Layout/SVGTextBox.h +++ b/Libraries/LibWeb/Layout/SVGTextBox.h @@ -23,7 +23,7 @@ public: SVG::SVGTextPositioningElement& dom_node() { return static_cast(SVGGraphicsBox::dom_node()); } SVG::SVGTextPositioningElement const& dom_node() const { return static_cast(SVGGraphicsBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: CSSPixelPoint viewbox_origin() const; diff --git a/Libraries/LibWeb/Layout/SVGTextPathBox.cpp b/Libraries/LibWeb/Layout/SVGTextPathBox.cpp index 602cc4e013..5e397242f0 100644 --- a/Libraries/LibWeb/Layout/SVGTextPathBox.cpp +++ b/Libraries/LibWeb/Layout/SVGTextPathBox.cpp @@ -16,7 +16,7 @@ SVGTextPathBox::SVGTextPathBox(DOM::Document& document, SVG::SVGTextPathElement& { } -GC::Ptr SVGTextPathBox::create_paintable() const +RefPtr SVGTextPathBox::create_paintable() const { return Painting::SVGPathPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGTextPathBox.h b/Libraries/LibWeb/Layout/SVGTextPathBox.h index 690c577d50..ba38affadf 100644 --- a/Libraries/LibWeb/Layout/SVGTextPathBox.h +++ b/Libraries/LibWeb/Layout/SVGTextPathBox.h @@ -22,7 +22,7 @@ public: SVG::SVGTextPathElement& dom_node() { return static_cast(SVGGraphicsBox::dom_node()); } SVG::SVGTextPathElement const& dom_node() const { return static_cast(SVGGraphicsBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: CSSPixelPoint viewbox_origin() const; diff --git a/Libraries/LibWeb/Layout/TextNode.cpp b/Libraries/LibWeb/Layout/TextNode.cpp index 50cf142b48..5f4392570e 100644 --- a/Libraries/LibWeb/Layout/TextNode.cpp +++ b/Libraries/LibWeb/Layout/TextNode.cpp @@ -804,7 +804,7 @@ Optional TextNode::ChunkIterator::try_commit_chunk(size_t start return {}; } -GC::Ptr TextNode::create_paintable() const +RefPtr TextNode::create_paintable() const { return Painting::TextPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/TextNode.h b/Libraries/LibWeb/Layout/TextNode.h index 366b7099ad..69d497c05d 100644 --- a/Libraries/LibWeb/Layout/TextNode.h +++ b/Libraries/LibWeb/Layout/TextNode.h @@ -83,7 +83,7 @@ public: Unicode::Segmenter& grapheme_segmenter() const; Unicode::Segmenter& line_segmenter() const; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_text_node() const final { return true; } diff --git a/Libraries/LibWeb/Layout/VideoBox.cpp b/Libraries/LibWeb/Layout/VideoBox.cpp index 29e51e408b..f620300455 100644 --- a/Libraries/LibWeb/Layout/VideoBox.cpp +++ b/Libraries/LibWeb/Layout/VideoBox.cpp @@ -44,7 +44,7 @@ CSS::SizeWithAspectRatio VideoBox::natural_size() const return { natural_size->width(), natural_size->height(), natural_size->width() / natural_size->height() }; } -GC::Ptr VideoBox::create_paintable() const +RefPtr VideoBox::create_paintable() const { return Painting::VideoPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/VideoBox.h b/Libraries/LibWeb/Layout/VideoBox.h index 1d65ff665e..c2f57b7c92 100644 --- a/Libraries/LibWeb/Layout/VideoBox.h +++ b/Libraries/LibWeb/Layout/VideoBox.h @@ -21,7 +21,7 @@ public: virtual bool can_have_children() const override; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: VideoBox(DOM::Document&, DOM::Element&, GC::Ref); diff --git a/Libraries/LibWeb/Layout/Viewport.cpp b/Libraries/LibWeb/Layout/Viewport.cpp index 022df27fa5..fef68bb998 100644 --- a/Libraries/LibWeb/Layout/Viewport.cpp +++ b/Libraries/LibWeb/Layout/Viewport.cpp @@ -29,7 +29,7 @@ DOM::Document const& Viewport::dom_node() const return static_cast(*Node::dom_node()); } -GC::Ptr Viewport::create_paintable() const +RefPtr Viewport::create_paintable() const { return Painting::ViewportPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/Viewport.h b/Libraries/LibWeb/Layout/Viewport.h index b76d8a0366..236959a54a 100644 --- a/Libraries/LibWeb/Layout/Viewport.h +++ b/Libraries/LibWeb/Layout/Viewport.h @@ -35,7 +35,7 @@ public: virtual void visit_edges(Visitor&) override; private: - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; void update_text_blocks(); diff --git a/Libraries/LibWeb/Page/AutoScrollHandler.cpp b/Libraries/LibWeb/Page/AutoScrollHandler.cpp index 0737c4f323..7c37fa918f 100644 --- a/Libraries/LibWeb/Page/AutoScrollHandler.cpp +++ b/Libraries/LibWeb/Page/AutoScrollHandler.cpp @@ -120,7 +120,7 @@ CSSPixelPoint AutoScrollHandler::process(CSSPixelPoint mouse_position) GC::Ptr AutoScrollHandler::find_scrollable_ancestor(Painting::Paintable const& paintable) { - auto* paintable_box = paintable.containing_block(); + auto paintable_box = paintable.containing_block(); while (paintable_box) { if (paintable_box->could_be_scrolled_by_wheel_event()) { if (auto* element = as_if(paintable_box->dom_node().ptr())) @@ -141,7 +141,7 @@ GC::Ptr AutoScrollHandler::find_scrollable_ancestor(Painting::Pain // Returns the paintable box that manages the scrollport for an auto-scroll container element. When the element is the // document's scrolling element, the viewport paintable is the scroll container. -GC::Ptr AutoScrollHandler::auto_scroll_paintable(DOM::Element& element) +RefPtr AutoScrollHandler::auto_scroll_paintable(DOM::Element& element) { if (element.document().scrolling_element().ptr() == &element) return element.document().paintable(); diff --git a/Libraries/LibWeb/Page/AutoScrollHandler.h b/Libraries/LibWeb/Page/AutoScrollHandler.h index 455ac4249a..94cf77f71e 100644 --- a/Libraries/LibWeb/Page/AutoScrollHandler.h +++ b/Libraries/LibWeb/Page/AutoScrollHandler.h @@ -25,7 +25,7 @@ public: bool is_active() const { return m_active; } static GC::Ptr find_scrollable_ancestor(Painting::Paintable const&); - static GC::Ptr auto_scroll_paintable(DOM::Element&); + static RefPtr auto_scroll_paintable(DOM::Element&); private: void activate(); diff --git a/Libraries/LibWeb/Page/ElementResizeAction.cpp b/Libraries/LibWeb/Page/ElementResizeAction.cpp index 6df33e0bf6..bfee7d64b4 100644 --- a/Libraries/LibWeb/Page/ElementResizeAction.cpp +++ b/Libraries/LibWeb/Page/ElementResizeAction.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -20,7 +21,7 @@ static Optional containing_block_padding_box_size(Layout::Node con auto parent_box = layout_node.containing_block(); if (!parent_box) return {}; - if (auto const* paintable_box = as_if(parent_box->first_paintable())) + if (auto first_paintable = parent_box->first_paintable(); auto const* paintable_box = as_if(first_paintable.ptr())) return paintable_box->absolute_padding_box_rect().size(); return {}; } @@ -29,14 +30,18 @@ ElementResizeAction::ElementResizeAction(GC::Ref element, CSSPixel : m_element(element) , m_pointer_down_origin(pointer_down_origin) { - auto const* paintable_box = m_element->paintable_box(); + auto paintable_box = element->paintable_box(); if (paintable_box) m_initial_border_box_size = paintable_box->absolute_border_box_rect().size(); } void ElementResizeAction::handle_pointer_move(CSSPixelPoint pointer_position) { - auto const* paintable_box = m_element->paintable_box(); + auto element = m_element.ptr(); + if (!element || !element->is_connected()) + return; + + auto paintable_box = element->paintable_box(); if (!paintable_box) return; auto const& layout_node = paintable_box->layout_node(); @@ -89,7 +94,7 @@ void ElementResizeAction::handle_pointer_move(CSSPixelPoint pointer_position) css_height -= metrics.padding.top + metrics.padding.bottom + computed.border_top().width + computed.border_bottom().width; } - auto style = m_element->style_for_bindings(); + auto style = element->style_for_bindings(); auto width_str = MUST(String::formatted("{:.2f}px", max(0.0, css_width.to_double()))); auto height_str = MUST(String::formatted("{:.2f}px", max(0.0, css_height.to_double()))); @@ -97,9 +102,4 @@ void ElementResizeAction::handle_pointer_move(CSSPixelPoint pointer_position) MUST(style->set_property(CSS::PropertyID::Height, height_str)); } -void ElementResizeAction::visit_edges(GC::Cell::Visitor& visitor) const -{ - visitor.visit(m_element); -} - } diff --git a/Libraries/LibWeb/Page/ElementResizeAction.h b/Libraries/LibWeb/Page/ElementResizeAction.h index 7566f7936e..ca2bb94f26 100644 --- a/Libraries/LibWeb/Page/ElementResizeAction.h +++ b/Libraries/LibWeb/Page/ElementResizeAction.h @@ -6,7 +6,7 @@ #pragma once -#include +#include #include #include @@ -20,10 +20,8 @@ public: void handle_pointer_move(CSSPixelPoint pointer_position); - void visit_edges(GC::Cell::Visitor&) const; - private: - GC::Ref m_element; + GC::Weak m_element; CSSPixelPoint m_pointer_down_origin; CSSPixelSize m_initial_border_box_size; }; diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp index 6cbcee5bec..bde18945d2 100644 --- a/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Libraries/LibWeb/Page/EventHandler.cpp @@ -67,7 +67,7 @@ static GC::Ptr dom_node_for_event_dispatch(Painting::Paintable& paint { if (auto node = paintable.dom_node()) return node; - auto* parent = paintable.parent(); + auto parent = paintable.parent(); while (parent) { if (auto node = parent->dom_node()) return node; @@ -197,9 +197,9 @@ static CSSPixelPoint compute_mouse_event_offset(CSSPixelPoint position, Painting // return the x-coordinate of the position where the event occurred, // ignoring the transforms that apply to the element and its ancestors, CSSPixelPoint offset_position = position; - if (is(paintable)) { - offset_position = static_cast(paintable).inverse_transform_point(position); - } else if (auto* containing_block = paintable.containing_block()) { + if (auto const* paintable_box = as_if(paintable)) { + offset_position = paintable_box->inverse_transform_point(position); + } else if (auto containing_block = paintable.containing_block()) { offset_position = containing_block->inverse_transform_point(position); } @@ -550,14 +550,14 @@ EventHandler::EventHandler(Badge, HTML::Navigable& navigable) EventHandler::~EventHandler() = default; -GC::Ptr EventHandler::paint_root() +RefPtr EventHandler::paint_root() { if (!m_navigable->active_document()) return nullptr; return m_navigable->active_document()->paintable_box(); } -GC::Ptr EventHandler::paint_root() const +RefPtr EventHandler::paint_root() const { if (!m_navigable->active_document()) return nullptr; @@ -587,12 +587,12 @@ EventResult EventHandler::handle_mousewheel(CSSPixelPoint visual_viewport_positi auto handled_event = EventResult::Dropped; - GC::Ptr paintable; + RefPtr paintable; if (auto result = target_for_mouse_position(visual_viewport_position); result.has_value()) paintable = result->paintable; if (paintable) { - Painting::Paintable* containing_block = paintable; + RefPtr containing_block = paintable; while (containing_block) { auto handled_scroll_event = containing_block->handle_mousewheel({}, visual_viewport_position, buttons, modifiers, wheel_delta_x, wheel_delta_y); if (handled_scroll_event) @@ -621,7 +621,9 @@ EventResult EventHandler::handle_mousewheel(CSSPixelPoint visual_viewport_positi return EventResult::Dropped; auto page_offset = compute_mouse_event_page_offset(viewport_position); - auto const& offset_paintable = layout_node->first_paintable() ? layout_node->first_paintable() : paintable.ptr(); + RefPtr offset_paintable = layout_node->first_paintable(); + if (!offset_paintable) + offset_paintable = paintable; auto scroll_offset = document->navigable()->viewport_scroll_offset(); auto offset = compute_mouse_event_offset(visual_viewport_position.translated(scroll_offset), *offset_paintable); bool could_scroll_viewport = document->paintable_box()->could_be_scrolled_by_wheel_event(); @@ -643,7 +645,7 @@ EventResult EventHandler::handle_mousewheel(CSSPixelPoint visual_viewport_positi return handled_event; } -void EventHandler::update_hovered_chrome_widget(GC::Ptr widget) +void EventHandler::update_hovered_chrome_widget(RefPtr widget) { if (m_hovered_chrome_widget == widget) return; @@ -657,13 +659,15 @@ void EventHandler::update_hovered_chrome_widget(GC::Ptr EventHandler::MouseEventCoordinates EventHandler::compute_mouse_event_coordinates(CSSPixelPoint visual_viewport_position, CSSPixelPoint viewport_position, Painting::Paintable const& paintable, Layout::Node const& layout_node) const { auto page_offset = compute_mouse_event_page_offset(viewport_position); - auto const& offset_paintable = layout_node.first_paintable() ? layout_node.first_paintable() : &paintable; + RefPtr offset_paintable = layout_node.first_paintable(); + if (!offset_paintable) + offset_paintable = paintable; auto scroll_offset = m_navigable->active_document()->navigable()->viewport_scroll_offset(); auto offset = compute_mouse_event_offset(visual_viewport_position.translated(scroll_offset), *offset_paintable); return { page_offset, visual_viewport_position, viewport_position, offset }; } -bool EventHandler::dispatch_chrome_widget_pointer_event(GC::Ptr target, FlyString const& type, unsigned button, CSSPixelPoint visual_viewport_position) +bool EventHandler::dispatch_chrome_widget_pointer_event(RefPtr target, FlyString const& type, unsigned button, CSSPixelPoint visual_viewport_position) { bool allow_default_behavior = true; @@ -688,7 +692,7 @@ bool EventHandler::dispatch_chrome_widget_pointer_event(GC::Ptr node, GC::Ptr chrome_widget, MouseEventCoordinates const& coordinates, CSSPixelPoint screen_position, CSSPixelPoint movement, unsigned button, unsigned buttons, unsigned modifiers, int click_count) +bool EventHandler::dispatch_a_pointer_event_for_a_device_that_supports_hover(PointerEventType type, GC::Ptr node, RefPtr chrome_widget, MouseEventCoordinates const& coordinates, CSSPixelPoint screen_position, CSSPixelPoint movement, unsigned button, unsigned buttons, unsigned modifiers, int click_count) { auto& document = *m_navigable->active_document(); auto& realm = document.realm(); @@ -837,7 +841,7 @@ static void set_page_cursor(Page& page, Gfx::Cursor cursor) } } -void EventHandler::update_cursor(GC::Ptr paintable, GC::Ptr host_element, GC::Ptr chrome_widget) +void EventHandler::update_cursor(RefPtr paintable, GC::Ptr host_element, RefPtr chrome_widget) { // AD-HOC: Update the cursor image based on the CSS rules before the steps terminate if the target hasn't changed. auto cursor = [&] -> Gfx::Cursor { @@ -1036,8 +1040,8 @@ EventResult EventHandler::handle_mouseup(CSSPixelPoint visual_viewport_position, if (!paint_root()) return EventResult::Dropped; - GC::Ptr paintable; - GC::Ptr chrome_widget; + RefPtr paintable; + RefPtr chrome_widget; if (auto result = target_for_mouse_position(visual_viewport_position); result.has_value()) { paintable = result->paintable; chrome_widget = result->chrome_widget; @@ -1140,11 +1144,11 @@ bool EventHandler::initiate_character_selection(DOM::Document& document, Paintin bool EventHandler::initiate_word_selection(DOM::Document& document, Painting::HitTestResult const& hit, CSS::UserSelect user_select) { - if (!is(*hit.paintable)) + auto* hit_paintable = as_if(*hit.paintable); + if (!hit_paintable) return false; - auto& hit_paintable = static_cast(*hit.paintable); - auto& hit_node = as(*hit_paintable.dom_node()); + auto& hit_node = as(*hit_paintable->dom_node()); size_t previous_boundary = 0; size_t next_boundary = 0; @@ -1153,7 +1157,7 @@ bool EventHandler::initiate_word_selection(DOM::Document& document, Painting::Hi next_boundary = hit_node.length_in_utf16_code_units(); } else { auto& segmenter = word_segmenter(); - segmenter.set_segmented_text(hit_paintable.layout_node().text_for_rendering()); + segmenter.set_segmented_text(hit_paintable->layout_node().text_for_rendering()); previous_boundary = segmenter.previous_boundary(hit.index_in_node, Unicode::Segmenter::Inclusive::Yes).value_or(0); next_boundary = segmenter.next_boundary(hit.index_in_node).value_or(hit_node.length()); @@ -1310,8 +1314,8 @@ EventResult EventHandler::handle_mousedown(CSSPixelPoint visual_viewport_positio GC::Ptr node; - GC::Ptr paintable; - GC::Ptr chrome_widget; + RefPtr paintable; + RefPtr chrome_widget; if (auto result = target_for_mouse_position(visual_viewport_position); result.has_value()) { paintable = result->paintable; chrome_widget = result->chrome_widget; @@ -1427,8 +1431,8 @@ EventResult EventHandler::handle_mousemove(CSSPixelPoint visual_viewport_positio } } - GC::Ptr paintable; - GC::Ptr chrome_widget; + RefPtr paintable; + RefPtr chrome_widget; Optional start_index; if (auto result = target_for_mouse_position(visual_viewport_position); result.has_value()) { @@ -1556,7 +1560,7 @@ EventResult EventHandler::handle_drag_and_drop_event(DragEvent::Type type, CSSPi if (!paint_root()) return EventResult::Dropped; - GC::Ptr paintable; + RefPtr paintable; if (auto result = target_for_mouse_position(visual_viewport_position); result.has_value()) paintable = result->paintable; else @@ -1678,7 +1682,7 @@ GC::Ptr EventHandler::focus_candidate_for_position(CSSPixelPoint visu if (!exact_hit.has_value()) return {}; - auto focus_dom_node = exact_hit->paintable ? exact_hit->paintable->dom_node() : nullptr; + auto focus_dom_node = exact_hit->paintable->dom_node(); while (focus_dom_node && !focus_dom_node->is_focusable()) focus_dom_node = focus_dom_node->parent_or_shadow_host(); @@ -2151,8 +2155,6 @@ bool EventHandler::should_ignore_device_input_event() const void EventHandler::visit_edges(JS::Cell::Visitor& visitor) const { m_drag_and_drop_event_handler->visit_edges(visitor); - visitor.visit(m_hovered_chrome_widget); - visitor.visit(m_captured_chrome_widget); if (m_mouse_selection_target) visitor.visit(m_mouse_selection_target->as_cell()); visitor.visit(m_selection_origin); diff --git a/Libraries/LibWeb/Page/EventHandler.h b/Libraries/LibWeb/Page/EventHandler.h index e3a8b78965..653fff582b 100644 --- a/Libraries/LibWeb/Page/EventHandler.h +++ b/Libraries/LibWeb/Page/EventHandler.h @@ -92,8 +92,8 @@ private: CSSPixelPoint compute_mouse_event_movement(CSSPixelPoint screen_position) const; struct Target { - GC::Ptr paintable; - GC::Ptr chrome_widget; + RefPtr paintable; + RefPtr chrome_widget; Optional index_in_node; }; Optional target_for_mouse_position(CSSPixelPoint position); @@ -112,11 +112,11 @@ private: PointerMove, PointerCancel }; - bool dispatch_a_pointer_event_for_a_device_that_supports_hover(PointerEventType, GC::Ptr, GC::Ptr, MouseEventCoordinates const&, CSSPixelPoint screen_position, CSSPixelPoint movement, unsigned button, unsigned buttons, unsigned modifiers, int click_count = 0); + bool dispatch_a_pointer_event_for_a_device_that_supports_hover(PointerEventType, GC::Ptr, RefPtr, MouseEventCoordinates const&, CSSPixelPoint screen_position, CSSPixelPoint movement, unsigned button, unsigned buttons, unsigned modifiers, int click_count = 0); void track_the_effective_position_of_the_legacy_mouse_pointer(GC::Ptr); - void update_cursor(GC::Ptr paintable, GC::Ptr host_element, GC::Ptr chrome_widget); - bool dispatch_chrome_widget_pointer_event(GC::Ptr, FlyString const& type, unsigned button, CSSPixelPoint visual_viewport_position); - void update_hovered_chrome_widget(GC::Ptr); + void update_cursor(RefPtr paintable, GC::Ptr host_element, RefPtr chrome_widget); + bool dispatch_chrome_widget_pointer_event(RefPtr, FlyString const& type, unsigned button, CSSPixelPoint visual_viewport_position); + void update_hovered_chrome_widget(RefPtr); bool fire_click_events(GC::Ref, MouseEventCoordinates const&, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, int click_count); void run_activation_behavior(GC::Ref, unsigned button, unsigned modifiers); void maybe_show_context_menu(GC::Ref, MouseEventCoordinates const&, CSSPixelPoint screen_position, CSSPixelPoint viewport_position, unsigned buttons, unsigned modifiers); @@ -126,8 +126,8 @@ private: void update_mouse_selection(CSSPixelPoint visual_viewport_position); void apply_mouse_selection(CSSPixelPoint visual_viewport_position); - GC::Ptr paint_root(); - GC::Ptr paint_root() const; + RefPtr paint_root(); + RefPtr paint_root() const; bool should_ignore_device_input_event() const; @@ -141,8 +141,8 @@ private: InputEventsTarget* m_mouse_selection_target { nullptr }; GC::Ptr m_selection_origin; - GC::Ptr m_hovered_chrome_widget; - GC::Ptr m_captured_chrome_widget; + RefPtr m_hovered_chrome_widget; + RefPtr m_captured_chrome_widget; NonnullOwnPtr m_drag_and_drop_event_handler; diff --git a/Libraries/LibWeb/Page/MiddleButtonScrollHandler.cpp b/Libraries/LibWeb/Page/MiddleButtonScrollHandler.cpp index bb1ec10346..c11c0aa417 100644 --- a/Libraries/LibWeb/Page/MiddleButtonScrollHandler.cpp +++ b/Libraries/LibWeb/Page/MiddleButtonScrollHandler.cpp @@ -25,7 +25,7 @@ MiddleButtonScrollHandler::MiddleButtonScrollHandler(DOM::Element& container, CS , m_origin(origin) , m_mouse_position(origin) { - if (auto* paintable = m_container_element->document().paintable()) + if (auto paintable = m_container_element->document().paintable()) paintable->set_needs_repaint(); } @@ -33,7 +33,7 @@ MiddleButtonScrollHandler::~MiddleButtonScrollHandler() { if (!m_container_element->document().layout_is_up_to_date()) return; - if (auto* paintable = m_container_element->document().paintable()) + if (auto paintable = m_container_element->document().paintable()) paintable->set_needs_repaint(); } diff --git a/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Libraries/LibWeb/Painting/BackgroundPainting.cpp index f209a08dbd..61b81b18e8 100644 --- a/Libraries/LibWeb/Painting/BackgroundPainting.cpp +++ b/Libraries/LibWeb/Painting/BackgroundPainting.cpp @@ -30,7 +30,7 @@ static void append_text_clip_paths(DisplayListRecordingContext& context, Paintab if (!layout_node.is_in_flow() && !layout_node.is_floating()) return TraversalDecision::SkipChildrenAndContinue; } - if (auto* paintable_lines = as_if(sub_paintable)) { + if (auto const* paintable_lines = as_if(sub_paintable)) { for (auto const& fragment : paintable_lines->fragments()) { if (!is(fragment.layout_node())) continue; diff --git a/Libraries/LibWeb/Painting/CanvasPaintable.cpp b/Libraries/LibWeb/Painting/CanvasPaintable.cpp index f8df497b9c..e2c9035607 100644 --- a/Libraries/LibWeb/Painting/CanvasPaintable.cpp +++ b/Libraries/LibWeb/Painting/CanvasPaintable.cpp @@ -9,11 +9,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(CanvasPaintable); - -GC::Ref CanvasPaintable::create(Layout::CanvasBox const& layout_box) +NonnullRefPtr CanvasPaintable::create(Layout::CanvasBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new CanvasPaintable(layout_box)); } CanvasPaintable::CanvasPaintable(Layout::CanvasBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/CanvasPaintable.h b/Libraries/LibWeb/Painting/CanvasPaintable.h index 86164239ac..1583b53322 100644 --- a/Libraries/LibWeb/Painting/CanvasPaintable.h +++ b/Libraries/LibWeb/Painting/CanvasPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class CanvasPaintable final : public PaintableBox { - GC_CELL(CanvasPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(CanvasPaintable); - public: - static GC::Ref create(Layout::CanvasBox const&); + static NonnullRefPtr create(Layout::CanvasBox const&); + virtual StringView class_name() const override { return "CanvasPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp b/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp index a69bb15b5e..f5d85f5c58 100644 --- a/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp +++ b/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp @@ -15,8 +15,6 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(CheckBoxPaintable); - static Gfx::Path check_mark_path(Gfx::IntRect checkbox_rect) { Gfx::Path path; @@ -35,10 +33,10 @@ static Gfx::Path check_mark_path(Gfx::IntRect checkbox_rect) return path.copy_transformed(scale_checkmark_to_fit); } -GC::Ref +NonnullRefPtr CheckBoxPaintable::create(Layout::CheckBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new CheckBoxPaintable(layout_box)); } CheckBoxPaintable::CheckBoxPaintable(Layout::CheckBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/CheckBoxPaintable.h b/Libraries/LibWeb/Painting/CheckBoxPaintable.h index 5125bcc30b..7606811042 100644 --- a/Libraries/LibWeb/Painting/CheckBoxPaintable.h +++ b/Libraries/LibWeb/Painting/CheckBoxPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class CheckBoxPaintable final : public PaintableBox { - GC_CELL(CheckBoxPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(CheckBoxPaintable); - public: - static GC::Ref create(Layout::CheckBox const&); + static NonnullRefPtr create(Layout::CheckBox const&); + virtual StringView class_name() const override { return "CheckBoxPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/ChromeWidget.h b/Libraries/LibWeb/Painting/ChromeWidget.h index f92c29cf73..aef095728b 100644 --- a/Libraries/LibWeb/Painting/ChromeWidget.h +++ b/Libraries/LibWeb/Painting/ChromeWidget.h @@ -7,6 +7,8 @@ #pragma once #include +#include +#include #include #include #include @@ -22,10 +24,12 @@ enum class MouseAction : u8 { AK_ENUM_BITWISE_OPERATORS(MouseAction); -class ChromeWidget : public JS::Cell { - GC_CELL(ChromeWidget, JS::Cell); - +class ChromeWidget + : public RefCounted + , public Weakable { public: + virtual ~ChromeWidget() = default; + virtual MouseAction handle_pointer_event(FlyString const& type, unsigned button, CSSPixelPoint visual_viewport_position) = 0; virtual void mouse_enter() = 0; virtual void mouse_leave() = 0; diff --git a/Libraries/LibWeb/Painting/FieldSetPaintable.cpp b/Libraries/LibWeb/Painting/FieldSetPaintable.cpp index 1c712b8383..0e191b0bc8 100644 --- a/Libraries/LibWeb/Painting/FieldSetPaintable.cpp +++ b/Libraries/LibWeb/Painting/FieldSetPaintable.cpp @@ -11,11 +11,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(FieldSetPaintable); - -GC::Ref FieldSetPaintable::create(Layout::FieldSetBox const& layout_box) +NonnullRefPtr FieldSetPaintable::create(Layout::FieldSetBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new FieldSetPaintable(layout_box)); } FieldSetPaintable::FieldSetPaintable(Layout::FieldSetBox const& layout_box) @@ -41,7 +39,7 @@ CSSPixels FieldSetPaintable::effective_border_top() const // whichever is greater. auto css_border_top = computed_values().border_top().width; if (auto legend = layout_box().rendered_legend()) { - auto const* legend_paintable = legend->paintable_box(); + auto legend_paintable = legend->paintable_box(); auto legend_margin_box_height = legend_paintable->box_model().margin.top + legend_paintable->absolute_border_box_rect().height() + legend_paintable->box_model().margin.bottom; @@ -90,7 +88,7 @@ void FieldSetPaintable::paint(DisplayListRecordingContext& context, PaintPhase p return; } - auto const* legend_paintable = legend->paintable_box(); + auto legend_paintable = legend->paintable_box(); auto legend_border_rect = context.rounded_device_rect(legend_paintable->absolute_border_box_rect()); diff --git a/Libraries/LibWeb/Painting/FieldSetPaintable.h b/Libraries/LibWeb/Painting/FieldSetPaintable.h index f7528fe745..d0bcd795f1 100644 --- a/Libraries/LibWeb/Painting/FieldSetPaintable.h +++ b/Libraries/LibWeb/Painting/FieldSetPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class FieldSetPaintable final : public PaintableBox { - GC_CELL(FieldSetPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(FieldSetPaintable); - public: - static GC::Ref create(Layout::FieldSetBox const&); + static NonnullRefPtr create(Layout::FieldSetBox const&); + virtual StringView class_name() const override { return "FieldSetPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; virtual void paint_background(DisplayListRecordingContext&) const override; diff --git a/Libraries/LibWeb/Painting/ImagePaintable.cpp b/Libraries/LibWeb/Painting/ImagePaintable.cpp index ff38ebd6a9..0707a162c7 100644 --- a/Libraries/LibWeb/Painting/ImagePaintable.cpp +++ b/Libraries/LibWeb/Painting/ImagePaintable.cpp @@ -16,19 +16,17 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(ImagePaintable); - -GC::Ref ImagePaintable::create(Layout::SVGImageBox const& layout_box) +NonnullRefPtr ImagePaintable::create(Layout::SVGImageBox const& layout_box) { - return layout_box.heap().allocate(layout_box, layout_box.dom_node(), false, String {}, true); + return adopt_ref(*new ImagePaintable(layout_box, layout_box.dom_node(), false, String {}, true)); } -GC::Ref ImagePaintable::create(Layout::ImageBox const& layout_box) +NonnullRefPtr ImagePaintable::create(Layout::ImageBox const& layout_box) { String alt; if (auto element = layout_box.dom_node()) alt = element->get_attribute_value(HTML::AttributeNames::alt); - return layout_box.heap().allocate(layout_box, layout_box.image_provider(), layout_box.renders_as_alt_text(), move(alt), false); + return adopt_ref(*new ImagePaintable(layout_box, layout_box.image_provider(), layout_box.renders_as_alt_text(), move(alt), false)); } ImagePaintable::ImagePaintable(Layout::Box const& layout_box, Layout::ImageProvider const& image_provider, bool renders_as_alt_text, String alt_text, bool is_svg_image) @@ -40,12 +38,6 @@ ImagePaintable::ImagePaintable(Layout::Box const& layout_box, Layout::ImageProvi { } -void ImagePaintable::visit_edges(JS::Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - m_image_provider.image_provider_visit_edges(visitor); -} - void ImagePaintable::reset_for_relayout() { PaintableBox::reset_for_relayout(); diff --git a/Libraries/LibWeb/Painting/ImagePaintable.h b/Libraries/LibWeb/Painting/ImagePaintable.h index 852fe56a48..4bfcd7e813 100644 --- a/Libraries/LibWeb/Painting/ImagePaintable.h +++ b/Libraries/LibWeb/Painting/ImagePaintable.h @@ -13,20 +13,15 @@ namespace Web::Painting { class ImagePaintable final : public PaintableBox { - GC_CELL(ImagePaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(ImagePaintable); - public: - static GC::Ref create(Layout::ImageBox const& layout_box); - static GC::Ref create(Layout::SVGImageBox const& layout_box); + static NonnullRefPtr create(Layout::ImageBox const& layout_box); + static NonnullRefPtr create(Layout::SVGImageBox const& layout_box); + virtual StringView class_name() const override { return "ImagePaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; virtual void reset_for_relayout() override; private: - // ^JS::Cell - virtual void visit_edges(Visitor&) override; - ImagePaintable(Layout::Box const& layout_box, Layout::ImageProvider const& image_provider, bool renders_as_alt_text, String alt_text, bool is_svg_image); bool m_renders_as_alt_text { false }; diff --git a/Libraries/LibWeb/Painting/MarkerPaintable.cpp b/Libraries/LibWeb/Painting/MarkerPaintable.cpp index 368ab31505..03e6ca48a6 100644 --- a/Libraries/LibWeb/Painting/MarkerPaintable.cpp +++ b/Libraries/LibWeb/Painting/MarkerPaintable.cpp @@ -12,11 +12,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(MarkerPaintable); - -GC::Ref MarkerPaintable::create(Layout::ListItemMarkerBox const& layout_box) +NonnullRefPtr MarkerPaintable::create(Layout::ListItemMarkerBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new MarkerPaintable(layout_box)); } MarkerPaintable::MarkerPaintable(Layout::ListItemMarkerBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/MarkerPaintable.h b/Libraries/LibWeb/Painting/MarkerPaintable.h index cd4744f2c5..f0a9d3930c 100644 --- a/Libraries/LibWeb/Painting/MarkerPaintable.h +++ b/Libraries/LibWeb/Painting/MarkerPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class MarkerPaintable final : public PaintableBox { - GC_CELL(MarkerPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(MarkerPaintable); - public: - static GC::Ref create(Layout::ListItemMarkerBox const&); + static NonnullRefPtr create(Layout::ListItemMarkerBox const&); + virtual StringView class_name() const override { return "MarkerPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.cpp b/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.cpp index fc4a586a62..6bff780797 100644 --- a/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.cpp +++ b/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.cpp @@ -16,11 +16,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(NavigableContainerViewportPaintable); - -GC::Ref NavigableContainerViewportPaintable::create(Layout::NavigableContainerViewport const& layout_box) +NonnullRefPtr NavigableContainerViewportPaintable::create(Layout::NavigableContainerViewport const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new NavigableContainerViewportPaintable(layout_box)); } NavigableContainerViewportPaintable::NavigableContainerViewportPaintable(Layout::NavigableContainerViewport const& layout_box) diff --git a/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.h b/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.h index 4f35494943..5f0379eaf0 100644 --- a/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.h +++ b/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.h @@ -12,13 +12,11 @@ namespace Web::Painting { class NavigableContainerViewportPaintable final : public PaintableBox { - GC_CELL(NavigableContainerViewportPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(NavigableContainerViewportPaintable); - public: virtual bool is_navigable_container_viewport_paintable() const override { return true; } - static GC::Ref create(Layout::NavigableContainerViewport const&); + static NonnullRefPtr create(Layout::NavigableContainerViewport const&); + virtual StringView class_name() const override { return "NavigableContainerViewportPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/Paintable.cpp b/Libraries/LibWeb/Painting/Paintable.cpp index b4f21c6dcc..2c43415b0c 100644 --- a/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Libraries/LibWeb/Painting/Paintable.cpp @@ -46,22 +46,6 @@ Paintable::Paintable(Layout::Node const& layout_node) Paintable::~Paintable() = default; -void Paintable::finalize() -{ - Base::finalize(); - if (m_list_node.is_in_list()) - m_list_node.remove(); -} - -void Paintable::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - TreeNode::visit_edges(visitor); - visitor.visit(m_dom_node); - visitor.visit(m_layout_node); - visitor.visit(m_containing_block); -} - String Paintable::debug_description() const { return MUST(String::formatted("{}({})", class_name(), layout_node().debug_description())); @@ -77,19 +61,29 @@ DOM::Document& Paintable::document() return layout_node().document(); } -PaintableBox* Paintable::containing_block() const +RefPtr Paintable::containing_block() const { - return m_containing_block.ensure([&] -> GC::Ptr { - auto containing_layout_box = m_layout_node->containing_block(); + if (m_containing_block.has_value()) { + if (auto containing_block = m_containing_block->strong_ref()) + return containing_block; + } + + auto containing_block = [&] -> RefPtr { + auto containing_layout_box = layout_node().containing_block(); if (!containing_layout_box) return nullptr; - return const_cast(containing_layout_box->paintable_box()); - }); + auto paintable_box = containing_layout_box->paintable_box(); + if (!paintable_box) + return nullptr; + return const_cast(*paintable_box); + }(); + m_containing_block = containing_block; + return containing_block; } CSS::ImmutableComputedValues const& Paintable::computed_values() const { - return m_layout_node->computed_values(); + return layout_node().computed_values(); } bool Paintable::visible_for_hit_testing() const @@ -101,17 +95,17 @@ bool Paintable::visible_for_hit_testing() const void Paintable::set_dom_node(GC::Ptr dom_node) { - m_dom_node = dom_node; + m_dom_node = dom_node.ptr(); } GC::Ptr Paintable::dom_node() { - return m_dom_node; + return m_dom_node.ptr(); } GC::Ptr Paintable::dom_node() const { - return m_dom_node; + return m_dom_node.ptr(); } GC::Ptr Paintable::navigable() const @@ -131,18 +125,19 @@ TraversalDecision Paintable::hit_test(CSSPixelPoint, HitTestType, Function(*this).stacking_context(); + if (auto const* paintable_box = as_if(this)) + return paintable_box->stacking_context(); return false; } -StackingContext* Paintable::enclosing_stacking_context() +RefPtr Paintable::enclosing_stacking_context() { - for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { - if (!ancestor->is_paintable_box()) + for (auto ancestor = parent(); ancestor; ancestor = ancestor->parent()) { + auto* paintable_box = as_if(ancestor.ptr()); + if (!paintable_box) continue; - if (auto* stacking_context = static_cast(*ancestor).stacking_context()) - return const_cast(stacking_context); + if (auto stacking_context = paintable_box->stacking_context()) + return stacking_context; } // We should always reach the viewport's stacking context. VERIFY_NOT_REACHED(); @@ -151,12 +146,16 @@ StackingContext* Paintable::enclosing_stacking_context() void Paintable::paint_inspector_overlay(DisplayListRecordingContext& context) const { auto& display_list_recorder = context.display_list_recorder(); - auto const* paintable_box = as_if(this); - if (!paintable_box) + RefPtr paintable_box; + if (is(*this)) + paintable_box = static_cast(*this); + else paintable_box = first_ancestor_of_type(); if (paintable_box) { - auto& visual_context_tree = const_cast(document().paintable())->visual_context_tree(); + auto viewport_paintable = document().paintable(); + VERIFY(viewport_paintable); + auto& visual_context_tree = const_cast(*viewport_paintable).visual_context_tree(); auto visual_context_index = paintable_box->accumulated_visual_context_index(); if (visual_context_index.value()) { @@ -189,7 +188,7 @@ void Paintable::paint_inspector_overlay(DisplayListRecordingContext& context) co void Paintable::set_needs_repaint(InvalidateDisplayList should_invalidate_display_list) { if (should_invalidate_display_list == InvalidateDisplayList::Yes) { - if (auto* containing_block = this->containing_block()) + if (auto containing_block = this->containing_block()) containing_block->invalidate_paint_cache(); } document().set_needs_repaint(Badge {}, should_invalidate_display_list); @@ -197,13 +196,13 @@ void Paintable::set_needs_repaint(InvalidateDisplayList should_invalidate_displa CSSPixelPoint Paintable::box_type_agnostic_position() const { - if (is_paintable_box()) - return static_cast(this)->absolute_position(); + if (auto const* paintable_box = as_if(this)) + return paintable_box->absolute_position(); VERIFY(is_inline()); CSSPixelPoint position; - if (auto const* block = containing_block(); block && is(*block)) { + if (auto block = containing_block(); block && is(*block)) { auto const& fragments = static_cast(*block).fragments(); if (!fragments.is_empty()) { position = fragments[0].absolute_rect().location(); @@ -352,11 +351,11 @@ void Paintable::set_selection_state(SelectionState state) m_selection_state = state; if (auto* box = as_if(this)) { box->invalidate_paint_cache(); - } else if (auto* containing_block = this->containing_block()) { + } else if (auto containing_block = this->containing_block()) { containing_block->invalidate_paint_cache(); for (auto const* ancestor = layout_node().parent(); ancestor && ancestor != &containing_block->layout_node(); ancestor = ancestor->parent()) { for (auto& paintable : ancestor->paintables()) { - if (auto* ancestor_box = as_if(paintable)) + if (auto* ancestor_box = as_if(paintable.ptr())) ancestor_box->invalidate_paint_cache(); } } @@ -366,11 +365,12 @@ void Paintable::set_selection_state(SelectionState state) void Paintable::scroll_ancestor_to_offset_into_view(size_t offset) { // Walk up to find the containing PaintableWithLines. - GC::Ptr paintable_with_lines; - for (auto* ancestor = this; ancestor; ancestor = ancestor->parent()) { - paintable_with_lines = as_if(*ancestor); - if (paintable_with_lines) + RefPtr paintable_with_lines; + for (RefPtr ancestor = *this; ancestor; ancestor = ancestor->parent()) { + if (auto* ancestor_lines = as_if(*ancestor)) { + paintable_with_lines = *ancestor_lines; break; + } } if (!paintable_with_lines) return; @@ -385,7 +385,7 @@ void Paintable::scroll_ancestor_to_offset_into_view(size_t offset) auto cursor_rect = fragment.range_rect(SelectionState::StartAndEnd, offset, offset); // Walk up the containing block chain to find the nearest scrollable ancestor. - for (auto* ancestor = containing_block(); ancestor; ancestor = ancestor->containing_block()) { + for (auto ancestor = containing_block(); ancestor; ancestor = ancestor->containing_block()) { if (ancestor->has_scrollable_overflow()) { ancestor->scroll_into_view(cursor_rect); break; diff --git a/Libraries/LibWeb/Painting/Paintable.h b/Libraries/LibWeb/Painting/Paintable.h index fc5ed12d3b..f62348692b 100644 --- a/Libraries/LibWeb/Painting/Paintable.h +++ b/Libraries/LibWeb/Painting/Paintable.h @@ -6,8 +6,11 @@ #pragma once +#include +#include +#include #include -#include +#include #include #include #include @@ -15,8 +18,8 @@ #include #include #include +#include #include -#include namespace Web::Painting { @@ -32,8 +35,8 @@ enum class PaintPhase { }; struct HitTestResult { - GC::Root paintable; - GC::Ptr chrome_widget {}; + NonnullRefPtr paintable; + RefPtr chrome_widget {}; size_t index_in_node { 0 }; Optional vertical_distance {}; Optional horizontal_distance {}; @@ -55,15 +58,15 @@ enum class HitTestType { }; class WEB_API Paintable - : public JS::Cell - , public TreeNode { - GC_CELL(Paintable, JS::Cell); + : public RefCounted + , public Weakable + , public RefCountedTreeNode { public: - static constexpr bool OVERRIDES_FINALIZE = true; - virtual ~Paintable(); + virtual StringView class_name() const { return "Paintable"sv; } + void detach_from_layout_node(); [[nodiscard]] bool is_visible() const @@ -80,7 +83,7 @@ public: [[nodiscard]] CSS::Display display() const { return m_display; } bool has_stacking_context() const; - StackingContext* enclosing_stacking_context(); + RefPtr enclosing_stacking_context(); virtual void paint(DisplayListRecordingContext&, PaintPhase) const { } void paint_inspector_overlay(DisplayListRecordingContext&) const; @@ -91,8 +94,12 @@ public: virtual bool handle_mousewheel(Badge, CSSPixelPoint, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y); - Layout::Node const& layout_node() const { return m_layout_node; } - Layout::Node& layout_node() { return const_cast(*m_layout_node); } + Layout::Node const& layout_node() const + { + VERIFY(m_layout_node); + return *m_layout_node; + } + Layout::Node& layout_node() { return const_cast(const_cast(*this).layout_node()); } [[nodiscard]] GC::Ptr dom_node(); [[nodiscard]] GC::Ptr dom_node() const; @@ -106,7 +113,7 @@ public: virtual void set_needs_repaint(InvalidateDisplayList = InvalidateDisplayList::Yes); - PaintableBox* containing_block() const; + RefPtr containing_block() const; template bool fast_is() const = delete; @@ -160,22 +167,17 @@ public: [[nodiscard]] String debug_description() const; - virtual void finalize() override; - friend class Layout::Node; protected: explicit Paintable(Layout::Node const&); virtual void paint_inspector_overlay_internal(DisplayListRecordingContext&) const { } - virtual void visit_edges(Cell::Visitor&) override; - - Optional> mutable m_containing_block; + Optional> mutable m_containing_block; private: - IntrusiveListNode m_list_node; - GC::Ptr m_dom_node; - GC::Ref m_layout_node; + GC::Weak m_dom_node; + GC::Weak m_layout_node; SelectionState m_selection_state { SelectionState::None }; diff --git a/Libraries/LibWeb/Painting/PaintableBox.cpp b/Libraries/LibWeb/Painting/PaintableBox.cpp index f7a3e3b768..7ee7c76685 100644 --- a/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -34,8 +34,6 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(PaintableBox); - static bool g_paint_viewport_scrollbars = true; void set_paint_viewport_scrollbars(bool const enabled) @@ -98,7 +96,7 @@ ResolvedCSSFilter resolve_css_filter(CSS::Filter const& computed_filter, Paintab result.svg_filter = filter_element->gfx_filter(layout_node); auto bounds = paintable_box.absolute_border_box_rect(); if (bounds.is_empty()) { - if (auto const* svg_ancestor = paintable_box.first_ancestor_of_type()) + if (auto svg_ancestor = paintable_box.first_ancestor_of_type()) result.svg_filter_bounds = svg_ancestor->absolute_rect(); } if (!bounds.is_empty()) @@ -109,14 +107,14 @@ ResolvedCSSFilter resolve_css_filter(CSS::Filter const& computed_filter, Paintab return result; } -GC::Ref PaintableBox::create(Layout::Box const& layout_box) +NonnullRefPtr PaintableBox::create(Layout::Box const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new PaintableBox(layout_box)); } -GC::Ref PaintableBox::create(Layout::InlineNode const& layout_box) +NonnullRefPtr PaintableBox::create(Layout::InlineNode const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new PaintableBox(layout_box)); } PaintableBox::PaintableBox(Layout::Box const& layout_box) @@ -169,15 +167,6 @@ void PaintableBox::reset_for_relayout() invalidate_stacking_context(); } -void PaintableBox::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_stacking_context); - visitor.visit(m_horizontal_scrollbar); - visitor.visit(m_vertical_scrollbar); - visitor.visit(m_resize_handle); -} - CSSPixelPoint PaintableBox::scroll_offset() const { if (is_viewport_paintable()) { @@ -308,7 +297,7 @@ CSSPixelPoint PaintableBox::offset() const CSSPixelRect PaintableBox::compute_absolute_rect() const { CSSPixelRect rect { offset(), content_size() }; - for (auto const* block = containing_block(); block; block = block->containing_block()) + for (auto block = containing_block(); block; block = block->containing_block()) rect.translate_by(block->offset()); return rect; } @@ -402,7 +391,7 @@ static CSSPixelRect united_rect_for_continuation_chain(PaintableBox const& start for (auto const& paintable : node->paintables()) { if (!is(paintable)) continue; - auto const& paintable_box = static_cast(paintable); + auto const& paintable_box = static_cast(*paintable); auto paintable_border_box_rect = get_rect(paintable_box); if (!result.has_value()) result = paintable_border_box_rect; @@ -444,16 +433,16 @@ Optional PaintableBox::get_clip_rect() const return {}; } -GC::Ptr PaintableBox::scrollbar(ScrollDirection direction) const +RefPtr PaintableBox::scrollbar(ScrollDirection direction) const { return direction == ScrollDirection::Horizontal ? m_horizontal_scrollbar : m_vertical_scrollbar; } -GC::Ref PaintableBox::ensure_scrollbar(ScrollDirection direction) +NonnullRefPtr PaintableBox::ensure_scrollbar(ScrollDirection direction) { auto& slot = direction == ScrollDirection::Horizontal ? m_horizontal_scrollbar : m_vertical_scrollbar; if (!slot) - slot = Scrollbar::create(heap(), const_cast(*this), direction); + slot = Scrollbar::create(const_cast(*this), direction); return *slot; } @@ -800,11 +789,21 @@ void PaintableBox::paint_inspector_overlay_internal(DisplayListRecordingContext& context.display_list_recorder().draw_text(size_text_device_rect, size_text, font->with_size(font->point_size() * context.device_pixels_per_css_pixel()), Gfx::TextAlignment::Center, context.palette().color(Gfx::ColorRole::TooltipText)); } -void PaintableBox::set_stacking_context(GC::Ref stacking_context) +void PaintableBox::set_stacking_context(NonnullRefPtr stacking_context) { m_stacking_context = move(stacking_context); } +RefPtr PaintableBox::stacking_context() +{ + return m_stacking_context; +} + +RefPtr PaintableBox::stacking_context() const +{ + return m_stacking_context; +} + void PaintableBox::invalidate_stacking_context() { m_stacking_context = nullptr; @@ -1013,15 +1012,15 @@ bool PaintableBox::is_chrome_mirrored() const || writing_mode == CSS::WritingMode::SidewaysRl; } -GC::Ptr PaintableBox::resize_handle() const +RefPtr PaintableBox::resize_handle() const { return m_resize_handle; } -GC::Ref PaintableBox::ensure_resize_handle() +NonnullRefPtr PaintableBox::ensure_resize_handle() { if (!m_resize_handle) - m_resize_handle = ResizeHandle::create(heap(), *this); + m_resize_handle = ResizeHandle::create(*this); return *m_resize_handle; } @@ -1168,7 +1167,7 @@ Optional PaintableBox::hit_test(CSSPixelPoint position, HitTestTy TraversalDecision PaintableBox::hit_test_children(CSSPixelPoint position, HitTestType type, Function const& callback) const { - for (auto const* child = last_child(); child; child = child->previous_sibling()) { + for (auto child = last_child(); child; child = child->previous_sibling()) { if (child->is_positioned() && child->computed_values().z_index().value_or(0) == 0) continue; if (child->has_stacking_context()) @@ -1252,7 +1251,7 @@ CSSPixelRect PaintableBox::transform_reference_box() const // FIXME: If a viewBox attribute is specified for the SVG viewport creating element: // - The reference box is positioned at the origin of the coordinate system established by the viewBox attribute. // - The dimension of the reference box is set to the width and height values of the viewBox attribute. - auto* svg_paintable = first_ancestor_of_type(); + auto svg_paintable = first_ancestor_of_type(); if (!svg_paintable) return absolute_border_box_rect(); return svg_paintable->absolute_rect(); @@ -1286,7 +1285,7 @@ ScrollFrameIndex PaintableBox::nearest_scroll_frame_index() const { if (is_fixed_position()) return {}; - auto const* paintable = this->containing_block(); + auto paintable = this->containing_block(); while (paintable) { if (paintable->own_scroll_frame_index().value()) return paintable->own_scroll_frame_index(); @@ -1299,9 +1298,9 @@ ScrollFrameIndex PaintableBox::nearest_scroll_frame_index() const return {}; } -PaintableBox const* PaintableBox::nearest_scrollable_ancestor() const +RefPtr PaintableBox::nearest_scrollable_ancestor() const { - auto const* paintable = this->containing_block(); + auto paintable = this->containing_block(); while (paintable) { if (paintable->could_be_scrolled_by_wheel_event()) return paintable; diff --git a/Libraries/LibWeb/Painting/PaintableBox.h b/Libraries/LibWeb/Painting/PaintableBox.h index 72582e8132..43e29e700d 100644 --- a/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Libraries/LibWeb/Painting/PaintableBox.h @@ -8,6 +8,8 @@ #pragma once #include +#include +#include #include #include #include @@ -32,21 +34,19 @@ WEB_API void set_paint_viewport_scrollbars(bool enabled); ResolvedCSSFilter resolve_css_filter(CSS::Filter const& computed_filter, PaintableBox const& paintable_box); class WEB_API PaintableBox : public Paintable { - GC_CELL(PaintableBox, Paintable); - GC_DECLARE_ALLOCATOR(PaintableBox); - public: - static GC::Ref create(Layout::Box const&); - static GC::Ref create(Layout::InlineNode const&); + static NonnullRefPtr create(Layout::Box const&); + static NonnullRefPtr create(Layout::InlineNode const&); virtual ~PaintableBox(); + virtual StringView class_name() const override { return "PaintableBox"sv; } virtual void reset_for_relayout(); virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; - StackingContext* stacking_context() { return m_stacking_context; } - StackingContext const* stacking_context() const { return m_stacking_context; } - void set_stacking_context(GC::Ref); + RefPtr stacking_context(); + RefPtr stacking_context() const; + void set_stacking_context(NonnullRefPtr); void invalidate_stacking_context(); Optional effective_z_index() const; @@ -174,8 +174,8 @@ public: ScrollStateSnapshot const* = nullptr) const; Optional absolute_scrollbar_rect(ScrollDirection direction, bool with_gutter, ChromeMetrics const& chrome_metrics) const; - GC::Ptr scrollbar(ScrollDirection) const; - GC::Ref ensure_scrollbar(ScrollDirection); + RefPtr scrollbar(ScrollDirection) const; + NonnullRefPtr ensure_scrollbar(ScrollDirection); enum class ConflictingElementKind { Cell, @@ -240,14 +240,14 @@ public: bool is_chrome_mirrored() const; bool has_resizer() const; - GC::Ptr resize_handle() const; - GC::Ref ensure_resize_handle(); + RefPtr resize_handle() const; + NonnullRefPtr ensure_resize_handle(); CSSPixelRect transform_reference_box() const; ScrollFrameIndex nearest_scroll_frame_index() const; - PaintableBox const* nearest_scrollable_ancestor() const; + RefPtr nearest_scrollable_ancestor() const; using StickyInsets = Painting::StickyInsets; StickyInsets const& sticky_insets() const { return *m_sticky_insets; } @@ -301,8 +301,6 @@ protected: explicit PaintableBox(Layout::Box const&); explicit PaintableBox(Layout::InlineNode const&); - virtual void visit_edges(Visitor&) override; - virtual void paint_border(DisplayListRecordingContext&) const; virtual void paint_backdrop_filter(DisplayListRecordingContext&) const; virtual void paint_background(DisplayListRecordingContext&) const; @@ -325,7 +323,7 @@ private: void paint_middle_button_scroll_indicator(DisplayListRecordingContext&) const; - GC::Ptr m_stacking_context; + RefPtr m_stacking_context; Optional m_overflow_data; @@ -346,9 +344,9 @@ private: ResolvedCSSFilter m_filter; - GC::Ptr m_horizontal_scrollbar; - GC::Ptr m_vertical_scrollbar; - GC::Ptr m_resize_handle; + RefPtr m_horizontal_scrollbar; + RefPtr m_vertical_scrollbar; + RefPtr m_resize_handle; bool m_has_non_invertible_css_transform { false }; OwnPtr m_sticky_insets; diff --git a/Libraries/LibWeb/Painting/PaintableFragment.cpp b/Libraries/LibWeb/Painting/PaintableFragment.cpp index 4243767552..8f182787f8 100644 --- a/Libraries/LibWeb/Painting/PaintableFragment.cpp +++ b/Libraries/LibWeb/Painting/PaintableFragment.cpp @@ -52,7 +52,7 @@ PaintableFragment::PaintableFragment(Layout::LineBoxFragment const& fragment) CSSPixelRect const PaintableFragment::absolute_rect() const { CSSPixelRect rect { offset(), size() }; - if (auto const* containing_block = paintable().containing_block()) + if (auto containing_block = paintable().containing_block()) rect.translate_by(containing_block->absolute_position()); return rect; } @@ -294,9 +294,10 @@ CSSPixelRect PaintableFragment::selection_rect() const Utf16View PaintableFragment::text() const { - if (!is(paintable())) + auto const* text_paintable = as_if(paintable()); + if (!text_paintable) return {}; - return as(paintable()).layout_node().text_for_rendering().substring_view(m_start_offset, m_length_in_code_units); + return text_paintable->layout_node().text_for_rendering().substring_view(m_start_offset, m_length_in_code_units); } } diff --git a/Libraries/LibWeb/Painting/PaintableWithLines.cpp b/Libraries/LibWeb/Painting/PaintableWithLines.cpp index 55db4ef8b2..110d14b76e 100644 --- a/Libraries/LibWeb/Painting/PaintableWithLines.cpp +++ b/Libraries/LibWeb/Painting/PaintableWithLines.cpp @@ -20,26 +20,25 @@ #include #include #include +#include #include #include namespace Web::Painting { -GC_DEFINE_ALLOCATOR(PaintableWithLines); - static void paint_text_decoration(DisplayListRecordingContext&, TextPaintable const&, PaintableFragment::FragmentSpan const&); static Gfx::Path build_triangle_wave_path(Gfx::IntPoint from, Gfx::IntPoint to, float amplitude); static void compute_render_spans(PaintableFragment const&, Vector&); static void paint_text_fragment(DisplayListRecordingContext&, PaintableFragment::FragmentSpan const&); -GC::Ref PaintableWithLines::create(Layout::BlockContainer const& block_container) +NonnullRefPtr PaintableWithLines::create(Layout::BlockContainer const& block_container) { - return block_container.heap().allocate(block_container); + return adopt_ref(*new PaintableWithLines(block_container)); } -GC::Ref PaintableWithLines::create(Layout::InlineNode const& inline_node, size_t line_index) +NonnullRefPtr PaintableWithLines::create(Layout::InlineNode const& inline_node, size_t line_index) { - return inline_node.heap().allocate(inline_node, line_index); + return adopt_ref(*new PaintableWithLines(inline_node, line_index)); } PaintableWithLines::PaintableWithLines(Layout::BlockContainer const& layout_box) @@ -288,8 +287,8 @@ void PaintableWithLines::paint(DisplayListRecordingContext& context, PaintPhase void compute_render_spans(PaintableFragment const& fragment, Vector& spans) { - auto const* text_paintable = as_if(fragment.paintable()); - if (!text_paintable) { + auto const* maybe_text_paintable = as_if(fragment.paintable()); + if (!maybe_text_paintable) { // Non-text fragments still need shadow painting. spans.append({ .fragment = fragment, @@ -302,11 +301,12 @@ void compute_render_spans(PaintableFragment const& fragment, Vectoris_visible()) + if (!text_paintable.is_visible()) return; - auto text_color = text_paintable->computed_values().webkit_text_fill_color(); + auto text_color = text_paintable.computed_values().webkit_text_fill_color(); auto selection_offsets = fragment.selection_offsets(); // No selection: single span with base styling. @@ -324,7 +324,7 @@ void compute_render_spans(PaintableFragment const& fragment, Vectorselection_style(); + auto selection_style = text_paintable.selection_style(); auto selection_text_color = selection_style.text_color.value_or(text_color); // Convert selection text decoration to fragment text decoration data. diff --git a/Libraries/LibWeb/Painting/PaintableWithLines.h b/Libraries/LibWeb/Painting/PaintableWithLines.h index f7efd81bec..c65f5746e3 100644 --- a/Libraries/LibWeb/Painting/PaintableWithLines.h +++ b/Libraries/LibWeb/Painting/PaintableWithLines.h @@ -14,13 +14,11 @@ namespace Web::Painting { class PaintableWithLines : public PaintableBox { - GC_CELL(PaintableWithLines, PaintableBox); - GC_DECLARE_ALLOCATOR(PaintableWithLines); - public: - static GC::Ref create(Layout::BlockContainer const&); - static GC::Ref create(Layout::InlineNode const&, size_t line_index); + static NonnullRefPtr create(Layout::BlockContainer const&); + static NonnullRefPtr create(Layout::InlineNode const&, size_t line_index); virtual ~PaintableWithLines() override; + virtual StringView class_name() const override { return "PaintableWithLines"sv; } virtual void reset_for_relayout() override; @@ -38,13 +36,6 @@ public: [[nodiscard]] virtual TraversalDecision hit_test(CSSPixelPoint position, HitTestType type, Function const& callback) const override; [[nodiscard]] TraversalDecision hit_test_fragments(CSSPixelPoint position, CSSPixelPoint local_position, HitTestType type, Function const& callback) const; - virtual void visit_edges(Cell::Visitor& visitor) override - { - Base::visit_edges(visitor); - for (auto& fragment : m_fragments) - visitor.visit(GC::Ref { fragment.layout_node() }); - } - size_t line_index() const { return m_line_index; } protected: diff --git a/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp b/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp index 709180ca42..6c2a4fb945 100644 --- a/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp +++ b/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp @@ -15,11 +15,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(RadioButtonPaintable); - -GC::Ref RadioButtonPaintable::create(Layout::RadioButton const& layout_box) +NonnullRefPtr RadioButtonPaintable::create(Layout::RadioButton const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new RadioButtonPaintable(layout_box)); } RadioButtonPaintable::RadioButtonPaintable(Layout::RadioButton const& layout_box) diff --git a/Libraries/LibWeb/Painting/RadioButtonPaintable.h b/Libraries/LibWeb/Painting/RadioButtonPaintable.h index a2d6b2b1b6..326f0e3a53 100644 --- a/Libraries/LibWeb/Painting/RadioButtonPaintable.h +++ b/Libraries/LibWeb/Painting/RadioButtonPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class RadioButtonPaintable final : public PaintableBox { - GC_CELL(RadioButtonPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(RadioButtonPaintable); - public: - static GC::Ref create(Layout::RadioButton const&); + static NonnullRefPtr create(Layout::RadioButton const&); + virtual StringView class_name() const override { return "RadioButtonPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/ResizeHandle.cpp b/Libraries/LibWeb/Painting/ResizeHandle.cpp index 325fbd1cc3..e4a12ed9c6 100644 --- a/Libraries/LibWeb/Painting/ResizeHandle.cpp +++ b/Libraries/LibWeb/Painting/ResizeHandle.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -14,11 +15,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(ResizeHandle); - -GC::Ref ResizeHandle::create(GC::Heap& heap, PaintableBox& paintable_box) +NonnullRefPtr ResizeHandle::create(PaintableBox& paintable_box) { - return heap.allocate(paintable_box); + return adopt_ref(*new ResizeHandle(paintable_box)); } ResizeHandle::ResizeHandle(PaintableBox& paintable_box) @@ -27,26 +26,23 @@ ResizeHandle::ResizeHandle(PaintableBox& paintable_box) { } -void ResizeHandle::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_paintable_box); - visitor.visit(m_element); - if (m_resize_action) - m_resize_action->visit_edges(visitor); -} - bool ResizeHandle::contains(CSSPixelPoint position, ChromeMetrics const& metrics) const { - return m_paintable_box->resizer_contains(position, metrics); + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return false; + return paintable_box->resizer_contains(position, metrics); } Optional ResizeHandle::cursor() const { - auto axes = m_paintable_box->physical_resize_axes(); + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return {}; + auto axes = paintable_box->physical_resize_axes(); if (axes.vertical) { if (axes.horizontal) { - if (m_paintable_box->is_chrome_mirrored()) + if (paintable_box->is_chrome_mirrored()) return CSS::CursorPredefined::SwResize; return CSS::CursorPredefined::SeResize; } @@ -64,8 +60,14 @@ MouseAction ResizeHandle::handle_pointer_event(FlyString const& type, unsigned b return MouseAction::None; } + auto element = m_element.ptr(); + if (!element || !element->is_connected()) { + m_resize_action.clear(); + return MouseAction::None; + } + if (!m_resize_action) - m_resize_action = make(m_element, visual_viewport_position); + m_resize_action = make(*element, visual_viewport_position); else m_resize_action->handle_pointer_move(visual_viewport_position); diff --git a/Libraries/LibWeb/Painting/ResizeHandle.h b/Libraries/LibWeb/Painting/ResizeHandle.h index 923a23e83c..9d95c8b8a4 100644 --- a/Libraries/LibWeb/Painting/ResizeHandle.h +++ b/Libraries/LibWeb/Painting/ResizeHandle.h @@ -6,17 +6,15 @@ #pragma once +#include #include #include namespace Web::Painting { class ResizeHandle final : public ChromeWidget { - GC_CELL(ResizeHandle, ChromeWidget); - GC_DECLARE_ALLOCATOR(ResizeHandle); - public: - static GC::Ref create(GC::Heap&, PaintableBox&); + static NonnullRefPtr create(PaintableBox&); bool contains(CSSPixelPoint position, ChromeMetrics const&) const; @@ -29,10 +27,8 @@ public: private: ResizeHandle(PaintableBox&); - virtual void visit_edges(Cell::Visitor&) override; - - GC::Ref m_paintable_box; - GC::Ref m_element; + WeakPtr m_paintable_box; + GC::Weak m_element; OwnPtr m_resize_action; }; diff --git a/Libraries/LibWeb/Painting/SVGClipPaintable.cpp b/Libraries/LibWeb/Painting/SVGClipPaintable.cpp index 676858f95b..6ab671a2e7 100644 --- a/Libraries/LibWeb/Painting/SVGClipPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGClipPaintable.cpp @@ -8,11 +8,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGClipPaintable); - -GC::Ref SVGClipPaintable::create(Layout::SVGClipBox const& layout_box) +NonnullRefPtr SVGClipPaintable::create(Layout::SVGClipBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGClipPaintable(layout_box)); } SVGClipPaintable::SVGClipPaintable(Layout::SVGClipBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGClipPaintable.h b/Libraries/LibWeb/Painting/SVGClipPaintable.h index 7aa2ae14ef..19a76acaaf 100644 --- a/Libraries/LibWeb/Painting/SVGClipPaintable.h +++ b/Libraries/LibWeb/Painting/SVGClipPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class SVGClipPaintable : public SVGPaintable { - GC_CELL(SVGClipPaintable, SVGPaintable); - GC_DECLARE_ALLOCATOR(SVGClipPaintable); - public: - static GC::Ref create(Layout::SVGClipBox const&); + static NonnullRefPtr create(Layout::SVGClipBox const&); + virtual StringView class_name() const override { return "SVGClipPaintable"sv; } bool forms_unconnected_subtree() const override { diff --git a/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.cpp b/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.cpp index ae0cb53dbd..56909a992e 100644 --- a/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.cpp @@ -9,11 +9,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGForeignObjectPaintable); - -GC::Ref SVGForeignObjectPaintable::create(Layout::SVGForeignObjectBox const& layout_box) +NonnullRefPtr SVGForeignObjectPaintable::create(Layout::SVGForeignObjectBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGForeignObjectPaintable(layout_box)); } SVGForeignObjectPaintable::SVGForeignObjectPaintable(Layout::SVGForeignObjectBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.h b/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.h index 960e8747f5..62e32ea78f 100644 --- a/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.h +++ b/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.h @@ -14,11 +14,9 @@ namespace Web::Painting { class SVGForeignObjectPaintable final : public PaintableWithLines , public SVGMaskable { - GC_CELL(SVGForeignObjectPaintable, PaintableWithLines); - GC_DECLARE_ALLOCATOR(SVGForeignObjectPaintable); - public: - static GC::Ref create(Layout::SVGForeignObjectBox const&); + static NonnullRefPtr create(Layout::SVGForeignObjectBox const&); + virtual StringView class_name() const override { return "SVGForeignObjectPaintable"sv; } virtual TraversalDecision hit_test(CSSPixelPoint, HitTestType, Function const& callback) const override; diff --git a/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp b/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp index 77a116004f..7c4476caf6 100644 --- a/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp @@ -14,11 +14,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGGraphicsPaintable); - -GC::Ref SVGGraphicsPaintable::create(Layout::SVGGraphicsBox const& layout_box) +NonnullRefPtr SVGGraphicsPaintable::create(Layout::SVGGraphicsBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGGraphicsPaintable(layout_box)); } SVGGraphicsPaintable::SVGGraphicsPaintable(Layout::SVGGraphicsBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h b/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h index 6b16ea0356..90b66eaaa3 100644 --- a/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h +++ b/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h @@ -14,9 +14,6 @@ namespace Web::Painting { class SVGGraphicsPaintable : public SVGPaintable , public SVGMaskable { - GC_CELL(SVGGraphicsPaintable, SVGPaintable); - GC_DECLARE_ALLOCATOR(SVGGraphicsPaintable); - public: class ComputedTransforms { public: @@ -48,7 +45,8 @@ public: Gfx::AffineTransform m_svg_transform {}; }; - static GC::Ref create(Layout::SVGGraphicsBox const&); + static NonnullRefPtr create(Layout::SVGGraphicsBox const&); + virtual StringView class_name() const override { return "SVGGraphicsPaintable"sv; } virtual GC::Ptr dom_node_of_svg() const override { return dom_node(); } virtual Optional get_mask_area() const override { return get_svg_mask_area(); } diff --git a/Libraries/LibWeb/Painting/SVGMaskPaintable.cpp b/Libraries/LibWeb/Painting/SVGMaskPaintable.cpp index cb4c367113..0824300234 100644 --- a/Libraries/LibWeb/Painting/SVGMaskPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGMaskPaintable.cpp @@ -8,11 +8,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGMaskPaintable); - -GC::Ref SVGMaskPaintable::create(Layout::SVGMaskBox const& layout_box) +NonnullRefPtr SVGMaskPaintable::create(Layout::SVGMaskBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGMaskPaintable(layout_box)); } SVGMaskPaintable::SVGMaskPaintable(Layout::SVGMaskBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGMaskPaintable.h b/Libraries/LibWeb/Painting/SVGMaskPaintable.h index 253fe35bdf..816aca1d36 100644 --- a/Libraries/LibWeb/Painting/SVGMaskPaintable.h +++ b/Libraries/LibWeb/Painting/SVGMaskPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class SVGMaskPaintable : public SVGGraphicsPaintable { - GC_CELL(SVGMaskPaintable, SVGGraphicsPaintable); - GC_DECLARE_ALLOCATOR(SVGMaskPaintable); - public: - static GC::Ref create(Layout::SVGMaskBox const&); + static NonnullRefPtr create(Layout::SVGMaskBox const&); + virtual StringView class_name() const override { return "SVGMaskPaintable"sv; } bool forms_unconnected_subtree() const override { diff --git a/Libraries/LibWeb/Painting/SVGPaintable.h b/Libraries/LibWeb/Painting/SVGPaintable.h index 00acac2343..a181d9009c 100644 --- a/Libraries/LibWeb/Painting/SVGPaintable.h +++ b/Libraries/LibWeb/Painting/SVGPaintable.h @@ -12,9 +12,9 @@ namespace Web::Painting { class SVGPaintable : public PaintableBox { - GC_CELL(SVGPaintable, PaintableBox); - public: + virtual StringView class_name() const override { return "SVGPaintable"sv; } + Layout::SVGBox const& layout_box() const; virtual Optional clip_path_geometry_bounds(Gfx::AffineTransform const& additional_transform) const; bool contributes_to_clip_path() const; diff --git a/Libraries/LibWeb/Painting/SVGPathPaintable.cpp b/Libraries/LibWeb/Painting/SVGPathPaintable.cpp index 3a16e6320b..2817b2a0e6 100644 --- a/Libraries/LibWeb/Painting/SVGPathPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGPathPaintable.cpp @@ -12,11 +12,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGPathPaintable); - -GC::Ref SVGPathPaintable::create(Layout::SVGGraphicsBox const& layout_box) +NonnullRefPtr SVGPathPaintable::create(Layout::SVGGraphicsBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGPathPaintable(layout_box)); } SVGPathPaintable::SVGPathPaintable(Layout::SVGGraphicsBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGPathPaintable.h b/Libraries/LibWeb/Painting/SVGPathPaintable.h index 4b76c9839c..097b0fb9b2 100644 --- a/Libraries/LibWeb/Painting/SVGPathPaintable.h +++ b/Libraries/LibWeb/Painting/SVGPathPaintable.h @@ -14,11 +14,9 @@ namespace Web::Painting { class WEB_API SVGPathPaintable final : public SVGGraphicsPaintable { - GC_CELL(SVGPathPaintable, SVGGraphicsPaintable); - GC_DECLARE_ALLOCATOR(SVGPathPaintable); - public: - static GC::Ref create(Layout::SVGGraphicsBox const&); + static NonnullRefPtr create(Layout::SVGGraphicsBox const&); + virtual StringView class_name() const override { return "SVGPathPaintable"sv; } virtual TraversalDecision hit_test(CSSPixelPoint, HitTestType, Function const& callback) const override; virtual Optional clip_path_geometry_bounds(Gfx::AffineTransform const& additional_transform) const override; diff --git a/Libraries/LibWeb/Painting/SVGPatternPaintable.cpp b/Libraries/LibWeb/Painting/SVGPatternPaintable.cpp index c7e1c66e5b..82c637484b 100644 --- a/Libraries/LibWeb/Painting/SVGPatternPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGPatternPaintable.cpp @@ -8,11 +8,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGPatternPaintable); - -GC::Ref SVGPatternPaintable::create(Layout::SVGPatternBox const& layout_box) +NonnullRefPtr SVGPatternPaintable::create(Layout::SVGPatternBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGPatternPaintable(layout_box)); } SVGPatternPaintable::SVGPatternPaintable(Layout::SVGPatternBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGPatternPaintable.h b/Libraries/LibWeb/Painting/SVGPatternPaintable.h index 59cd0ecd92..5014d77738 100644 --- a/Libraries/LibWeb/Painting/SVGPatternPaintable.h +++ b/Libraries/LibWeb/Painting/SVGPatternPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class SVGPatternPaintable : public SVGPaintable { - GC_CELL(SVGPatternPaintable, SVGPaintable); - GC_DECLARE_ALLOCATOR(SVGPatternPaintable); - public: - static GC::Ref create(Layout::SVGPatternBox const&); + static NonnullRefPtr create(Layout::SVGPatternBox const&); + virtual StringView class_name() const override { return "SVGPatternPaintable"sv; } bool forms_unconnected_subtree() const override { diff --git a/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp b/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp index 626468251c..cf1bc893c8 100644 --- a/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp @@ -10,11 +10,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGSVGPaintable); - -GC::Ref SVGSVGPaintable::create(Layout::SVGSVGBox const& layout_box) +NonnullRefPtr SVGSVGPaintable::create(Layout::SVGSVGBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGSVGPaintable(layout_box)); } SVGSVGPaintable::SVGSVGPaintable(Layout::SVGSVGBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGSVGPaintable.h b/Libraries/LibWeb/Painting/SVGSVGPaintable.h index 76779e4b80..8b84bb1b83 100644 --- a/Libraries/LibWeb/Painting/SVGSVGPaintable.h +++ b/Libraries/LibWeb/Painting/SVGSVGPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class SVGSVGPaintable final : public PaintableBox { - GC_CELL(SVGSVGPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(SVGSVGPaintable); - public: - static GC::Ref create(Layout::SVGSVGBox const&); + static NonnullRefPtr create(Layout::SVGSVGBox const&); + virtual StringView class_name() const override { return "SVGSVGPaintable"sv; } static void paint_svg_box(DisplayListRecordingContext& context, PaintableBox const& svg_box, PaintPhase phase); static void paint_descendants(DisplayListRecordingContext& context, PaintableBox const& paintable, PaintPhase phase); diff --git a/Libraries/LibWeb/Painting/ScrollFrame.cpp b/Libraries/LibWeb/Painting/ScrollFrame.cpp index 1b1e77a44f..a8bdfb93fd 100644 --- a/Libraries/LibWeb/Painting/ScrollFrame.cpp +++ b/Libraries/LibWeb/Painting/ScrollFrame.cpp @@ -4,8 +4,6 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include #include #include @@ -18,4 +16,11 @@ ScrollFrame::ScrollFrame(PaintableBox const& paintable_box, bool sticky, ScrollF { } +PaintableBox const& ScrollFrame::paintable_box() const +{ + auto paintable_box = m_paintable_box.strong_ref(); + VERIFY(paintable_box); + return *paintable_box; +} + } diff --git a/Libraries/LibWeb/Painting/ScrollFrame.h b/Libraries/LibWeb/Painting/ScrollFrame.h index a65c2f7318..0497cfaa14 100644 --- a/Libraries/LibWeb/Painting/ScrollFrame.h +++ b/Libraries/LibWeb/Painting/ScrollFrame.h @@ -7,7 +7,7 @@ #pragma once #include -#include +#include #include #include @@ -36,7 +36,7 @@ public: ScrollFrame() = default; ScrollFrame(PaintableBox const& paintable_box, bool sticky, ScrollFrameIndex parent_index); - PaintableBox const& paintable_box() const { return *m_paintable_box; } + PaintableBox const& paintable_box() const; bool is_sticky() const { return m_sticky; } @@ -57,7 +57,7 @@ private: friend class ScrollState; friend class ScrollStateSnapshot; - GC::Weak m_paintable_box; + WeakPtr m_paintable_box; bool m_sticky { false }; ScrollFrameIndex m_parent_index; CSSPixelPoint m_own_offset; diff --git a/Libraries/LibWeb/Painting/Scrollbar.cpp b/Libraries/LibWeb/Painting/Scrollbar.cpp index e88872fcdd..68e20713b1 100644 --- a/Libraries/LibWeb/Painting/Scrollbar.cpp +++ b/Libraries/LibWeb/Painting/Scrollbar.cpp @@ -14,11 +14,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(Scrollbar); - -GC::Ref Scrollbar::create(GC::Heap& heap, PaintableBox& paintable_box, PaintableBox::ScrollDirection direction) +NonnullRefPtr Scrollbar::create(PaintableBox& paintable_box, PaintableBox::ScrollDirection direction) { - return heap.allocate(paintable_box, direction); + return adopt_ref(*new Scrollbar(paintable_box, direction)); } Scrollbar::Scrollbar(PaintableBox& paintable_box, PaintableBox::ScrollDirection direction) @@ -27,15 +25,12 @@ Scrollbar::Scrollbar(PaintableBox& paintable_box, PaintableBox::ScrollDirection { } -void Scrollbar::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_paintable_box); -} - bool Scrollbar::contains(CSSPixelPoint position, ChromeMetrics const& metrics) const { - if (auto rect = m_paintable_box->absolute_scrollbar_rect(m_direction, is_enlarged(), metrics); rect.has_value()) + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return false; + if (auto rect = paintable_box->absolute_scrollbar_rect(m_direction, is_enlarged(), metrics); rect.has_value()) return rect->contains(position); return false; } @@ -49,9 +44,13 @@ MouseAction Scrollbar::handle_pointer_event(FlyString const& type, unsigned butt return MouseAction::None; } - auto position = m_paintable_box->transform_to_local_coordinates(visual_viewport_position); + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return MouseAction::None; + + auto position = paintable_box->transform_to_local_coordinates(visual_viewport_position); scroll_to_mouse_position(position); - m_paintable_box->set_needs_repaint(); + paintable_box->set_needs_repaint(); if (type == UIEvents::EventNames::pointerup) { m_thumb_grab_position.clear(); @@ -64,7 +63,10 @@ MouseAction Scrollbar::handle_pointer_event(FlyString const& type, unsigned butt MouseAction Scrollbar::mouse_move(CSSPixelPoint position) { if (m_thumb_grab_position.has_value()) { - position = m_paintable_box->transform_to_local_coordinates(position); + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return MouseAction::None; + position = paintable_box->transform_to_local_coordinates(position); scroll_to_mouse_position(position); return MouseAction::SwallowEvent; } @@ -74,7 +76,8 @@ MouseAction Scrollbar::mouse_move(CSSPixelPoint position) MouseAction Scrollbar::mouse_up(CSSPixelPoint, unsigned) { m_thumb_grab_position.clear(); - m_paintable_box->set_needs_repaint(); + if (auto paintable_box = m_paintable_box.strong_ref()) + paintable_box->set_needs_repaint(); return MouseAction::None; } @@ -83,7 +86,8 @@ void Scrollbar::mouse_enter() if (m_hovered) return; m_hovered = true; - m_paintable_box->set_needs_repaint(); + if (auto paintable_box = m_paintable_box.strong_ref()) + paintable_box->set_needs_repaint(); } void Scrollbar::mouse_leave() @@ -91,15 +95,20 @@ void Scrollbar::mouse_leave() if (!m_hovered) return; m_hovered = false; - m_paintable_box->set_needs_repaint(); + if (auto paintable_box = m_paintable_box.strong_ref()) + paintable_box->set_needs_repaint(); } void Scrollbar::scroll_to_mouse_position(CSSPixelPoint position) { - ChromeMetrics metrics = m_paintable_box->document().page().chrome_metrics(); + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return; - auto const& scroll_state = m_paintable_box->document().paintable()->scroll_state_snapshot(); - auto scrollbar_data = m_paintable_box->compute_scrollbar_data(m_direction, metrics, &scroll_state); + ChromeMetrics metrics = paintable_box->document().page().chrome_metrics(); + + auto const& scroll_state = paintable_box->document().paintable()->scroll_state_snapshot(); + auto scrollbar_data = paintable_box->compute_scrollbar_data(m_direction, metrics, &scroll_state); VERIFY(scrollbar_data.has_value()); auto orientation = m_direction == PaintableBox::ScrollDirection::Horizontal ? Orientation::Horizontal : Orientation::Vertical; @@ -119,13 +128,13 @@ void Scrollbar::scroll_to_mouse_position(CSSPixelPoint position) auto constrained_offset = AK::clamp(offset_relative_to_gutter - m_thumb_grab_position.value(), 0, gutter_size - thumb_size); auto scroll_position = constrained_offset.to_double() / (gutter_size - thumb_size).to_double(); - auto scrollable_overflow_size = m_paintable_box->scrollable_overflow_rect()->primary_size_for_orientation(orientation); - auto padding_size = m_paintable_box->absolute_padding_box_rect().primary_size_for_orientation(orientation); + auto scrollable_overflow_size = paintable_box->scrollable_overflow_rect()->primary_size_for_orientation(orientation); + auto padding_size = paintable_box->absolute_padding_box_rect().primary_size_for_orientation(orientation); auto scroll_position_in_pixels = CSSPixels::nearest_value_for(scroll_position * (scrollable_overflow_size - padding_size)); - auto new_scroll_offset = m_paintable_box->scroll_offset(); + auto new_scroll_offset = paintable_box->scroll_offset(); new_scroll_offset.set_primary_offset_for_orientation(orientation, scroll_position_in_pixels); - m_paintable_box->set_scroll_offset(new_scroll_offset); + paintable_box->set_scroll_offset(new_scroll_offset); } } diff --git a/Libraries/LibWeb/Painting/Scrollbar.h b/Libraries/LibWeb/Painting/Scrollbar.h index 257973d59e..f718dc01af 100644 --- a/Libraries/LibWeb/Painting/Scrollbar.h +++ b/Libraries/LibWeb/Painting/Scrollbar.h @@ -12,11 +12,8 @@ namespace Web::Painting { class Scrollbar final : public ChromeWidget { - GC_CELL(Scrollbar, ChromeWidget); - GC_DECLARE_ALLOCATOR(Scrollbar); - public: - static GC::Ref create(GC::Heap&, PaintableBox&, PaintableBox::ScrollDirection); + static NonnullRefPtr create(PaintableBox&, PaintableBox::ScrollDirection); PaintableBox::ScrollDirection direction() const { return m_direction; } bool is_enlarged() const { return m_hovered || m_thumb_grab_position.has_value(); } @@ -30,14 +27,12 @@ public: private: Scrollbar(PaintableBox&, PaintableBox::ScrollDirection); - virtual void visit_edges(Cell::Visitor&) override; - MouseAction mouse_down(CSSPixelPoint, unsigned button); MouseAction mouse_move(CSSPixelPoint); MouseAction mouse_up(CSSPixelPoint, unsigned button); void scroll_to_mouse_position(CSSPixelPoint); - GC::Ref m_paintable_box; + WeakPtr m_paintable_box; PaintableBox::ScrollDirection m_direction; bool m_hovered { false }; Optional m_thumb_grab_position; diff --git a/Libraries/LibWeb/Painting/StackingContext.cpp b/Libraries/LibWeb/Painting/StackingContext.cpp index e6eb1b3c03..2f84c24cc8 100644 --- a/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Libraries/LibWeb/Painting/StackingContext.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -25,13 +26,11 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(StackingContext); - static void paint_node(Paintable const& paintable, DisplayListRecordingContext& context, PaintPhase phase) { TemporaryChange save_nesting_level(context.display_list_recorder().m_save_nesting_level, 0); - auto const* paintable_box = as_if(paintable); + RefPtr paintable_box = as_if(paintable); if (paintable_box) { // Text fragments in a PaintableWithLines are content of the block container. @@ -58,14 +57,20 @@ static void paint_node(Paintable const& paintable, DisplayListRecordingContext& VERIFY(context.display_list_recorder().m_save_nesting_level == 0); } -StackingContext::StackingContext(PaintableBox& paintable, StackingContext* parent, size_t index_in_tree_order) +NonnullRefPtr StackingContext::create(PaintableBox& paintable, RefPtr parent, size_t index_in_tree_order) +{ + auto stacking_context = adopt_ref(*new StackingContext(paintable, parent, index_in_tree_order)); + if (parent) + parent->m_children.append(stacking_context); + return stacking_context; +} + +StackingContext::StackingContext(PaintableBox& paintable, RefPtr parent, size_t index_in_tree_order) : m_paintable(paintable) , m_parent(parent) , m_index_in_tree_order(index_in_tree_order) { - VERIFY(m_parent != this); - if (m_parent) - m_parent->m_children.append(*this); + VERIFY(!parent || parent.ptr() != this); } void StackingContext::sort() @@ -78,24 +83,14 @@ void StackingContext::sort() return a_z_index < b_z_index; }); - for (auto child : m_children) + for (auto& child : m_children) child->sort(); } -void StackingContext::visit_edges(Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_paintable); - visitor.visit(m_non_positioned_floating_descendants); - visitor.visit(m_positioned_descendants_and_stacking_contexts_with_stack_level_0); - visitor.visit(m_parent); - visitor.visit(m_children); -} - void StackingContext::set_last_paint_generation_id(u64 generation_id) { if (m_last_paint_generation_id.has_value() && m_last_paint_generation_id.value() >= generation_id) { - dbgln("FIXME: Painting commands are recorded twice for stacking context: {}", m_paintable->layout_node().debug_description()); + dbgln("FIXME: Painting commands are recorded twice for stacking context: {}", paintable_box().layout_node().debug_description()); } m_last_paint_generation_id = generation_id; } @@ -255,7 +250,7 @@ void StackingContext::paint_internal(DisplayListRecordingContext& context) const // Here, we treat non-positioned stacking contexts as if they were positioned, because CSS 2.0 spec does not // account for new properties like `transform` and `opacity` that can create stacking contexts. // https://github.com/w3c/csswg-drafts/issues/2717 - for (auto child : m_children) { + for (auto& child : m_children) { if (child->paintable_box().effective_z_index().has_value() && child->paintable_box().effective_z_index().value() < 0) paint_child(context, *child); } @@ -273,13 +268,16 @@ void StackingContext::paint_internal(DisplayListRecordingContext& context) const // Here, we treat non-positioned stacking contexts as if they were positioned, because CSS 2.0 spec does not // account for new properties like `transform` and `opacity` that can create stacking contexts. // https://github.com/w3c/csswg-drafts/issues/2717 - for (auto const& paintable : m_positioned_descendants_and_stacking_contexts_with_stack_level_0) { + for (auto const& weak_paintable : m_positioned_descendants_and_stacking_contexts_with_stack_level_0) { + auto paintable = weak_paintable.strong_ref(); + if (!paintable) + continue; // At this point, `paintable_box` is a positioned descendant with z-index: auto. // FIXME: This is basically duplicating logic found elsewhere in this same function. Find a way to make this more elegant. - if (auto* child = paintable->stacking_context()) { + if (auto child = paintable->stacking_context()) { paint_child(context, *child); } else { - paint_node_as_stacking_context(paintable, context); + paint_node_as_stacking_context(*paintable, context); } }; @@ -288,7 +286,7 @@ void StackingContext::paint_internal(DisplayListRecordingContext& context) const // Here, we treat non-positioned stacking contexts as if they were positioned, because CSS 2.0 spec does not // account for new properties like `transform` and `opacity` that can create stacking contexts. // https://github.com/w3c/csswg-drafts/issues/2717 - for (auto child : m_children) { + for (auto& child : m_children) { if (child->paintable_box().effective_z_index().has_value() && child->paintable_box().effective_z_index().value() >= 1) paint_child(context, *child); } @@ -385,7 +383,7 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType // 7. the child stacking contexts with positive stack levels (least positive first). // NOTE: Hit testing follows reverse painting order, that's why the conditions here are reversed. - for (auto const child : m_children.in_reverse()) { + for (auto const& child : m_children.in_reverse()) { if (child->paintable_box().effective_z_index().value_or(0) <= 0) break; if (child->hit_test(position, type, callback) == TraversalDecision::Break) @@ -393,7 +391,10 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType } // 6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0. - for (auto const& paintable_box : m_positioned_descendants_and_stacking_contexts_with_stack_level_0.in_reverse()) { + for (auto const& weak_paintable_box : m_positioned_descendants_and_stacking_contexts_with_stack_level_0.in_reverse()) { + auto paintable_box = weak_paintable_box.strong_ref(); + if (!paintable_box) + continue; if (paintable_box->stacking_context()) { if (paintable_box->stacking_context()->hit_test(position, type, callback) == TraversalDecision::Break) return TraversalDecision::Break; @@ -405,7 +406,7 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType // 5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks. if (paintable_box().layout_node().children_are_inline() && is(paintable_box().layout_node())) { - for (auto const* paintable = paintable_box().last_child(); paintable; paintable = paintable->previous_sibling()) { + for (auto paintable = paintable_box().last_child(); paintable; paintable = paintable->previous_sibling()) { if (paintable->is_inline() && !paintable->is_absolutely_positioned() && !paintable->has_stacking_context()) { if (paintable->hit_test(position, type, callback) == TraversalDecision::Break) return TraversalDecision::Break; @@ -413,26 +414,28 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType } // Hit test the stacking context root's own fragments if it's a PaintableWithLines. - if (is(paintable_box())) { - auto const& paintable_with_lines = as(paintable_box()); + if (auto const* paintable_with_lines = as_if(paintable_box())) { auto local_position = paintable_box().transform_point_to_local(position); if (local_position.has_value()) { - if (paintable_with_lines.hit_test_fragments(position, local_position.value(), type, callback) == TraversalDecision::Break) + if (paintable_with_lines->hit_test_fragments(position, local_position.value(), type, callback) == TraversalDecision::Break) return TraversalDecision::Break; } } } // 4. the non-positioned floats. - for (auto const& paintable_box : m_non_positioned_floating_descendants.in_reverse()) { + for (auto const& weak_paintable_box : m_non_positioned_floating_descendants.in_reverse()) { + auto paintable_box = weak_paintable_box.strong_ref(); + if (!paintable_box) + continue; if (paintable_box->hit_test(position, type, callback) == TraversalDecision::Break) return TraversalDecision::Break; } // 3. the in-flow, non-inline-level, non-positioned descendants. if (!paintable_box().layout_node().children_are_inline()) { - for (auto const* child = paintable_box().last_child(); child; child = child->previous_sibling()) { + for (auto child = paintable_box().last_child(); child; child = child->previous_sibling()) { if (!child->is_paintable_box()) continue; @@ -446,7 +449,7 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType // 2. the child stacking contexts with negative stack levels (most negative first). // NB: Hit testing follows reverse painting order, so we visit the least negative stack levels first. - for (auto const child : m_children.in_reverse()) { + for (auto const& child : m_children.in_reverse()) { // Skip positive/ zero index child stacking contexts, which have already been handled above. if (child->paintable_box().effective_z_index().value_or(0) >= 0) continue; diff --git a/Libraries/LibWeb/Painting/StackingContext.h b/Libraries/LibWeb/Painting/StackingContext.h index e69144938f..481773b620 100644 --- a/Libraries/LibWeb/Painting/StackingContext.h +++ b/Libraries/LibWeb/Painting/StackingContext.h @@ -6,25 +6,34 @@ #pragma once +#include +#include +#include #include -#include +#include +#include #include #include namespace Web::Painting { -class WEB_API StackingContext final : public GC::Cell { - GC_CELL(StackingContext, GC::Cell); - GC_DECLARE_ALLOCATOR(StackingContext); +class WEB_API StackingContext final + : public RefCounted + , public Weakable { friend class ViewportPaintable; public: - StackingContext(PaintableBox&, StackingContext* parent, size_t index_in_tree_order); + static NonnullRefPtr create(PaintableBox&, RefPtr parent, size_t index_in_tree_order); - StackingContext* parent() { return m_parent; } - StackingContext const* parent() const { return m_parent; } + RefPtr parent() { return m_parent.strong_ref(); } + RefPtr parent() const { return m_parent.strong_ref(); } - PaintableBox const& paintable_box() const { return *m_paintable; } + PaintableBox const& paintable_box() const + { + auto paintable = m_paintable.strong_ref(); + VERIFY(paintable); + return *paintable; + } enum class StackingContextPaintPhase { BackgroundAndBorders, @@ -46,17 +55,17 @@ public: void set_last_paint_generation_id(u64 generation_id); - virtual void visit_edges(Visitor&) override; - private: - GC::Ref m_paintable; - GC::Ptr m_parent; - Vector> m_children; + StackingContext(PaintableBox&, RefPtr parent, size_t index_in_tree_order); + + WeakPtr m_paintable; + WeakPtr m_parent; + Vector> m_children; size_t m_index_in_tree_order { 0 }; Optional m_last_paint_generation_id; - Vector> m_positioned_descendants_and_stacking_contexts_with_stack_level_0; - Vector> m_non_positioned_floating_descendants; + Vector> m_positioned_descendants_and_stacking_contexts_with_stack_level_0; + Vector> m_non_positioned_floating_descendants; static void paint_child(DisplayListRecordingContext&, StackingContext const&); void paint_internal(DisplayListRecordingContext&) const; diff --git a/Libraries/LibWeb/Painting/TableBordersPainting.cpp b/Libraries/LibWeb/Painting/TableBordersPainting.cpp index 1e1064b51f..0d4ee43a22 100644 --- a/Libraries/LibWeb/Painting/TableBordersPainting.cpp +++ b/Libraries/LibWeb/Painting/TableBordersPainting.cpp @@ -297,7 +297,7 @@ static void paint_collected_edges(DisplayListRecordingContext& context, Vector snap_cells_to_device_coordinates(HashMap const& cell_coordinates_to_box, size_t row_count, size_t column_count, DisplayListRecordingContext const& context) +static HashMap snap_cells_to_device_coordinates(HashMap> const& cell_coordinates_to_box, size_t row_count, size_t column_count, DisplayListRecordingContext const& context) { Vector y_line_start_coordinates; Vector y_line_end_coordinates; @@ -364,14 +364,14 @@ void paint_table_borders(DisplayListRecordingContext& context, PaintableBox cons Vector cell_boxes; collect_cell_boxes(cell_boxes, table_paintable); Vector border_edge_painting_info_list; - HashMap cell_coordinates_to_box; + HashMap> cell_coordinates_to_box; size_t row_count = 0; size_t column_count = 0; for (auto const& cell_box : cell_boxes) { cell_coordinates_to_box.set(CellCoordinates { .row_index = cell_box.table_cell_coordinates()->row_index, .column_index = cell_box.table_cell_coordinates()->column_index }, - &cell_box); + cell_box); row_count = max(row_count, cell_box.table_cell_coordinates()->row_index + cell_box.table_cell_coordinates()->row_span); column_count = max(column_count, cell_box.table_cell_coordinates()->column_index + cell_box.table_cell_coordinates()->column_span); } diff --git a/Libraries/LibWeb/Painting/TextPaintable.cpp b/Libraries/LibWeb/Painting/TextPaintable.cpp index 1a9f656223..d293453960 100644 --- a/Libraries/LibWeb/Painting/TextPaintable.cpp +++ b/Libraries/LibWeb/Painting/TextPaintable.cpp @@ -9,11 +9,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(TextPaintable); - -GC::Ref TextPaintable::create(Layout::TextNode const& layout_node) +NonnullRefPtr TextPaintable::create(Layout::TextNode const& layout_node) { - return layout_node.heap().allocate(layout_node); + return adopt_ref(*new TextPaintable(layout_node)); } TextPaintable::TextPaintable(Layout::TextNode const& layout_node) @@ -23,8 +21,9 @@ TextPaintable::TextPaintable(Layout::TextNode const& layout_node) void TextPaintable::paint_inspector_overlay_internal(DisplayListRecordingContext& context) const { - if (auto const* parent_paintable = as_if(parent())) { - for (auto const& fragment : parent_paintable->fragments()) { + auto parent_paintable = parent(); + if (auto const* paintable_with_lines = as_if(parent_paintable.ptr())) { + for (auto const& fragment : paintable_with_lines->fragments()) { if (&fragment.paintable() == this) { PaintableWithLines::paint_text_fragment_debug_highlight(context, fragment); } diff --git a/Libraries/LibWeb/Painting/TextPaintable.h b/Libraries/LibWeb/Painting/TextPaintable.h index e8b954f411..e502d4bf72 100644 --- a/Libraries/LibWeb/Painting/TextPaintable.h +++ b/Libraries/LibWeb/Painting/TextPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class TextPaintable final : public Paintable { - GC_CELL(TextPaintable, Paintable); - GC_DECLARE_ALLOCATOR(TextPaintable); - public: - static GC::Ref create(Layout::TextNode const&); + static NonnullRefPtr create(Layout::TextNode const&); + virtual StringView class_name() const override { return "TextPaintable"sv; } Layout::TextNode const& layout_node() const { return static_cast(Paintable::layout_node()); } diff --git a/Libraries/LibWeb/Painting/VideoPaintable.cpp b/Libraries/LibWeb/Painting/VideoPaintable.cpp index fa85cb2e47..0b93f39039 100644 --- a/Libraries/LibWeb/Painting/VideoPaintable.cpp +++ b/Libraries/LibWeb/Painting/VideoPaintable.cpp @@ -20,11 +20,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(VideoPaintable); - -GC::Ref VideoPaintable::create(Layout::VideoBox const& layout_box) +NonnullRefPtr VideoPaintable::create(Layout::VideoBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new VideoPaintable(layout_box)); } VideoPaintable::VideoPaintable(Layout::VideoBox const& layout_box) @@ -37,7 +35,7 @@ void VideoPaintable::paint(DisplayListRecordingContext& context, PaintPhase phas if (!is_visible()) return; - Base::paint(context, phase); + PaintableBox::paint(context, phase); if (phase != PaintPhase::Foreground) return; diff --git a/Libraries/LibWeb/Painting/VideoPaintable.h b/Libraries/LibWeb/Painting/VideoPaintable.h index b29505e0c2..fdca334178 100644 --- a/Libraries/LibWeb/Painting/VideoPaintable.h +++ b/Libraries/LibWeb/Painting/VideoPaintable.h @@ -13,11 +13,9 @@ namespace Web::Painting { class VideoPaintable final : public PaintableBox { - GC_CELL(VideoPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(VideoPaintable); - public: - static GC::Ref create(Layout::VideoBox const&); + static NonnullRefPtr create(Layout::VideoBox const&); + virtual StringView class_name() const override { return "VideoPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/ViewportPaintable.cpp b/Libraries/LibWeb/Painting/ViewportPaintable.cpp index 914c167cf5..b14c7228aa 100644 --- a/Libraries/LibWeb/Painting/ViewportPaintable.cpp +++ b/Libraries/LibWeb/Painting/ViewportPaintable.cpp @@ -24,11 +24,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(ViewportPaintable); - -GC::Ref ViewportPaintable::create(Layout::Viewport const& layout_viewport) +NonnullRefPtr ViewportPaintable::create(Layout::Viewport const& layout_viewport) { - return layout_viewport.heap().allocate(layout_viewport); + return adopt_ref(*new ViewportPaintable(layout_viewport)); } ViewportPaintable::ViewportPaintable(Layout::Viewport const& layout_viewport) @@ -58,12 +56,12 @@ void ViewportPaintable::build_stacking_context_tree_if_needed() void ViewportPaintable::build_stacking_context_tree() { - set_stacking_context(heap().allocate(*this, nullptr, 0)); + set_stacking_context(StackingContext::create(*this, nullptr, 0)); size_t index_in_tree_order = 1; for_each_in_subtree_of_type([&](auto& paintable_box) { paintable_box.invalidate_stacking_context(); - auto* parent_context = paintable_box.enclosing_stacking_context(); + auto parent_context = paintable_box.enclosing_stacking_context(); auto establishes_stacking_context = paintable_box.layout_node().establishes_stacking_context(); if ((paintable_box.is_positioned() || establishes_stacking_context) && paintable_box.effective_z_index().value_or(0) == 0) parent_context->m_positioned_descendants_and_stacking_contexts_with_stack_level_0.append(paintable_box); @@ -74,7 +72,7 @@ void ViewportPaintable::build_stacking_context_tree() return TraversalDecision::Continue; } VERIFY(parent_context); - paintable_box.set_stacking_context(heap().allocate(paintable_box, parent_context, index_in_tree_order++)); + paintable_box.set_stacking_context(StackingContext::create(paintable_box, parent_context, index_in_tree_order++)); return TraversalDecision::Continue; }); @@ -97,12 +95,13 @@ void ViewportPaintable::assign_scroll_frames() return; auto const& scroll_ancestor_paintable = m_scroll_state.frame_at(nearest_scrolling_ancestor_index).paintable_box(); + RefPtr scroll_ancestor_paintable_ref = scroll_ancestor_paintable; auto sticky_border_box_rect = paintable_box.absolute_border_box_rect(); - auto const* containing_block_of_sticky = paintable_box.containing_block(); + RefPtr containing_block_of_sticky = paintable_box.containing_block(); CSSPixelRect containing_block_region; bool needs_parent_offset_adjustment = false; - if (containing_block_of_sticky == &scroll_ancestor_paintable) { + if (containing_block_of_sticky == scroll_ancestor_paintable_ref) { containing_block_region = { {}, containing_block_of_sticky->scrollable_overflow_rect()->size() }; } else { containing_block_region = containing_block_of_sticky->absolute_border_box_rect() @@ -342,7 +341,8 @@ void ViewportPaintable::assign_accumulated_visual_contexts() set_accumulated_visual_context_for_descendants(viewport_state_for_descendants); for_each_in_subtree_of_type([&](auto& paintable_box) { - auto* visual_parent = as_if(paintable_box.parent()); + auto visual_parent_paintable = paintable_box.parent(); + auto* visual_parent = as_if(visual_parent_paintable.ptr()); if (!visual_parent) return TraversalDecision::Continue; @@ -359,7 +359,7 @@ void ViewportPaintable::assign_accumulated_visual_contexts() inherited_state = m_visual_viewport_context_index; } else if (paintable_box.is_absolutely_positioned()) { // For position: absolute, use containing block's state to correctly escape scroll containers. - auto* containing = paintable_box.containing_block(); + auto containing = paintable_box.containing_block(); inherited_state = containing->accumulated_visual_context_for_descendants_index(); // Abspos elements escape scroll containers and overflow clips of non-positioned @@ -369,8 +369,9 @@ void ViewportPaintable::assign_accumulated_visual_contexts() // NOTE: transforms/perspectives/filters establish containing blocks for abspos, // so they cannot appear as intermediates. Vector intermediate_effects; - for (Paintable* paintable = visual_parent; paintable && paintable != containing; paintable = paintable->parent()) { - auto* ancestor_box = as_if(paintable); + RefPtr containing_paintable = containing; + for (RefPtr paintable = visual_parent; paintable && paintable != containing_paintable; paintable = paintable->parent()) { + auto* ancestor_box = as_if(paintable.ptr()); if (!ancestor_box) continue; if (auto effects = make_effects_data(*ancestor_box); effects.has_value()) @@ -542,14 +543,14 @@ void ViewportPaintable::recompute_selection_states(DOM::Range& range) // 2. If it's a text node, mark it as StartAndEnd and return. if (is(*start_container) && !range.start().node->is_inert()) { - if (auto* paintable = start_container->unsafe_paintable()) + if (auto paintable = start_container->unsafe_paintable()) paintable->set_selection_state(SelectionState::StartAndEnd); return; } } // 3. Mark the selection start node as Start (if text) or Full (if anything else). - if (auto* paintable = start_container->unsafe_paintable(); paintable && !range.start().node->is_inert()) { + if (auto paintable = start_container->unsafe_paintable(); paintable && !range.start().node->is_inert()) { if (is(*start_container)) paintable->set_selection_state(SelectionState::Start); else @@ -572,12 +573,12 @@ void ViewportPaintable::recompute_selection_states(DOM::Range& range) for (auto* node = start_at; node && (node != stop_at && !(node == end_container && !end_container->has_children())); node = node->next_in_pre_order(end_container)) { if (node->is_inert()) continue; - if (auto* paintable = node->unsafe_paintable()) + if (auto paintable = node->unsafe_paintable()) paintable->set_selection_state(SelectionState::Full); } // 5. Mark the selection end node as End if it is a text node. - if (auto* paintable = end_container->unsafe_paintable(); paintable && !range.end().node->is_inert() && is(*end_container)) { + if (auto paintable = end_container->unsafe_paintable(); paintable && !range.end().node->is_inert() && is(*end_container)) { paintable->set_selection_state(SelectionState::End); } } @@ -587,10 +588,4 @@ bool ViewportPaintable::handle_mousewheel(Badge, CSSPixelPoint, un return false; } -void ViewportPaintable::visit_edges(Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_paintable_boxes_with_auto_content_visibility); -} - } diff --git a/Libraries/LibWeb/Painting/ViewportPaintable.h b/Libraries/LibWeb/Painting/ViewportPaintable.h index 91c970f2d5..5252c0769c 100644 --- a/Libraries/LibWeb/Painting/ViewportPaintable.h +++ b/Libraries/LibWeb/Painting/ViewportPaintable.h @@ -14,12 +14,10 @@ namespace Web::Painting { class WEB_API ViewportPaintable final : public PaintableWithLines { - GC_CELL(ViewportPaintable, PaintableWithLines); - GC_DECLARE_ALLOCATOR(ViewportPaintable); - public: - static GC::Ref create(Layout::Viewport const&); + static NonnullRefPtr create(Layout::Viewport const&); virtual ~ViewportPaintable() override; + virtual StringView class_name() const override { return "ViewportPaintable"sv; } virtual void reset_for_relayout() override; @@ -41,8 +39,8 @@ public: ScrollState const& scroll_state() const { return m_scroll_state; } ScrollStateSnapshot const& scroll_state_snapshot() const { return m_scroll_state_snapshot; } - void set_paintable_boxes_with_auto_content_visibility(Vector> paintable_boxes) { m_paintable_boxes_with_auto_content_visibility = move(paintable_boxes); } - ReadonlySpan> paintable_boxes_with_auto_content_visibility() const { return m_paintable_boxes_with_auto_content_visibility; } + void set_paintable_boxes_with_auto_content_visibility(Vector> paintable_boxes) { m_paintable_boxes_with_auto_content_visibility = move(paintable_boxes); } + Vector> const& paintable_boxes_with_auto_content_visibility() const { return m_paintable_boxes_with_auto_content_visibility; } AccumulatedVisualContextTree const& visual_context_tree() const { @@ -62,13 +60,11 @@ private: explicit ViewportPaintable(Layout::Viewport const&); - virtual void visit_edges(Visitor&) override; - ScrollState m_scroll_state; ScrollStateSnapshot m_scroll_state_snapshot; bool m_needs_to_refresh_scroll_state { true }; - Vector> m_paintable_boxes_with_auto_content_visibility; + Vector> m_paintable_boxes_with_auto_content_visibility; RefPtr m_visual_context_tree; VisualContextIndex m_visual_viewport_context_index {}; diff --git a/Libraries/LibWeb/SVG/SVGFilterElement.cpp b/Libraries/LibWeb/SVG/SVGFilterElement.cpp index 15c92b1c6a..ebf82cd37d 100644 --- a/Libraries/LibWeb/SVG/SVGFilterElement.cpp +++ b/Libraries/LibWeb/SVG/SVGFilterElement.cpp @@ -281,7 +281,7 @@ Optional SVGFilterElement::gfx_filter(Layout::NodeWithStyle const& // during layout update, before the layout-is-up-to-date flag // has been set. The paintable is valid since layout has already // been performed at this point. - auto* paintable_box = dom_node->unsafe_paintable_box(); + auto paintable_box = dom_node->unsafe_paintable_box(); if (!paintable_box) return IterationDecision::Continue; diff --git a/Libraries/LibWeb/SVG/SVGPatternElement.cpp b/Libraries/LibWeb/SVG/SVGPatternElement.cpp index 9b7d24db65..f99887db2f 100644 --- a/Libraries/LibWeb/SVG/SVGPatternElement.cpp +++ b/Libraries/LibWeb/SVG/SVGPatternElement.cpp @@ -249,7 +249,7 @@ Optional SVGPatternElement::to_gfx_paint_style(SVGPaintCon if (!pattern_box) return {}; - auto* pattern_paintable = pattern_box->paintable_box(); + auto pattern_paintable = pattern_box->paintable_box(); if (!pattern_paintable) return {}; @@ -296,7 +296,8 @@ Optional SVGPatternElement::to_gfx_paint_style(SVGPaintCon auto paint_context_copy = recording_context.clone(display_list_recorder); Gfx::AffineTransform target_svg_transform; - if (auto const* svg_graphics_paintable = as_if(*target_layout_node.first_paintable())) + auto first_paintable = target_layout_node.first_paintable(); + if (auto const* svg_graphics_paintable = as_if(first_paintable.ptr())) target_svg_transform = svg_graphics_paintable->computed_transforms().svg_transform(); paint_context_copy.set_svg_transform(target_svg_transform); diff --git a/Libraries/LibWeb/Selection/Selection.cpp b/Libraries/LibWeb/Selection/Selection.cpp index e49a6b1fe9..21494114da 100644 --- a/Libraries/LibWeb/Selection/Selection.cpp +++ b/Libraries/LibWeb/Selection/Selection.cpp @@ -734,7 +734,7 @@ void Selection::scroll_focus_into_view() m_document->update_layout(DOM::UpdateLayoutReason::ScrollCursorIntoView); - auto* paintable = focus->paintable(); + auto paintable = focus->paintable(); if (!paintable) return; diff --git a/Libraries/LibWeb/TreeNode.h b/Libraries/LibWeb/TreeNode.h index d5a4fc4c48..7d9b3f96d0 100644 --- a/Libraries/LibWeb/TreeNode.h +++ b/Libraries/LibWeb/TreeNode.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include diff --git a/Libraries/LibWeb/WebDriver/Actions.cpp b/Libraries/LibWeb/WebDriver/Actions.cpp index 89661f3f96..4de4306cd4 100644 --- a/Libraries/LibWeb/WebDriver/Actions.cpp +++ b/Libraries/LibWeb/WebDriver/Actions.cpp @@ -150,7 +150,7 @@ static CSSPixelPoint get_parent_offset(HTML::BrowsingContext const& browsing_con CSSPixels border_left_width = 0; CSSPixels border_top_width = 0; - if (auto* paintable_box = container_element->paintable_box()) { + if (auto paintable_box = container_element->paintable_box()) { // 7. Let borderLeftWidth be the computed border-left-width of containerElement in CSS pixels. border_left_width = paintable_box->computed_values().border_left().width; diff --git a/Libraries/LibWeb/WebDriver/ElementReference.cpp b/Libraries/LibWeb/WebDriver/ElementReference.cpp index f9ff8c9f11..608809fcf2 100644 --- a/Libraries/LibWeb/WebDriver/ElementReference.cpp +++ b/Libraries/LibWeb/WebDriver/ElementReference.cpp @@ -257,7 +257,7 @@ bool is_element_pointer_interactable(Web::HTML::BrowsingContext const& browsing_ if (!document) return false; - auto const* paint_root = document->paintable_box(); + auto paint_root = document->paintable_box(); if (!paint_root) return false; diff --git a/Services/WebContent/ConnectionFromClient.cpp b/Services/WebContent/ConnectionFromClient.cpp index d34394d7bc..4c967826a0 100644 --- a/Services/WebContent/ConnectionFromClient.cpp +++ b/Services/WebContent/ConnectionFromClient.cpp @@ -307,7 +307,7 @@ void ConnectionFromClient::debug_request(u64 page_id, ByteString request, ByteSt if (request == "dump-paint-tree") { if (auto* doc = page->page().top_level_browsing_context().active_document()) { - if (auto* paintable = doc->paintable()) + if (auto paintable = doc->paintable()) Web::dump_tree(*paintable); } return; @@ -318,7 +318,7 @@ void ConnectionFromClient::debug_request(u64 page_id, ByteString request, ByteSt if (auto* viewport = doc->layout_node()) { auto& viewport_paintable = static_cast(*viewport->paintable_box()); viewport_paintable.build_stacking_context_tree_if_needed(); - if (auto* stacking_context = viewport_paintable.stacking_context()) { + if (auto stacking_context = viewport_paintable.stacking_context()) { StringBuilder builder; stacking_context->dump(builder); dbgln("{}", builder.string_view()); @@ -517,11 +517,12 @@ void ConnectionFromClient::inspect_dom_node(u64 page_id, WebView::DOMNodePropert }; auto serialize_layout = [&](Web::Layout::Node const* layout_node) { - if (!layout_node || !layout_node->is_box() || !layout_node->first_paintable() || !layout_node->first_paintable()->is_paintable_box()) { + auto first_paintable = layout_node ? layout_node->first_paintable() : nullptr; + if (!layout_node || !layout_node->is_box() || !first_paintable || !first_paintable->is_paintable_box()) { return JsonObject {}; } - auto const& paintable_box = as(*layout_node->first_paintable()); + auto const& paintable_box = as(*first_paintable); auto const& box_model = paintable_box.box_model(); JsonObject serialized; @@ -1025,7 +1026,7 @@ static void append_stacking_context_tree(Web::Page& page, StringBuilder& builder auto& viewport_paintable = static_cast(*layout_root->paintable_box()); viewport_paintable.build_stacking_context_tree_if_needed(); - if (auto* stacking_context = viewport_paintable.stacking_context()) { + if (auto stacking_context = viewport_paintable.stacking_context()) { stacking_context->dump(builder); } }