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
--- a/gfx/public/nsMargin.h
+++ b/gfx/public/nsMargin.h
@@ -99,16 +99,18 @@ struct nsMargin {
right += aMargin.right;
bottom += aMargin.bottom;
return *this;}
nsMargin& operator-=(const nsMargin& aMargin) {left -= aMargin.left;
top -= aMargin.top;
right -= aMargin.right;
bottom -= aMargin.bottom;
return *this;}
+
+ PRBool IsZero() { return !left && !top && !right && !bottom; }
};
struct nsIntMargin {
PRInt32 top, right, bottom, left;
// Constructors
nsIntMargin() {}
nsIntMargin(const nsIntMargin& aMargin) {*this = aMargin;}
@@ -133,11 +135,13 @@ struct nsIntMargin {
PRBool operator!=(const nsIntMargin& aMargin) const {
return (PRBool) ((left != aMargin.left) || (top != aMargin.top) ||
(right != aMargin.right) || (bottom != aMargin.bottom));
}
nsIntMargin operator+(const nsIntMargin& aMargin) const {
return nsIntMargin(left + aMargin.left, top + aMargin.top,
right + aMargin.right, bottom + aMargin.bottom);
}
+
+ PRBool IsZero() { return !left && !top && !right && !bottom; }
};
#endif /* NSMARGIN_H */
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1404,62 +1404,65 @@ nsTableFrame::BuildDisplayList(nsDisplay
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!IsVisibleInSelection(aBuilder))
return NS_OK;
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);
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
nsTableFrame::PaintTableBorderBackground(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsPoint aPt)
{
nsPresContext* presContext = PresContext();
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();
if (!IsBorderCollapse()) {
PRIntn skipSides = GetSkipSides();
nsRect rect(aPt, mRect.Size());
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
aDirtyRect, rect, *border, mStyleContext,
@@ -2588,16 +2591,17 @@ nsTableFrame::GetIncludedOuterBCBorder()
return border;
}
nsMargin
nsTableFrame::GetExcludedOuterBCBorder() const
{
return GetOuterBCBorder() - GetIncludedOuterBCBorder();
}
+
static
void GetSeparateModelBorderPadding(const nsHTMLReflowState* aReflowState,
nsStyleContext& aStyleContext,
nsMargin& aBorderPadding)
{
// XXXbz Either we _do_ have a reflow state and then we can use its
// mComputedBorderPadding or we don't and then we get the padding
// wrong!
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -293,16 +293,22 @@ public:
nsMargin GetIncludedOuterBCBorder() const;
/** Same as above, but only if it's excluded from the border-box width
* of the table. This is the area that leaks out into the margin
* (or potentially past it, if there is no margin).
*/
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
*/
nscoord GetContinuousLeftBCBorderWidth() const;
void SetContinuousLeftBCBorderWidth(nscoord aValue);
friend class nsDelayedCalcBCBorders;
--- a/layout/tables/nsTablePainter.cpp
+++ b/layout/tables/nsTablePainter.cpp
@@ -277,25 +277,23 @@ TableBackgroundPainter::~TableBackground
mRow.Destroy(mPresContext);
MOZ_COUNT_DTOR(TableBackgroundPainter);
}
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
//to make degenerate tables' borders reasonable to deal with
nsMargin border, tempBorder;
nsTableColFrame* colFrame = aTableFrame->GetColFrame(mNumCols - 1);
if (colFrame) {
colFrame->GetContinuousBCBorderWidth(tempBorder);
@@ -349,32 +347,37 @@ TableBackgroundPainter::TranslateContext
mCols[i].mColGroup->mRect.MoveBy(-aDX, -aDY);
lastColGroup = mCols[i].mColGroup;
}
}
}
}
nsresult
-TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
- nsMargin* aDeflate)
+TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
+ const nsMargin& aDeflate,
+ PRBool aPaintTableBackground)
{
NS_PRECONDITION(aTableFrame, "null table frame");
nsTableFrame::RowGroupArray rowGroups;
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) {
nsFrameList& colGroupList = aTableFrame->GetColGroups();
NS_ASSERTION(colGroupList.FirstChild(), "table should have at least one colgroup");
mCols = new ColData[mNumCols];
if (!mCols) return NS_ERROR_OUT_OF_MEMORY;
--- a/layout/tables/nsTablePainter.h
+++ b/layout/tables/nsTablePainter.h
@@ -88,31 +88,36 @@ class TableBackgroundPainter
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 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)
* 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
*/
@@ -138,17 +143,17 @@ class TableBackgroundPainter
* @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
*/
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
* See Public versions for function descriptions
*/
nsresult PaintRowGroup(nsTableRowGroupFrame* aFrame,
PRBool aPassThrough);
nsresult PaintRow(nsTableRowFrame* aFrame,