Bug 505184. When 'deflation' of the background area is not required, paint table backgrounds using a dedicated nsDisplayBackground instead of the multipurpose nsDisplayTableBorderBackground. r=fantasai

This commit is contained in:
Robert O'Callahan 2009-07-22 12:44:52 +12:00
parent 53a0bb6bba
commit bec635e65d
5 changed files with 62 additions and 40 deletions

View File

@ -104,6 +104,8 @@ struct nsMargin {
right -= aMargin.right;
bottom -= aMargin.bottom;
return *this;}
PRBool IsZero() { return !left && !top && !right && !bottom; }
};
struct nsIntMargin {
@ -138,6 +140,8 @@ struct nsIntMargin {
return nsIntMargin(left + aMargin.left, top + aMargin.top,
right + aMargin.right, bottom + aMargin.bottom);
}
PRBool IsZero() { return !left && !top && !right && !bottom; }
};
#endif /* NSMARGIN_H */

View File

@ -1409,9 +1409,21 @@ nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255));
if (GetStyleVisibility()->IsVisible()) {
nsMargin deflate = GetDeflationForBackground(PresContext());
// 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.IsZero()) {
nsresult rv = DisplayBackgroundUnconditional(aBuilder, aLists, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
}
}
// This background is created regardless of whether this frame is
// visible or not. Visibility decisions are delegated to the
// table background painter.
// table background painter. This handles borders and backgrounds
// for the table.
nsDisplayTableItem* item = new (aBuilder) nsDisplayTableBorderBackground(this);
nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
NS_ENSURE_SUCCESS(rv, rv);
@ -1419,6 +1431,16 @@ nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
return DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, item);
}
nsMargin
nsTableFrame::GetDeflationForBackground(nsPresContext* aPresContext) const
{
if (eCompatibility_NavQuirks != aPresContext->CompatibilityMode() ||
!IsBorderCollapse())
return nsMargin(0,0,0,0);
return GetOuterBCBorder();
}
// 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.
void
@ -1431,30 +1453,11 @@ nsTableFrame::PaintTableBorderBackground(nsIRenderingContext& aRenderingContext,
TableBackgroundPainter painter(this, TableBackgroundPainter::eOrigin_Table,
presContext, aRenderingContext,
aDirtyRect, aPt);
nsresult rv;
if (eCompatibility_NavQuirks == presContext->CompatibilityMode()) {
nsMargin deflate(0,0,0,0);
if (IsBorderCollapse()) {
PRInt32 p2t = nsPresContext::AppUnitsPerCSSPixel();
BCPropertyData* propData =
(BCPropertyData*)nsTableFrame::GetProperty((nsIFrame*)this,
nsGkAtoms::tableBCProperty,
PR_FALSE);
if (propData) {
deflate.top = BC_BORDER_TOP_HALF_COORD(p2t, propData->mTopBorderWidth);
deflate.right = BC_BORDER_RIGHT_HALF_COORD(p2t, propData->mRightBorderWidth);
deflate.bottom = BC_BORDER_BOTTOM_HALF_COORD(p2t, propData->mBottomBorderWidth);
deflate.left = BC_BORDER_LEFT_HALF_COORD(p2t, propData->mLeftBorderWidth);
}
}
rv = painter.PaintTable(this, &deflate);
if (NS_FAILED(rv)) return;
}
else {
rv = painter.PaintTable(this, nsnull);
if (NS_FAILED(rv)) return;
}
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.
nsresult rv = painter.PaintTable(this, deflate, !deflate.IsZero());
if (NS_FAILED(rv)) return;
if (GetStyleVisibility()->IsVisible()) {
const nsStyleBorder* border = GetStyleBorder();
@ -2593,6 +2596,7 @@ nsTableFrame::GetExcludedOuterBCBorder() const
{
return GetOuterBCBorder() - GetIncludedOuterBCBorder();
}
static
void GetSeparateModelBorderPadding(const nsHTMLReflowState* aReflowState,
nsStyleContext& aStyleContext,

View File

@ -298,6 +298,12 @@ public:
*/
nsMargin GetExcludedOuterBCBorder() const;
/**
* In quirks mode, the size of the table background is reduced
* by the outer BC border. Compute the reduction needed.
*/
nsMargin GetDeflationForBackground(nsPresContext* aPresContext) const;
/** Get width of table + colgroup + col collapse: elements that
* continue along the length of the whole left side.
* see nsTablePainter about continuous borders

View File

@ -282,15 +282,13 @@ nsresult
TableBackgroundPainter::PaintTableFrame(nsTableFrame* aTableFrame,
nsTableRowGroupFrame* aFirstRowGroup,
nsTableRowGroupFrame* aLastRowGroup,
nsMargin* aDeflate)
const nsMargin& aDeflate)
{
NS_PRECONDITION(aTableFrame, "null frame");
TableBackgroundData tableData;
tableData.SetFull(aTableFrame);
tableData.mRect.MoveTo(0,0); //using table's coords
if (aDeflate) {
tableData.mRect.Deflate(*aDeflate);
}
tableData.mRect.Deflate(aDeflate);
if (mIsBorderCollapse && tableData.ShouldSetBCBorder()) {
if (aFirstRowGroup && aLastRowGroup && mNumCols > 0) {
//only handle non-degenerate tables; we need a more robust BC model
@ -354,8 +352,9 @@ TableBackgroundPainter::TranslateContext(nscoord aDX,
}
nsresult
TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
nsMargin* aDeflate)
TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
const nsMargin& aDeflate,
PRBool aPaintTableBackground)
{
NS_PRECONDITION(aTableFrame, "null table frame");
@ -363,13 +362,17 @@ TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
aTableFrame->OrderRowGroups(rowGroups);
if (rowGroups.Length() < 1) { //degenerate case
PaintTableFrame(aTableFrame, nsnull, nsnull, nsnull);
if (aPaintTableBackground) {
PaintTableFrame(aTableFrame, nsnull, nsnull, nsMargin(0,0,0,0));
}
/* No cells; nothing else to paint */
return NS_OK;
}
PaintTableFrame(aTableFrame, rowGroups[0], rowGroups[rowGroups.Length() - 1],
aDeflate);
if (aPaintTableBackground) {
PaintTableFrame(aTableFrame, rowGroups[0], rowGroups[rowGroups.Length() - 1],
aDeflate);
}
/*Set up column background/border data*/
if (mNumCols > 0) {

View File

@ -93,21 +93,26 @@ class TableBackgroundPainter
/* ~*~ Using nsTablePainter Background Painting ~*~
A call to PaintTable will normally paint all of the table's
elements (except the cells in non-BC). Elements with views
however, will be skipped and must create their own painter
to call the appropriate paint function in their ::Paint
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 and its children down through cells
/** 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
*/
nsresult PaintTable(nsTableFrame* aTableFrame, nsMargin* aDeflate);
nsresult PaintTable(nsTableFrame* aTableFrame, const nsMargin& aDeflate,
PRBool aPaintTableBackground);
/** Paint background for the row group and its children down through cells
* (Cells themselves will only be painted in border collapse)
@ -143,7 +148,7 @@ class TableBackgroundPainter
nsresult PaintTableFrame(nsTableFrame* aTableFrame,
nsTableRowGroupFrame* aFirstRowGroup,
nsTableRowGroupFrame* aLastRowGroup,
nsMargin* aDeflate = nsnull);
const nsMargin& aDeflate);
/* aPassThrough params indicate whether to paint the element or to just
* pass through and paint underlying layers only