Skip to content

Commit

Permalink
LibWeb+WebContent: Move paint recording init into Navigable
Browse files Browse the repository at this point in the history
This refactoring makes WebContent less aware of LibWeb internals.
The code that initializes paint recording commands now resides in
`Navigable::paint()`. Additionally, we no longer need to reuse
PaintContext across iframes, allowing us to avoid saving and restoring
its state before recursing into an iframe.
  • Loading branch information
kalenikaliaksandr authored and awesomekling committed Jan 15, 2024
1 parent 72dd374 commit cc447c9
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 47 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions Userland/Libraries/LibWeb/HTML/Navigable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <LibWeb/Loader/GeneratedPagesLoader.h>
#include <LibWeb/Page/Page.h>
#include <LibWeb/Painting/Paintable.h>
#include <LibWeb/Painting/ViewportPaintable.h>
#include <LibWeb/Platform/EventLoopPlugin.h>
#include <LibWeb/XHR/FormData.h>

Expand Down Expand Up @@ -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<int>() };

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<Gfx::IntPoint> 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<int>();
recording_painter.apply_scroll_offsets(scroll_offsets_by_frame_id);
}
}

}
7 changes: 7 additions & 0 deletions Userland/Libraries/LibWeb/HTML/Navigable.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ class Navigable : public JS::Cell {

[[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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<int>());

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<ViewportPaintable*>(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<DOM::Document*>(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) {
Expand Down
44 changes: 7 additions & 37 deletions Userland/Services/WebContent/PageClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<int>() };

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);

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);
Gfx::IntRect bitmap_rect { {}, content_rect.size().to_type<int>() };
recording_painter.fill_rect(bitmap_rect, Web::CSS::SystemColor::canvas());

Vector<Gfx::IntPoint> 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<int>();
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
Expand Down
5 changes: 2 additions & 3 deletions Userland/Services/WebContent/PageClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ class PageClient final : public Web::PageClient {
void color_picker_update(Optional<Color> picked_color, Web::HTML::ColorPickerUpdateState state);
void select_dropdown_closed(Optional<String> 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);

Expand All @@ -76,7 +76,6 @@ class PageClient final : public Web::PageClient {
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;
Expand Down

0 comments on commit cc447c9

Please sign in to comment.