Skip to content

Commit dba261f

Browse files
trflynn89awesomekling
authored andcommitted
LibWeb: Propagate body background properties to root HTML element
The Acid1 test has a bit of an unusual background - the html and body tags have different background colors. Our painting order of the DOM was such that the body background was painted first, then all other elements were painted in-phase according to Appendix E of CSS 2.1. So the html element's background color was painted over the body background. This removes the special handling of the body background from InitialContainingBlockBox and now all boxes are painted in-phase. Doing this also exposed that we weren't handling Section 2.11.2 of the spec; when the html background is unset, the body's background should be propagated to the html element.
1 parent d1ed6bc commit dba261f

File tree

5 files changed

+42
-20
lines changed

5 files changed

+42
-20
lines changed

Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,12 @@ HTMLHtmlElement::~HTMLHtmlElement()
1717
{
1818
}
1919

20+
bool HTMLHtmlElement::should_use_body_background_properties() const
21+
{
22+
auto background_color = layout_node()->computed_values().background_color();
23+
const auto* background_image = layout_node()->background_image();
24+
25+
return (background_color == Color::Transparent) && !background_image;
26+
}
27+
2028
}

Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class HTMLHtmlElement final : public HTMLElement {
1616

1717
HTMLHtmlElement(DOM::Document&, QualifiedName);
1818
virtual ~HTMLHtmlElement() override;
19+
20+
bool should_use_body_background_properties() const;
1921
};
2022

2123
}

Userland/Libraries/LibWeb/Layout/Box.cpp

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <LibGfx/Painter.h>
88
#include <LibWeb/DOM/Document.h>
99
#include <LibWeb/HTML/HTMLBodyElement.h>
10+
#include <LibWeb/HTML/HTMLHtmlElement.h>
1011
#include <LibWeb/Layout/BlockBox.h>
1112
#include <LibWeb/Layout/Box.h>
1213
#include <LibWeb/Page/Frame.h>
@@ -25,13 +26,37 @@ void Box::paint(PaintContext& context, PaintPhase phase)
2526

2627
auto padded_rect = this->padded_rect();
2728

28-
if (phase == PaintPhase::Background && !is_body()) {
29-
auto background_rect = enclosing_int_rect(padded_rect);
30-
context.painter().fill_rect(background_rect, computed_values().background_color());
31-
32-
if (background_image() && background_image()->bitmap()) {
33-
paint_background_image(context, *background_image()->bitmap(), computed_values().background_repeat_x(), computed_values().background_repeat_y(), move(background_rect));
29+
if (phase == PaintPhase::Background) {
30+
// If the body's background properties were propagated to the root element, do no re-paint the body's background.
31+
if (is_body() && document().html_element()->should_use_body_background_properties())
32+
return;
33+
34+
Gfx::IntRect background_rect;
35+
36+
Color background_color = computed_values().background_color();
37+
const Gfx::Bitmap* background_image = this->background_image() ? this->background_image()->bitmap() : nullptr;
38+
CSS::Repeat background_repeat_x = computed_values().background_repeat_x();
39+
CSS::Repeat background_repeat_y = computed_values().background_repeat_y();
40+
41+
if (is_root_element()) {
42+
// CSS 2.1 Appendix E.2: If the element is a root element, paint the background over the entire canvas.
43+
background_rect = context.viewport_rect();
44+
45+
// Section 2.11.2: If the computed value of background-image on the root element is none and its background-color is transparent,
46+
// user agents must instead propagate the computed values of the background properties from that element’s first HTML BODY child element.
47+
if (document().html_element()->should_use_body_background_properties()) {
48+
background_color = document().background_color(context.palette());
49+
background_image = document().background_image();
50+
background_repeat_x = document().background_repeat_x();
51+
background_repeat_y = document().background_repeat_y();
52+
}
53+
} else {
54+
background_rect = enclosing_int_rect(padded_rect);
3455
}
56+
57+
context.painter().fill_rect(background_rect, move(background_color));
58+
if (background_image)
59+
paint_background_image(context, *background_image, background_repeat_x, background_repeat_y, move(background_rect));
3560
}
3661

3762
if (phase == PaintPhase::Border) {

Userland/Libraries/LibWeb/Layout/InitialContainingBlockBox.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,20 +42,9 @@ void InitialContainingBlockBox::build_stacking_context_tree()
4242
});
4343
}
4444

45-
void InitialContainingBlockBox::paint_document_background(PaintContext& context)
46-
{
47-
context.painter().fill_rect(Gfx::IntRect { {}, context.viewport_rect().size() }, document().background_color(context.palette()));
48-
context.painter().translate(-context.viewport_rect().location());
49-
50-
if (auto background_bitmap = document().background_image()) {
51-
Gfx::IntRect background_rect = { 0, 0, context.viewport_rect().x() + context.viewport_rect().width(), context.viewport_rect().y() + context.viewport_rect().height() };
52-
paint_background_image(context, *background_bitmap, document().background_repeat_x(), document().background_repeat_y(), move(background_rect));
53-
}
54-
}
55-
5645
void InitialContainingBlockBox::paint_all_phases(PaintContext& context)
5746
{
58-
paint_document_background(context);
47+
context.painter().translate(-context.viewport_rect().location());
5948
stacking_context()->paint(context);
6049
}
6150

Userland/Libraries/LibWeb/Layout/InitialContainingBlockBox.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ class InitialContainingBlockBox final : public BlockBox {
2020

2121
void paint_all_phases(PaintContext&);
2222

23-
void paint_document_background(PaintContext&);
24-
2523
virtual HitTestResult hit_test(const Gfx::IntPoint&, HitTestType) const override;
2624

2725
const LayoutRange& selection() const { return m_selection; }

0 commit comments

Comments
 (0)