Bug 929484 - Draw each table's background on their own display item. r=mstange

This patch do following things:
1. Create nsDisplayTableBorderCollapse that draws all collapse border of
table.
2. Don't use nsDisplayTableBorderBackground.
3. Let column and column group frame generate display items.
4. When traversing the table, also traverse the column and column group
frames.
5. For each type of table frame (col group, col, row group, row and
cell), draw their own background.

MozReview-Commit-ID: 1s2VLv6G8xi
This commit is contained in:
Morris Tseng
2017-05-05 14:30:15 +08:00
parent 411cbb77a9
commit 6476db5de7
13 changed files with 227 additions and 228 deletions

View File

@@ -59,6 +59,7 @@ DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_BACKGROUND) DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_BACKGROUND)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_GROUP_BACKGROUND) DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_GROUP_BACKGROUND)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_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)
DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW) DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW)
DECLARE_DISPLAY_ITEM_TYPE_FLAGS(TRANSFORM,TYPE_RENDERS_NO_IMAGES) DECLARE_DISPLAY_ITEM_TYPE_FLAGS(TRANSFORM,TYPE_RENDERS_NO_IMAGES)

View File

@@ -3062,11 +3062,16 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
const nsRect& aBackgroundRect, const nsRect& aBackgroundRect,
nsDisplayList* aList, nsDisplayList* aList,
bool aAllowWillPaintBorderOptimization, bool aAllowWillPaintBorderOptimization,
nsStyleContext* aStyleContext) nsStyleContext* aStyleContext,
const nsRect& aBackgroundOriginRect)
{ {
nsStyleContext* bgSC = aStyleContext; nsStyleContext* bgSC = aStyleContext;
const nsStyleBackground* bg = nullptr; const nsStyleBackground* bg = nullptr;
nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame); nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame);
nsRect bgOriginRect = bgRect;
if (!aBackgroundOriginRect.IsEmpty()) {
bgOriginRect = aBackgroundOriginRect + aBuilder->ToReferenceFrame(aFrame);
}
nsPresContext* presContext = aFrame->PresContext(); nsPresContext* presContext = aFrame->PresContext();
bool isThemed = aFrame->IsThemed(); bool isThemed = aFrame->IsThemed();
if (!isThemed) { if (!isThemed) {
@@ -3175,7 +3180,7 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
nsDisplayList thisItemList; nsDisplayList thisItemList;
nsDisplayBackgroundImage::InitData bgData = 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); LayerizeFixed::DO_NOT_LAYERIZE_FIXED_BACKGROUND_IF_AVOIDING_COMPONENT_ALPHA_LAYERS);
if (bgData.shouldFixToViewport) { if (bgData.shouldFixToViewport) {

View File

@@ -3071,7 +3071,8 @@ public:
const nsRect& aBackgroundRect, const nsRect& aBackgroundRect,
nsDisplayList* aList, nsDisplayList* aList,
bool aAllowWillPaintBorderOptimization = true, bool aAllowWillPaintBorderOptimization = true,
nsStyleContext* aStyleContext = nullptr); nsStyleContext* aStyleContext = nullptr,
const nsRect& aBackgroundOriginRect = nsRect());
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager, LayerManager* aManager,

View File

@@ -490,71 +490,51 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) const nsDisplayListSet& aLists)
{ {
DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame"); DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
if (IsVisibleInSelection(aBuilder)) { nsTableFrame* tableFrame = GetTableFrame();
nsTableFrame* tableFrame = GetTableFrame(); int32_t emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ?
int32_t emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ? StyleTableBorder()->mEmptyCells
StyleTableBorder()->mEmptyCells : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
: NS_STYLE_TABLE_EMPTY_CELLS_SHOW; // take account of 'empty-cells'
// take account of 'empty-cells' if (StyleVisibility()->IsVisible() &&
if (StyleVisibility()->IsVisible() && (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) {
(NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) { // display outset box-shadows if we need to.
// display outset box-shadows if we need to. bool hasBoxShadow = !!StyleEffects()->mBoxShadow;
bool hasBoxShadow = !!StyleEffects()->mBoxShadow; if (hasBoxShadow) {
if (hasBoxShadow) { aLists.BorderBackground()->AppendNewToTop(
aLists.BorderBackground()->AppendNewToTop( new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this)); }
}
// display background if we need to.
// display background if we need to. if (aBuilder->IsForEventDelivery() ||
if (aBuilder->IsForEventDelivery() || !StyleBackground()->IsTransparent(this) ||
!StyleBackground()->IsTransparent(this) || StyleDisplay()->UsedAppearance()) {
StyleDisplay()->UsedAppearance()) { nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder,
if (!tableFrame->IsBorderCollapse()) { this,
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, GetRectRelativeToSelf(),
this, aLists.BorderBackground());
GetRectRelativeToSelf(), }
aLists.BorderBackground());
} else if (aBuilder->IsAtRootOfPseudoStackingContext() || // display inset box-shadows if we need to.
aBuilder->IsForEventDelivery()) { if (hasBoxShadow) {
// The cell background was not painted by the nsTablePainter, aLists.BorderBackground()->AppendNewToTop(
// so we need to do it. We have special background processing here new (aBuilder) nsDisplayBoxShadowInner(aBuilder, this));
// so we need to duplicate some code from nsFrame::DisplayBorderBackgroundOutline }
nsDisplayTableItem* item =
new (aBuilder) nsDisplayTableCellBackground(aBuilder, this); // display borders if we need to
aLists.BorderBackground()->AppendNewToTop(item); ProcessBorders(tableFrame, aBuilder, aLists);
item->UpdateForFrameBackground(this);
} else { // and display the selection border if we need to
// The nsTablePainter will paint our background. Make sure it if (IsSelected()) {
// knows if we're background-attachment:fixed. aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem(); nsDisplayGeneric(aBuilder, this, ::PaintTableCellSelection,
if (currentItem) { "TableCellSelection",
currentItem->UpdateForFrameBackground(this); nsDisplayItem::TYPE_TABLE_CELL_SELECTION));
}
}
}
// 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 // Push a null 'current table item' so that descendant tables can't
// accidentally mess with our table // accidentally mess with our table
nsAutoPushCurrentTableItem pushTableItem; nsAutoPushCurrentTableItem pushTableItem;

View File

@@ -122,6 +122,14 @@ nsTableColFrame::Reflow(nsPresContext* aPresContext,
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize); 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() int32_t nsTableColFrame::GetSpan()
{ {
return StyleTable()->mSpan; return StyleTable()->mSpan;

View File

@@ -53,12 +53,9 @@ public:
const ReflowInput& aReflowInput, const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override; nsReflowStatus& aStatus) override;
/**
* Table columns never paint anything, nor receive events.
*/
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override {} const nsDisplayListSet& aLists) override;
#ifdef DEBUG_FRAME_DUMP #ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override; virtual nsresult GetFrameName(nsAString& aResult) const override;

View File

@@ -386,6 +386,14 @@ nsTableColGroupFrame::Reflow(nsPresContext* aPresContext,
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize); 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() nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
{ {
return GetNextColumn(nullptr); return GetNextColumn(nullptr);

View File

@@ -50,12 +50,9 @@ public:
return static_cast<nsTableFrame*>(parent); return static_cast<nsTableFrame*>(parent);
} }
/**
* ColGroups never paint anything, nor receive events.
*/
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override {} const nsDisplayListSet& aLists) override;
/** A colgroup can be caused by three things: /** A colgroup can be caused by three things:
* 1) An element with table-column-group display * 1) An element with table-column-group display

View File

@@ -1238,6 +1238,46 @@ nsDisplayTableItem::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); 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 { class nsDisplayTableBorderBackground : public nsDisplayTableItem {
public: public:
nsDisplayTableBorderBackground(nsDisplayListBuilder* aBuilder, nsDisplayTableBorderBackground(nsDisplayListBuilder* aBuilder,
@@ -1257,20 +1297,6 @@ public:
NS_DISPLAY_DECL_NAME("TableBorderBackground", TYPE_TABLE_BORDER_BACKGROUND) 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 void
nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder, nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) nsRenderingContext* aCtx)
@@ -1282,25 +1308,6 @@ nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
nsDisplayTableItemGeometry::UpdateDrawResult(this, result); 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 /* static */ void
nsTableFrame::GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame, nsTableFrame::GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
const nsRect& aDirtyRect, const nsDisplayListSet& aLists) const nsRect& aDirtyRect, const nsDisplayListSet& aLists)
@@ -1313,31 +1320,73 @@ nsTableFrame::GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
// stacking context, in which case the child won't use its passed-in // stacking context, in which case the child won't use its passed-in
// BorderBackground list anyway. It does affect cell borders though; this // BorderBackground list anyway. It does affect cell borders though; this
// lets us get cell borders into the nsTableFrame's BorderBackground list. // 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()) { for (nsIFrame* kid : aFrame->PrincipalChildList()) {
aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists); 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 /* static */ void
nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder, nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
nsFrame* aFrame, nsFrame* aFrame,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const nsDisplayListSet& aLists, const nsDisplayListSet& aLists,
nsDisplayTableItem* aDisplayItem,
DisplayGenericTablePartTraversal aTraversal) 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)) { if (aFrame->IsVisibleForPainting(aBuilder)) {
nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem(); nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
// currentItem may be null, when none of the table parts have a // currentItem may be null, when none of the table parts have a
@@ -1349,34 +1398,74 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
// Paint the outset box-shadows for the table frames // Paint the outset box-shadows for the table frames
bool hasBoxShadow = aFrame->StyleEffects()->mBoxShadow != nullptr; bool hasBoxShadow = aFrame->StyleEffects()->mBoxShadow != nullptr;
if (hasBoxShadow) { if (hasBoxShadow) {
lists->BorderBackground()->AppendNewToTop( aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame)); new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
} }
// Create dedicated background display items per-frame when we're if (aFrame->IsTableRowGroupFrame()) {
// handling events. nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame);
// XXX how to handle collapsed borders? PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists);
if (aBuilder->IsForEventDelivery()) { } 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, nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
aFrame->GetRectRelativeToSelf(), aFrame->GetRectRelativeToSelf(),
lists->BorderBackground()); aLists.BorderBackground());
} }
// Paint the inset box-shadows for the table frames // Paint the inset box-shadows for the table frames
if (hasBoxShadow) { if (hasBoxShadow) {
lists->BorderBackground()->AppendNewToTop( aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame)); new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
} }
} }
aTraversal(aBuilder, aFrame, aDirtyRect, *lists); aTraversal(aBuilder, aFrame, aDirtyRect, aLists);
if (sortEventBackgrounds) { if (aFrame->IsVisibleForPainting(aBuilder)) {
// Ensure that the table frame event background goes before the if (aFrame->IsTableFrame()) {
// table rowgroups event backgrounds, before the table row event backgrounds, nsTableFrame* table = static_cast<nsTableFrame*>(aFrame);
// before everything else (cells and their blocks) // In the collapsed border model, overlay all collapsed borders.
separatedCollection.BorderBackground()->Sort<nsDisplayItem*>(TablePartRankComparator()); if (table->IsBorderCollapse()) {
separatedCollection.MoveTo(aLists); aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayTableBorderCollapse(aBuilder, table));
} else {
aLists.BorderBackground()->AppendNewToTop(
new (aBuilder) nsDisplayBorder(aBuilder, table));
}
}
} }
aFrame->DisplayOutline(aBuilder, aLists); aFrame->DisplayOutline(aBuilder, aLists);
@@ -1404,43 +1493,6 @@ static inline bool FrameHasBorderOrBackground(nsTableFrame* tableFrame, nsIFrame
return false; 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 // table paint code is concerned primarily with borders and bg color
// SEC: TODO: adjust the rect for captions // SEC: TODO: adjust the rect for captions
void void
@@ -1450,35 +1502,7 @@ nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
{ {
DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255)); DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255));
nsDisplayTableItem* item = nullptr; DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
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);
}
} }
nsMargin nsMargin

View File

@@ -245,7 +245,6 @@ public:
nsFrame* aFrame, nsFrame* aFrame,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const nsDisplayListSet& aLists, const nsDisplayListSet& aLists,
nsDisplayTableItem* aDisplayItem,
DisplayGenericTablePartTraversal aTraversal = GenericTraversal); DisplayGenericTablePartTraversal aTraversal = GenericTraversal);
// Return the closest sibling of aPriorChildFrame (including aPriroChildFrame) // Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)

View File

@@ -621,21 +621,7 @@ nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) const nsDisplayListSet& aLists)
{ {
nsDisplayTableItem* item = nullptr; nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
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);
} }
nsIFrame::LogicalSides nsIFrame::LogicalSides

View File

@@ -293,19 +293,8 @@ nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) 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, nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect,
aLists, item, DisplayRows); aLists, DisplayRows);
} }
nsIFrame::LogicalSides nsIFrame::LogicalSides

View File

@@ -190,7 +190,11 @@ nsTableWrapperFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// Now we have to sort everything by content order, since the caption // Now we have to sort everything by content order, since the caption
// may be somewhere inside the table // 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); set.MoveTo(aLists);
} }