diff --git a/Tests/LibWeb/Ref/reference/images/css-background-repeat-ref.png b/Tests/LibWeb/Ref/reference/images/css-background-repeat-ref.png index 6472b658db..80a21b736a 100644 Binary files a/Tests/LibWeb/Ref/reference/images/css-background-repeat-ref.png and b/Tests/LibWeb/Ref/reference/images/css-background-repeat-ref.png differ diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp index f7a081c034..7581855b83 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -2032,4 +2033,45 @@ void Navigable::inform_the_navigation_api_about_aborting_navigation() }); } +void Navigable::paint(Painting::RecordingPainter& recording_painter, PaintConfig config) +{ + auto document = active_document(); + if (!document) + return; + + auto const& page = traversable_navigable()->page(); + auto viewport_rect = page.css_to_device_rect(this->viewport_rect()); + Gfx::IntRect bitmap_rect { {}, viewport_rect.size().to_type() }; + + document->update_layout(); + auto background_color = document->background_color(); + + recording_painter.fill_rect(bitmap_rect, background_color); + if (!document->paintable()) + return; + + Web::PaintContext context(recording_painter, page.palette(), page.client().device_pixels_per_css_pixel()); + context.set_device_viewport_rect(viewport_rect); + context.set_should_show_line_box_borders(config.should_show_line_box_borders); + context.set_should_paint_overlay(config.paint_overlay); + context.set_has_focus(config.has_focus); + + if (is_traversable()) { + document->paintable()->collect_scroll_frames(context); + } + + document->paintable()->paint_all_phases(context); + + // FIXME: Support scrollable frames inside iframes. + if (is_traversable()) { + Vector scroll_offsets_by_frame_id; + scroll_offsets_by_frame_id.resize(context.scroll_frames().size()); + for (auto [_, scrollable_frame] : context.scroll_frames()) + scroll_offsets_by_frame_id[scrollable_frame.id] = context.rounded_device_point( + scrollable_frame.offset) + .to_type(); + recording_painter.apply_scroll_offsets(scroll_offsets_by_frame_id); + } +} + } diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.h b/Userland/Libraries/LibWeb/HTML/Navigable.h index 94827f7fa7..7de25ca6c9 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.h +++ b/Userland/Libraries/LibWeb/HTML/Navigable.h @@ -170,6 +170,13 @@ public: [[nodiscard]] TargetSnapshotParams snapshot_target_snapshot_params(); + struct PaintConfig { + bool paint_overlay { false }; + bool should_show_line_box_borders { false }; + bool has_focus { false }; + }; + void paint(Painting::RecordingPainter&, PaintConfig); + protected: Navigable(); diff --git a/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp b/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp index c819a70a91..6850da2c69 100644 --- a/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp @@ -41,25 +41,25 @@ void NestedBrowsingContextPaintable::paint(PaintContext& context, PaintPhase pha auto clip_rect = context.rounded_device_rect(absolute_rect); ScopedCornerRadiusClip corner_clip { context, clip_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) }; - auto* hosted_document = layout_box().dom_node().content_document_without_origin_check(); + auto const* hosted_document = layout_box().dom_node().content_document_without_origin_check(); if (!hosted_document) return; - auto* hosted_paint_tree = hosted_document->paintable(); + auto const* hosted_paint_tree = hosted_document->paintable(); if (!hosted_paint_tree) return; context.recording_painter().save(); - auto old_viewport_rect = context.device_viewport_rect(); context.recording_painter().add_clip_rect(clip_rect.to_type()); - auto absolute_device_rect = context.enclosing_device_rect(absolute_rect); context.recording_painter().translate(absolute_device_rect.x().value(), absolute_device_rect.y().value()); - context.set_device_viewport_rect({ {}, context.enclosing_device_size(layout_box().dom_node().content_navigable()->size()) }); - const_cast(hosted_paint_tree)->paint_all_phases(context); + HTML::Navigable::PaintConfig paint_config; + paint_config.paint_overlay = context.should_paint_overlay(); + paint_config.should_show_line_box_borders = context.should_show_line_box_borders(); + paint_config.has_focus = context.has_focus(); + const_cast(hosted_document)->navigable()->paint(context.recording_painter(), paint_config); - context.set_device_viewport_rect(old_viewport_rect); context.recording_painter().restore(); if constexpr (HIGHLIGHT_FOCUSED_FRAME_DEBUG) { diff --git a/Userland/Services/WebContent/PageClient.cpp b/Userland/Services/WebContent/PageClient.cpp index b15f9b4ec4..77d3255464 100644 --- a/Userland/Services/WebContent/PageClient.cpp +++ b/Userland/Services/WebContent/PageClient.cpp @@ -171,48 +171,18 @@ Web::Layout::Viewport* PageClient::layout_root() return document->layout_node(); } -Gfx::Color PageClient::background_color() const -{ - auto document = page().top_level_browsing_context().active_document(); - if (!document) - return Gfx::Color::Transparent; - return document->background_color(); -} - void PageClient::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& target, Web::PaintOptions paint_options) { - Gfx::IntRect bitmap_rect { {}, content_rect.size().to_type() }; - - auto document = page().top_level_browsing_context().active_document(); - if (document) { - document->update_layout(); - } - - auto background_color = this->background_color(); - Web::Painting::RecordingPainter recording_painter; - Web::PaintContext context(recording_painter, palette(), device_pixels_per_css_pixel()); - if (background_color.alpha() < 255) - recording_painter.fill_rect(bitmap_rect, Web::CSS::SystemColor::canvas()); - recording_painter.fill_rect(bitmap_rect, background_color); + Gfx::IntRect bitmap_rect { {}, content_rect.size().to_type() }; + recording_painter.fill_rect(bitmap_rect, Web::CSS::SystemColor::canvas()); - if (!document->paintable()) - return; - - context.set_should_show_line_box_borders(m_should_show_line_box_borders); - context.set_should_paint_overlay(paint_options.paint_overlay == Web::PaintOptions::PaintOverlay::Yes); - context.set_device_viewport_rect(content_rect); - context.set_has_focus(m_has_focus); - - document->paintable()->collect_scroll_frames(context); - document->paintable()->paint_all_phases(context); - - Vector scroll_offsets_by_frame_id; - scroll_offsets_by_frame_id.resize(context.scroll_frames().size()); - for (auto [_, scrollable_frame] : context.scroll_frames()) - scroll_offsets_by_frame_id[scrollable_frame.id] = context.rounded_device_point(scrollable_frame.offset).to_type(); - recording_painter.apply_scroll_offsets(scroll_offsets_by_frame_id); + Web::HTML::Navigable::PaintConfig paint_config; + paint_config.paint_overlay = paint_options.paint_overlay == Web::PaintOptions::PaintOverlay::Yes; + paint_config.should_show_line_box_borders = m_should_show_line_box_borders; + paint_config.has_focus = m_has_focus; + page().top_level_traversable()->paint(recording_painter, paint_config); if (s_use_gpu_painter) { #ifdef HAS_ACCELERATED_GRAPHICS diff --git a/Userland/Services/WebContent/PageClient.h b/Userland/Services/WebContent/PageClient.h index 2c0589c353..2b6b167f92 100644 --- a/Userland/Services/WebContent/PageClient.h +++ b/Userland/Services/WebContent/PageClient.h @@ -61,12 +61,12 @@ public: void color_picker_update(Optional picked_color, Web::HTML::ColorPickerUpdateState state); void select_dropdown_closed(Optional value); - [[nodiscard]] Gfx::Color background_color() const; - void set_user_style(String source); void ready_to_paint(); + virtual double device_pixels_per_css_pixel() const override { return m_device_pixels_per_css_pixel; } + private: PageClient(PageHost&, u64 id); @@ -76,7 +76,6 @@ private: virtual bool is_connection_open() const override; virtual Gfx::Palette palette() const override; virtual Web::DevicePixelRect screen_rect() const override { return m_screen_rect; } - virtual double device_pixels_per_css_pixel() const override { return m_device_pixels_per_css_pixel; } virtual Web::CSS::PreferredColorScheme preferred_color_scheme() const override { return m_preferred_color_scheme; } virtual void page_did_invalidate(Web::CSSPixelRect const&) override; virtual void page_did_request_cursor_change(Gfx::StandardCursor) override;