summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--layout/base/nsDisplayList.cpp29
-rw-r--r--layout/base/nsDisplayList.h25
-rw-r--r--layout/forms/nsButtonFrameRenderer.cpp4
-rw-r--r--layout/forms/nsFieldSetFrame.cpp6
-rw-r--r--layout/generic/nsFrame.cpp44
-rw-r--r--layout/mathml/nsMathMLChar.cpp3
-rw-r--r--layout/reftests/position-relative/1409114-1-ref.html12
-rw-r--r--layout/reftests/position-relative/1409114-1.html11
-rw-r--r--layout/reftests/position-relative/1409114-2.html13
-rw-r--r--layout/reftests/position-relative/1409114-3.html13
-rw-r--r--layout/reftests/position-relative/reftest.list3
-rw-r--r--layout/reftests/table-background/border-collapse-opacity-table-column-group-ref.html6
-rw-r--r--layout/reftests/table-background/border-collapse-opacity-table-column-ref.html6
-rw-r--r--layout/reftests/table-background/border-separate-opacity-table-column-group-ref.html6
-rw-r--r--layout/reftests/table-background/border-separate-opacity-table-column-ref.html6
-rw-r--r--layout/reftests/table-background/reftest.list3
-rw-r--r--layout/reftests/table-background/table-col-overlapping-ref.html28
-rw-r--r--layout/reftests/table-background/table-col-overlapping.html28
-rw-r--r--layout/reftests/table-background/table-col-span-1-ref.html15
-rw-r--r--layout/reftests/table-background/table-col-span-1.html15
-rw-r--r--layout/tables/nsTableCellFrame.cpp51
-rw-r--r--layout/tables/nsTableColFrame.cpp8
-rw-r--r--layout/tables/nsTableColGroupFrame.cpp8
-rw-r--r--layout/tables/nsTableFrame.cpp286
-rw-r--r--layout/tables/nsTableFrame.h95
-rw-r--r--layout/tables/nsTableRowFrame.cpp57
-rw-r--r--layout/tables/nsTableRowFrame.h5
-rw-r--r--layout/tables/nsTableRowGroupFrame.cpp39
-rw-r--r--layout/xul/nsGroupBoxFrame.cpp3
29 files changed, 488 insertions, 340 deletions
diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp
index a869564a4f..55461f7c0a 100644
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -721,7 +721,6 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
: mReferenceFrame(aReferenceFrame),
mIgnoreScrollFrame(nullptr),
mLayerEventRegions(nullptr),
- mCurrentTableItem(nullptr),
mCurrentFrame(aReferenceFrame),
mCurrentReferenceFrame(aReferenceFrame),
mCurrentAGR(&mRootAGR),
@@ -731,6 +730,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mGlassDisplayItem(nullptr),
mScrollInfoItemsForHoisting(nullptr),
mMode(aMode),
+ mTableBackgroundSet(nullptr),
mCurrentScrollParentId(FrameMetrics::NULL_SCROLL_ID),
mCurrentScrollbarTarget(FrameMetrics::NULL_SCROLL_ID),
mCurrentScrollbarFlags(0),
@@ -926,7 +926,6 @@ nsDisplayListBuilder::~nsDisplayListBuilder() {
"All frames should have been unmarked");
NS_ASSERTION(mPresShellStates.Length() == 0,
"All presshells should have been exited");
- NS_ASSERTION(!mCurrentTableItem, "No table item should be active");
nsCSSRendering::EndFrameTreesLocked();
@@ -2579,8 +2578,7 @@ static nsStyleContext* GetBackgroundStyleContext(nsIFrame* aFrame)
/* static */ void
SetBackgroundClipRegion(DisplayListClipState::AutoSaveRestore& aClipState,
- nsIFrame* aFrame, const nsPoint& aToReferenceFrame,
- const nsStyleImageLayers::Layer& aLayer,
+ nsIFrame* aFrame, const nsStyleImageLayers::Layer& aLayer,
const nsRect& aBackgroundRect,
bool aWillPaintBorder)
{
@@ -2640,14 +2638,16 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
bool aAllowWillPaintBorderOptimization,
nsStyleContext* aStyleContext,
const nsRect& aBackgroundOriginRect,
- nsIFrame* aSecondaryReferenceFrame)
+ nsIFrame* aSecondaryReferenceFrame,
+ Maybe<nsDisplayListBuilder::AutoBuildingDisplayList>*
+ aAutoBuildingDisplayList)
{
nsStyleContext* bgSC = aStyleContext;
const nsStyleBackground* bg = nullptr;
- nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame);
+ nsRect bgRect = aBackgroundRect;
nsRect bgOriginRect = bgRect;
if (!aBackgroundOriginRect.IsEmpty()) {
- bgOriginRect = aBackgroundOriginRect + aBuilder->ToReferenceFrame(aFrame);
+ bgOriginRect = aBackgroundOriginRect;
}
nsPresContext* presContext = aFrame->PresContext();
bool isThemed = aFrame->IsThemed();
@@ -2683,8 +2683,6 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
!isThemed && !hasInsetShadow &&
borderStyle->HasBorder();
- nsPoint toRef = aBuilder->ToReferenceFrame(aFrame);
-
// An auxiliary list is necessary in case we have background blending; if that
// is the case, background items need to be wrapped by a blend container to
// isolate blending to the background
@@ -2693,6 +2691,9 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
// to create an item for hit testing.
if ((drawBackgroundColor && color != NS_RGBA(0,0,0,0)) ||
aBuilder->IsForEventDelivery()) {
+ if (aAutoBuildingDisplayList && !*aAutoBuildingDisplayList) {
+ aAutoBuildingDisplayList->emplace(aBuilder, aFrame);
+ }
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
if (bg && !aBuilder->IsForEventDelivery()) {
// Disable the will-paint-border optimization for background
@@ -2704,7 +2705,7 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
// artifacts along the rounded corners.
bool useWillPaintBorderOptimization = willPaintBorder &&
nsLayoutUtils::HasNonZeroCorner(borderStyle->mBorderRadius);
- SetBackgroundClipRegion(clipState, aFrame, toRef,
+ SetBackgroundClipRegion(clipState, aFrame,
bg->BottomLayer(), bgRect,
useWillPaintBorderOptimization);
}
@@ -2757,6 +2758,10 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
continue;
}
+ if (aAutoBuildingDisplayList && !*aAutoBuildingDisplayList) {
+ aAutoBuildingDisplayList->emplace(aBuilder, aFrame);
+ }
+
if (bg->mImage.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
needBlendContainer = true;
}
@@ -2764,8 +2769,8 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
if (!aBuilder->IsForEventDelivery()) {
const nsStyleImageLayers::Layer& layer = bg->mImage.mLayers[i];
- SetBackgroundClipRegion(clipState, aFrame, toRef,
- layer, bgRect, willPaintBorder);
+ SetBackgroundClipRegion(clipState, aFrame, layer, bgRect,
+ willPaintBorder);
}
nsDisplayList thisItemList;
diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h
index 3aeb20d196..ff2a14dd77 100644
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -48,6 +48,7 @@ class nsISelection;
class nsIScrollableFrame;
class nsDisplayLayerEventRegions;
class nsDisplayScrollInfoLayer;
+class nsDisplayTableBackgroundSet;
class nsCaret;
namespace mozilla {
@@ -588,6 +589,16 @@ public:
mSyncDecodeImages = aSyncDecodeImages;
}
+ nsDisplayTableBackgroundSet* SetTableBackgroundSet(
+ nsDisplayTableBackgroundSet* aTableSet) {
+ nsDisplayTableBackgroundSet* old = mTableBackgroundSet;
+ mTableBackgroundSet = aTableSet;
+ return old;
+ }
+ nsDisplayTableBackgroundSet* GetTableBackgroundSet() const {
+ return mTableBackgroundSet;
+ }
+
/**
* Helper method to generate background painting flags based on the
* information available in the display list builder. Currently only
@@ -711,6 +722,10 @@ public:
class AutoBuildingDisplayList {
public:
+ AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild)
+ : AutoBuildingDisplayList(
+ aBuilder, aForChild, aBuilder->GetDirtyRect(), aForChild->IsTransformed()){}
+
AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild,
const nsRect& aDirtyRect, bool aIsRoot)
: mBuilder(aBuilder),
@@ -992,10 +1007,6 @@ public:
return mPreserves3DCtx.mAccumulatedRectLevels;
}
- // Helpers for tables
- nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
- void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
-
struct OutOfFlowDisplayData {
OutOfFlowDisplayData(const DisplayItemClip* aContainingBlockClip,
const DisplayItemScrollClip* aContainingBlockScrollClip,
@@ -1213,7 +1224,6 @@ private:
AutoTArray<PresShellState,8> mPresShellStates;
AutoTArray<nsIFrame*,400> mFramesMarkedForDisplay;
AutoTArray<ThemeGeometry,2> mThemeGeometries;
- nsDisplayTableItem* mCurrentTableItem;
DisplayListClipState mClipState;
// mCurrentFrame is the frame that we're currently calling (or about to call)
// BuildDisplayList on.
@@ -1256,6 +1266,7 @@ private:
nsTArray<DisplayItemScrollClip*> mScrollClipsToDestroy;
nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy;
nsDisplayListBuilderMode mMode;
+ nsDisplayTableBackgroundSet* mTableBackgroundSet;
ViewID mCurrentScrollParentId;
ViewID mCurrentScrollbarTarget;
uint32_t mCurrentScrollbarFlags;
@@ -2751,7 +2762,9 @@ public:
bool aAllowWillPaintBorderOptimization = true,
nsStyleContext* aStyleContext = nullptr,
const nsRect& aBackgroundOriginRect = nsRect(),
- nsIFrame* aSecondaryReferenceFrame = nullptr);
+ nsIFrame* aSecondaryReferenceFrame = nullptr,
+ mozilla::Maybe<nsDisplayListBuilder::AutoBuildingDisplayList>*
+ aAutoBuildingDisplayList = nullptr);
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
diff --git a/layout/forms/nsButtonFrameRenderer.cpp b/layout/forms/nsButtonFrameRenderer.cpp
index 096031385b..5372acb7fb 100644
--- a/layout/forms/nsButtonFrameRenderer.cpp
+++ b/layout/forms/nsButtonFrameRenderer.cpp
@@ -263,8 +263,8 @@ nsButtonFrameRenderer::DisplayButton(nsDisplayListBuilder* aBuilder,
nsDisplayButtonBoxShadowOuter(aBuilder, this));
}
- nsRect buttonRect;
- GetButtonRect(mFrame->GetRectRelativeToSelf(), buttonRect);
+ nsRect buttonRect =
+ mFrame->GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(mFrame);
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
aBuilder, mFrame, buttonRect, aBackground);
diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp
index ccab0faf5a..a5177560de 100644
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -165,9 +165,11 @@ nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsDisplayBoxShadowOuter(aBuilder, this));
}
+ const nsRect rect =
+ VisualBorderRectRelativeToSelf() + aBuilder->ToReferenceFrame(this);
+
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
- aBuilder, this, VisualBorderRectRelativeToSelf(),
- aLists.BorderBackground(),
+ aBuilder, this, rect, aLists.BorderBackground(),
/* aAllowWillPaintBorderOptimization = */ false);
aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp
index c8415a7e70..8ba0bbf124 100644
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1793,6 +1793,13 @@ void
nsFrame::DisplayOutlineUnconditional(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)
{
+ // Per https://drafts.csswg.org/css-tables-3/#global-style-overrides:
+ // "All css properties of table-column and table-column-group boxes are
+ // ignored, except when explicitly specified by this specification."
+ // CSS outlines fall into this category, so we skip them on these boxes.
+
+ MOZ_ASSERT(GetType() != nsGkAtoms::tableColGroupFrame && GetType() != nsGkAtoms::tableColFrame);
+
if (StyleOutline()->mOutlineStyle == NS_STYLE_BORDER_STYLE_NONE) {
return;
}
@@ -1839,7 +1846,9 @@ nsFrame::DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
if (aBuilder->IsForEventDelivery() || aForceBackground ||
!StyleBackground()->IsTransparent() || StyleDisplay()->mAppearance) {
return nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
- aBuilder, this, GetRectRelativeToSelf(), aLists.BorderBackground());
+ aBuilder, this,
+ GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this),
+ aLists.BorderBackground());
}
return false;
}
@@ -1872,7 +1881,9 @@ nsFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
// If there's a themed background, we should not create a border item.
// It won't be rendered.
- if (!bgIsThemed && StyleBorder()->HasBorder()) {
+ // Don't paint borders for tables here, since they paint them in a different
+ // order.
+ if (!bgIsThemed && StyleBorder()->HasBorder() && GetType() != nsGkAtoms::tableFrame) {
aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayBorder(aBuilder, this));
}
@@ -2626,8 +2637,33 @@ static bool DescendIntoChild(nsDisplayListBuilder* aBuilder,
return true;
}
+ if (aChild->IsFrameOfType(nsIFrame::eTablePart)) {
+ // Relative positioning and transforms can cause table parts to move, but we
+ // will still paint the backgrounds for their ancestor parts under them at
+ // their 'normal' position. That means that we must consider the overflow
+ // rects at both positions.
+
+ // We convert the overflow rect into the nsTableFrame's coordinate
+ // space, applying the normal position offset at each step. Then we
+ // compare that against the builder's cached dirty rect in table
+ // coordinate space.
+ const nsIFrame* f = aChild;
+ nsRect normalPositionOverflowRelativeToTable = overflow;
+
+ while (f->IsFrameOfType(nsIFrame::eTablePart)) {
+ normalPositionOverflowRelativeToTable += f->GetNormalPosition();
+ f = f->GetParent();
+ }
+
+ nsDisplayTableBackgroundSet* tableBGs = aBuilder->GetTableBackgroundSet();
+ if (tableBGs &&
+ tableBGs->GetDirtyRect().Intersects(normalPositionOverflowRelativeToTable)) {
+ return true;
+ }
+ }
+
return false;
- }
+}
void
nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
@@ -2770,7 +2806,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
// If you change this, also change IsPseudoStackingContextFromStyle()
pseudoStackingContext = true;
}
-
+
NS_ASSERTION(!isStackingContext || pseudoStackingContext,
"Stacking contexts must also be pseudo-stacking-contexts");
diff --git a/layout/mathml/nsMathMLChar.cpp b/layout/mathml/nsMathMLChar.cpp
index 507e32b22d..4b02a52d8d 100644
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -1992,7 +1992,8 @@ nsMathMLChar::Display(nsDisplayListBuilder* aBuilder,
if (styleContext != parentContext &&
NS_GET_A(backg->mBackgroundColor) > 0) {
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
- aBuilder, aForFrame, mRect, aLists.BorderBackground(),
+ aBuilder, aForFrame, mRect + aBuilder->ToReferenceFrame(aForFrame),
+ aLists.BorderBackground(),
/* aAllowWillPaintBorderOptimization */ true, styleContext);
}
//else
diff --git a/layout/reftests/position-relative/1409114-1-ref.html b/layout/reftests/position-relative/1409114-1-ref.html
new file mode 100644
index 0000000000..7668cbdef6
--- /dev/null
+++ b/layout/reftests/position-relative/1409114-1-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<table>
+ <col style="background:green">
+ <tr>
+ <td style="width:20px; height:20px"></td>
+ </tr>
+</table>
+</body>
+
+</html> \ No newline at end of file
diff --git a/layout/reftests/position-relative/1409114-1.html b/layout/reftests/position-relative/1409114-1.html
new file mode 100644
index 0000000000..1b984ab0c3
--- /dev/null
+++ b/layout/reftests/position-relative/1409114-1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<body>
+<table>
+ <col style="background:green">
+ <tr>
+ <td style="position:relative; left:-100px; width:20px; height:20px"></td>
+ </tr>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/layout/reftests/position-relative/1409114-2.html b/layout/reftests/position-relative/1409114-2.html
new file mode 100644
index 0000000000..de18ed40db
--- /dev/null
+++ b/layout/reftests/position-relative/1409114-2.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<body style="overflow:hidden">
+<table style="position:relative; top:-50px">
+ <col style="background:green; width: 40px;">
+ <tr style="position:relative; left:-100px; height: 40px">
+ <td rowspan=2></td>
+ </tr>
+ <tr style="height: 40px"></tr>
+</table>
+</body>
+
+</html> \ No newline at end of file
diff --git a/layout/reftests/position-relative/1409114-3.html b/layout/reftests/position-relative/1409114-3.html
new file mode 100644
index 0000000000..3dc66122f1
--- /dev/null
+++ b/layout/reftests/position-relative/1409114-3.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<body style="overflow:hidden">
+<table style="position:relative; top:-50px">
+ <tbody style="background:green">
+ <tr style="position:relative; left:-100px; height: 40px">
+ <td rowspan=2 style="width: 40px;"></td>
+ </tr>
+ <tr style="height: 40px"></tr>
+ </tbody>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/layout/reftests/position-relative/reftest.list b/layout/reftests/position-relative/reftest.list
index 880a38e8d5..495588ab79 100644
--- a/layout/reftests/position-relative/reftest.list
+++ b/layout/reftests/position-relative/reftest.list
@@ -7,3 +7,6 @@
== table-separate-3.html table-separate-3-ref.html
== table-separate-4.html table-separate-4-ref.html
== 1115999-1.html 1115999-1-ref.html
+== 1409114-1.html 1409114-1-ref.html
+!= 1409114-2.html about:blank
+!= 1409114-3.html about:blank
diff --git a/layout/reftests/table-background/border-collapse-opacity-table-column-group-ref.html b/layout/reftests/table-background/border-collapse-opacity-table-column-group-ref.html
index bb03f15257..9ec969236a 100644
--- a/layout/reftests/table-background/border-collapse-opacity-table-column-group-ref.html
+++ b/layout/reftests/table-background/border-collapse-opacity-table-column-group-ref.html
@@ -10,8 +10,6 @@
html, body { margin: 0; padding: 0; border: 0; font-size: 16px; }
body { padding: 15px; }
- .o { opacity: 0.5; }
-
/*
table {
margin: 0px 3px 2px 4px;
@@ -55,8 +53,8 @@
</head>
<body>
-<div class="color o"></div>
-<div class="imagetl o"></div>
+<div class="color"></div>
+<div class="imagetl"></div>
<div class="imagebr"></div>
</body>
diff --git a/layout/reftests/table-background/border-collapse-opacity-table-column-ref.html b/layout/reftests/table-background/border-collapse-opacity-table-column-ref.html
index 7b7df902e5..82795ef8be 100644
--- a/layout/reftests/table-background/border-collapse-opacity-table-column-ref.html
+++ b/layout/reftests/table-background/border-collapse-opacity-table-column-ref.html
@@ -10,8 +10,6 @@
html, body { margin: 0; padding: 0; border: 0; font-size: 16px; }
body { padding: 15px; }
- .o { opacity: 0.5; }
-
/*
table {
margin: 0px 3px 2px 4px;
@@ -55,8 +53,8 @@
</head>
<body>
-<div class="color o"></div>
-<div class="imagetl o"></div>
+<div class="color"></div>
+<div class="imagetl"></div>
<div class="imagebr"></div>
</body>
diff --git a/layout/reftests/table-background/border-separate-opacity-table-column-group-ref.html b/layout/reftests/table-background/border-separate-opacity-table-column-group-ref.html
index ad6ca24539..6985dae64d 100644
--- a/layout/reftests/table-background/border-separate-opacity-table-column-group-ref.html
+++ b/layout/reftests/table-background/border-separate-opacity-table-column-group-ref.html
@@ -10,8 +10,6 @@
html, body { margin: 0; padding: 0; border: 0; font-size: 16px; }
body { padding: 15px; }
- .o { opacity: 0.5; }
-
/*
table {
margin: 0px 3px 2px 4px;
@@ -65,8 +63,8 @@
<body>
<div class="color"></div>
-<div class="imagetl o"></div>
-<div class="imagebr o"></div>
+<div class="imagetl"></div>
+<div class="imagebr"></div>
<div class="hstripe" style="top: 46px"></div>
<div class="hstripe" style="top: 70px"></div>
diff --git a/layout/reftests/table-background/border-separate-opacity-table-column-ref.html b/layout/reftests/table-background/border-separate-opacity-table-column-ref.html
index e00193dc3a..a6629347d2 100644
--- a/layout/reftests/table-background/border-separate-opacity-table-column-ref.html
+++ b/layout/reftests/table-background/border-separate-opacity-table-column-ref.html
@@ -10,8 +10,6 @@
html, body { margin: 0; padding: 0; border: 0; font-size: 16px; }
body { padding: 15px; }
- .o { opacity: 0.5; }
-
/*
table {
margin: 0px 3px 2px 4px;
@@ -65,8 +63,8 @@
<body>
<div class="color"></div>
-<div class="imagetl o"></div>
-<div class="imagebr o"></div>
+<div class="imagetl"></div>
+<div class="imagebr"></div>
<div class="hstripe" style="top: 46px"></div>
<div class="hstripe" style="top: 70px"></div>
diff --git a/layout/reftests/table-background/reftest.list b/layout/reftests/table-background/reftest.list
index 68dc43e956..a89115ef44 100644
--- a/layout/reftests/table-background/reftest.list
+++ b/layout/reftests/table-background/reftest.list
@@ -60,3 +60,6 @@ fuzzy-if(d2d||skiaContent,1,95000) == border-separate-opacity-table.html border-
== empty-cells-default-2.html empty-cells-default-2-ref.html
fuzzy-if(OSX,1,113) fuzzy-if(winWidget,1,12) fuzzy-if(Android,1,39) fuzzy-if(winWidget&&!layersGPUAccelerated,82,116) fuzzy-if(skiaContent,84,5500) == table-row-opacity-dynamic-1.html table-row-opacity-dynamic-1-ref.html
== table-row-opacity-dynamic-2.html table-row-opacity-dynamic-2-ref.html
+
+== table-col-overlapping.html table-col-overlapping-ref.html
+== table-col-span-1.html table-col-span-1-ref.html
diff --git a/layout/reftests/table-background/table-col-overlapping-ref.html b/layout/reftests/table-background/table-col-overlapping-ref.html
new file mode 100644
index 0000000000..37515fa283
--- /dev/null
+++ b/layout/reftests/table-background/table-col-overlapping-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+ td {
+ width: 20px;
+ height: 20px;
+ background-color: green;
+ }
+ table {
+ border-collapse:separate;
+ border-spacing: 0px;
+ }
+</style>
+</head>
+<body>
+<table>
+ <tr>
+ <td></td>
+ <td style="background-color: blue"></td>
+ <tr>
+ <td></td>
+ <td></td>
+ </tr>
+</table>
+</body>
+
+</html> \ No newline at end of file
diff --git a/layout/reftests/table-background/table-col-overlapping.html b/layout/reftests/table-background/table-col-overlapping.html
new file mode 100644
index 0000000000..69acab789a
--- /dev/null
+++ b/layout/reftests/table-background/table-col-overlapping.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+ td {
+ width: 20px;
+ height: 20px;
+ }
+ table {
+ border-collapse:separate;
+ border-spacing: 0px;
+ }
+</style>
+</head>
+<body>
+<table>
+ <col style="background: green"></col>
+ <col style="background: blue"></col>
+ <tr>
+ <td></td>
+ <td rowspan=2></td>
+ <tr>
+ <td colspan=2></td>
+ </tr>
+</table>
+</body>
+
+</html> \ No newline at end of file
diff --git a/layout/reftests/table-background/table-col-span-1-ref.html b/layout/reftests/table-background/table-col-span-1-ref.html
new file mode 100644
index 0000000000..dfe953ea44
--- /dev/null
+++ b/layout/reftests/table-background/table-col-span-1-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<body>
+ <table border>
+ <col style="background:purple"></col>
+ <col style="background:purple"></col>
+ <col style="background:blue"></col>
+ <tr>
+ <td>x</td>
+ <td>y</td>
+ <td>z</td>
+ </tr>
+ </table>
+</body>
+</html> \ No newline at end of file
diff --git a/layout/reftests/table-background/table-col-span-1.html b/layout/reftests/table-background/table-col-span-1.html
new file mode 100644
index 0000000000..ee9f62d7e9
--- /dev/null
+++ b/layout/reftests/table-background/table-col-span-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<body>
+ <table border>
+ <col span=2 style="background:purple"></col>
+ <col style="background:blue"></col>
+ <tr>
+ <td>x</td>
+ <td>y</td>
+ <td>z</td>
+ </tr>
+ </table>
+</body>
+
+</html> \ No newline at end of file
diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp
index 64e7d2cfe6..9c715d999b 100644
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -461,14 +461,14 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
}
+ nsRect bgRect = GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this);
+
// display background if we need to.
if (aBuilder->IsForEventDelivery() ||
!StyleBackground()->IsTransparent() ||
StyleDisplay()->mAppearance) {
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder,
- this,
- GetRectRelativeToSelf(),
- aLists.BorderBackground());
+ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
+ aBuilder, this, bgRect, aLists.BorderBackground());
}
// display inset box-shadows if we need to.
@@ -487,16 +487,49 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
"TableCellSelection",
nsDisplayItem::TYPE_TABLE_CELL_SELECTION));
}
+
+ // This can be null if display list building initiated in the middle
+ // of the table, which can happen with background-clip:text and
+ // -moz-element.
+ nsDisplayTableBackgroundSet* backgrounds =
+ aBuilder->GetTableBackgroundSet();
+ if (backgrounds) {
+ // Compute bgRect relative to reference frame, but using the
+ // normal (without position:relative offsets) positions for the
+ // cell, row and row group.
+ bgRect = GetRectRelativeToSelf() + GetNormalPosition();
+
+ nsTableRowFrame* row = GetTableRowFrame();
+ bgRect += row->GetNormalPosition();
+
+ nsTableRowGroupFrame* rowGroup = row->GetTableRowGroupFrame();
+ bgRect += rowGroup->GetNormalPosition();
+
+ bgRect += backgrounds->TableToReferenceFrame();
+
+ // Create backgrounds items as needed for the column and column
+ // group that this cell occupies.
+ nsTableColFrame* col = backgrounds->GetColForIndex(ColIndex());
+ nsTableColGroupFrame* colGroup = col->GetTableColGroupFrame();
+
+ Maybe<nsDisplayListBuilder::AutoBuildingDisplayList> buildingForColGroup;
+ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
+ aBuilder, colGroup, bgRect, backgrounds->ColGroupBackgrounds(), false,
+ nullptr, colGroup->GetRect() + backgrounds->TableToReferenceFrame(),
+ this, &buildingForColGroup);
+
+ Maybe<nsDisplayListBuilder::AutoBuildingDisplayList> buildingForCol;
+ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
+ aBuilder, col, bgRect, backgrounds->ColBackgrounds(), false, nullptr,
+ col->GetRect() + colGroup->GetPosition() +
+ backgrounds->TableToReferenceFrame(),
+ this, &buildingForCol);
+ }
}
// the 'empty-cells' property has no effect on 'outline'
DisplayOutline(aBuilder, aLists);
- // Push a null 'current table item' so that descendant tables can't
- // accidentally mess with our table
- nsAutoPushCurrentTableItem pushTableItem;
- pushTableItem.Push(aBuilder, nullptr);
-
nsIFrame* kid = mFrames.FirstChild();
NS_ASSERTION(kid && !kid->GetNextSibling(), "Table cells should have just one child");
// The child's background will go in our BorderBackground() list.
diff --git a/layout/tables/nsTableColFrame.cpp b/layout/tables/nsTableColFrame.cpp
index 659f0fd352..6723f4701a 100644
--- a/layout/tables/nsTableColFrame.cpp
+++ b/layout/tables/nsTableColFrame.cpp
@@ -112,7 +112,13 @@ void
nsTableColFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)
{
- nsTableFrame::DisplayGenericTablePart(aBuilder, this, aLists);
+ // Per https://drafts.csswg.org/css-tables-3/#global-style-overrides:
+ // "All css properties of table-column and table-column-group boxes are
+ // ignored, except when explicitly specified by this specification."
+ // CSS outlines and box-shadows fall into this category, so we skip them
+ // on these boxes.
+
+ MOZ_ASSERT_UNREACHABLE("Cols don't paint themselves");
}
int32_t nsTableColFrame::GetSpan()
diff --git a/layout/tables/nsTableColGroupFrame.cpp b/layout/tables/nsTableColGroupFrame.cpp
index 7327834289..be5b71bb24 100644
--- a/layout/tables/nsTableColGroupFrame.cpp
+++ b/layout/tables/nsTableColGroupFrame.cpp
@@ -387,7 +387,13 @@ void
nsTableColGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)
{
- nsTableFrame::DisplayGenericTablePart(aBuilder, this, aLists);
+ // Per https://drafts.csswg.org/css-tables-3/#global-style-overrides:
+ // "All css properties of table-column and table-column-group boxes are
+ // ignored, except when explicitly specified by this specification."
+ // CSS outlines and box-shadows fall into this category, so we skip them
+ // on these boxes.
+
+ MOZ_ASSERT_UNREACHABLE("Colgroups don't paint themselves");
}
nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp
index 57b249fb32..59a6d0f1ab 100644
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1166,113 +1166,7 @@ nsDisplayTableBorderCollapse::Paint(nsDisplayListBuilder* aBuilder,
static_cast<nsTableFrame*>(mFrame)->PaintBCBorders(*drawTarget, mVisibleRect - pt);
}
-/* static */ void
-nsTableFrame::GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
- const nsDisplayListSet& aLists)
-{
- // This is similar to what nsContainerFrame::BuildDisplayListForNonBlockChildren
- // does, except that we allow the children's background and borders to go
- // in our BorderBackground list. This doesn't really affect background
- // painting --- the children won't actually draw their own backgrounds
- // because the nsTableFrame already drew them, unless a child has its own
- // stacking context, in which case the child won't use its passed-in
- // BorderBackground list anyway. It does affect cell borders though; this
- // lets us get cell borders into the nsTableFrame's BorderBackground list.
- for (nsIFrame* kid : aFrame->GetChildList(kColGroupList)) {
- aFrame->BuildDisplayListForChild(aBuilder, kid, aLists);
- }
-
- for (nsIFrame* kid : aFrame->PrincipalChildList()) {
- aFrame->BuildDisplayListForChild(aBuilder, kid, aLists);
- }
-}
-
-static void
-PaintRowBackground(nsTableRowFrame* aRow,
- nsIFrame* aFrame,
- nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists,
- const nsPoint& aOffset = nsPoint())
-{
- // Compute background rect by iterating over all cell frames.
- for (nsTableCellFrame* cell = aRow->GetFirstCell(); cell; cell = cell->GetNextCell()) {
- if (!cell->ShouldPaintBackground(aBuilder)) {
- continue;
- }
-
- auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset;
- if (!aBuilder->GetDirtyRect().Intersects(cellRect)) {
- continue;
- }
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
- aLists.BorderBackground(),
- true, nullptr,
- aFrame->GetRectRelativeToSelf(),
- cell);
- }
-}
-
-static void
-PaintRowGroupBackground(nsTableRowGroupFrame* aRowGroup,
- nsIFrame* aFrame,
- nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists)
-{
- for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
- if (!aBuilder->GetDirtyRect().Intersects(nsRect(row->GetNormalPosition(),
- row->GetSize()))) {
- continue;
- }
- PaintRowBackground(row, aFrame, aBuilder, aLists, row->GetNormalPosition());
- }
-}
-
-static void
-PaintRowGroupBackgroundByColIdx(nsTableRowGroupFrame* aRowGroup,
- nsIFrame* aFrame,
- nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists,
- const nsTArray<uint32_t>& aColIdx,
- const nsPoint& aOffset)
-{
- MOZ_DIAGNOSTIC_ASSERT(!aColIdx.IsEmpty(),
- "Must be painting backgrounds for something");
- for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
- auto rowPos = row->GetNormalPosition() + aOffset;
- if (!aBuilder->GetDirtyRect().Intersects(nsRect(rowPos, row->GetSize()))) {
- continue;
- }
- for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
-
- uint32_t curColIdx = cell->ColIndex();
- if (!aColIdx.Contains(curColIdx)) {
- if (curColIdx > aColIdx.LastElement()) {
- // We can just stop looking at this row.
- break;
- }
- continue;
- }
-
- if (!cell->ShouldPaintBackground(aBuilder)) {
- continue;
- }
-
- auto cellPos = cell->GetNormalPosition() + rowPos;
- auto cellRect = nsRect(cellPos, cell->GetSize());
- if (!aBuilder->GetDirtyRect().Intersects(cellRect)) {
- continue;
- }
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
- aLists.BorderBackground(),
- true, nullptr,
- aFrame->GetRectRelativeToSelf(),
- cell);
- }
- }
-}
-
-static inline bool FrameHasBorder(nsIFrame* f)
-{
+static inline bool FrameHasBorder(nsIFrame* f) {
if (!f->StyleVisibility()->IsVisible()) {
return false;
}
@@ -1284,8 +1178,7 @@ static inline bool FrameHasBorder(nsIFrame* f)
return false;
}
-void nsTableFrame::CalcHasBCBorders()
-{
+void nsTableFrame::CalcHasBCBorders() {
if (!IsBorderCollapse()) {
SetHasBCBorders(false);
return;
@@ -1303,8 +1196,9 @@ void nsTableFrame::CalcHasBCBorders()
return;
}
- nsTableColGroupFrame *colGroup = static_cast<nsTableColGroupFrame*>(f);
- for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) {
+ nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(f);
+ for (nsTableColFrame* col = colGroup->GetFirstColumn(); col;
+ col = col->GetNextCol()) {
if (FrameHasBorder(col)) {
SetHasBCBorders(true);
return;
@@ -1321,13 +1215,15 @@ void nsTableFrame::CalcHasBCBorders()
return;
}
- for (nsTableRowFrame* row = rowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
+ for (nsTableRowFrame* row = rowGroup->GetFirstRow(); row;
+ row = row->GetNextRow()) {
if (FrameHasBorder(row)) {
SetHasBCBorders(true);
return;
}
- for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
+ for (nsTableCellFrame* cell = row->GetFirstCell(); cell;
+ cell = cell->GetNextCell()) {
if (FrameHasBorder(cell)) {
SetHasBCBorders(true);
return;
@@ -1339,138 +1235,58 @@ void nsTableFrame::CalcHasBCBorders()
SetHasBCBorders(false);
}
-/* static */ void
-nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
- nsFrame* aFrame,
- const nsDisplayListSet& aLists,
- DisplayGenericTablePartTraversal aTraversal)
-{
- bool isVisible = aFrame->IsVisibleForPainting(aBuilder);
- bool isTable = (aFrame->GetType() == nsGkAtoms::tableFrame);
-
- if (isVisible || !isTable) {
- nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
- // currentItem may be null, when none of the table parts have a
- // background or border
- if (currentItem) {
- currentItem->UpdateForFrameBackground(aFrame);
- }
- }
-
- if (isVisible) {
- // XXX: should box-shadow for rows/rowgroups/columns/colgroups get painted
- // just because we're visible? Or should it depend on the cell visibility
- // when we're not the whole table?
-
- // Paint the outset box-shadows for the table frames
- if (aFrame->StyleEffects()->mBoxShadow) {
- aLists.BorderBackground()->AppendNewToTop(
- new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
- }
- }
-
- // Background visibility for rows, rowgroups, columns, colgroups depends on
- // the visibility of the _cell_, not of the row/col(group).
- // See spec at https://drafts.csswg.org/css-tables-3/#drawing-cell-backgrounds
- if (aFrame->GetType() == nsGkAtoms::tableRowGroupFrame) {
- nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame);
- PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists);
- } else if (aFrame->GetType() == nsGkAtoms::tableRowFrame) {
- nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame);
- PaintRowBackground(row, aFrame, aBuilder, aLists);
- } else if (aFrame->GetType() == nsGkAtoms::tableColGroupFrame) {
- // Compute background rect by iterating all cell frame.
- nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(aFrame);
- // Collecting column index.
- AutoTArray<uint32_t, 1> colIdx;
- for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) {
- MOZ_ASSERT(colIdx.IsEmpty() ||
- static_cast<uint32_t>(col->GetColIndex()) > colIdx.LastElement());
- colIdx.AppendElement(col->GetColIndex());
- }
-
- if (!colIdx.IsEmpty()) {
- // We have some actual cells that live inside this rowgroup.
- nsTableFrame* table = colGroup->GetTableFrame();
- RowGroupArray rowGroups;
- table->OrderRowGroups(rowGroups);
- for (nsTableRowGroupFrame* rowGroup : rowGroups) {
- auto offset = rowGroup->GetNormalPosition() - colGroup->GetNormalPosition();
- if (!aBuilder->GetDirtyRect().Intersects(nsRect(offset, rowGroup->GetSize()))) {
- continue;
- }
- PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
- }
- }
- } else if (aFrame->GetType() == nsGkAtoms::tableColFrame) {
- // Compute background rect by iterating all cell frame.
- nsTableColFrame* col = static_cast<nsTableColFrame*>(aFrame);
- AutoTArray<uint32_t, 1> colIdx;
- colIdx.AppendElement(col->GetColIndex());
+// table paint code is concerned primarily with borders and bg color
+// SEC: TODO: adjust the rect for captions
+void
+nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists)
+{
+ DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255));
- nsTableFrame* table = col->GetTableFrame();
- RowGroupArray rowGroups;
- table->OrderRowGroups(rowGroups);
- for (nsTableRowGroupFrame* rowGroup : rowGroups) {
- auto offset = rowGroup->GetNormalPosition() -
- col->GetNormalPosition() -
- col->GetTableColGroupFrame()->GetNormalPosition();
- if (!aBuilder->GetDirtyRect().Intersects(nsRect(offset, rowGroup->GetSize()))) {
- continue;
- }
- PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
- }
- } else if (isVisible) {
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
- aFrame->GetRectRelativeToSelf(),
- aLists.BorderBackground());
- }
+ DisplayBorderBackgroundOutline(aBuilder, aLists);
- if (isVisible) {
- // XXX: should box-shadow for rows/rowgroups/columns/colgroups get painted
- // just because we're visible? Or should it depend on the cell visibility
- // when we're not the whole table?
+ nsDisplayTableBackgroundSet tableBGs(aBuilder, this);
+ nsDisplayListCollection lists(aBuilder);
- // Paint the inset box-shadows for the table frames
- if (aFrame->StyleEffects()->mBoxShadow) {
- aLists.BorderBackground()->AppendNewToTop(
- new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
+// This is similar to what
+ // nsContainerFrame::BuildDisplayListForNonBlockChildren does, except that we
+ // allow the children's background and borders to go in our BorderBackground
+ // list. This doesn't really affect background painting --- the children won't
+ // actually draw their own backgrounds because the nsTableFrame already drew
+ // them, unless a child has its own stacking context, in which case the child
+ // won't use its passed-in BorderBackground list anyway. It does affect cell
+ // borders though; this lets us get cell borders into the nsTableFrame's
+ // BorderBackground list.
+ for (nsIFrame* colGroup : FirstContinuation()->GetChildList(kColGroupList)) {
+ for (nsIFrame* col : colGroup->PrincipalChildList()) {
+ tableBGs.AddColumn((nsTableColFrame*)col);
}
}
- aTraversal(aBuilder, aFrame, aLists);
+ for (nsIFrame* kid : PrincipalChildList()) {
+ BuildDisplayListForChild(aBuilder, kid, lists);
+ }
- if (isVisible) {
- if (isTable) {
- nsTableFrame* table = static_cast<nsTableFrame*>(aFrame);
- // In the collapsed border model, overlay all collapsed borders.
- if (table->IsBorderCollapse()) {
- if (table->HasBCBorders()) {
- aLists.BorderBackground()->AppendNewToTop(
- new (aBuilder) nsDisplayTableBorderCollapse(aBuilder, table));
- }
- } else {
- const nsStyleBorder* borderStyle = aFrame->StyleBorder();
- if (borderStyle->HasBorder()) {
- aLists.BorderBackground()->AppendNewToTop(
- new (aBuilder) nsDisplayBorder(aBuilder, table));
- }
+ tableBGs.MoveTo(aLists);
+ lists.MoveTo(aLists);
+
+ if (IsVisibleForPainting(aBuilder)) {
+ // In the collapsed border model, overlay all collapsed borders.
+ if (IsBorderCollapse()) {
+ if (HasBCBorders()) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayTableBorderCollapse
+ (aBuilder, this));
+ }
+ } else {
+ const nsStyleBorder* borderStyle = StyleBorder();
+ if (borderStyle->HasBorder()) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBorder
+ (aBuilder, this));
}
}
}
-
- aFrame->DisplayOutline(aBuilder, aLists);
-}
-
-// table paint code is concerned primarily with borders and bg color
-// SEC: TODO: adjust the rect for captions
-void
-nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists)
-{
- DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255));
-
- DisplayGenericTablePart(aBuilder, this, aLists);
}
nsMargin
diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h
index 8a23841345..7fcdcb9d87 100644
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -72,36 +72,59 @@ private:
bool mDrawsBackground;
};
-class nsAutoPushCurrentTableItem
-{
-public:
- nsAutoPushCurrentTableItem() : mBuilder(nullptr) {}
+class nsDisplayTableBackgroundSet {
+ public:
+ nsDisplayList* ColGroupBackgrounds() { return &mColGroupBackgrounds; }
+
+ nsDisplayList* ColBackgrounds() { return &mColBackgrounds; }
+
+ nsDisplayTableBackgroundSet(nsDisplayListBuilder* aBuilder, nsIFrame* aTable)
+ : mBuilder(aBuilder) {
+ mPrevTableBackgroundSet = mBuilder->SetTableBackgroundSet(this);
+ mozilla::DebugOnly<const nsIFrame*> reference =
+ mBuilder->FindReferenceFrameFor(aTable, &mToReferenceFrame);
+ MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(reference, aTable));
+ mDirtyRect = mBuilder->GetDirtyRect();
+ }
- void Push(nsDisplayListBuilder* aBuilder, nsDisplayTableItem* aPushItem)
- {
- mBuilder = aBuilder;
- mOldCurrentItem = aBuilder->GetCurrentTableItem();
- aBuilder->SetCurrentTableItem(aPushItem);
-#ifdef DEBUG
- mPushedItem = aPushItem;
-#endif
+ ~nsDisplayTableBackgroundSet() {
+ mozilla::DebugOnly<nsDisplayTableBackgroundSet*> result =
+ mBuilder->SetTableBackgroundSet(mPrevTableBackgroundSet);
+ MOZ_ASSERT(result == this);
}
- ~nsAutoPushCurrentTableItem() {
- if (!mBuilder)
- return;
-#ifdef DEBUG
- NS_ASSERTION(mBuilder->GetCurrentTableItem() == mPushedItem,
- "Someone messed with the current table item behind our back!");
-#endif
- mBuilder->SetCurrentTableItem(mOldCurrentItem);
+
+ /**
+ * Move all display items in our lists to top of the corresponding lists in
+ * the destination.
+ */
+ void MoveTo(const nsDisplayListSet& aDestination) {
+ aDestination.BorderBackground()->AppendToTop(ColGroupBackgrounds());
+ aDestination.BorderBackground()->AppendToTop(ColBackgrounds());
}
-private:
+ void AddColumn(nsTableColFrame* aFrame) { mColumns.AppendElement(aFrame); }
+
+ nsTableColFrame* GetColForIndex(int32_t aIndex) { return mColumns[aIndex]; }
+
+ const nsPoint& TableToReferenceFrame() { return mToReferenceFrame; }
+
+ const nsRect& GetDirtyRect() { return mDirtyRect; }
+
+ private:
+ // This class is only used on stack, so we don't have to worry about leaking
+ // it. Don't let us be heap-allocated!
+ void* operator new(size_t sz) CPP_THROW_NEW;
+
+ protected:
nsDisplayListBuilder* mBuilder;
- nsDisplayTableItem* mOldCurrentItem;
-#ifdef DEBUG
- nsDisplayTableItem* mPushedItem;
-#endif
+ nsDisplayTableBackgroundSet* mPrevTableBackgroundSet;
+
+ nsDisplayList mColGroupBackgrounds;
+ nsDisplayList mColBackgrounds;
+
+ nsTArray<nsTableColFrame*> mColumns;
+ nsPoint mToReferenceFrame;
+ nsRect mDirtyRect;
};
/* ============================================================================ */
@@ -229,28 +252,6 @@ public:
nsIFrame* aSourceFrame,
bool* aDidPassThrough);
- typedef void (* DisplayGenericTablePartTraversal)
- (nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
- const nsDisplayListSet& aLists);
- static void GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
- const nsDisplayListSet& aLists);
-
- /**
- * Helper method to handle display common to table frames, rowgroup frames
- * and row frames. It creates a background display item for handling events
- * if necessary, an outline display item if necessary, and displays
- * all the the frame's children.
- * @param aDisplayItem the display item created for this part, or null
- * if this part's border/background painting is delegated to an ancestor
- * @param aTraversal a function that gets called to traverse the table
- * part's child frames and add their display list items to a
- * display list set.
- */
- static void DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
- nsFrame* aFrame,
- const nsDisplayListSet& aLists,
- DisplayGenericTablePartTraversal aTraversal = GenericTraversal);
-
// Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
// of type aChildType.
static nsIFrame* GetFrameAtOrBefore(nsIFrame* aParentFrame,
diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp
index 685f4fdeae..18f11f876b 100644
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -549,11 +549,66 @@ nsTableRowFrame::CalcBSize(const ReflowInput& aReflowInput)
return GetInitialBSize();
}
+void nsTableRowFrame::PaintCellBackgroundsForFrame(
+ nsIFrame* aFrame, nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists, const nsPoint& aOffset) {
+ // Compute background rect by iterating all cell frame.
+ const nsPoint toReferenceFrame = aBuilder->ToReferenceFrame(aFrame);
+ for (nsTableCellFrame* cell = GetFirstCell(); cell;
+ cell = cell->GetNextCell()) {
+ if (!cell->ShouldPaintBackground(aBuilder)) {
+ continue;
+ }
+
+ auto cellRect =
+ cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset;
+ if (!aBuilder->GetDirtyRect().Intersects(cellRect)) {
+ continue;
+ }
+ cellRect += toReferenceFrame;
+ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
+ aBuilder, aFrame, cellRect, aLists.BorderBackground(), true, nullptr,
+ aFrame->GetRectRelativeToSelf() + toReferenceFrame, cell);
+ }
+}
+
void
nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)
{
- nsTableFrame::DisplayGenericTablePart(aBuilder, this, aLists);
+ if (IsVisibleForPainting(aBuilder)) {
+ // XXXbz should box-shadow for rows/rowgroups/columns/colgroups get painted
+ // just because we're visible? Or should it depend on the cell visibility
+ // when we're not the whole table?
+
+ // Paint the outset box-shadows for the table frames
+ if (StyleEffects()->mBoxShadow) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBoxShadowOuter
+ (aBuilder, this));
+ }
+ }
+
+ PaintCellBackgroundsForFrame(this, aBuilder, aLists);
+
+ if (IsVisibleForPainting(aBuilder)) {
+ // XXXbz should box-shadow for rows/rowgroups/columns/colgroups get painted
+ // just because we're visible? Or should it depend on the cell visibility
+ // when we're not the whole table?
+
+ // Paint the inset box-shadows for the table frames
+ if (StyleEffects()->mBoxShadow) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBoxShadowInner
+ (aBuilder, this));
+ }
+ }
+
+ DisplayOutline(aBuilder, aLists);
+
+ for (nsIFrame* kid : PrincipalChildList()) {
+ BuildDisplayListForChild(aBuilder, kid, aLists);
+ }
}
nsIFrame::LogicalSides
diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h
index 350b4f6f76..4b6dd2628c 100644
--- a/layout/tables/nsTableRowFrame.h
+++ b/layout/tables/nsTableRowFrame.h
@@ -81,6 +81,11 @@ public:
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
+ void PaintCellBackgroundsForFrame(nsIFrame* aFrame,
+ nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists,
+ const nsPoint& aOffset = nsPoint());
+
// Implemented in nsTableCellFrame.h, because it needs to know about the
// nsTableCellFrame class, but we can't include nsTableCellFrame.h here.
inline nsTableCellFrame* GetFirstCell() const;
diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp
index 1b7f029c89..b6d8a43647 100644
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -207,8 +207,43 @@ void
nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)
{
- nsTableFrame::DisplayGenericTablePart(aBuilder, this,
- aLists, DisplayRows);
+ if (IsVisibleForPainting(aBuilder)) {
+ // XXXbz should box-shadow for rows/rowgroups/columns/colgroups get painted
+ // just because we're visible? Or should it depend on the cell visibility
+ // when we're not the whole table?
+
+ // Paint the outset box-shadows for the table frames
+ if (StyleEffects()->mBoxShadow) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBoxShadowOuter
+ (aBuilder, this));
+ }
+ }
+
+ for (nsTableRowFrame* row = GetFirstRow(); row; row = row->GetNextRow()) {
+ if (!aBuilder->GetDirtyRect().Intersects(row->GetVisualOverflowRect() + row->GetNormalPosition())) {
+ continue;
+ }
+ row->PaintCellBackgroundsForFrame(this, aBuilder, aLists,
+ row->GetNormalPosition());
+ }
+
+ if (IsVisibleForPainting(aBuilder)) {
+ // XXXbz should box-shadow for rows/rowgroups/columns/colgroups get painted
+ // just because we're visible? Or should it depend on the cell visibility
+ // when we're not the whole table?
+
+ // Paint the inset box-shadows for the table frames
+ if (StyleEffects()->mBoxShadow) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBoxShadowInner
+ (aBuilder, this));
+ }
+ }
+
+ DisplayOutline(aBuilder, aLists);
+
+ DisplayRows(aBuilder, this, aLists);
}
nsIFrame::LogicalSides
diff --git a/layout/xul/nsGroupBoxFrame.cpp b/layout/xul/nsGroupBoxFrame.cpp
index fcdc1d1905..df3955cf3e 100644
--- a/layout/xul/nsGroupBoxFrame.cpp
+++ b/layout/xul/nsGroupBoxFrame.cpp
@@ -149,7 +149,8 @@ nsGroupBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// Paint our background and border
if (IsVisibleForPainting(aBuilder)) {
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
- aBuilder, this, GetBackgroundRectRelativeToSelf(),
+ aBuilder, this,
+ GetBackgroundRectRelativeToSelf() + aBuilder->ToReferenceFrame(this),
aLists.BorderBackground());
aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayXULGroupBorder(aBuilder, this));