☠☠ backed out by 3f788935a3a4 ☠ ☠ | |
author | Morris Tseng <mtseng@mozilla.com> |
Thu, 04 May 2017 17:32:08 +0800 | |
changeset 356463 | 93acd240b5782a90f1ce9bd4059f64907fa98137 |
parent 356462 | 70a0d63da2648671e29ee92ec01bb447e934fc46 |
child 356464 | 3dc8c2aea9bf2e5b54a18b67feed9723696b42eb |
push id | 89901 |
push user | mtseng@mozilla.com |
push date | Thu, 04 May 2017 09:32:58 +0000 |
treeherder | mozilla-inbound@7c902365910c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mstange |
bugs | 929484 |
milestone | 55.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- 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) {