diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp index c236fb2b6c..e6d22e12ac 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp @@ -460,6 +460,18 @@ void LayoutState::commit(Box& root) resolve_border_radii(); resolve_box_shadow_data(); + + for (auto& it : used_values_per_layout_node) { + auto& used_values = *it.value; + auto& node = const_cast(used_values.node()); + auto* paintable = node.paintable(); + if (paintable && is(*paintable)) { + auto& inline_paintable = static_cast(*paintable); + // FIXME: Marking fragments contained by inline node is a hack required to skip them while painting + // PaintableWithLines content. + inline_paintable.mark_contained_fragments(); + } + } } void LayoutState::UsedValues::set_node(NodeWithStyle& node, UsedValues const* containing_block_used_values) diff --git a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h index cdefae8740..07ace56168 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h +++ b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h @@ -79,6 +79,9 @@ public: Painting::BorderRadiiData const& border_radii_data() const { return m_border_radii_data; } void set_border_radii_data(Painting::BorderRadiiData const& border_radii_data) { m_border_radii_data = border_radii_data; } + bool contained_by_inline_node() const { return m_contained_by_inline_node; } + void set_contained_by_inline_node() { m_contained_by_inline_node = true; } + private: JS::NonnullGCPtr m_layout_node; int m_start { 0 }; @@ -90,6 +93,7 @@ private: CSSPixels m_baseline { 0 }; Vector m_glyph_run; Painting::BorderRadiiData m_border_radii_data; + bool m_contained_by_inline_node { false }; }; } diff --git a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp index ceb4883b35..3ffb27a542 100644 --- a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp @@ -146,6 +146,13 @@ void InlinePaintable::paint(PaintContext& context, PaintPhase phase) const } } + if (phase == PaintPhase::Foreground) { + for_each_fragment([&](auto const& fragment, bool, bool) { + if (is(fragment.layout_node())) + paint_text_fragment(context, static_cast(fragment.layout_node()), fragment, phase); + }); + } + if (phase == PaintPhase::Overlay && layout_node().document().inspected_layout_node() == &layout_node()) { // FIXME: This paints a double-thick border between adjacent fragments, where ideally there // would be none. Once we implement non-rectangular outlines for the `outline` CSS @@ -173,6 +180,15 @@ void InlinePaintable::for_each_fragment(Callback callback) const } } +void InlinePaintable::mark_contained_fragments() +{ + verify_cast(*containing_block()->paintable_box()).for_each_fragment([&](auto& fragment) { + if (layout_node().is_inclusive_ancestor_of(fragment.layout_node())) + const_cast(fragment).set_contained_by_inline_node(); + return IterationDecision::Continue; + }); +} + CSSPixelRect InlinePaintable::bounding_rect() const { auto top = CSSPixels::max(); diff --git a/Userland/Libraries/LibWeb/Painting/InlinePaintable.h b/Userland/Libraries/LibWeb/Painting/InlinePaintable.h index 204413be6b..6718bed6c5 100644 --- a/Userland/Libraries/LibWeb/Painting/InlinePaintable.h +++ b/Userland/Libraries/LibWeb/Painting/InlinePaintable.h @@ -24,6 +24,8 @@ public: CSSPixelRect bounding_rect() const; + void mark_contained_fragments(); + private: InlinePaintable(Layout::InlineNode const&); diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index 1ee868c4aa..3218d6ef6d 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -484,7 +484,7 @@ void PaintableBox::clear_clip_overflow_rect(PaintContext& context, PaintPhase ph } } -static void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment) +void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment) { auto const& browsing_context = text_node.browsing_context(); @@ -518,7 +518,7 @@ static void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const context.recording_painter().draw_rect(cursor_device_rect, text_node.computed_values().color()); } -static void paint_text_decoration(PaintContext& context, Layout::Node const& text_node, Layout::LineBoxFragment const& fragment) +void paint_text_decoration(PaintContext& context, Layout::Node const& text_node, Layout::LineBoxFragment const& fragment) { auto& painter = context.recording_painter(); auto& font = fragment.layout_node().first_available_font(); @@ -600,7 +600,7 @@ static void paint_text_decoration(PaintContext& context, Layout::Node const& tex } } -static void paint_text_fragment(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment, PaintPhase phase) +void paint_text_fragment(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment, PaintPhase phase) { auto& painter = context.recording_painter(); @@ -680,6 +680,8 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const if (phase == PaintPhase::Foreground) { for (auto& line_box : m_line_boxes) { for (auto& fragment : line_box.fragments()) { + if (fragment.contained_by_inline_node()) + continue; if (is(fragment.layout_node())) { auto& text_shadow = fragment.layout_node().computed_values().text_shadow(); if (!text_shadow.is_empty()) { @@ -704,6 +706,8 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const for (auto& line_box : m_line_boxes) { for (auto& fragment : line_box.fragments()) { + if (fragment.contained_by_inline_node()) + continue; auto fragment_absolute_rect = fragment.absolute_rect(); auto fragment_absolute_device_rect = context.enclosing_device_rect(fragment_absolute_rect); if (context.should_show_line_box_borders()) { diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index c30ab28175..85a5d8f861 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -272,4 +272,8 @@ private: Vector m_line_boxes; }; +void paint_text_decoration(PaintContext& context, Layout::Node const& text_node, Layout::LineBoxFragment const& fragment); +void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment); +void paint_text_fragment(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment, PaintPhase phase); + }