--- a/layout/painting/nsDisplayItemTypesList.h
+++ b/layout/painting/nsDisplayItemTypesList.h
@@ -54,16 +54,17 @@ DECLARE_DISPLAY_ITEM_TYPE(FILTER)
DECLARE_DISPLAY_ITEM_TYPE(SVG_OUTER_SVG)
DECLARE_DISPLAY_ITEM_TYPE(SVG_GEOMETRY)
DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_BACKGROUND)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_GROUP_BACKGROUND)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_COLLAPSE)
DECLARE_DISPLAY_ITEM_TYPE(TEXT)
DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW)
DECLARE_DISPLAY_ITEM_TYPE_FLAGS(TRANSFORM,TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE_FLAGS(PERSPECTIVE,TYPE_RENDERS_NO_IMAGES)
DECLARE_DISPLAY_ITEM_TYPE(VIDEO)
DECLARE_DISPLAY_ITEM_TYPE(WRAP_LIST)
DECLARE_DISPLAY_ITEM_TYPE(ZOOM)
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -3057,21 +3057,26 @@ SpecialCutoutRegionCase(nsDisplayListBui
/*static*/ bool
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
const nsRect& aBackgroundRect,
nsDisplayList* aList,
bool aAllowWillPaintBorderOptimization,
- nsStyleContext* aStyleContext)
+ nsStyleContext* aStyleContext,
+ const nsRect& aBackgroundOriginRect)
{
nsStyleContext* bgSC = aStyleContext;
const nsStyleBackground* bg = nullptr;
nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame);
+ nsRect bgOriginRect = bgRect;
+ if (!aBackgroundOriginRect.IsEmpty()) {
+ bgOriginRect = aBackgroundOriginRect + aBuilder->ToReferenceFrame(aFrame);
+ }
nsPresContext* presContext = aFrame->PresContext();
bool isThemed = aFrame->IsThemed();
if (!isThemed) {
if (!bgSC) {
bgSC = GetBackgroundStyleContext(aFrame);
}
if (bgSC) {
bg = bgSC->StyleBackground();
@@ -3170,17 +3175,17 @@ nsDisplayBackgroundImage::AppendBackgrou
if (!aBuilder->IsForEventDelivery()) {
const nsStyleImageLayers::Layer& layer = bg->mImage.mLayers[i];
SetBackgroundClipRegion(clipState, aFrame, toRef,
layer, bgRect, willPaintBorder);
}
nsDisplayList thisItemList;
nsDisplayBackgroundImage::InitData bgData =
- nsDisplayBackgroundImage::GetInitData(aBuilder, aFrame, i, bgRect, bg,
+ nsDisplayBackgroundImage::GetInitData(aBuilder, aFrame, i, bgOriginRect, bg,
LayerizeFixed::DO_NOT_LAYERIZE_FIXED_BACKGROUND_IF_AVOIDING_COMPONENT_ALPHA_LAYERS);
if (bgData.shouldFixToViewport) {
auto* displayData = aBuilder->GetCurrentFixedBackgroundDisplayData();
nsDisplayListBuilder::AutoBuildingDisplayList
buildingDisplayList(aBuilder, aFrame, aBuilder->GetDirtyRect(), false);
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -3066,17 +3066,18 @@ public:
// aAllowWillPaintBorderOptimization should usually be left at true, unless
// aFrame has special border drawing that causes opaque borders to not
// actually be opaque.
static bool AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
const nsRect& aBackgroundRect,
nsDisplayList* aList,
bool aAllowWillPaintBorderOptimization = true,
- nsStyleContext* aStyleContext = nullptr);
+ nsStyleContext* aStyleContext = nullptr,
+ const nsRect& aBackgroundOriginRect = nsRect());
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -485,81 +485,61 @@ PaintTableCellSelection(nsIFrame* aFrame
}
void
nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
- if (IsVisibleInSelection(aBuilder)) {
- nsTableFrame* tableFrame = GetTableFrame();
- int32_t emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ?
- StyleTableBorder()->mEmptyCells
- : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
- // take account of 'empty-cells'
- if (StyleVisibility()->IsVisible() &&
- (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) {
- // display outset box-shadows if we need to.
- bool hasBoxShadow = !!StyleEffects()->mBoxShadow;
- if (hasBoxShadow) {
- aLists.BorderBackground()->AppendNewToTop(
- new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
- }
-
- // display background if we need to.
- if (aBuilder->IsForEventDelivery() ||
- !StyleBackground()->IsTransparent(this) ||
- StyleDisplay()->UsedAppearance()) {
- if (!tableFrame->IsBorderCollapse()) {
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder,
- this,
- GetRectRelativeToSelf(),
- aLists.BorderBackground());
- } else if (aBuilder->IsAtRootOfPseudoStackingContext() ||
- aBuilder->IsForEventDelivery()) {
- // The cell background was not painted by the nsTablePainter,
- // so we need to do it. We have special background processing here
- // so we need to duplicate some code from nsFrame::DisplayBorderBackgroundOutline
- nsDisplayTableItem* item =
- new (aBuilder) nsDisplayTableCellBackground(aBuilder, this);
- aLists.BorderBackground()->AppendNewToTop(item);
- item->UpdateForFrameBackground(this);
- } else {
- // The nsTablePainter will paint our background. Make sure it
- // knows if we're background-attachment:fixed.
- nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
- if (currentItem) {
- currentItem->UpdateForFrameBackground(this);
- }
- }
- }
-
- // display inset box-shadows if we need to.
- if (hasBoxShadow) {
- aLists.BorderBackground()->AppendNewToTop(
- new (aBuilder) nsDisplayBoxShadowInner(aBuilder, this));
- }
-
- // display borders if we need to
- ProcessBorders(tableFrame, aBuilder, aLists);
-
- // and display the selection border if we need to
- if (IsSelected()) {
- aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
- nsDisplayGeneric(aBuilder, this, ::PaintTableCellSelection,
- "TableCellSelection",
- nsDisplayItem::TYPE_TABLE_CELL_SELECTION));
- }
+ nsTableFrame* tableFrame = GetTableFrame();
+ int32_t emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ?
+ StyleTableBorder()->mEmptyCells
+ : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
+ // take account of 'empty-cells'
+ if (StyleVisibility()->IsVisible() &&
+ (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) {
+ // display outset box-shadows if we need to.
+ bool hasBoxShadow = !!StyleEffects()->mBoxShadow;
+ if (hasBoxShadow) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
}
-
- // the 'empty-cells' property has no effect on 'outline'
- DisplayOutline(aBuilder, aLists);
+
+ // display background if we need to.
+ if (aBuilder->IsForEventDelivery() ||
+ !StyleBackground()->IsTransparent(this) ||
+ StyleDisplay()->UsedAppearance()) {
+ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder,
+ this,
+ GetRectRelativeToSelf(),
+ aLists.BorderBackground());
+ }
+
+ // display inset box-shadows if we need to.
+ if (hasBoxShadow) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBoxShadowInner(aBuilder, this));
+ }
+
+ // display borders if we need to
+ ProcessBorders(tableFrame, aBuilder, aLists);
+
+ // and display the selection border if we need to
+ if (IsSelected()) {
+ aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
+ nsDisplayGeneric(aBuilder, this, ::PaintTableCellSelection,
+ "TableCellSelection",
+ nsDisplayItem::TYPE_TABLE_CELL_SELECTION));
+ }
}
+ // 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.
--- a/layout/tables/nsTableColFrame.cpp
+++ b/layout/tables/nsTableColFrame.cpp
@@ -117,16 +117,24 @@ nsTableColFrame::Reflow(nsPresContext*
bool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colVis->mVisible);
if (collapseCol) {
GetTableFrame()->SetNeedToCollapse(true);
}
aStatus.Reset();
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
+void
+nsTableColFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists)
+{
+ nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
+}
+
int32_t nsTableColFrame::GetSpan()
{
return StyleTable()->mSpan;
}
#ifdef DEBUG
void nsTableColFrame::Dump(int32_t aIndent)
{
--- a/layout/tables/nsTableColFrame.h
+++ b/layout/tables/nsTableColFrame.h
@@ -48,22 +48,19 @@ public:
/** @see nsIFrame::DidSetStyleContext */
virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override;
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
- /**
- * Table columns never paint anything, nor receive events.
- */
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
- const nsDisplayListSet& aLists) override {}
+ const nsDisplayListSet& aLists) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
virtual nsSplittableType GetSplittableType() const override;
nsTableColGroupFrame* GetTableColGroupFrame() const
--- a/layout/tables/nsTableColGroupFrame.cpp
+++ b/layout/tables/nsTableColGroupFrame.cpp
@@ -381,16 +381,24 @@ nsTableColGroupFrame::Reflow(nsPresConte
FinishReflowChild(kidFrame, aPresContext, kidSize, nullptr, 0, 0, 0);
}
aDesiredSize.ClearSize();
aStatus.Reset();
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
+void
+nsTableColGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists)
+{
+ nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
+}
+
nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
{
return GetNextColumn(nullptr);
}
nsTableColFrame * nsTableColGroupFrame::GetNextColumn(nsIFrame *aChildFrame)
{
nsTableColFrame *result = nullptr;
--- a/layout/tables/nsTableColGroupFrame.h
+++ b/layout/tables/nsTableColGroupFrame.h
@@ -45,22 +45,19 @@ public:
{
nsIFrame* parent = GetParent();
MOZ_ASSERT(parent && parent->IsTableFrame());
MOZ_ASSERT(!parent->GetPrevInFlow(),
"Col group should always be in a first-in-flow table frame");
return static_cast<nsTableFrame*>(parent);
}
- /**
- * ColGroups never paint anything, nor receive events.
- */
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
- const nsDisplayListSet& aLists) override {}
+ const nsDisplayListSet& aLists) override;
/** A colgroup can be caused by three things:
* 1) An element with table-column-group display
* 2) An element with a table-column display without a
* table-column-group parent
* 3) Cells that are not in a column (and hence get an anonymous
* column and colgroup).
* @return colgroup type
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1233,16 +1233,56 @@ nsDisplayTableItem::ComputeInvalidationR
geometry->ShouldInvalidateToSyncDecodeImages())) {
bool snap;
aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
}
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
+// A display item that draws all collapsed borders for a table.
+// At some point, we may want to find a nicer partitioning for dividing
+// border-collapse segments into their own display items.
+class nsDisplayTableBorderCollapse : public nsDisplayTableItem {
+public:
+ nsDisplayTableBorderCollapse(nsDisplayListBuilder* aBuilder,
+ nsTableFrame* aFrame)
+ : nsDisplayTableItem(aBuilder, aFrame) {
+ MOZ_COUNT_CTOR(nsDisplayTableBorderCollapse);
+ }
+#ifdef NS_BUILD_REFCNT_LOGGING
+ virtual ~nsDisplayTableBorderCollapse() {
+ MOZ_COUNT_DTOR(nsDisplayTableBorderCollapse);
+ }
+#endif
+
+ virtual void Paint(nsDisplayListBuilder* aBuilder,
+ nsRenderingContext* aCtx) override;
+ NS_DISPLAY_DECL_NAME("TableBorderCollapse", TYPE_TABLE_BORDER_COLLAPSE)
+};
+
+void
+nsDisplayTableBorderCollapse::Paint(nsDisplayListBuilder* aBuilder,
+ nsRenderingContext* aCtx)
+{
+ nsPoint pt = ToReferenceFrame();
+ DrawTarget* drawTarget = aCtx->GetDrawTarget();
+
+ gfxPoint devPixelOffset =
+ nsLayoutUtils::PointToGfxPoint(pt, mFrame->PresContext()->AppUnitsPerDevPixel());
+
+ // XXX we should probably get rid of this translation at some stage
+ // But that would mean modifying PaintBCBorders, ugh
+ AutoRestoreTransform autoRestoreTransform(drawTarget);
+ drawTarget->SetTransform(
+ drawTarget->GetTransform().PreTranslate(ToPoint(devPixelOffset)));
+
+ static_cast<nsTableFrame*>(mFrame)->PaintBCBorders(*drawTarget, mVisibleRect - pt);
+}
+
class nsDisplayTableBorderBackground : public nsDisplayTableItem {
public:
nsDisplayTableBorderBackground(nsDisplayListBuilder* aBuilder,
nsTableFrame* aFrame,
bool aDrawsBackground) :
nsDisplayTableItem(aBuilder, aFrame, aDrawsBackground) {
MOZ_COUNT_CTOR(nsDisplayTableBorderBackground);
}
@@ -1252,136 +1292,185 @@ public:
}
#endif
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) override;
NS_DISPLAY_DECL_NAME("TableBorderBackground", TYPE_TABLE_BORDER_BACKGROUND)
};
-#ifdef DEBUG
-static bool
-IsFrameAllowedInTable(LayoutFrameType aType)
-{
- return IS_TABLE_CELL(aType) ||
- LayoutFrameType::TableRow == aType ||
- LayoutFrameType::TableRowGroup == aType ||
- LayoutFrameType::Scroll == aType ||
- LayoutFrameType::Table == aType ||
- LayoutFrameType::TableCol == aType ||
- LayoutFrameType::TableColGroup == aType;
-}
-#endif
-
void
nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
DrawResult result = static_cast<nsTableFrame*>(mFrame)->
PaintTableBorderBackground(aBuilder, *aCtx, mVisibleRect,
ToReferenceFrame());
nsDisplayTableItemGeometry::UpdateDrawResult(this, result);
}
-static int32_t
-GetTablePartRank(nsDisplayItem* aItem)
-{
- LayoutFrameType type = aItem->Frame()->Type();
- if (type == LayoutFrameType::Table)
- return 0;
- if (type == LayoutFrameType::TableRowGroup)
- return 1;
- if (type == LayoutFrameType::TableRow)
- return 2;
- return 3;
-}
-
-struct TablePartRankComparator {
- bool operator()(nsDisplayItem* aItem1, nsDisplayItem* aItem2) const {
- return GetTablePartRank(aItem1) < GetTablePartRank(aItem2);
- }
-};
-
/* static */ void
nsTableFrame::GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
const nsRect& aDirtyRect, 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, aDirtyRect, aLists);
+ }
+
for (nsIFrame* kid : aFrame->PrincipalChildList()) {
aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
}
}
+static void
+PaintRowBackground(nsTableRowFrame* aRow,
+ nsIFrame* aFrame,
+ nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists,
+ const nsPoint& aOffset = nsPoint())
+{
+ // Compute background rect by iterating all cell frame.
+ for (nsTableCellFrame* cell = aRow->GetFirstCell(); cell; cell = cell->GetNextCell()) {
+ auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset;
+ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
+ aLists.BorderBackground(),
+ true, nullptr,
+ aFrame->GetRectRelativeToSelf());
+ }
+}
+
+static void
+PaintRowGroupBackground(nsTableRowGroupFrame* aRowGroup,
+ nsIFrame* aFrame,
+ nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists)
+{
+ for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
+ PaintRowBackground(row, aFrame, aBuilder, aLists, row->GetNormalPosition());
+ }
+}
+
+static void
+PaintRowGroupBackgroundByColIdx(nsTableRowGroupFrame* aRowGroup,
+ nsIFrame* aFrame,
+ nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists,
+ const nsTArray<int32_t>& aColIdx,
+ const nsPoint& aOffset)
+{
+ for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
+ for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
+ int32_t curColIdx;
+ cell->GetColIndex(curColIdx);
+ if (aColIdx.Contains(curColIdx)) {
+ auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + row->GetNormalPosition() + aOffset;
+ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
+ aLists.BorderBackground(),
+ true, nullptr,
+ aFrame->GetRectRelativeToSelf());
+ }
+ }
+ }
+}
+
/* static */ void
nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
nsFrame* aFrame,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists,
- nsDisplayTableItem* aDisplayItem,
DisplayGenericTablePartTraversal aTraversal)
{
- nsDisplayList eventsBorderBackground;
- // If we need to sort the event backgrounds, then we'll put descendants'
- // display items into their own set of lists.
- bool sortEventBackgrounds = aDisplayItem && aBuilder->IsForEventDelivery();
- nsDisplayListCollection separatedCollection;
- const nsDisplayListSet* lists = sortEventBackgrounds ? &separatedCollection : &aLists;
-
- nsAutoPushCurrentTableItem pushTableItem;
- if (aDisplayItem) {
- pushTableItem.Push(aBuilder, aDisplayItem);
- }
-
if (aFrame->IsVisibleForPainting(aBuilder)) {
nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
// currentItem may be null, when none of the table parts have a
// background or border
if (currentItem) {
currentItem->UpdateForFrameBackground(aFrame);
}
// Paint the outset box-shadows for the table frames
bool hasBoxShadow = aFrame->StyleEffects()->mBoxShadow != nullptr;
if (hasBoxShadow) {
- lists->BorderBackground()->AppendNewToTop(
+ aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
}
- // Create dedicated background display items per-frame when we're
- // handling events.
- // XXX how to handle collapsed borders?
- if (aBuilder->IsForEventDelivery()) {
+ if (aFrame->IsTableRowGroupFrame()) {
+ nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame);
+ PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists);
+ } else if (aFrame->IsTableRowFrame()) {
+ nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame);
+ PaintRowBackground(row, aFrame, aBuilder, aLists);
+ } else if (aFrame->IsTableColGroupFrame()) {
+ // Compute background rect by iterating all cell frame.
+ nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(aFrame);
+ // Collecting column index.
+ AutoTArray<int32_t, 1> colIdx;
+ for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) {
+ colIdx.AppendElement(col->GetColIndex());
+ }
+
+ nsTableFrame* table = colGroup->GetTableFrame();
+ RowGroupArray rowGroups;
+ table->OrderRowGroups(rowGroups);
+ for (nsTableRowGroupFrame* rowGroup : rowGroups) {
+ auto offset = rowGroup->GetNormalPosition() - colGroup->GetNormalPosition();
+ PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
+ }
+ } else if (aFrame->IsTableColFrame()) {
+ // Compute background rect by iterating all cell frame.
+ nsTableColFrame* col = static_cast<nsTableColFrame*>(aFrame);
+ AutoTArray<int32_t, 1> colIdx;
+ colIdx.AppendElement(col->GetColIndex());
+
+ nsTableFrame* table = col->GetTableFrame();
+ RowGroupArray rowGroups;
+ table->OrderRowGroups(rowGroups);
+ for (nsTableRowGroupFrame* rowGroup : rowGroups) {
+ auto offset = rowGroup->GetNormalPosition() -
+ col->GetNormalPosition() -
+ col->GetTableColGroupFrame()->GetNormalPosition();
+ PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
+ }
+ } else {
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
aFrame->GetRectRelativeToSelf(),
- lists->BorderBackground());
+ aLists.BorderBackground());
}
// Paint the inset box-shadows for the table frames
if (hasBoxShadow) {
- lists->BorderBackground()->AppendNewToTop(
+ aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
}
}
- aTraversal(aBuilder, aFrame, aDirtyRect, *lists);
-
- if (sortEventBackgrounds) {
- // Ensure that the table frame event background goes before the
- // table rowgroups event backgrounds, before the table row event backgrounds,
- // before everything else (cells and their blocks)
- separatedCollection.BorderBackground()->Sort<nsDisplayItem*>(TablePartRankComparator());
- separatedCollection.MoveTo(aLists);
+ aTraversal(aBuilder, aFrame, aDirtyRect, aLists);
+
+ if (aFrame->IsVisibleForPainting(aBuilder)) {
+ if (aFrame->IsTableFrame()) {
+ nsTableFrame* table = static_cast<nsTableFrame*>(aFrame);
+ // In the collapsed border model, overlay all collapsed borders.
+ if (table->IsBorderCollapse()) {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayTableBorderCollapse(aBuilder, table));
+ } else {
+ aLists.BorderBackground()->AppendNewToTop(
+ new (aBuilder) nsDisplayBorder(aBuilder, table));
+ }
+ }
}
aFrame->DisplayOutline(aBuilder, aLists);
}
static inline bool FrameHasBorderOrBackground(nsTableFrame* tableFrame, nsIFrame* f)
{
if (!f->StyleVisibility()->IsVisible()) {
@@ -1399,91 +1488,26 @@ static inline bool FrameHasBorderOrBackg
if (cellFrame && !tableFrame->IsBorderCollapse()) {
return false;
}
return true;
}
return false;
}
-static bool
-AnyTablePartHasBorderOrBackground(nsTableFrame* aTableFrame,
- nsIFrame* aStart,
- nsIFrame* aEnd)
-{
- for (nsIFrame* f = aStart; f != aEnd; f = f->GetNextSibling()) {
- NS_ASSERTION(IsFrameAllowedInTable(f->Type()), "unexpected frame type");
-
- if (FrameHasBorderOrBackground(aTableFrame, f))
- return true;
-
- nsTableCellFrame *cellFrame = do_QueryFrame(f);
- if (cellFrame)
- continue;
-
- if (AnyTablePartHasBorderOrBackground(aTableFrame,
- f->PrincipalChildList().FirstChild(),
- nullptr))
- return true;
- }
-
- return false;
-}
-
-static void
-UpdateItemForColGroupBackgrounds(nsDisplayTableItem* item,
- const nsFrameList& aFrames) {
- for (nsFrameList::Enumerator e(aFrames); !e.AtEnd(); e.Next()) {
- nsTableColGroupFrame* cg = static_cast<nsTableColGroupFrame*>(e.get());
- item->UpdateForFrameBackground(cg);
- for (nsTableColFrame* colFrame = cg->GetFirstColumn(); colFrame;
- colFrame = colFrame->GetNextCol()) {
- item->UpdateForFrameBackground(colFrame);
- }
- }
-}
-
// table paint code is concerned primarily with borders and bg color
// SEC: TODO: adjust the rect for captions
void
nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255));
- nsDisplayTableItem* item = nullptr;
- if (IsVisibleInSelection(aBuilder)) {
- nsMargin deflate = GetDeflationForBackground(PresContext());
- if (StyleVisibility()->IsVisible()) {
- // If 'deflate' is (0,0,0,0) then we can paint the table background
- // in its own display item, so do that to take advantage of
- // opacity and visibility optimizations
- if (deflate == nsMargin(0, 0, 0, 0)) {
- DisplayBackgroundUnconditional(aBuilder, aLists, false);
- }
- }
-
- // This background is created if any of the table parts are visible,
- // or if we're doing event handling (since DisplayGenericTablePart
- // needs the item for the |sortEventBackgrounds|-dependent code).
- // Specific visibility decisions are delegated to the table background
- // painter, which handles borders and backgrounds for the table.
- if (aBuilder->IsForEventDelivery() ||
- AnyTablePartHasBorderOrBackground(this, this, GetNextSibling()) ||
- AnyTablePartHasBorderOrBackground(this, mColGroups.FirstChild(), nullptr)) {
- item = new (aBuilder) nsDisplayTableBorderBackground(aBuilder, this,
- deflate != nsMargin(0, 0, 0, 0));
- aLists.BorderBackground()->AppendNewToTop(item);
- }
- }
- DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, item);
- if (item) {
- UpdateItemForColGroupBackgrounds(item, mColGroups);
- }
+ DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
}
nsMargin
nsTableFrame::GetDeflationForBackground(nsPresContext* aPresContext) const
{
if (eCompatibility_NavQuirks != aPresContext->CompatibilityMode() ||
!IsBorderCollapse())
return nsMargin(0,0,0,0);
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -240,17 +240,16 @@ public:
* @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 nsRect& aDirtyRect,
const nsDisplayListSet& aLists,
- nsDisplayTableItem* aDisplayItem,
DisplayGenericTablePartTraversal aTraversal = GenericTraversal);
// Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
// of type aChildType.
static nsIFrame* GetFrameAtOrBefore(nsIFrame* aParentFrame,
nsIFrame* aPriorChildFrame,
mozilla::LayoutFrameType aChildType);
bool IsAutoBSize(mozilla::WritingMode aWM);
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -616,31 +616,17 @@ nsDisplayTableRowBackground::Paint(nsDis
nsDisplayTableItemGeometry::UpdateDrawResult(this, result);
}
void
nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
- nsDisplayTableItem* item = nullptr;
- if (IsVisibleInSelection(aBuilder)) {
- bool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
- if (isRoot) {
- // This background is created regardless of whether this frame is
- // visible or not. Visibility decisions are delegated to the
- // table background painter.
- // We would use nsDisplayGeneric for this rare case except that we
- // need the background to be larger than the row frame in some
- // cases.
- item = new (aBuilder) nsDisplayTableRowBackground(aBuilder, this);
- aLists.BorderBackground()->AppendNewToTop(item);
- }
- }
- nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, item);
+ nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
}
nsIFrame::LogicalSides
nsTableRowFrame::GetLogicalSkipSides(const ReflowInput* aReflowInput) const
{
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
StyleBoxDecorationBreak::Clone)) {
return LogicalSides();
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -288,29 +288,18 @@ DisplayRows(nsDisplayListBuilder* aBuild
}
}
void
nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
- nsDisplayTableItem* item = nullptr;
- if (IsVisibleInSelection(aBuilder)) {
- bool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
- if (isRoot) {
- // This background is created regardless of whether this frame is
- // visible or not. Visibility decisions are delegated to the
- // table background painter.
- item = new (aBuilder) nsDisplayTableRowGroupBackground(aBuilder, this);
- aLists.BorderBackground()->AppendNewToTop(item);
- }
- }
nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect,
- aLists, item, DisplayRows);
+ aLists, DisplayRows);
}
nsIFrame::LogicalSides
nsTableRowGroupFrame::GetLogicalSkipSides(const ReflowInput* aReflowInput) const
{
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
StyleBoxDecorationBreak::Clone)) {
return LogicalSides();
--- a/layout/tables/nsTableWrapperFrame.cpp
+++ b/layout/tables/nsTableWrapperFrame.cpp
@@ -185,17 +185,21 @@ nsTableWrapperFrame::BuildDisplayList(ns
BuildDisplayListForInnerTable(aBuilder, aDirtyRect, set);
nsDisplayListSet captionSet(set, set.BlockBorderBackgrounds());
BuildDisplayListForChild(aBuilder, mCaptionFrames.FirstChild(),
aDirtyRect, captionSet);
// Now we have to sort everything by content order, since the caption
// may be somewhere inside the table
- set.SortAllByContentOrder(GetContent());
+ set.BlockBorderBackgrounds()->SortByContentOrder(GetContent());
+ set.Floats()->SortByContentOrder(GetContent());
+ set.Content()->SortByContentOrder(GetContent());
+ set.PositionedDescendants()->SortByContentOrder(GetContent());
+ set.Outlines()->SortByContentOrder(GetContent());
set.MoveTo(aLists);
}
void
nsTableWrapperFrame::BuildDisplayListForInnerTable(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{