Diff
Modified: trunk/Source/WebCore/ChangeLog (269821 => 269822)
--- trunk/Source/WebCore/ChangeLog 2020-11-14 21:43:44 UTC (rev 269821)
+++ trunk/Source/WebCore/ChangeLog 2020-11-15 01:38:12 UTC (rev 269822)
@@ -1,3 +1,42 @@
+2020-11-14 Simon Fraser <[email protected]>
+
+ [LFC Display] Implement propagation background style from body to root
+ https://bugs.webkit.org/show_bug.cgi?id=218947
+
+ Reviewed by Zalan Bujtas.
+
+ The root display box needs to get its background style from the document element box,
+ if it has one, otherwise the body box. If the body background style is propagated
+ to the root, then the body box needs to not paint its background.
+
+ Implement by adding BoxFactory::determineRootBackgroundPropagation(), and consulting
+ the result when creating the display boxes for the root and body. This is complicated
+ slightly by the need to pass the correct style to constructBoxDecorationData(),
+ which deals with both backgrounds and other (non-propagating) properties.
+
+ * display/DisplayTreeBuilder.cpp:
+ (WebCore::Display::TreeBuilder::build):
+ (WebCore::Display::TreeBuilder::recursiveBuildDisplayTree const):
+ (WebCore::Display::TreeBuilder::build const): Deleted.
+ * display/DisplayTreeBuilder.h:
+ * display/css/DisplayBoxFactory.cpp:
+ (WebCore::Display::BoxFactory::determineRootBackgroundPropagation):
+ (WebCore::Display::BoxFactory::displayBoxForRootBox const):
+ (WebCore::Display::BoxFactory::displayBoxForBodyBox const):
+ (WebCore::Display::BoxFactory::displayBoxForLayoutBox const):
+ (WebCore::Display::BoxFactory::constructBoxDecorationData const):
+ (WebCore::Display::BoxFactory::setupBoxModelBox const):
+ (WebCore::Display::BoxFactory::documentElementBoxFromRootBox):
+ (WebCore::Display::BoxFactory::bodyBoxFromRootBox):
+ * display/css/DisplayBoxFactory.h:
+ * display/css/DisplayFillLayerImageGeometry.cpp:
+ (WebCore::Display::calculateFillLayerImageGeometry):
+ * display/css/DisplayFillLayerImageGeometry.h:
+ * display/css/DisplayStyle.cpp:
+ (WebCore::Display::Style::Style):
+ (WebCore::Display::Style::setupBackground):
+ * display/css/DisplayStyle.h:
+
2020-11-14 Zalan Bujtas <[email protected]>
[LFC][IFC] Negative margin before (>border box height value) completely pulls the inline level box out of the line box
Modified: trunk/Source/WebCore/display/DisplayTreeBuilder.cpp (269821 => 269822)
--- trunk/Source/WebCore/display/DisplayTreeBuilder.cpp 2020-11-14 21:43:44 UTC (rev 269821)
+++ trunk/Source/WebCore/display/DisplayTreeBuilder.cpp 2020-11-15 01:38:12 UTC (rev 269822)
@@ -51,7 +51,7 @@
{
}
-std::unique_ptr<Tree> TreeBuilder::build(const Layout::LayoutState& layoutState) const
+std::unique_ptr<Tree> TreeBuilder::build(const Layout::LayoutState& layoutState)
{
ASSERT(layoutState.hasRoot());
@@ -61,8 +61,10 @@
LOG_WITH_STREAM(FormattingContextLayout, stream << "Building display tree for:\n" << layoutTreeAsText(rootLayoutBox, &layoutState));
#endif
+ m_rootBackgroundPropgation = BoxFactory::determineRootBackgroundPropagation(rootLayoutBox);
+
auto geometry = layoutState.geometryForBox(rootLayoutBox);
- auto rootDisplayBox = m_boxFactory.displayBoxForRootBox(rootLayoutBox, geometry);
+ auto rootDisplayBox = m_boxFactory.displayBoxForRootBox(rootLayoutBox, geometry, m_rootBackgroundPropgation);
auto rootDisplayContainerBox = std::unique_ptr<ContainerBox> { downcast<ContainerBox>(rootDisplayBox.release()) };
if (!rootLayoutBox.firstChild())
@@ -119,8 +121,13 @@
void TreeBuilder::recursiveBuildDisplayTree(const Layout::LayoutState& layoutState, LayoutSize offsetFromRoot, const Layout::Box& layoutBox, InsertionPosition& insertionPosition) const
{
auto geometry = layoutState.geometryForBox(layoutBox);
- auto displayBox = m_boxFactory.displayBoxForLayoutBox(layoutBox, geometry, offsetFromRoot);
+ std::unique_ptr<Box> displayBox;
+ if (layoutBox.isBodyBox())
+ displayBox = m_boxFactory.displayBoxForBodyBox(layoutBox, geometry, m_rootBackgroundPropgation, offsetFromRoot);
+ else
+ displayBox = m_boxFactory.displayBoxForLayoutBox(layoutBox, geometry, offsetFromRoot);
+
insert(WTFMove(displayBox), insertionPosition);
if (!is<Layout::ContainerBox>(layoutBox))
Modified: trunk/Source/WebCore/display/DisplayTreeBuilder.h (269821 => 269822)
--- trunk/Source/WebCore/display/DisplayTreeBuilder.h 2020-11-14 21:43:44 UTC (rev 269821)
+++ trunk/Source/WebCore/display/DisplayTreeBuilder.h 2020-11-15 01:38:12 UTC (rev 269822)
@@ -55,7 +55,7 @@
public:
explicit TreeBuilder(float pixelSnappingFactor);
- std::unique_ptr<Tree> build(const Layout::LayoutState&) const;
+ std::unique_ptr<Tree> build(const Layout::LayoutState&);
private:
struct InsertionPosition {
@@ -70,6 +70,7 @@
void insert(std::unique_ptr<Box>&&, InsertionPosition&) const;
BoxFactory m_boxFactory;
+ RootBackgroundPropagation m_rootBackgroundPropgation { RootBackgroundPropagation::None };
};
#if ENABLE(TREE_DEBUGGING)
Modified: trunk/Source/WebCore/display/css/DisplayBoxFactory.cpp (269821 => 269822)
--- trunk/Source/WebCore/display/css/DisplayBoxFactory.cpp 2020-11-14 21:43:44 UTC (rev 269821)
+++ trunk/Source/WebCore/display/css/DisplayBoxFactory.cpp 2020-11-15 01:38:12 UTC (rev 269822)
@@ -36,7 +36,9 @@
#include "InlineLineGeometry.h"
#include "LayoutBoxGeometry.h"
#include "LayoutContainerBox.h"
+#include "LayoutInitialContainingBlock.h"
#include "LayoutReplacedBox.h"
+#include "Logging.h"
namespace WebCore {
namespace Display {
@@ -46,19 +48,62 @@
{
}
-std::unique_ptr<Box> BoxFactory::displayBoxForRootBox(const Layout::ContainerBox& rootLayoutBox, const Layout::BoxGeometry& geometry) const
+RootBackgroundPropagation BoxFactory::determineRootBackgroundPropagation(const Layout::ContainerBox& rootLayoutBox)
{
+ auto* documentElementBox = documentElementBoxFromRootBox(rootLayoutBox);
+ auto* bodyBox = bodyBoxFromRootBox(rootLayoutBox);
+
+ if (documentElementBox && documentElementBox->style().hasBackground())
+ return RootBackgroundPropagation::None;
+
+ if (bodyBox && bodyBox->style().hasBackground())
+ return RootBackgroundPropagation::BodyToRoot;
+
+ return RootBackgroundPropagation::None;
+}
+
+std::unique_ptr<Box> BoxFactory::displayBoxForRootBox(const Layout::ContainerBox& rootLayoutBox, const Layout::BoxGeometry& geometry, RootBackgroundPropagation rootBackgroundPropagation) const
+{
+ ASSERT(is<Layout::InitialContainingBlock>(rootLayoutBox));
+
// FIXME: Need to do logical -> physical coordinate mapping here.
auto borderBoxRect = LayoutRect { Layout::BoxGeometry::borderBoxRect(geometry) };
- auto style = Style { rootLayoutBox.style() };
+ auto* documentElementBox = documentElementBoxFromRootBox(rootLayoutBox);
+
+ const RenderStyle* styleForBackground = documentElementBox ? &documentElementBox->style() : nullptr;
+
+ if (rootBackgroundPropagation == RootBackgroundPropagation::BodyToRoot) {
+ if (auto* bodyBox = bodyBoxFromRootBox(rootLayoutBox))
+ styleForBackground = &bodyBox->style();
+ }
+
+ auto style = Style { rootLayoutBox.style(), styleForBackground };
+
auto rootBox = makeUnique<ContainerBox>(snapRectToDevicePixels(borderBoxRect, m_pixelSnappingFactor), WTFMove(style));
- setupBoxModelBox(*rootBox, rootLayoutBox, geometry, { });
+ setupBoxModelBox(*rootBox, rootLayoutBox, styleForBackground, geometry, { });
return rootBox;
}
+std::unique_ptr<Box> BoxFactory::displayBoxForBodyBox(const Layout::Box& layoutBox, const Layout::BoxGeometry& geometry, RootBackgroundPropagation rootBackgroundPropagation, LayoutSize offsetFromRoot) const
+{
+ const RenderStyle* styleForBackground = &layoutBox.style();
+
+ if (rootBackgroundPropagation == RootBackgroundPropagation::BodyToRoot)
+ styleForBackground = nullptr;
+
+ auto style = Style { layoutBox.style(), styleForBackground };
+ return displayBoxForLayoutBox(layoutBox, styleForBackground, geometry, offsetFromRoot, WTFMove(style));
+}
+
std::unique_ptr<Box> BoxFactory::displayBoxForLayoutBox(const Layout::Box& layoutBox, const Layout::BoxGeometry& geometry, LayoutSize offsetFromRoot) const
{
+ auto style = Style { layoutBox.style() };
+ return displayBoxForLayoutBox(layoutBox, &layoutBox.style(), geometry, offsetFromRoot, WTFMove(style));
+}
+
+std::unique_ptr<Box> BoxFactory::displayBoxForLayoutBox(const Layout::Box& layoutBox, const RenderStyle* styleForBackground, const Layout::BoxGeometry& geometry, LayoutSize offsetFromRoot, Style&& style) const
+{
// FIXME: Need to map logical to physical rects.
auto borderBoxRect = LayoutRect { Layout::BoxGeometry::borderBoxRect(geometry) };
borderBoxRect.move(offsetFromRoot);
@@ -65,10 +110,6 @@
auto pixelSnappedBorderBoxRect = snapRectToDevicePixels(borderBoxRect, m_pixelSnappingFactor);
// FIXME: Handle isAnonymous()
- // FIXME: Do hoisting of <body> styles to the root where appropriate.
-
- // FIXME: Need to do logical -> physical coordinate mapping here.
- auto style = Style { layoutBox.style() };
if (is<Layout::ReplacedBox>(layoutBox)) {
// FIXME: Don't assume it's an image.
@@ -77,7 +118,7 @@
image = cachedImage->image();
auto imageBox = makeUnique<ImageBox>(pixelSnappedBorderBoxRect, WTFMove(style), WTFMove(image));
- setupBoxModelBox(*imageBox, layoutBox, geometry, offsetFromRoot);
+ setupBoxModelBox(*imageBox, layoutBox, styleForBackground, geometry, offsetFromRoot);
return imageBox;
}
@@ -84,7 +125,7 @@
if (is<Layout::ContainerBox>(layoutBox)) {
// FIXME: The decision to make a ContainerBox should be made based on whether this Display::Box will have children.
auto containerBox = makeUnique<ContainerBox>(pixelSnappedBorderBoxRect, WTFMove(style));
- setupBoxModelBox(*containerBox, layoutBox, geometry, offsetFromRoot);
+ setupBoxModelBox(*containerBox, layoutBox, styleForBackground, geometry, offsetFromRoot);
return containerBox;
}
@@ -128,12 +169,14 @@
}
}
-std::unique_ptr<BoxDecorationData> BoxFactory::constructBoxDecorationData(const Layout::Box& layoutBox, const Layout::BoxGeometry& layoutGeometry, LayoutSize offsetFromRoot) const
+std::unique_ptr<BoxDecorationData> BoxFactory::constructBoxDecorationData(const Layout::Box& layoutBox, const RenderStyle* styleForBackground, const Layout::BoxGeometry& layoutGeometry, LayoutSize offsetFromRoot) const
{
auto boxDecorationData = makeUnique<BoxDecorationData>();
- auto backgroundImageGeometry = calculateFillLayerImageGeometry(layoutBox, layoutGeometry, offsetFromRoot, m_pixelSnappingFactor);
- boxDecorationData->setBackgroundImageGeometry(WTFMove(backgroundImageGeometry));
+ if (styleForBackground) {
+ auto backgroundImageGeometry = calculateFillLayerImageGeometry(*styleForBackground, layoutGeometry, offsetFromRoot, m_pixelSnappingFactor);
+ boxDecorationData->setBackgroundImageGeometry(WTFMove(backgroundImageGeometry));
+ }
bool includeLogicalLeftEdge = true; // FIXME.
bool includeLogicalRightEdge = true; // FIXME.
@@ -154,19 +197,40 @@
return boxDecorationData;
}
-void BoxFactory::setupBoxModelBox(BoxModelBox& box, const Layout::Box& layoutBox, const Layout::BoxGeometry& layoutGeometry, LayoutSize offsetFromRoot) const
+void BoxFactory::setupBoxModelBox(BoxModelBox& box, const Layout::Box& layoutBox, const RenderStyle* styleForBackground, const Layout::BoxGeometry& layoutGeometry, LayoutSize offsetFromRoot) const
{
setupBoxGeometry(box, layoutBox, layoutGeometry, offsetFromRoot);
auto& renderStyle = layoutBox.style();
- if (!renderStyle.hasBackground() && !renderStyle.hasBorder())
+ if (!(styleForBackground && styleForBackground->hasBackground()) && !renderStyle.hasBorder())
return;
- auto boxDecorationData = constructBoxDecorationData(layoutBox, layoutGeometry, offsetFromRoot);
+ auto boxDecorationData = constructBoxDecorationData(layoutBox, styleForBackground, layoutGeometry, offsetFromRoot);
box.setBoxDecorationData(WTFMove(boxDecorationData));
}
+const Layout::ContainerBox* BoxFactory::documentElementBoxFromRootBox(const Layout::ContainerBox& rootLayoutBox)
+{
+ auto* documentBox = rootLayoutBox.firstChild();
+ if (!documentBox || !documentBox->isDocumentBox() || !is<Layout::ContainerBox>(documentBox))
+ return nullptr;
+ return downcast<Layout::ContainerBox>(documentBox);
+}
+
+const Layout::Box* BoxFactory::bodyBoxFromRootBox(const Layout::ContainerBox& rootLayoutBox)
+{
+ auto* documentBox = rootLayoutBox.firstChild();
+ if (!documentBox || !documentBox->isDocumentBox() || !is<Layout::ContainerBox>(documentBox))
+ return nullptr;
+
+ auto* bodyBox = downcast<Layout::ContainerBox>(documentBox)->firstChild();
+ if (!bodyBox || !bodyBox->isBodyBox())
+ return nullptr;
+
+ return bodyBox;
+}
+
} // namespace Display
} // namespace WebCore
Modified: trunk/Source/WebCore/display/css/DisplayBoxFactory.h (269821 => 269822)
--- trunk/Source/WebCore/display/css/DisplayBoxFactory.h 2020-11-14 21:43:44 UTC (rev 269821)
+++ trunk/Source/WebCore/display/css/DisplayBoxFactory.h 2020-11-15 01:38:12 UTC (rev 269822)
@@ -47,21 +47,34 @@
class BoxDecorationData;
class BoxModelBox;
+enum class RootBackgroundPropagation : uint8_t {
+ None,
+ BodyToRoot,
+};
+
class BoxFactory {
public:
explicit BoxFactory(float pixelSnappingFactor);
- std::unique_ptr<Box> displayBoxForRootBox(const Layout::ContainerBox&, const Layout::BoxGeometry&) const;
+ static RootBackgroundPropagation determineRootBackgroundPropagation(const Layout::ContainerBox& rootLayoutBox);
+
+ std::unique_ptr<Box> displayBoxForRootBox(const Layout::ContainerBox&, const Layout::BoxGeometry&, RootBackgroundPropagation) const;
+ std::unique_ptr<Box> displayBoxForBodyBox(const Layout::Box&, const Layout::BoxGeometry&, RootBackgroundPropagation, LayoutSize offsetFromRoot) const;
std::unique_ptr<Box> displayBoxForLayoutBox(const Layout::Box&, const Layout::BoxGeometry&, LayoutSize offsetFromRoot) const;
std::unique_ptr<Box> displayBoxForTextRun(const Layout::LineRun&, const Layout::InlineLineGeometry&, LayoutSize offsetFromRoot) const;
+
private:
+ std::unique_ptr<Box> displayBoxForLayoutBox(const Layout::Box&, const RenderStyle* styleForBackground, const Layout::BoxGeometry&, LayoutSize offsetFromRoot, Style&&) const;
void setupBoxGeometry(BoxModelBox&, const Layout::Box&, const Layout::BoxGeometry&, LayoutSize offsetFromRoot) const;
- void setupBoxModelBox(BoxModelBox&, const Layout::Box&, const Layout::BoxGeometry&, LayoutSize offsetFromRoot) const;
+ void setupBoxModelBox(BoxModelBox&, const Layout::Box&, const RenderStyle* styleForBackground, const Layout::BoxGeometry&, LayoutSize offsetFromRoot) const;
- std::unique_ptr<BoxDecorationData> constructBoxDecorationData(const Layout::Box&, const Layout::BoxGeometry&, LayoutSize offsetFromRoot) const;
+ std::unique_ptr<BoxDecorationData> constructBoxDecorationData(const Layout::Box&, const RenderStyle* styleForBackground, const Layout::BoxGeometry&, LayoutSize offsetFromRoot) const;
+ static const Layout::ContainerBox* documentElementBoxFromRootBox(const Layout::ContainerBox& rootLayoutBox);
+ static const Layout::Box* bodyBoxFromRootBox(const Layout::ContainerBox& rootLayoutBox);
+
float m_pixelSnappingFactor { 1 };
};
Modified: trunk/Source/WebCore/display/css/DisplayFillLayerImageGeometry.cpp (269821 => 269822)
--- trunk/Source/WebCore/display/css/DisplayFillLayerImageGeometry.cpp 2020-11-14 21:43:44 UTC (rev 269821)
+++ trunk/Source/WebCore/display/css/DisplayFillLayerImageGeometry.cpp 2020-11-15 01:38:12 UTC (rev 269822)
@@ -374,10 +374,8 @@
return pixelSnappedFillLayerImageGeometry(destinationRect, tileSize, phase, spaceSize, fillLayer.attachment(), pixelSnappingFactor);
}
-Vector<FillLayerImageGeometry, 1> calculateFillLayerImageGeometry(const Layout::Box& layoutBox, const Layout::BoxGeometry& boxGeometry, LayoutSize offsetFromRoot, float pixelSnappingFactor)
+Vector<FillLayerImageGeometry, 1> calculateFillLayerImageGeometry(const RenderStyle& renderStyle, const Layout::BoxGeometry& boxGeometry, LayoutSize offsetFromRoot, float pixelSnappingFactor)
{
- auto& renderStyle = layoutBox.style();
-
// FIXME: Need to map logical to physical rects.
auto borderBoxRect = LayoutRect { Layout::BoxGeometry::borderBoxRect(boxGeometry) };
borderBoxRect.move(offsetFromRoot);
Modified: trunk/Source/WebCore/display/css/DisplayFillLayerImageGeometry.h (269821 => 269822)
--- trunk/Source/WebCore/display/css/DisplayFillLayerImageGeometry.h 2020-11-14 21:43:44 UTC (rev 269821)
+++ trunk/Source/WebCore/display/css/DisplayFillLayerImageGeometry.h 2020-11-15 01:38:12 UTC (rev 269822)
@@ -33,6 +33,7 @@
namespace WebCore {
class FillLayer;
+class RenderStyle;
class StyleImage;
namespace Layout {
@@ -80,7 +81,7 @@
bool m_hasNonLocalGeometry { false }; // Has background-attachment: fixed. Implies that we can't always cheaply compute destRect.
};
-Vector<FillLayerImageGeometry, 1> calculateFillLayerImageGeometry(const Layout::Box&, const Layout::BoxGeometry&, LayoutSize offsetFromRoot, float pixelSnappingFactor);
+Vector<FillLayerImageGeometry, 1> calculateFillLayerImageGeometry(const RenderStyle&, const Layout::BoxGeometry&, LayoutSize offsetFromRoot, float pixelSnappingFactor);
} // namespace Display
} // namespace WebCore
Modified: trunk/Source/WebCore/display/css/DisplayStyle.cpp (269821 => 269822)
--- trunk/Source/WebCore/display/css/DisplayStyle.cpp 2020-11-14 21:43:44 UTC (rev 269821)
+++ trunk/Source/WebCore/display/css/DisplayStyle.cpp 2020-11-15 01:38:12 UTC (rev 269822)
@@ -57,6 +57,11 @@
}
Style::Style(const RenderStyle& style)
+ : Style(style, &style)
+{
+}
+
+Style::Style(const RenderStyle& style, const RenderStyle* styleForBackground)
: m_fontCascade(style.fontCascade())
, m_whiteSpace(style.whiteSpace())
, m_tabSize(style.tabSize())
@@ -64,8 +69,8 @@
// FIXME: Is currentColor resolved here?
m_color = style.visitedDependentColorWithColorFilter(CSSPropertyColor);
- m_backgroundColor = style.visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor);
- m_backgroundLayers = deepCopy(style.backgroundLayers());
+ if (styleForBackground)
+ setupBackground(*styleForBackground);
if (!style.hasAutoUsedZIndex())
m_zIndex = style.usedZIndex();
@@ -74,6 +79,12 @@
setIsFloating(style.floating() != Float::No);
}
+void Style::setupBackground(const RenderStyle& style)
+{
+ m_backgroundColor = style.visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor);
+ m_backgroundLayers = deepCopy(style.backgroundLayers());
+}
+
bool Style::hasBackground() const
{
return m_backgroundColor.isVisible() || hasBackgroundImage();
Modified: trunk/Source/WebCore/display/css/DisplayStyle.h (269821 => 269822)
--- trunk/Source/WebCore/display/css/DisplayStyle.h 2020-11-14 21:43:44 UTC (rev 269821)
+++ trunk/Source/WebCore/display/css/DisplayStyle.h 2020-11-15 01:38:12 UTC (rev 269822)
@@ -58,6 +58,7 @@
};
explicit Style(const RenderStyle&);
+ explicit Style(const RenderStyle&, const RenderStyle* styleForBackground);
const Color& color() const { return m_color; }
@@ -87,6 +88,8 @@
const TabSize& tabSize() const { return m_tabSize; }
private:
+ void setupBackground(const RenderStyle&);
+
void setIsPositioned(bool value) { m_flags.set({ Flags::Positioned }, value); }
void setIsFloating(bool value) { m_flags.set({ Flags::Floating }, value); }