nsresult TableBackgroundPainter::PaintTableFrame(nsTableFrame* aTableFrame, nsTableRowGroupFrame* aFirstRowGroup, nsTableRowGroupFrame* aLastRowGroup, const nsMargin& aDeflate) { NS_PRECONDITION(aTableFrame, "null frame"); TableBackgroundData tableData; tableData.SetFull(aTableFrame); tableData.mRect.MoveTo(0,0); //using table's coords 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); } border.right = tempBorder.right; aLastRowGroup->GetContinuousBCBorderWidth(tempBorder); border.bottom = tempBorder.bottom; nsTableRowFrame* rowFrame = aFirstRowGroup->GetFirstRow(); if (rowFrame) { rowFrame->GetContinuousBCBorderWidth(tempBorder); border.top = tempBorder.top; } border.left = aTableFrame->GetContinuousLeftBCBorderWidth(); nsresult rv = tableData.SetBCBorder(border, this); if (NS_FAILED(rv)) { tableData.Destroy(mPresContext); return rv; } } } if (tableData.IsVisible()) { nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext, tableData.mFrame, mDirtyRect, tableData.mRect + mRenderPt, tableData.mFrame->StyleContext(), *tableData.mBorder, mBGPaintFlags); } tableData.Destroy(mPresContext); return NS_OK; }
nsresult TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame, const nsMargin& aDeflate, bool aPaintTableBackground) { NS_PRECONDITION(aTableFrame, "null table frame"); nsTableFrame::RowGroupArray rowGroups; aTableFrame->OrderRowGroups(rowGroups); if (rowGroups.Length() < 1) { //degenerate case if (aPaintTableBackground) { PaintTableFrame(aTableFrame, nullptr, nullptr, nsMargin(0,0,0,0)); } /* No cells; nothing else to paint */ return NS_OK; } 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; TableBackgroundData* cgData = nullptr; nsMargin border; /* BC left borders aren't stored on cols, but the previous column's right border is the next one's left border.*/ //Start with table's left border. nscoord lastLeftBorder = aTableFrame->GetContinuousLeftBCBorderWidth(); 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; } /*Create data struct for column group*/ cgData = new TableBackgroundData; if (!cgData) return NS_ERROR_OUT_OF_MEMORY; cgData->SetFull(cgFrame); if (mIsBorderCollapse && cgData->ShouldSetBCBorder()) { border.left = lastLeftBorder; cgFrame->GetContinuousBCBorderWidth(border); nsresult rv = cgData->SetBCBorder(border, this); if (NS_FAILED(rv)) { cgData->Destroy(mPresContext); delete cgData; return rv; } } // Boolean that indicates whether mCols took ownership of cgData bool cgDataOwnershipTaken = false; /*Loop over columns in this colgroup*/ for (nsTableColFrame* col = cgFrame->GetFirstColumn(); col; col = static_cast<nsTableColFrame*>(col->GetNextSibling())) { /*Create data struct for column*/ uint32_t colIndex = col->GetColIndex(); NS_ASSERTION(colIndex < mNumCols, "prevent array boundary violation"); if (mNumCols <= colIndex) break; mCols[colIndex].mCol.SetFull(col); //Bring column mRect into table's coord system mCols[colIndex].mCol.mRect.MoveBy(cgData->mRect.x, cgData->mRect.y); //link to parent colgroup's data mCols[colIndex].mColGroup = cgData; cgDataOwnershipTaken = true; if (mIsBorderCollapse) { border.left = lastLeftBorder; lastLeftBorder = col->GetContinuousBCBorderWidth(border); if (mCols[colIndex].mCol.ShouldSetBCBorder()) { nsresult rv = mCols[colIndex].mCol.SetBCBorder(border, this); if (NS_FAILED(rv)) return rv; } } } if (!cgDataOwnershipTaken) { cgData->Destroy(mPresContext); delete cgData; } } } for (uint32_t i = 0; i < rowGroups.Length(); i++) { nsTableRowGroupFrame* rg = rowGroups[i]; mRowGroup.SetFrame(rg); // Need to compute the right rect via GetOffsetTo, since the row // group may not be a child of the table. mRowGroup.mRect.MoveTo(rg->GetOffsetTo(aTableFrame)); if (mRowGroup.mRect.Intersects(mDirtyRect - mRenderPt)) { nsresult rv = PaintRowGroup(rg, rg->IsPseudoStackingContextFromStyle()); if (NS_FAILED(rv)) return rv; } } return NS_OK; }