diff options
Diffstat (limited to 'layout/tables')
-rw-r--r-- | layout/tables/moz.build | 1 | ||||
-rw-r--r-- | layout/tables/nsTableCellFrame.cpp | 123 | ||||
-rw-r--r-- | layout/tables/nsTableCellFrame.h | 8 | ||||
-rw-r--r-- | layout/tables/nsTableColFrame.cpp | 8 | ||||
-rw-r--r-- | layout/tables/nsTableColFrame.h | 5 | ||||
-rw-r--r-- | layout/tables/nsTableColGroupFrame.cpp | 8 | ||||
-rw-r--r-- | layout/tables/nsTableColGroupFrame.h | 5 | ||||
-rw-r--r-- | layout/tables/nsTableFrame.cpp | 329 | ||||
-rw-r--r-- | layout/tables/nsTableFrame.h | 14 | ||||
-rw-r--r-- | layout/tables/nsTablePainter.cpp | 696 | ||||
-rw-r--r-- | layout/tables/nsTablePainter.h | 268 | ||||
-rw-r--r-- | layout/tables/nsTableRowFrame.cpp | 66 | ||||
-rw-r--r-- | layout/tables/nsTableRowFrame.h | 1 | ||||
-rw-r--r-- | layout/tables/nsTableRowGroupFrame.cpp | 77 | ||||
-rw-r--r-- | layout/tables/nsTableRowGroupFrame.h | 1 | ||||
-rw-r--r-- | layout/tables/nsTableWrapperFrame.cpp | 6 |
16 files changed, 225 insertions, 1391 deletions
diff --git a/layout/tables/moz.build b/layout/tables/moz.build index b77776320..e28e21ee0 100644 --- a/layout/tables/moz.build +++ b/layout/tables/moz.build @@ -21,7 +21,6 @@ UNIFIED_SOURCES += [ 'nsTableColFrame.cpp', 'nsTableColGroupFrame.cpp', 'nsTableFrame.cpp', - 'nsTablePainter.cpp', 'nsTableRowFrame.cpp', 'nsTableRowGroupFrame.cpp', 'nsTableWrapperFrame.cpp', diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index 316a96613..ec9458f76 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -12,7 +12,6 @@ #include "nsTableColFrame.h" #include "nsTableRowFrame.h" #include "nsTableRowGroupFrame.h" -#include "nsTablePainter.h" #include "nsStyleContext.h" #include "nsStyleConsts.h" #include "nsPresContext.h" @@ -380,19 +379,6 @@ nsTableCellFrame::PaintBackground(nsRenderingContext& aRenderingContext, return nsCSSRendering::PaintBackground(params); } -// Called by nsTablePainter -DrawResult -nsTableCellFrame::PaintCellBackground(nsRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, nsPoint aPt, - uint32_t aFlags) -{ - if (!StyleVisibility()->IsVisible()) { - return DrawResult::SUCCESS; - } - - return PaintBackground(aRenderingContext, aDirtyRect, aPt, aFlags); -} - nsresult nsTableCellFrame::ProcessBorders(nsTableFrame* aFrame, nsDisplayListBuilder* aBuilder, @@ -484,70 +470,51 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, 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() || StyleDisplay()->mAppearance) { - 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)); + } + + // display background if we need to. + if (aBuilder->IsForEventDelivery() || + !StyleBackground()->IsTransparent() || + StyleDisplay()->mAppearance) { + 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); } + // 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; @@ -796,12 +763,12 @@ nsTableCellFrame::GetPrefISize(nsRenderingContext *aRenderingContext) } /* virtual */ nsIFrame::IntrinsicISizeOffsetData -nsTableCellFrame::IntrinsicISizeOffsets() +nsTableCellFrame::IntrinsicISizeOffsets(nscoord aPercentageBasis) { - IntrinsicISizeOffsetData result = nsContainerFrame::IntrinsicISizeOffsets(); + IntrinsicISizeOffsetData result = + nsContainerFrame::IntrinsicISizeOffsets(aPercentageBasis); result.hMargin = 0; - result.hPctMargin = 0; WritingMode wm = GetWritingMode(); result.hBorder = GetBorderWidth(wm).IStartEnd(wm); diff --git a/layout/tables/nsTableCellFrame.h b/layout/tables/nsTableCellFrame.h index 6717e1b70..5f87c5f6d 100644 --- a/layout/tables/nsTableCellFrame.h +++ b/layout/tables/nsTableCellFrame.h @@ -107,18 +107,14 @@ public: const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; - DrawResult PaintCellBackground(nsRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, nsPoint aPt, - uint32_t aFlags); - - virtual nsresult ProcessBorders(nsTableFrame* aFrame, nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists); virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override; virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override; - virtual IntrinsicISizeOffsetData IntrinsicISizeOffsets() override; + IntrinsicISizeOffsetData IntrinsicISizeOffsets(nscoord aPercentageBasis = + NS_UNCONSTRAINEDSIZE) override; virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, diff --git a/layout/tables/nsTableColFrame.cpp b/layout/tables/nsTableColFrame.cpp index 8f449c3d9..54b03522b 100644 --- a/layout/tables/nsTableColFrame.cpp +++ b/layout/tables/nsTableColFrame.cpp @@ -108,6 +108,14 @@ nsTableColFrame::Reflow(nsPresContext* aPresContext, 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; diff --git a/layout/tables/nsTableColFrame.h b/layout/tables/nsTableColFrame.h index e95fe76b1..fb989061f 100644 --- a/layout/tables/nsTableColFrame.h +++ b/layout/tables/nsTableColFrame.h @@ -59,12 +59,9 @@ public: 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; /** * Get the "type" of the frame diff --git a/layout/tables/nsTableColGroupFrame.cpp b/layout/tables/nsTableColGroupFrame.cpp index ff8879a0b..6ee7f0b24 100644 --- a/layout/tables/nsTableColGroupFrame.cpp +++ b/layout/tables/nsTableColGroupFrame.cpp @@ -383,6 +383,14 @@ nsTableColGroupFrame::Reflow(nsPresContext* aPresContext, 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); diff --git a/layout/tables/nsTableColGroupFrame.h b/layout/tables/nsTableColGroupFrame.h index 2a25fdc44..b3dfb94e7 100644 --- a/layout/tables/nsTableColGroupFrame.h +++ b/layout/tables/nsTableColGroupFrame.h @@ -43,12 +43,9 @@ public: 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 diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index b9b6ca5fe..890d050fd 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -23,7 +23,6 @@ #include "nsTableRowFrame.h" #include "nsTableRowGroupFrame.h" #include "nsTableWrapperFrame.h" -#include "nsTablePainter.h" #include "BasicTableLayoutStrategy.h" #include "FixedTableLayoutStrategy.h" @@ -1131,67 +1130,40 @@ nsDisplayTableItem::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); } -class nsDisplayTableBorderBackground : public nsDisplayTableItem { +// A display item that draws all collapsed borders for a table. +class nsDisplayTableBorderCollapse : public nsDisplayTableItem { public: - nsDisplayTableBorderBackground(nsDisplayListBuilder* aBuilder, - nsTableFrame* aFrame, - bool aDrawsBackground) : - nsDisplayTableItem(aBuilder, aFrame, aDrawsBackground) { - MOZ_COUNT_CTOR(nsDisplayTableBorderBackground); - } + nsDisplayTableBorderCollapse(nsDisplayListBuilder* aBuilder, + nsTableFrame* aFrame) + : nsDisplayTableItem(aBuilder, aFrame) { + MOZ_COUNT_CTOR(nsDisplayTableBorderCollapse); + } #ifdef NS_BUILD_REFCNT_LOGGING - virtual ~nsDisplayTableBorderBackground() { - MOZ_COUNT_DTOR(nsDisplayTableBorderBackground); + virtual ~nsDisplayTableBorderCollapse() { + MOZ_COUNT_DTOR(nsDisplayTableBorderCollapse); } #endif virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) override; - NS_DISPLAY_DECL_NAME("TableBorderBackground", TYPE_TABLE_BORDER_BACKGROUND) + NS_DISPLAY_DECL_NAME("TableBorderCollapse", TYPE_TABLE_BORDER_COLLAPSE) }; -#ifdef DEBUG -static bool -IsFrameAllowedInTable(nsIAtom* aType) -{ - return IS_TABLE_CELL(aType) || - nsGkAtoms::tableRowFrame == aType || - nsGkAtoms::tableRowGroupFrame == aType || - nsGkAtoms::scrollFrame == aType || - nsGkAtoms::tableFrame == aType || - nsGkAtoms::tableColFrame == aType || - nsGkAtoms::tableColGroupFrame == aType; -} -#endif - void -nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx) +nsDisplayTableBorderCollapse::Paint(nsDisplayListBuilder* aBuilder, + nsRenderingContext* aCtx) { - DrawResult result = static_cast<nsTableFrame*>(mFrame)-> - PaintTableBorderBackground(aBuilder, *aCtx, mVisibleRect, - ToReferenceFrame()); + nsPoint pt = ToReferenceFrame(); + DrawTarget* drawTarget = aCtx->GetDrawTarget(); - nsDisplayTableItemGeometry::UpdateDrawResult(this, result); -} + gfxPoint devPixelOffset = + nsLayoutUtils::PointToGfxPoint(pt, mFrame->PresContext()->AppUnitsPerDevPixel()); -static int32_t -GetTablePartRank(nsDisplayItem* aItem) -{ - nsIAtom* type = aItem->Frame()->GetType(); - if (type == nsGkAtoms::tableFrame) - return 0; - if (type == nsGkAtoms::tableRowGroupFrame) - return 1; - if (type == nsGkAtoms::tableRowFrame) - return 2; - return 3; -} + AutoRestoreTransform autoRestoreTransform(drawTarget); + drawTarget->SetTransform( + drawTarget->GetTransform().PreTranslate(ToPoint(devPixelOffset))); -static bool CompareByTablePartRank(nsDisplayItem* aItem1, nsDisplayItem* aItem2, - void* aClosure) -{ - return GetTablePartRank(aItem1) <= GetTablePartRank(aItem2); + static_cast<nsTableFrame*>(mFrame)->PaintBCBorders(*drawTarget, mVisibleRect - pt); } /* static */ void @@ -1206,31 +1178,75 @@ nsTableFrame::GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame, // 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 over all cell frames. + 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(), + cell); + } +} + +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(), + cell); + } + } + } +} + /* 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 @@ -1242,72 +1258,79 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder, // 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->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<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->GetType() == nsGkAtoms::tableColFrame) { + // 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); + aTraversal(aBuilder, aFrame, aDirtyRect, aLists); - 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(CompareByTablePartRank, nullptr); - separatedCollection.MoveTo(aLists); + if (aFrame->IsVisibleForPainting(aBuilder)) { + if (aFrame->GetType() == nsGkAtoms::tableFrame) { + 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 bool -AnyTablePartHasBorderOrBackground(nsIFrame* aStart, nsIFrame* aEnd) -{ - for (nsIFrame* f = aStart; f != aEnd; f = f->GetNextSibling()) { - NS_ASSERTION(IsFrameAllowedInTable(f->GetType()), "unexpected frame type"); - - if (FrameHasBorderOrBackground(f)) - return true; - - nsTableCellFrame *cellFrame = do_QueryFrame(f); - if (cellFrame) - continue; - - if (AnyTablePartHasBorderOrBackground(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 @@ -1317,35 +1340,7 @@ nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, { 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, GetNextSibling()) || - AnyTablePartHasBorderOrBackground(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 @@ -1359,59 +1354,6 @@ nsTableFrame::GetDeflationForBackground(nsPresContext* aPresContext) const return GetOuterBCBorder(wm).GetPhysicalMargin(wm); } -// XXX We don't put the borders and backgrounds in tree order like we should. -// That requires some major surgery which we aren't going to do right now. -DrawResult -nsTableFrame::PaintTableBorderBackground(nsDisplayListBuilder* aBuilder, - nsRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsPoint aPt) -{ - nsPresContext* presContext = PresContext(); - - uint32_t bgFlags = aBuilder->GetBackgroundPaintFlags(); - PaintBorderFlags borderFlags = aBuilder->ShouldSyncDecodeImages() - ? PaintBorderFlags::SYNC_DECODE_IMAGES - : PaintBorderFlags(); - - TableBackgroundPainter painter(this, TableBackgroundPainter::eOrigin_Table, - presContext, aRenderingContext, - aDirtyRect, aPt, bgFlags); - nsMargin deflate = GetDeflationForBackground(presContext); - // If 'deflate' is (0,0,0,0) then we'll paint the table background - // in a separate display item, so don't do it here. - DrawResult result = - painter.PaintTable(this, deflate, deflate != nsMargin(0, 0, 0, 0)); - - if (StyleVisibility()->IsVisible()) { - if (!IsBorderCollapse()) { - Sides skipSides = GetSkipSides(); - nsRect rect(aPt, mRect.Size()); - - result &= - nsCSSRendering::PaintBorder(presContext, aRenderingContext, this, - aDirtyRect, rect, mStyleContext, - borderFlags, skipSides); - } else { - DrawTarget* drawTarget = aRenderingContext.GetDrawTarget(); - - gfxPoint devPixelOffset = - nsLayoutUtils::PointToGfxPoint(aPt, - 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))); - - PaintBCBorders(*drawTarget, aDirtyRect - aPt); - } - } - - return result; -} - nsIFrame::LogicalSides nsTableFrame::GetLogicalSkipSides(const ReflowInput* aReflowInput) const { @@ -1564,16 +1506,15 @@ nsTableFrame::GetPrefISize(nsRenderingContext *aRenderingContext) } /* virtual */ nsIFrame::IntrinsicISizeOffsetData -nsTableFrame::IntrinsicISizeOffsets() +nsTableFrame::IntrinsicISizeOffsets(nscoord aPercentageBasis) { - IntrinsicISizeOffsetData result = nsContainerFrame::IntrinsicISizeOffsets(); + IntrinsicISizeOffsetData result = + nsContainerFrame::IntrinsicISizeOffsets(aPercentageBasis); result.hMargin = 0; - result.hPctMargin = 0; if (IsBorderCollapse()) { result.hPadding = 0; - result.hPctPadding = 0; WritingMode wm = GetWritingMode(); LogicalMargin outerBC = GetIncludedOuterBCBorder(wm); diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index 7e56c28c1..a6b786402 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -250,7 +250,6 @@ public: nsFrame* aFrame, const nsRect& aDirtyRect, const nsDisplayListSet& aLists, - nsDisplayTableItem* aDisplayItem, DisplayGenericTablePartTraversal aTraversal = GenericTraversal); // Return the closest sibling of aPriorChildFrame (including aPriroChildFrame) @@ -272,16 +271,6 @@ public: const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; - /** - * Paint the background of the table and its parts (column groups, - * columns, row groups, rows, and cells), and the table border, and all - * internal borders if border-collapse is on. - */ - DrawResult PaintTableBorderBackground(nsDisplayListBuilder* aBuilder, - nsRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsPoint aPt); - /** Get the outer half (i.e., the part outside the height and width of * the table) of the largest segment (?) of border-collapsed border on * the table on each side, or 0 for non border-collapsed tables. @@ -324,7 +313,8 @@ public: // border to the results of these functions. virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override; virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override; - virtual IntrinsicISizeOffsetData IntrinsicISizeOffsets() override; + IntrinsicISizeOffsetData IntrinsicISizeOffsets(nscoord aPercentageBasis = + NS_UNCONSTRAINEDSIZE) override; virtual mozilla::LogicalSize ComputeSize(nsRenderingContext* aRenderingContext, diff --git a/layout/tables/nsTablePainter.cpp b/layout/tables/nsTablePainter.cpp deleted file mode 100644 index bfe2a7d42..000000000 --- a/layout/tables/nsTablePainter.cpp +++ /dev/null @@ -1,696 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsTableFrame.h" -#include "nsTableRowGroupFrame.h" -#include "nsTableRowFrame.h" -#include "nsTableColGroupFrame.h" -#include "nsTableColFrame.h" -#include "nsTableCellFrame.h" -#include "nsTablePainter.h" -#include "nsCSSRendering.h" -#include "nsDisplayList.h" -#include "mozilla/WritingModes.h" - -/* ~*~ Table Background Painting ~*~ - - Mozilla's Table Background painting follows CSS2.1:17.5.1 - That section does not, however, describe the effect of - borders on background image positioning. What we do is: - - - in separate borders, the borders are passed in so that - their width figures in image positioning, even for rows/cols, which - don't have visible borders. This is done to allow authors - to position row backgrounds by, for example, aligning the - top left corner with the top left padding corner of the - top left table cell in the row in cases where all cells - have consistent border widths. If we didn't honor these - invisible borders, there would be no way to align - backgrounds with the padding edges, and designs would be - lost underneath the border. - - - in collapsing borders, because the borders collapse, we - use the -continuous border- width to synthesize a border - style and pass that in instead of using the element's - assigned style directly. - - The continuous border on a given edge of an element is - the collapse of all borders guaranteed to be continuous - along that edge. Cell borders are ignored (because, for - example, setting a thick border on the leftmost cell - should not shift the row background over; this way a - striped background set on <tr> will line up across rows - even if the cells are assigned arbitrary border widths. - - For example, the continuous border on the top edge of a - row group is the collapse of any row group, row, and - table borders involved. (The first row group's top would - be [table-top + row group top + first row top]. It's bottom - would be [row group bottom + last row bottom + next row - top + next row group top].) - The top edge of a column group likewise includes the - table top, row group top, and first row top borders. However, - it *also* includes its own top border, since that is guaranteed - to be continuous. It does not include column borders because - those are not guaranteed to be continuous: there may be two - columns with different borders in a single column group. - - An alternative would be to define the continuous border as - [table? + row group + row] for horizontal - [table? + col group + col] for vertical - This makes it easier to line up backgrounds across elements - despite varying border widths, but it does not give much - flexibility in aligning /to/ those border widths. -*/ - - -/* ~*~ TableBackgroundPainter ~*~ - - The TableBackgroundPainter is created and destroyed in one painting call. - Its principal function is PaintTable, which paints all table element - backgrounds. The initial code in that method sets up an array of column - data that caches the background styles and the border sizes for the - columns and colgroups in TableBackgroundData structs in mCols. Data for - BC borders are calculated and stashed in a synthesized border style struct - in the data struct since collapsed borders aren't the same width as style- - assigned borders. The data struct optimizes by only doing this if there's - an image background; otherwise we don't care. //XXX should also check background-origin - The class then loops through the row groups, rows, and cells. At the cell - level, it paints the backgrounds, one over the other, inside the cell rect. - - The exception to this pattern is when a table element creates a (pseudo) - stacking context. Elements with stacking contexts (e.g., 'opacity' applied) - are <dfn>passed through</dfn>, which means their data (and their - descendants' data) are not cached. The full loop is still executed, however, - so that underlying layers can get painted at the cell level. - - The TableBackgroundPainter is then destroyed. - - Elements with stacking contexts set up their own painter to finish the - painting process, since they were skipped. They call the appropriate - sub-part of the loop (e.g. PaintRow) which will paint the frame and - descendants. - - XXX views are going - */ - -using namespace mozilla; -using namespace mozilla::image; - -TableBackgroundPainter::TableBackgroundData::TableBackgroundData() - : mFrame(nullptr) - , mVisible(false) - , mUsesSynthBorder(false) -{ -} - -TableBackgroundPainter::TableBackgroundData::TableBackgroundData(nsIFrame* aFrame) - : mFrame(aFrame) - , mRect(aFrame->GetRect()) - , mVisible(mFrame->IsVisibleForPainting()) - , mUsesSynthBorder(false) -{ -} - -inline bool -TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder() const -{ - /* we only need accurate border data when positioning background images*/ - if (!mVisible) { - return false; - } - - const nsStyleImageLayers& layers = mFrame->StyleBackground()->mImage; - NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, layers) { - if (!layers.mLayers[i].mImage.IsEmpty()) - return true; - } - return false; -} - -void -TableBackgroundPainter::TableBackgroundData::SetBCBorder(const nsMargin& aBorder) -{ - mUsesSynthBorder = true; - mSynthBorderWidths = aBorder; -} - -nsStyleBorder -TableBackgroundPainter::TableBackgroundData::StyleBorder(const nsStyleBorder& aZeroBorder) const -{ - MOZ_ASSERT(mVisible, "Don't call StyleBorder on an invisible TableBackgroundData"); - - if (mUsesSynthBorder) { - nsStyleBorder result = aZeroBorder; - NS_FOR_CSS_SIDES(side) { - result.SetBorderWidth(side, mSynthBorderWidths.Side(side)); - } - return result; - } - - MOZ_ASSERT(mFrame); - - return *mFrame->StyleBorder(); -} - -TableBackgroundPainter::TableBackgroundPainter(nsTableFrame* aTableFrame, - Origin aOrigin, - nsPresContext* aPresContext, - nsRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - const nsPoint& aRenderPt, - uint32_t aBGPaintFlags) - : mPresContext(aPresContext), - mRenderingContext(aRenderingContext), - mRenderPt(aRenderPt), - mDirtyRect(aDirtyRect), - mOrigin(aOrigin), - mZeroBorder(aPresContext), - mBGPaintFlags(aBGPaintFlags) -{ - MOZ_COUNT_CTOR(TableBackgroundPainter); - - NS_FOR_CSS_SIDES(side) { - mZeroBorder.SetBorderStyle(side, NS_STYLE_BORDER_STYLE_SOLID); - mZeroBorder.SetBorderWidth(side, 0); - } - - mIsBorderCollapse = aTableFrame->IsBorderCollapse(); -#ifdef DEBUG - mCompatMode = mPresContext->CompatibilityMode(); -#endif - mNumCols = aTableFrame->GetColCount(); -} - -TableBackgroundPainter::~TableBackgroundPainter() -{ - MOZ_COUNT_DTOR(TableBackgroundPainter); -} - -DrawResult -TableBackgroundPainter::PaintTableFrame(nsTableFrame* aTableFrame, - nsTableRowGroupFrame* aFirstRowGroup, - nsTableRowGroupFrame* aLastRowGroup, - const nsMargin& aDeflate) -{ - MOZ_ASSERT(aTableFrame, "null frame"); - TableBackgroundData tableData(aTableFrame); - tableData.mRect.MoveTo(0,0); //using table's coords - tableData.mRect.Deflate(aDeflate); - WritingMode wm = aTableFrame->GetWritingMode(); - if (mIsBorderCollapse && tableData.ShouldSetBCBorder()) { - if (aFirstRowGroup && aLastRowGroup && mNumCols > 0) { - //only handle non-degenerate tables; we need a more robust BC model - //to make degenerate tables' borders reasonable to deal with - LogicalMargin border(wm); - LogicalMargin tempBorder(wm); - nsTableColFrame* colFrame = aTableFrame->GetColFrame(mNumCols - 1); - if (colFrame) { - colFrame->GetContinuousBCBorderWidth(wm, tempBorder); - } - border.IEnd(wm) = tempBorder.IEnd(wm); - - aLastRowGroup->GetContinuousBCBorderWidth(wm, tempBorder); - border.BEnd(wm) = tempBorder.BEnd(wm); - - nsTableRowFrame* rowFrame = aFirstRowGroup->GetFirstRow(); - if (rowFrame) { - rowFrame->GetContinuousBCBorderWidth(wm, tempBorder); - border.BStart(wm) = tempBorder.BStart(wm); - } - - border.IStart(wm) = aTableFrame->GetContinuousIStartBCBorderWidth(); - - tableData.SetBCBorder(border.GetPhysicalMargin(wm)); - } - } - - DrawResult result = DrawResult::SUCCESS; - - if (tableData.IsVisible()) { - nsCSSRendering::PaintBGParams params = - nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, - mRenderingContext, - mDirtyRect, - tableData.mRect + mRenderPt, - tableData.mFrame, - mBGPaintFlags); - - result &= - nsCSSRendering::PaintBackgroundWithSC(params, - tableData.mFrame->StyleContext(), - tableData.StyleBorder(mZeroBorder)); - } - - return result; -} - -void -TableBackgroundPainter::TranslateContext(nscoord aDX, - nscoord aDY) -{ - mRenderPt += nsPoint(aDX, aDY); - for (auto& col : mCols) { - col.mCol.mRect.MoveBy(-aDX, -aDY); - } - for (auto& colGroup : mColGroups) { - colGroup.mRect.MoveBy(-aDX, -aDY); - } -} - -TableBackgroundPainter::ColData::ColData(nsIFrame* aFrame, TableBackgroundData& aColGroupBGData) - : mCol(aFrame) - , mColGroup(aColGroupBGData) -{ -} - -DrawResult -TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame, - const nsMargin& aDeflate, - bool aPaintTableBackground) -{ - NS_PRECONDITION(aTableFrame, "null table frame"); - - nsTableFrame::RowGroupArray rowGroups; - aTableFrame->OrderRowGroups(rowGroups); - WritingMode wm = aTableFrame->GetWritingMode(); - - DrawResult result = DrawResult::SUCCESS; - - if (rowGroups.Length() < 1) { //degenerate case - if (aPaintTableBackground) { - result &= PaintTableFrame(aTableFrame, nullptr, nullptr, nsMargin(0,0,0,0)); - } - /* No cells; nothing else to paint */ - return result; - } - - if (aPaintTableBackground) { - result &= - PaintTableFrame(aTableFrame, rowGroups[0], rowGroups[rowGroups.Length() - 1], - aDeflate); - } - - /*Set up column background/border data*/ - if (mNumCols > 0) { - nsFrameList& colGroupList = aTableFrame->GetColGroups(); - NS_ASSERTION(colGroupList.FirstChild(), "table should have at least one colgroup"); - - // Collect all col group frames first so that we know how many there are. - nsTArray<nsTableColGroupFrame*> colGroupFrames; - for (nsTableColGroupFrame* cgFrame = static_cast<nsTableColGroupFrame*>(colGroupList.FirstChild()); - cgFrame; cgFrame = static_cast<nsTableColGroupFrame*>(cgFrame->GetNextSibling())) { - - if (cgFrame->GetColCount() < 1) { - //No columns, no cells, so no need for data - continue; - } - colGroupFrames.AppendElement(cgFrame); - } - - // Ensure that mColGroups won't reallocate during the loop below, because - // we grab references to its contents and need those to stay valid until - // mColGroups is destroyed as part of TablePainter destruction. - mColGroups.SetCapacity(colGroupFrames.Length()); - - LogicalMargin border(wm); - /* BC iStart borders aren't stored on cols, but the previous column's - iEnd border is the next one's iStart border.*/ - //Start with table's iStart border. - nscoord lastIStartBorder = aTableFrame->GetContinuousIStartBCBorderWidth(); - - for (nsTableColGroupFrame* cgFrame : colGroupFrames) { - /*Create data struct for column group*/ - TableBackgroundData& cgData = *mColGroups.AppendElement(TableBackgroundData(cgFrame)); - if (mIsBorderCollapse && cgData.ShouldSetBCBorder()) { - border.IStart(wm) = lastIStartBorder; - cgFrame->GetContinuousBCBorderWidth(wm, border); - cgData.SetBCBorder(border.GetPhysicalMargin(wm)); - } - - /*Loop over columns in this colgroup*/ - for (nsTableColFrame* col = cgFrame->GetFirstColumn(); col; - col = static_cast<nsTableColFrame*>(col->GetNextSibling())) { - MOZ_ASSERT(size_t(col->GetColIndex()) == mCols.Length()); - // Store a reference to the colGroup in the ColData element. - ColData& colData = *mCols.AppendElement(ColData(col, cgData)); - //Bring column mRect into table's coord system - colData.mCol.mRect.MoveBy(cgData.mRect.x, cgData.mRect.y); - if (mIsBorderCollapse) { - border.IStart(wm) = lastIStartBorder; - lastIStartBorder = col->GetContinuousBCBorderWidth(wm, border); - if (colData.mCol.ShouldSetBCBorder()) { - colData.mCol.SetBCBorder(border.GetPhysicalMargin(wm)); - } - } - } - } - } - - for (uint32_t i = 0; i < rowGroups.Length(); i++) { - nsTableRowGroupFrame* rg = rowGroups[i]; - TableBackgroundData rowGroupBGData(rg); - // Need to compute the right rect via GetOffsetTo, since the row - // group may not be a child of the table. - rowGroupBGData.mRect.MoveTo(rg->GetOffsetTo(aTableFrame)); - - // We have to draw backgrounds not only within the overflow region of this - // row group, but also possibly (in the case of column / column group - // backgrounds) at its pre-relative-positioning location. - nsRect rgVisualOverflow = rg->GetVisualOverflowRectRelativeToSelf(); - nsRect rgOverflowRect = rgVisualOverflow + rg->GetPosition(); - nsRect rgNormalRect = rgVisualOverflow + rg->GetNormalPosition(); - - if (rgOverflowRect.Union(rgNormalRect).Intersects(mDirtyRect - mRenderPt)) { - result &= - PaintRowGroup(rg, rowGroupBGData, rg->IsPseudoStackingContextFromStyle()); - } - } - - return result; -} - -DrawResult -TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame) -{ - return PaintRowGroup(aFrame, TableBackgroundData(aFrame), false); -} - -DrawResult -TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame, - TableBackgroundData aRowGroupBGData, - bool aPassThrough) -{ - MOZ_ASSERT(aFrame, "null frame"); - - nsTableRowFrame* firstRow = aFrame->GetFirstRow(); - WritingMode wm = aFrame->GetWritingMode(); - - /* Load row group data */ - if (aPassThrough) { - aRowGroupBGData.MakeInvisible(); - } else { - if (mIsBorderCollapse && aRowGroupBGData.ShouldSetBCBorder()) { - LogicalMargin border(wm); - if (firstRow) { - //pick up first row's bstart border (= rg bstart border) - firstRow->GetContinuousBCBorderWidth(wm, border); - /* (row group doesn't store its bstart border) */ - } - //overwrite sides+bottom borders with rg's own - aFrame->GetContinuousBCBorderWidth(wm, border); - aRowGroupBGData.SetBCBorder(border.GetPhysicalMargin(wm)); - } - aPassThrough = !aRowGroupBGData.IsVisible(); - } - - /* translate everything into row group coord system*/ - if (eOrigin_TableRowGroup != mOrigin) { - TranslateContext(aRowGroupBGData.mRect.x, aRowGroupBGData.mRect.y); - } - nsRect rgRect = aRowGroupBGData.mRect; - aRowGroupBGData.mRect.MoveTo(0, 0); - - /* Find the right row to start with */ - - // Note that mDirtyRect - mRenderPt is guaranteed to be in the row - // group's coordinate system here, so passing its .y to - // GetFirstRowContaining is ok. - nscoord overflowAbove; - nsIFrame* cursor = aFrame->GetFirstRowContaining(mDirtyRect.y - mRenderPt.y, &overflowAbove); - - // Sadly, it seems like there may be non-row frames in there... or something? - // There are certainly null-checks in GetFirstRow() and GetNextRow(). :( - while (cursor && cursor->GetType() != nsGkAtoms::tableRowFrame) { - cursor = cursor->GetNextSibling(); - } - - // It's OK if cursor is null here. - nsTableRowFrame* row = static_cast<nsTableRowFrame*>(cursor); - if (!row) { - // No useful cursor; just start at the top. Don't bother to set up a - // cursor; if we've gotten this far then we've already built the display - // list for the rowgroup, so not having a cursor means that there's some - // good reason we don't have a cursor and we shouldn't create one here. - row = firstRow; - } - - DrawResult result = DrawResult::SUCCESS; - - /* Finally paint */ - for (; row; row = row->GetNextRow()) { - TableBackgroundData rowBackgroundData(row); - - // Be sure to consider our positions both pre- and post-relative - // positioning, since we potentially need to paint at both places. - nscoord rowY = std::min(rowBackgroundData.mRect.y, row->GetNormalPosition().y); - - // Intersect wouldn't handle rowspans. - if (cursor && - (mDirtyRect.YMost() - mRenderPt.y) <= (rowY - overflowAbove)) { - // All done; cells originating in later rows can't intersect mDirtyRect. - break; - } - - result &= - PaintRow(row, aRowGroupBGData, rowBackgroundData, - aPassThrough || row->IsPseudoStackingContextFromStyle()); - } - - /* translate back into table coord system */ - if (eOrigin_TableRowGroup != mOrigin) { - TranslateContext(-rgRect.x, -rgRect.y); - } - - return result; -} - -DrawResult -TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame) -{ - return PaintRow(aFrame, TableBackgroundData(), TableBackgroundData(aFrame), false); -} - -DrawResult -TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame, - const TableBackgroundData& aRowGroupBGData, - TableBackgroundData aRowBGData, - bool aPassThrough) -{ - MOZ_ASSERT(aFrame, "null frame"); - - /* Load row data */ - WritingMode wm = aFrame->GetWritingMode(); - if (aPassThrough) { - aRowBGData.MakeInvisible(); - } else { - if (mIsBorderCollapse && aRowBGData.ShouldSetBCBorder()) { - LogicalMargin border(wm); - nsTableRowFrame* nextRow = aFrame->GetNextRow(); - if (nextRow) { //outer bStart after us is inner bEnd for us - border.BEnd(wm) = nextRow->GetOuterBStartContBCBorderWidth(); - } - else { //acquire rg's bEnd border - nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame->GetParent()); - rowGroup->GetContinuousBCBorderWidth(wm, border); - } - //get the rest of the borders; will overwrite all but bEnd - aFrame->GetContinuousBCBorderWidth(wm, border); - - aRowBGData.SetBCBorder(border.GetPhysicalMargin(wm)); - } - aPassThrough = !aRowBGData.IsVisible(); - } - - /* Translate */ - if (eOrigin_TableRow == mOrigin) { - /* If we originate from the row, then make the row the origin. */ - aRowBGData.mRect.MoveTo(0, 0); - } - //else: Use row group's coord system -> no translation necessary - - DrawResult result = DrawResult::SUCCESS; - - for (nsTableCellFrame* cell = aFrame->GetFirstCell(); cell; cell = cell->GetNextCell()) { - nsRect cellBGRect, rowBGRect, rowGroupBGRect, colBGRect; - ComputeCellBackgrounds(cell, aRowGroupBGData, aRowBGData, - cellBGRect, rowBGRect, - rowGroupBGRect, colBGRect); - - // Find the union of all the cell background layers. - nsRect combinedRect(cellBGRect); - combinedRect.UnionRect(combinedRect, rowBGRect); - combinedRect.UnionRect(combinedRect, rowGroupBGRect); - combinedRect.UnionRect(combinedRect, colBGRect); - - if (combinedRect.Intersects(mDirtyRect)) { - bool passCell = aPassThrough || cell->IsPseudoStackingContextFromStyle(); - result &= - PaintCell(cell, aRowGroupBGData, aRowBGData, cellBGRect, rowBGRect, - rowGroupBGRect, colBGRect, passCell); - } - } - - return result; -} - -DrawResult -TableBackgroundPainter::PaintCell(nsTableCellFrame* aCell, - const TableBackgroundData& aRowGroupBGData, - const TableBackgroundData& aRowBGData, - nsRect& aCellBGRect, - nsRect& aRowBGRect, - nsRect& aRowGroupBGRect, - nsRect& aColBGRect, - bool aPassSelf) -{ - MOZ_ASSERT(aCell, "null frame"); - - const nsStyleTableBorder* cellTableStyle; - cellTableStyle = aCell->StyleTableBorder(); - if (NS_STYLE_TABLE_EMPTY_CELLS_SHOW != cellTableStyle->mEmptyCells && - aCell->GetContentEmpty() && !mIsBorderCollapse) { - return DrawResult::SUCCESS; - } - - int32_t colIndex; - aCell->GetColIndex(colIndex); - // We're checking mNumCols instead of mCols.Length() here because mCols can - // be empty even if mNumCols > 0. - NS_ASSERTION(size_t(colIndex) < mNumCols, "out-of-bounds column index"); - if (size_t(colIndex) >= mNumCols) { - return DrawResult::SUCCESS; - } - - // If callers call PaintRowGroup or PaintRow directly, we haven't processed - // our columns. Ignore column / col group backgrounds in that case. - bool haveColumns = !mCols.IsEmpty(); - - DrawResult result = DrawResult::SUCCESS; - - //Paint column group background - if (haveColumns && mCols[colIndex].mColGroup.IsVisible()) { - nsCSSRendering::PaintBGParams params = - nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, mRenderingContext, - mDirtyRect, - mCols[colIndex].mColGroup.mRect + mRenderPt, - mCols[colIndex].mColGroup.mFrame, - mBGPaintFlags); - params.bgClipRect = &aColBGRect; - result &= - nsCSSRendering::PaintBackgroundWithSC(params, - mCols[colIndex].mColGroup.mFrame->StyleContext(), - mCols[colIndex].mColGroup.StyleBorder(mZeroBorder)); - } - - //Paint column background - if (haveColumns && mCols[colIndex].mCol.IsVisible()) { - nsCSSRendering::PaintBGParams params = - nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, mRenderingContext, - mDirtyRect, - mCols[colIndex].mCol.mRect + mRenderPt, - mCols[colIndex].mCol.mFrame, - mBGPaintFlags); - params.bgClipRect = &aColBGRect; - result &= - nsCSSRendering::PaintBackgroundWithSC(params, - mCols[colIndex].mCol.mFrame->StyleContext(), - mCols[colIndex].mCol.StyleBorder(mZeroBorder)); - } - - //Paint row group background - if (aRowGroupBGData.IsVisible()) { - nsCSSRendering::PaintBGParams params = - nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, mRenderingContext, - mDirtyRect, - aRowGroupBGData.mRect + mRenderPt, - aRowGroupBGData.mFrame, mBGPaintFlags); - params.bgClipRect = &aRowGroupBGRect; - result &= - nsCSSRendering::PaintBackgroundWithSC(params, - aRowGroupBGData.mFrame->StyleContext(), - aRowGroupBGData.StyleBorder(mZeroBorder)); - } - - //Paint row background - if (aRowBGData.IsVisible()) { - nsCSSRendering::PaintBGParams params = - nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, mRenderingContext, - mDirtyRect, - aRowBGData.mRect + mRenderPt, - aRowBGData.mFrame, mBGPaintFlags); - params.bgClipRect = &aRowBGRect; - result &= - nsCSSRendering::PaintBackgroundWithSC(params, - aRowBGData.mFrame->StyleContext(), - aRowBGData.StyleBorder(mZeroBorder)); - } - - //Paint cell background in border-collapse unless we're just passing - if (mIsBorderCollapse && !aPassSelf) { - result &= - aCell->PaintCellBackground(mRenderingContext, mDirtyRect, - aCellBGRect.TopLeft(), mBGPaintFlags); - } - - return result; -} - -void -TableBackgroundPainter::ComputeCellBackgrounds(nsTableCellFrame* aCell, - const TableBackgroundData& aRowGroupBGData, - const TableBackgroundData& aRowBGData, - nsRect& aCellBGRect, - nsRect& aRowBGRect, - nsRect& aRowGroupBGRect, - nsRect& aColBGRect) -{ - // We need to compute table background layer rects for this cell space, - // adjusted for possible relative positioning. This behavior is not specified - // at the time of this writing, but the approach below should be web - // compatible. - // - // Our goal is that relative positioning of a table part should leave - // backgrounds *under* that part unchanged. ("Under" being defined by CSS 2.1 - // Section 17.5.1.) If a cell is positioned, we do not expect the row - // background to move. On the other hand, the backgrounds of layers *above* - // the positioned part are taken along for the ride -- for example, - // positioning a row group will also cause the row background to be drawn in - // the new location, unless it has further positioning applied. - // - // Each table part layer has its position stored in the coordinate space of - // the layer below (which is to say, its geometric parent), and the stored - // position is the post-relative-positioning one. The position of each - // background layer rect is thus determined by peeling off successive table - // part layers, removing the contribution of each layer's positioning one by - // one. Every rect we generate will be the same size, the size of the cell - // space. - - // We cannot rely on the row group background data to be available, since some - // callers enter through PaintRow. - nsIFrame* rowGroupFrame = - aRowGroupBGData.mFrame ? aRowGroupBGData.mFrame : aRowBGData.mFrame->GetParent(); - - // The cell background goes at the cell's position, translated to use the same - // coordinate system as aRowBGData. - aCellBGRect = aCell->GetRect() + aRowBGData.mRect.TopLeft() + mRenderPt; - - // The row background goes at the normal position of the cell, which is to say - // the position without relative positioning applied. - aRowBGRect = aCellBGRect + (aCell->GetNormalPosition() - aCell->GetPosition()); - - // The row group background goes at the position we'd find the cell if neither - // the cell's relative positioning nor the row's were applied. - aRowGroupBGRect = aRowBGRect + - (aRowBGData.mFrame->GetNormalPosition() - aRowBGData.mFrame->GetPosition()); - - // The column and column group backgrounds (they're always at the same - // location, since relative positioning doesn't apply to columns or column - // groups) are drawn at the position we'd find the cell if none of the cell's, - // row's, or row group's relative positioning were applied. - aColBGRect = aRowGroupBGRect + - (rowGroupFrame->GetNormalPosition() - rowGroupFrame->GetPosition()); - -} diff --git a/layout/tables/nsTablePainter.h b/layout/tables/nsTablePainter.h deleted file mode 100644 index dfba42156..000000000 --- a/layout/tables/nsTablePainter.h +++ /dev/null @@ -1,268 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsTablePainter_h__ -#define nsTablePainter_h__ - -#include "imgIContainer.h" - -#include "celldata.h" - -// flags for Paint, PaintChild, PaintChildren are currently only used by tables. -//Table-based paint call; not a direct call as with views -#define NS_PAINT_FLAG_TABLE_BG_PAINT 0x00000001 -//Cells should paint their backgrounds only, no children -#define NS_PAINT_FLAG_TABLE_CELL_BG_PASS 0x00000002 - -class nsIFrame; -class nsTableFrame; -class nsTableRowGroupFrame; -class nsTableRowFrame; -class nsTableCellFrame; - -class TableBackgroundPainter -{ - /* - * Helper class for painting table backgrounds - * - */ - - typedef mozilla::image::DrawResult DrawResult; - - public: - - enum Origin { eOrigin_Table, eOrigin_TableRowGroup, eOrigin_TableRow }; - - /** Public constructor - * @param aTableFrame - the table's table frame - * @param aOrigin - what type of table frame is creating this instance - * @param aPresContext - the presentation context - * @param aRenderingContext - the rendering context - * @param aDirtyRect - the area that needs to be painted, - * relative to aRenderingContext - * @param aPt - offset of the table frame relative to - * aRenderingContext - * @param aBGPaintFlags - Flags of the nsCSSRendering::PAINTBG_* variety - */ - TableBackgroundPainter(nsTableFrame* aTableFrame, - Origin aOrigin, - nsPresContext* aPresContext, - nsRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - const nsPoint& aPt, - uint32_t aBGPaintFlags); - - /** Destructor */ - ~TableBackgroundPainter(); - - /* ~*~ The Border Collapse Painting Issue ~*~ - - In border-collapse, the *table* paints the cells' borders, - so we need to make sure the backgrounds get painted first - (underneath) by doing a cell-background-only painting pass. - */ - - /* ~*~ Using nsTablePainter Background Painting ~*~ - - A call to PaintTable will normally paint all of the table's - elements (except for the table background, if aPaintTableBackground - is false). - Elements with views however, will be skipped and must create their - own painter to call the appropriate paint function in their ::Paint - method (e.g. painter.PaintRow in nsTableRow::Paint) - */ - - /** Paint background for the table frame (if requested) and its children - * down through cells. - * (Cells themselves will only be painted in border collapse) - * Table must do a flagged TABLE_BG_PAINT ::Paint call on its - * children afterwards - * @param aTableFrame - the table frame - * @param aDeflate - deflation needed to bring table's mRect - * to the outer grid lines in border-collapse - * @param aPaintTableBackground - if true, the table background - * is included, otherwise it isn't - * @returns DrawResult::SUCCESS if all painting was successful. If some - * painting failed or an improved result could be achieved by sync - * decoding images, returns another value. - */ - DrawResult PaintTable(nsTableFrame* aTableFrame, const nsMargin& aDeflate, - bool aPaintTableBackground); - - /** Paint background for the row group and its children down through cells - * (Cells themselves will only be painted in border collapse) - * Standards mode only - * Table Row Group must do a flagged TABLE_BG_PAINT ::Paint call on its - * children afterwards - * @param aFrame - the table row group frame - * @returns DrawResult::SUCCESS if all painting was successful. If some - * painting failed or an improved result could be achieved by sync - * decoding images, returns another value. - */ - DrawResult PaintRowGroup(nsTableRowGroupFrame* aFrame); - - /** Paint background for the row and its children down through cells - * (Cells themselves will only be painted in border collapse) - * Standards mode only - * Table Row must do a flagged TABLE_BG_PAINT ::Paint call on its - * children afterwards - * @param aFrame - the table row frame - * @returns DrawResult::SUCCESS if all painting was successful. If some - * painting failed or an improved result could be achieved by sync - * decoding images, returns another value. - */ - DrawResult PaintRow(nsTableRowFrame* aFrame); - - private: - struct TableBackgroundData; - - /** Paint table frame's background - * @param aTableFrame - the table frame - * @param aFirstRowGroup - the first (in layout order) row group - * may be null - * @param aLastRowGroup - the last (in layout order) row group - * may be null - * @param aDeflate - adjustment to frame's rect (used for quirks BC) - * may be null - */ - DrawResult PaintTableFrame(nsTableFrame* aTableFrame, - nsTableRowGroupFrame* aFirstRowGroup, - nsTableRowGroupFrame* aLastRowGroup, - const nsMargin& aDeflate); - - /* aPassThrough params indicate whether to paint the element or to just - * pass through and paint underlying layers only. - * aRowGroupBGData is not a const reference because the function modifies - * its copy. Same for aRowBGData in PaintRow. - * See Public versions for function descriptions - */ - DrawResult PaintRowGroup(nsTableRowGroupFrame* aFrame, - TableBackgroundData aRowGroupBGData, - bool aPassThrough); - - DrawResult PaintRow(nsTableRowFrame* aFrame, - const TableBackgroundData& aRowGroupBGData, - TableBackgroundData aRowBGData, - bool aPassThrough); - - /** Paint table background layers for this cell space - * Also paints cell's own background in border-collapse mode - * @param aCell - the cell - * @param aRowGroupBGData - background drawing info for the row group - * @param aRowBGData - background drawing info for the row - * @param aCellBGRect - background rect for the cell - * @param aRowBGRect - background rect for the row - * @param aRowGroupBGRect - background rect for the row group - * @param aColBGRect - background rect for the column and column group - * @param aPassSelf - pass this cell; i.e. paint only underlying layers - */ - DrawResult PaintCell(nsTableCellFrame* aCell, - const TableBackgroundData& aRowGroupBGData, - const TableBackgroundData& aRowBGData, - nsRect& aCellBGRect, - nsRect& aRowBGRect, - nsRect& aRowGroupBGRect, - nsRect& aColBGRect, - bool aPassSelf); - - /** Compute table background layer positions for this cell space - * @param aCell - the cell - * @param aRowGroupBGData - background drawing info for the row group - * @param aRowBGData - background drawing info for the row - * @param aCellBGRectOut - outparam: background rect for the cell - * @param aRowBGRectOut - outparam: background rect for the row - * @param aRowGroupBGRectOut - outparam: background rect for the row group - * @param aColBGRectOut - outparam: background rect for the column - and column group - */ - void ComputeCellBackgrounds(nsTableCellFrame* aCell, - const TableBackgroundData& aRowGroupBGData, - const TableBackgroundData& aRowBGData, - nsRect& aCellBGRect, - nsRect& aRowBGRect, - nsRect& aRowGroupBGRect, - nsRect& aColBGRect); - - /** Translate mRenderingContext, mDirtyRect, and mCols' column and - * colgroup coords - * @param aDX - origin's x-coord change - * @param aDY - origin's y-coord change - */ - void TranslateContext(nscoord aDX, - nscoord aDY); - - struct TableBackgroundData { - public: - /** - * Construct an empty TableBackgroundData instance, which is invisible. - */ - TableBackgroundData(); - - /** - * Construct a TableBackgroundData instance for a frame. Visibility will - * be derived from the frame and can be overridden using MakeInvisible(). - */ - explicit TableBackgroundData(nsIFrame* aFrame); - - /** Destructor */ - ~TableBackgroundData() {} - - /** Data is valid & frame is visible */ - bool IsVisible() const { return mVisible; } - - /** Override visibility of the frame, force it to be invisible */ - void MakeInvisible() { mVisible = false; } - - /** True if need to set border-collapse border; must call SetFull beforehand */ - bool ShouldSetBCBorder() const; - - /** Set border-collapse border with aBorderWidth as widths */ - void SetBCBorder(const nsMargin& aBorderWidth); - - /** - * @param aZeroBorder An nsStyleBorder instance that has been initialized - * for the right nsPresContext, with all border widths - * set to zero and border styles set to solid. - * @return The nsStyleBorder that should be used for rendering - * this background. - */ - nsStyleBorder StyleBorder(const nsStyleBorder& aZeroBorder) const; - - nsIFrame* const mFrame; - - /** mRect is the rect of mFrame in the current coordinate system */ - nsRect mRect; - - private: - nsMargin mSynthBorderWidths; - bool mVisible; - bool mUsesSynthBorder; - }; - - struct ColData { - ColData(nsIFrame* aFrame, TableBackgroundData& aColGroupBGData); - TableBackgroundData mCol; - TableBackgroundData& mColGroup; // reference to col's parent colgroup's data, owned by TablePainter in mColGroups - }; - - nsPresContext* mPresContext; - nsRenderingContext& mRenderingContext; - nsPoint mRenderPt; - nsRect mDirtyRect; -#ifdef DEBUG - nsCompatibility mCompatMode; -#endif - bool mIsBorderCollapse; - Origin mOrigin; //user's table frame type - - nsTArray<TableBackgroundData> mColGroups; - nsTArray<ColData> mCols; - size_t mNumCols; - - nsStyleBorder mZeroBorder; //cached zero-width border - uint32_t mBGPaintFlags; -}; - -#endif diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index 1b6051ef2..ea2477b73 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -561,65 +561,12 @@ nsTableRowFrame::CalcBSize(const ReflowInput& aReflowInput) return GetInitialBSize(); } -/** - * We need a custom display item for table row backgrounds. This is only used - * when the table row is the root of a stacking context (e.g., has 'opacity'). - * Table row backgrounds can extend beyond the row frame bounds, when - * the row contains row-spanning cells. - */ -class nsDisplayTableRowBackground : public nsDisplayTableItem { -public: - nsDisplayTableRowBackground(nsDisplayListBuilder* aBuilder, - nsTableRowFrame* aFrame) : - nsDisplayTableItem(aBuilder, aFrame) { - MOZ_COUNT_CTOR(nsDisplayTableRowBackground); - } -#ifdef NS_BUILD_REFCNT_LOGGING - virtual ~nsDisplayTableRowBackground() { - MOZ_COUNT_DTOR(nsDisplayTableRowBackground); - } -#endif - - virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx) override; - NS_DISPLAY_DECL_NAME("TableRowBackground", TYPE_TABLE_ROW_BACKGROUND) -}; - -void -nsDisplayTableRowBackground::Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx) -{ - auto rowFrame = static_cast<nsTableRowFrame*>(mFrame); - TableBackgroundPainter painter(rowFrame->GetTableFrame(), - TableBackgroundPainter::eOrigin_TableRow, - mFrame->PresContext(), *aCtx, - mVisibleRect, ToReferenceFrame(), - aBuilder->GetBackgroundPaintFlags()); - - DrawResult result = painter.PaintRow(rowFrame); - 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 @@ -979,12 +926,11 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext, // be merged into the else below if we can.) nsMargin* computedOffsetProp = kidFrame->GetProperty(nsIFrame::ComputedOffsetProperty()); - // Bug 975644: a position:sticky kid can end up with a null - // property value here. - LogicalMargin computedOffsets(wm, computedOffsetProp ? - *computedOffsetProp : nsMargin()); - ReflowInput::ApplyRelativePositioning(kidFrame, wm, computedOffsets, - &kidPosition, containerSize); + + // On our fist reflow sticky children may not have the property yet (we + // need to reflow the children first to size the scroll frame). + LogicalMargin computedOffsets(wm, computedOffsetProp ? *computedOffsetProp : nsMargin()); + ReflowInput::ApplyRelativePositioning(kidFrame, wm, computedOffsets, &kidPosition, containerSize); } // In vertical-rl mode, we are likely to have containerSize.width = 0 diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h index a6aba81e7..9e15d851f 100644 --- a/layout/tables/nsTableRowFrame.h +++ b/layout/tables/nsTableRowFrame.h @@ -8,7 +8,6 @@ #include "mozilla/Attributes.h" #include "nscore.h" #include "nsContainerFrame.h" -#include "nsTablePainter.h" #include "nsTableRowGroupFrame.h" #include "mozilla/WritingModes.h" diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index 8f014b204..f613c8b79 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -154,46 +154,6 @@ nsTableRowGroupFrame::InitRepeatedFrame(nsTableRowGroupFrame* aHeaderFooterFrame return NS_OK; } -/** - * We need a custom display item for table row backgrounds. This is only used - * when the table row is the root of a stacking context (e.g., has 'opacity'). - * Table row backgrounds can extend beyond the row frame bounds, when - * the row contains row-spanning cells. - */ -class nsDisplayTableRowGroupBackground : public nsDisplayTableItem { -public: - nsDisplayTableRowGroupBackground(nsDisplayListBuilder* aBuilder, - nsTableRowGroupFrame* aFrame) : - nsDisplayTableItem(aBuilder, aFrame) { - MOZ_COUNT_CTOR(nsDisplayTableRowGroupBackground); - } -#ifdef NS_BUILD_REFCNT_LOGGING - virtual ~nsDisplayTableRowGroupBackground() { - MOZ_COUNT_DTOR(nsDisplayTableRowGroupBackground); - } -#endif - - virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx) override; - - NS_DISPLAY_DECL_NAME("TableRowGroupBackground", TYPE_TABLE_ROW_GROUP_BACKGROUND) -}; - -void -nsDisplayTableRowGroupBackground::Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx) -{ - auto rgFrame = static_cast<nsTableRowGroupFrame*>(mFrame); - TableBackgroundPainter painter(rgFrame->GetTableFrame(), - TableBackgroundPainter::eOrigin_TableRowGroup, - mFrame->PresContext(), *aCtx, - mVisibleRect, ToReferenceFrame(), - aBuilder->GetBackgroundPaintFlags()); - - DrawResult result = painter.PaintRowGroup(rgFrame); - nsDisplayTableItemGeometry::UpdateDrawResult(this, result); -} - // Handle the child-traversal part of DisplayGenericTablePart static void DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame, @@ -204,7 +164,7 @@ DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame, // Don't try to use the row cursor if we have to descend into placeholders; // we might have rows containing placeholders, where the row's overflow // area doesn't intersect the dirty rect but we need to descend into the row - // to see out of flows. + // to see out-of-flows. // Note that we really want to check ShouldDescendIntoFrame for all // the rows in |f|, but that's exactly what we're trying to avoid, so we // approximate it by checking it for |f|: if it's true for any row @@ -213,11 +173,11 @@ DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame, nullptr : f->GetFirstRowContaining(aDirtyRect.y, &overflowAbove); if (kid) { - // have a cursor, use it + // If we have a cursor, use it while (kid) { - if (kid->GetRect().y - overflowAbove >= aDirtyRect.YMost() && - kid->GetNormalRect().y - overflowAbove >= aDirtyRect.YMost()) + if (kid->GetRect().y - overflowAbove >= aDirtyRect.YMost()) { break; + } f->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists); kid = kid->GetNextSibling(); } @@ -249,19 +209,8 @@ 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 @@ -1962,12 +1911,12 @@ nsTableRowGroupFrame::GetFirstRowContaining(nscoord aY, nscoord* aOverflowAbove) // encountering a row whose overflowArea.YMost() is <= aY but which has // a row above it containing cell(s) that span to include aY. while (cursorIndex > 0 && - cursorFrame->GetNormalRect().YMost() + property->mOverflowBelow > aY) { + cursorFrame->GetRect().YMost() + property->mOverflowBelow > aY) { --cursorIndex; cursorFrame = property->mFrames[cursorIndex]; } while (cursorIndex + 1 < frameCount && - cursorFrame->GetNormalRect().YMost() + property->mOverflowBelow <= aY) { + cursorFrame->GetRect().YMost() + property->mOverflowBelow <= aY) { ++cursorIndex; cursorFrame = property->mFrames[cursorIndex]; } @@ -1980,13 +1929,11 @@ nsTableRowGroupFrame::GetFirstRowContaining(nscoord aY, nscoord* aOverflowAbove) bool nsTableRowGroupFrame::FrameCursorData::AppendFrame(nsIFrame* aFrame) { - // Relative positioning can cause table parts to move, but we will still paint - // the backgrounds for the parts under them at their 'normal' position. That - // means that we must consider the overflow rects at both positions. For - // example, if we use relative positioning to move a row-spanning cell, we - // will still paint the row background for that cell at its normal position, - // which will overflow the row. - // XXX(seth): This probably isn't correct in the presence of transforms. + // Relative positioning can cause table parts to move, which can cause issues + // with the cursor position to know which rows can be skipped. + // To make this work, use the max difference between the frame's rect and the + // union of the frame's "normal" position and the overflow rect to cover the + // area of relatively positioned elements even if they are out of order. nsRect positionedOverflowRect = aFrame->GetVisualOverflowRect(); nsPoint positionedToNormal = aFrame->GetNormalPosition() - aFrame->GetPosition(); nsRect normalOverflowRect = positionedOverflowRect + positionedToNormal; diff --git a/layout/tables/nsTableRowGroupFrame.h b/layout/tables/nsTableRowGroupFrame.h index 7abdd4b74..721d91046 100644 --- a/layout/tables/nsTableRowGroupFrame.h +++ b/layout/tables/nsTableRowGroupFrame.h @@ -10,7 +10,6 @@ #include "nsContainerFrame.h" #include "nsIAtom.h" #include "nsILineIterator.h" -#include "nsTablePainter.h" #include "nsTArray.h" #include "nsTableFrame.h" #include "mozilla/WritingModes.h" diff --git a/layout/tables/nsTableWrapperFrame.cpp b/layout/tables/nsTableWrapperFrame.cpp index f0b6d1512..da71375d5 100644 --- a/layout/tables/nsTableWrapperFrame.cpp +++ b/layout/tables/nsTableWrapperFrame.cpp @@ -190,7 +190,11 @@ nsTableWrapperFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, // 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); } |