From 9cbc8e0e5aa824c138e2e730d2f5f31cfd72d5ad Mon Sep 17 00:00:00 2001 From: Lou ! Date: Tue, 18 Mar 2025 11:44:12 +0100 Subject: [PATCH] vaev-driver: Handle correctly HTML/BODY backgrounds outside of layout builder. --- src/main.cpp | 4 +- src/web/vaev-driver/render.cpp | 8 ++- src/web/vaev-layout/backgroundCanvas.cpp | 55 +++++++++++++++++++ src/web/vaev-layout/builder.cpp | 4 +- src/web/vaev-layout/mod.cpp | 1 + src/web/vaev-view/view.cpp | 10 ++-- tests/css/colors/stupid-backgrounds.xhtml | 65 +++++++++++++++++++++++ 7 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 src/web/vaev-layout/backgroundCanvas.cpp create mode 100644 tests/css/colors/stupid-backgrounds.xhtml diff --git a/src/main.cpp b/src/main.cpp index ceacb1b6..1e1266e9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -157,7 +157,7 @@ Async::Task<> renderAsync( }; auto media = constructMediaForRender(options.scale, imageSize); - auto [style, layout, paint, frags] = Vaev::Driver::render(*dom, media, {.small = imageSize}); + auto [style, layout, paint, frags, canvasColor] = Vaev::Driver::render(*dom, media, {.small = imageSize}); auto image = Gfx::Surface::alloc( imageSize.cast() * options.density.toDppx(), @@ -166,7 +166,7 @@ Async::Task<> renderAsync( Gfx::CpuCanvas g; g.begin(*image); - g.clear(Gfx::WHITE); + g.clear(canvasColor); g.scale(options.density.toDppx()); paint->paint(g); if (options.wireframe) diff --git a/src/web/vaev-driver/render.cpp b/src/web/vaev-driver/render.cpp index 1dcd640e..6e984aaa 100644 --- a/src/web/vaev-driver/render.cpp +++ b/src/web/vaev-driver/render.cpp @@ -20,6 +20,7 @@ export struct RenderResult { Rc layout; Rc scenes; Rc frag; + Gfx::Color canvasColor; }; export RenderResult render(Gc::Ref dom, Style::Media const& media, Layout::Viewport viewport) { @@ -43,9 +44,11 @@ export RenderResult render(Gc::Ref dom, Style::Media const& media Style::Computer computer{media, stylebook, fontBook}; computer.loadFontFaces(); + auto canvasColor = Layout::BGSearch(computer, dom); + Layout::Tree tree = { Layout::build(computer, dom), - viewport, + viewport }; elapsed = Sys::now() - start; @@ -79,7 +82,8 @@ export RenderResult render(Gc::Ref dom, Style::Media const& media std::move(stylebook), makeRc(std::move(tree.root)), sceneRoot, - makeRc(std::move(root)) + makeRc(std::move(root)), + canvasColor }; } diff --git a/src/web/vaev-layout/backgroundCanvas.cpp b/src/web/vaev-layout/backgroundCanvas.cpp new file mode 100644 index 00000000..92a9cc52 --- /dev/null +++ b/src/web/vaev-layout/backgroundCanvas.cpp @@ -0,0 +1,55 @@ +module; + +#include +#include +#include +#include +#include + +export module Vaev.Layout:backgroundCanvas; + +import :values; + +namespace Vaev::Layout { + +Gfx::Color ColorToGfx(Color color) { + if (auto isRes = color.is()) { + return *isRes; + } else { + logWarn("color was not a Gfx color"); + return Gfx::WHITE; + } +} + +export Gfx::Color BGSearch(Style::Computer& c, Gc::Ref doc) { + auto el = doc->documentElement(); + if (!el) { + return Gfx::WHITE; + } + + auto style = c.computeFor(Style::Computed::initial(), *el); + if (style->backgrounds->color != Gfx::ALPHA) { + style->backgrounds.cow().color = Gfx::PINK; + return ColorToGfx(style->backgrounds->color); + } + + for (auto child = el->firstChild(); child; child = child->nextSibling()) { + if (auto isRes = child->is()) { + if (isRes->tagName != Html::BODY) { + continue; + } + + auto childStyle = c.computeFor(*style, *isRes); + if (childStyle->backgrounds->color != Gfx::ALPHA) { + childStyle->backgrounds.cow().color = Gfx::PINK; + return ColorToGfx(childStyle->backgrounds->color); + } else { + return Gfx::WHITE; + } + } + } + + return Gfx::WHITE; +} + +} // namespace Vaev::Layout diff --git a/src/web/vaev-layout/builder.cpp b/src/web/vaev-layout/builder.cpp index 77f55d60..e57b137e 100644 --- a/src/web/vaev-layout/builder.cpp +++ b/src/web/vaev-layout/builder.cpp @@ -275,6 +275,7 @@ static void _buildElement(Style::Computer& c, Gc::Ref el, Box& par } auto style = c.computeFor(*parent.style, el); + auto font = _lookupFontface(c.fontBook, *style); auto display = style->display; @@ -295,12 +296,11 @@ static void _buildNode(Style::Computer& c, Gc::Ref node, Box& parent) _buildElement(c, *el, parent); } else if (auto text = node->is()) { _buildRun(c, *text, parent); - } else if (auto doc = node->is()) { - _buildChildren(c, *doc, parent); } } export Box build(Style::Computer& c, Gc::Ref doc) { + if (auto el = doc->documentElement()) { auto style = c.computeFor(Style::Computed::initial(), *el); auto font = _lookupFontface(c.fontBook, *style); diff --git a/src/web/vaev-layout/mod.cpp b/src/web/vaev-layout/mod.cpp index f581cda0..3ae73495 100644 --- a/src/web/vaev-layout/mod.cpp +++ b/src/web/vaev-layout/mod.cpp @@ -13,3 +13,4 @@ export import :replaced; export import :table; export import :values; export import :writing; +export import :backgroundCanvas; diff --git a/src/web/vaev-view/view.cpp b/src/web/vaev-view/view.cpp index 831bf97d..31d46221 100644 --- a/src/web/vaev-view/view.cpp +++ b/src/web/vaev-view/view.cpp @@ -71,6 +71,7 @@ struct View : public Ui::View { } void paint(Gfx::Canvas& g, Math::Recti rect) override { + // Painting browser's viewport. auto viewport = bound().size(); if (not _renderResult) { auto media = _constructMedia(viewport); @@ -82,10 +83,11 @@ struct View : public Ui::View { g.origin(bound().xy.cast()); g.clip(viewport); - auto [_, layout, paint, frag] = *_renderResult; - g.clear(rect, Gfx::WHITE); + auto [_, layout, paint, frag, canvasColor] = *_renderResult; + auto paintRect = rect.offset(-bound().xy); + g.clear(paintRect, canvasColor); - paint->paint(g, rect.offset(-bound().xy).cast()); + paint->paint(g, paintRect.cast()); if (_props.wireframe) Layout::wireframe(*frag, g); @@ -100,7 +102,7 @@ struct View : public Ui::View { Math::Vec2i size(Math::Vec2i size, Ui::Hint) override { // FIXME: This is wasteful, we should cache the result auto media = _constructMedia(size); - auto [_, layout, _, frag] = Driver::render(*_dom, media, {.small = size.cast()}); + auto [_, layout, _, frag, _] = Driver::render(*_dom, media, {.small = size.cast()}); return { frag->metrics.borderBox().width.cast(), diff --git a/tests/css/colors/stupid-backgrounds.xhtml b/tests/css/colors/stupid-backgrounds.xhtml new file mode 100644 index 00000000..b3d7b0ae --- /dev/null +++ b/tests/css/colors/stupid-backgrounds.xhtml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + +