Skip to content

Commit 9034707

Browse files
committed
vaev-driver: Handle correctly HTML/BODY backgrounds outside of layout builder.
1 parent 33e99c1 commit 9034707

File tree

8 files changed

+216
-21
lines changed

8 files changed

+216
-21
lines changed

src/main.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ Async::Task<> renderAsync(
164164
};
165165

166166
auto media = constructMediaForRender(options.scale, imageSize);
167-
auto [style, layout, paint, frags] = Vaev::Driver::render(*dom, media, {.small = imageSize});
167+
auto [style, layout, paint, frags, canvasColor] = Vaev::Driver::render(*dom, media, {.small = imageSize});
168168

169169
auto image = Gfx::Surface::alloc(
170170
imageSize.cast<isize>() * options.density.toDppx(),
@@ -173,7 +173,15 @@ Async::Task<> renderAsync(
173173

174174
Gfx::CpuCanvas g;
175175
g.begin(*image);
176-
g.clear(Gfx::WHITE);
176+
177+
if (canvasColor.alpha < 255) {
178+
g.clear(Gfx::WHITE);
179+
auto rectangle = Math::Rectf{0, 0, options.width._val, options.height._val};
180+
g.fillStyle(canvasColor);
181+
g.fill(rectangle.cast<i64>(), Math::Radiif{0});
182+
} else
183+
g.clear(canvasColor);
184+
177185
g.scale(options.density.toDppx());
178186
paint->paint(g);
179187
if (options.wireframe)

src/web/vaev-driver/render.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export struct RenderResult {
2020
Rc<Layout::Box> layout;
2121
Rc<Scene::Node> scenes;
2222
Rc<Layout::Frag> frag;
23+
Gfx::Color canvasColor;
2324
};
2425

2526
export RenderResult render(Gc::Ref<Dom::Document> dom, Style::Media const& media, Layout::Viewport viewport) {
@@ -45,9 +46,11 @@ export RenderResult render(Gc::Ref<Dom::Document> dom, Style::Media const& media
4546

4647
Layout::Tree tree = {
4748
Layout::build(computer, dom),
48-
viewport,
49+
viewport
4950
};
5051

52+
auto canvasColor = Layout::BGSearch(computer, dom, tree);
53+
5154
elapsed = Sys::now() - start;
5255

5356
logDebugIf(DEBUG_RENDER, "layout tree build time: {}", elapsed);
@@ -79,7 +82,8 @@ export RenderResult render(Gc::Ref<Dom::Document> dom, Style::Media const& media
7982
std::move(stylebook),
8083
makeRc<Layout::Box>(std::move(tree.root)),
8184
sceneRoot,
82-
makeRc<Layout::Frag>(std::move(root))
85+
makeRc<Layout::Frag>(std::move(root)),
86+
canvasColor
8387
};
8488
}
8589

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
module;
2+
3+
#include <karm-image/loader.h>
4+
#include <karm-text/loader.h>
5+
#include <karm-text/prose.h>
6+
#include <vaev-dom/document.h>
7+
#include <vaev-style/computer.h>
8+
9+
export module Vaev.Layout:backgroundCanvas;
10+
11+
import :values;
12+
13+
namespace Vaev::Layout {
14+
15+
Gfx::Color ColorToGfx(Color color) {
16+
if (auto isRes = color.is<Gfx::Color>()) {
17+
return *isRes;
18+
} else {
19+
logWarn("color was not a Gfx color");
20+
return Gfx::WHITE;
21+
}
22+
}
23+
24+
void patchBackgrounds(MutSlice<Layout::Box>& children) {
25+
for (auto& child : children) {
26+
if (child.origin->tagName == Html::BODY) {
27+
child.style->backgrounds.cow().color = Gfx::ALPHA;
28+
}
29+
}
30+
}
31+
32+
export Gfx::Color BGSearch(Style::Computer& c, Gc::Ref<Dom::Document> doc, Layout::Tree& tree) {
33+
auto el = doc->documentElement();
34+
if (!el) {
35+
return Gfx::WHITE;
36+
}
37+
38+
auto style = c.computeFor(Style::Computed::initial(), *el);
39+
if (style->backgrounds->color != Gfx::ALPHA) {
40+
tree.root.style->backgrounds.cow().color = Gfx::ALPHA;
41+
return ColorToGfx(style->backgrounds->color);
42+
}
43+
44+
for (auto child = el->firstChild(); child; child = child->nextSibling()) {
45+
if (auto isRes = child->is<Dom::Element>()) {
46+
if (isRes->tagName != Html::BODY) {
47+
continue;
48+
}
49+
50+
auto childStyle = c.computeFor(*style, *isRes);
51+
if (childStyle->backgrounds->color != Gfx::ALPHA) {
52+
auto children = tree.root.children();
53+
patchBackgrounds(children);
54+
return ColorToGfx(childStyle->backgrounds->color);
55+
} else {
56+
return Gfx::WHITE;
57+
}
58+
}
59+
}
60+
61+
return Gfx::WHITE;
62+
}
63+
64+
} // namespace Vaev::Layout

src/web/vaev-layout/base.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,12 +254,13 @@ struct Box : public Meta::NoCopy {
254254
Content content = NONE;
255255
Attrs attrs;
256256
Opt<Rc<FormatingContext>> formatingContext = NONE;
257+
Gc::Ptr<Dom::Element> origin;
257258

258-
Box(Rc<Style::Computed> style, Rc<Text::Fontface> font)
259-
: style{std::move(style)}, fontFace{font} {}
259+
Box(Rc<Style::Computed> style, Rc<Text::Fontface> font, Gc::Ptr<Dom::Element> og)
260+
: style{std::move(style)}, fontFace{font} , origin{og} {}
260261

261-
Box(Rc<Style::Computed> style, Rc<Text::Fontface> font, Content content)
262-
: style{std::move(style)}, fontFace{font}, content{std::move(content)} {}
262+
Box(Rc<Style::Computed> style, Rc<Text::Fontface> font, Content content, Gc::Ptr<Dom::Element> og)
263+
: style{std::move(style)}, fontFace{font}, content{std::move(content)} , origin{og} {}
263264

264265
Slice<Box> children() const {
265266
if (auto children = content.is<Vec<Box>>())

src/web/vaev-layout/builder.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ static void _buildRun(Style::Computer& c, Gc::Ref<Dom::Text> node, Box& parent)
175175
}
176176
}
177177

178-
parent.add({style, fontFace, std::move(prose)});
178+
parent.add({style, fontFace, std::move(prose), nullptr});
179179
}
180180

181181
// MARK: Build Block -----------------------------------------------------------
@@ -188,7 +188,7 @@ void _buildChildren(Style::Computer& c, Gc::Ref<Dom::Node> node, Box& parent) {
188188

189189
static void _buildBlock(Style::Computer& c, Rc<Style::Computed> style, Gc::Ref<Dom::Element> el, Box& parent) {
190190
auto font = _lookupFontface(c.fontBook, *style);
191-
Box box = {style, font};
191+
Box box = {style, font, el};
192192
_buildChildren(c, el, box);
193193
box.attrs = _parseDomAttr(el);
194194
parent.add(std::move(box));
@@ -207,7 +207,7 @@ static void _buildImage(Style::Computer& c, Gc::Ref<Dom::Element> el, Box& paren
207207
auto img = Karm::Image::load(url).unwrapOrElse([] {
208208
return Karm::Image::loadOrFallback("bundle://vaev-driver/missing.qoi"_url).unwrap();
209209
});
210-
parent.add({style, font, img});
210+
parent.add({style, font, img, el});
211211
}
212212

213213
// MARK: Build Table -----------------------------------------------------------
@@ -216,6 +216,7 @@ static void _buildTableChildren(Style::Computer& c, Gc::Ref<Dom::Node> node, Box
216216
Box tableBox{
217217
tableBoxStyle,
218218
tableWrapperBox.fontFace,
219+
node->is<Dom::Element>()
219220
};
220221

221222
tableBox.style->display = Display::Internal::TABLE_BOX;
@@ -259,7 +260,7 @@ static void _buildTable(Style::Computer& c, Rc<Style::Computed> style, Gc::Ref<D
259260
wrapperStyle->display = style->display;
260261
wrapperStyle->margin = style->margin;
261262

262-
Box wrapper = {wrapperStyle, font};
263+
Box wrapper = {wrapperStyle, font, el};
263264
_buildTableChildren(c, el, wrapper, style);
264265
wrapper.attrs = _parseDomAttr(el);
265266

@@ -295,16 +296,14 @@ static void _buildNode(Style::Computer& c, Gc::Ref<Dom::Node> node, Box& parent)
295296
_buildElement(c, *el, parent);
296297
} else if (auto text = node->is<Dom::Text>()) {
297298
_buildRun(c, *text, parent);
298-
} else if (auto doc = node->is<Dom::Document>()) {
299-
_buildChildren(c, *doc, parent);
300299
}
301300
}
302301

303302
export Box build(Style::Computer& c, Gc::Ref<Dom::Document> doc) {
304303
if (auto el = doc->documentElement()) {
305304
auto style = c.computeFor(Style::Computed::initial(), *el);
306305
auto font = _lookupFontface(c.fontBook, *style);
307-
Box root = {style, _lookupFontface(c.fontBook, *style)};
306+
Box root = {style, _lookupFontface(c.fontBook, *style), el};
308307
_buildChildren(c, *el, root);
309308
return root;
310309
}
@@ -313,6 +312,7 @@ export Box build(Style::Computer& c, Gc::Ref<Dom::Document> doc) {
313312
return {
314313
style,
315314
_lookupFontface(c.fontBook, *style),
315+
nullptr
316316
};
317317
}
318318

@@ -335,10 +335,10 @@ export Box buildForPseudoElement(Text::FontBook& fontBook, Rc<Style::Computed> s
335335
auto prose = makeRc<Text::Prose>(proseStyle);
336336
if (style->content) {
337337
prose->append(style->content.str());
338-
return {style, fontFace, prose};
338+
return {style, fontFace, prose, nullptr};
339339
}
340340

341-
return {style, fontFace};
341+
return {style, fontFace, nullptr};
342342
}
343343

344344
} // namespace Vaev::Layout

src/web/vaev-layout/mod.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ export import :replaced;
1313
export import :table;
1414
export import :values;
1515
export import :writing;
16+
export import :backgroundCanvas;

src/web/vaev-view/view.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ struct View : public Ui::View<View> {
7171
}
7272

7373
void paint(Gfx::Canvas& g, Math::Recti rect) override {
74+
// Painting browser's viewport.
7475
auto viewport = bound().size();
7576
if (not _renderResult) {
7677
auto media = _constructMedia(viewport);
@@ -82,10 +83,17 @@ struct View : public Ui::View<View> {
8283
g.origin(bound().xy.cast<f64>());
8384
g.clip(viewport);
8485

85-
auto [_, layout, paint, frag] = *_renderResult;
86-
g.clear(rect, Gfx::WHITE);
86+
auto [_, layout, paint, frag, canvasColor] = *_renderResult;
87+
auto paintRect = rect.offset(-bound().xy);
8788

88-
paint->paint(g, rect.offset(-bound().xy).cast<f64>());
89+
if (canvasColor.alpha < 255) {
90+
g.clear(paintRect, Gfx::WHITE);
91+
g.rect(paintRect.cast<f64>());
92+
g.fill(canvasColor);
93+
} else
94+
g.clear(paintRect, canvasColor);
95+
96+
paint->paint(g, paintRect.cast<f64>());
8997
if (_props.wireframe)
9098
Layout::wireframe(*frag, g);
9199

@@ -100,7 +108,7 @@ struct View : public Ui::View<View> {
100108
Math::Vec2i size(Math::Vec2i size, Ui::Hint) override {
101109
// FIXME: This is wasteful, we should cache the result
102110
auto media = _constructMedia(size);
103-
auto [_, layout, _, frag] = Driver::render(*_dom, media, {.small = size.cast<Au>()});
111+
auto [_, layout, _, frag, _] = Driver::render(*_dom, media, {.small = size.cast<Au>()});
104112

105113
return {
106114
frag->metrics.borderBox().width.cast<isize>(),
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<test name="html-body-bg">
2+
<container>
3+
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
4+
5+
<head>
6+
<style>
7+
body {
8+
height: 100svh;
9+
width: 100vw;
10+
margin: 0;
11+
}
12+
13+
html {
14+
height: 100svh;
15+
width: 100vw;
16+
}
17+
18+
#ref {
19+
height: 100svh;
20+
width: 100vw;
21+
background-color: #b98af1;
22+
}
23+
</style>
24+
</head>
25+
26+
<body>
27+
<slot/>
28+
</body>
29+
30+
</html>
31+
</container>
32+
33+
<rendering>
34+
<div id="ref" style="height: 100svh;width: 100vw;background-color: #b98af1;"></div>
35+
</rendering>
36+
37+
<rendering>
38+
<style>
39+
html {
40+
background-color: #b98af1;
41+
}
42+
</style>
43+
</rendering>
44+
45+
<rendering>
46+
<style>
47+
body {
48+
background-color: #b98af1;
49+
}
50+
</style>
51+
</rendering>
52+
53+
<rendering>
54+
<style>
55+
html {
56+
background-color: #b98af1;
57+
}
58+
59+
body {
60+
background-color: #ff2b8d;
61+
display: none;
62+
}
63+
</style>
64+
</rendering>
65+
</test>
66+
<test name="html-body-bg-delete-bg">
67+
<container>
68+
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
69+
70+
<head>
71+
<style>
72+
body {
73+
height: 100svh;
74+
width: 100vw;
75+
margin: 0;
76+
}
77+
78+
html {
79+
height: 100svh;
80+
width: 100vw;
81+
}
82+
83+
#ref {
84+
height: 100svh;
85+
width: 100vw;
86+
background-color: rgba(185, 138, 241, 0.4);
87+
}
88+
</style>
89+
</head>
90+
91+
<body>
92+
<slot/>
93+
</body>
94+
95+
</html>
96+
</container>
97+
98+
<rendering>
99+
<div id="ref" style="height: 100svh;width: 100vw"></div>
100+
</rendering>
101+
102+
<rendering>
103+
<style>
104+
body {
105+
background-color: rgba(185, 138, 241, 0.4);
106+
}
107+
</style>
108+
</rendering>
109+
</test>

0 commit comments

Comments
 (0)