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(); DrawResult cellResult = PaintCell(cell, aRowGroupBGData, aRowBGData, cellBGRect, rowBGRect, rowGroupBGRect, colBGRect, passCell); UpdateDrawResult(&result, cellResult); } } return result; }
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; } DrawResult rowResult = PaintRow(row, aRowGroupBGData, rowBackgroundData, aPassThrough || row->IsPseudoStackingContextFromStyle()); UpdateDrawResult(&result, rowResult); } /* translate back into table coord system */ if (eOrigin_TableRowGroup != mOrigin) { TranslateContext(-rgRect.x, -rgRect.y); } return result; }