Skip to content

Commit 060627b

Browse files
committed
vaev-driver: Handle correctly HTML/BODY backgrounds outside of layout builder.
1 parent f88a4d5 commit 060627b

File tree

7 files changed

+173
-8
lines changed

7 files changed

+173
-8
lines changed

src/main.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ Async::Task<> renderAsync(
157157
};
158158

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

162162
auto image = Gfx::Surface::alloc(
163163
imageSize.cast<isize>() * options.density.toDppx(),
@@ -166,7 +166,7 @@ Async::Task<> renderAsync(
166166

167167
Gfx::CpuCanvas g;
168168
g.begin(*image);
169-
g.clear(Gfx::WHITE);
169+
g.clear(canvasColor);
170170
g.scale(options.density.toDppx());
171171
paint->paint(g);
172172
if (options.wireframe)

src/web/vaev-driver/render.cpp

+6-2
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) {
@@ -43,9 +44,11 @@ export RenderResult render(Gc::Ref<Dom::Document> dom, Style::Media const& media
4344
Style::Computer computer{media, stylebook, fontBook};
4445
computer.loadFontFaces();
4546

47+
auto canvasColor = Layout::BGSearch(computer, dom);
48+
4649
Layout::Tree tree = {
4750
Layout::build(computer, dom),
48-
viewport,
51+
viewport
4952
};
5053

5154
elapsed = Sys::now() - start;
@@ -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

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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+
static void _searchChildren(Style::Computer& c, Gc::Ref<Dom::Node> node, Box& parent, Color& canvasColor);
16+
17+
static void extractBackground(TagName& tagname, Cow<BackgroundProps>& background, Color& canvasColor) {
18+
if (tagname == Html::HTML and background->color != Gfx::ALPHA) {
19+
canvasColor = background->color;
20+
background.cow().color = Gfx::ALPHA;
21+
}
22+
23+
if (tagname == Html::BODY and canvasColor == Gfx::ALPHA) {
24+
if (background->color != Gfx::ALPHA) {
25+
canvasColor = background->color;
26+
background.cow().color = Gfx::ALPHA;
27+
} else {
28+
canvasColor = Gfx::WHITE;
29+
}
30+
}
31+
}
32+
33+
static void _searchElement(Style::Computer& c, Gc::Ref<Dom::Element> el, Box& parent, Color& canvasColor) {
34+
if (el->tagName == Html::IMG) {
35+
return;
36+
}
37+
38+
auto style = c.computeFor(*parent.style, el);
39+
40+
auto display = style->display;
41+
extractBackground(el->tagName, style->backgrounds, canvasColor);
42+
43+
if (display == Display::NONE) {
44+
// Do nothing
45+
} else if (display == Display::CONTENTS) {
46+
_searchChildren(c, el, parent, canvasColor);
47+
} else if (display == Display::TABLE) {
48+
return;
49+
} else {
50+
return;
51+
}
52+
}
53+
54+
static void _searchNode(Style::Computer& c, Gc::Ref<Dom::Node> node, Box& parent, Color& canvasColor) {
55+
if (auto el = node->is<Dom::Element>()) {
56+
_searchElement(c, *el, parent, canvasColor);
57+
} else if (auto text = node->is<Dom::Text>()) {
58+
return;
59+
} else if (auto doc = node->is<Dom::Document>()) {
60+
_searchChildren(c, *doc, parent, canvasColor);
61+
}
62+
}
63+
64+
void _searchChildren(Style::Computer& c, Gc::Ref<Dom::Node> node, Box& parent, Color& canvasColor) {
65+
for (auto child = node->firstChild(); child; child = child->nextSibling()) {
66+
_searchNode(c, *child, parent, canvasColor);
67+
}
68+
}
69+
70+
export Gfx::Color BGSearch(Style::Computer& c, Gc::Ref<Dom::Document> doc) {
71+
72+
if (auto el = doc->documentElement()) {
73+
Color canvasColor = Gfx::ALPHA;
74+
auto style = c.computeFor(Style::Computed::initial(), *el);
75+
extractBackground(el->tagName, style->backgrounds, canvasColor);
76+
Box root = {style, Text::Fontface::fallback()};
77+
_searchChildren(c, *el, root, canvasColor);
78+
79+
Gfx::Color gfxCanvasCol;
80+
if (auto isRes = canvasColor.is<Gfx::Color>()) {
81+
gfxCanvasCol = *isRes;
82+
} else {
83+
logWarn("canvas color was not a Gfx color");
84+
gfxCanvasCol = Gfx::WHITE;
85+
}
86+
return gfxCanvasCol;
87+
}
88+
// NOTE: Fallback in case of an empty document
89+
return Gfx::WHITE;
90+
}
91+
} // namespace Vaev::Layout

src/web/vaev-layout/builder.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ static void _buildElement(Style::Computer& c, Gc::Ref<Dom::Element> el, Box& par
275275
}
276276

277277
auto style = c.computeFor(*parent.style, el);
278+
278279
auto font = _lookupFontface(c.fontBook, *style);
279280

280281
auto display = style->display;
@@ -301,6 +302,7 @@ static void _buildNode(Style::Computer& c, Gc::Ref<Dom::Node> node, Box& parent)
301302
}
302303

303304
export Box build(Style::Computer& c, Gc::Ref<Dom::Document> doc) {
305+
304306
if (auto el = doc->documentElement()) {
305307
auto style = c.computeFor(Style::Computed::initial(), *el);
306308
auto font = _lookupFontface(c.fontBook, *style);

src/web/vaev-layout/mod.cpp

+1
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

+6-4
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,11 @@ 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);
88+
g.clear(paintRect, canvasColor);
8789

88-
paint->paint(g, rect.offset(-bound().xy).cast<f64>());
90+
paint->paint(g, paintRect.cast<f64>());
8991
if (_props.wireframe)
9092
Layout::wireframe(*frag, g);
9193

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

105107
return {
106108
frag->metrics.borderBox().width.cast<isize>(),
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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>

0 commit comments

Comments
 (0)