layout/tables/nsTablePainter.cpp

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsTableFrame.h"
     7 #include "nsTableRowGroupFrame.h"
     8 #include "nsTableRowFrame.h"
     9 #include "nsTableColGroupFrame.h"
    10 #include "nsTableColFrame.h"
    11 #include "nsTableCellFrame.h"
    12 #include "nsTablePainter.h"
    13 #include "nsCSSRendering.h"
    14 #include "nsDisplayList.h"
    16 /* ~*~ Table Background Painting ~*~
    18    Mozilla's Table Background painting follows CSS2.1:17.5.1
    19    That section does not, however, describe the effect of
    20    borders on background image positioning. What we do is:
    22      - in separate borders, the borders are passed in so that
    23        their width figures in image positioning, even for rows/cols, which
    24        don't have visible borders. This is done to allow authors
    25        to position row backgrounds by, for example, aligning the
    26        top left corner with the top left padding corner of the
    27        top left table cell in the row in cases where all cells
    28        have consistent border widths. If we didn't honor these
    29        invisible borders, there would be no way to align
    30        backgrounds with the padding edges, and designs would be
    31        lost underneath the border.
    33      - in collapsing borders, because the borders collapse, we
    34        use the -continuous border- width to synthesize a border
    35        style and pass that in instead of using the element's
    36        assigned style directly.
    38        The continuous border on a given edge of an element is
    39        the collapse of all borders guaranteed to be continuous
    40        along that edge. Cell borders are ignored (because, for
    41        example, setting a thick border on the leftmost cell
    42        should not shift the row background over; this way a
    43        striped background set on <tr> will line up across rows
    44        even if the cells are assigned arbitrary border widths.
    46        For example, the continuous border on the top edge of a
    47        row group is the collapse of any row group, row, and
    48        table borders involved. (The first row group's top would
    49        be [table-top + row group top + first row top]. It's bottom
    50        would be [row group bottom + last row bottom + next row
    51        top + next row group top].)
    52        The top edge of a column group likewise includes the
    53        table top, row group top, and first row top borders. However,
    54        it *also* includes its own top border, since that is guaranteed
    55        to be continuous. It does not include column borders because
    56        those are not guaranteed to be continuous: there may be two
    57        columns with different borders in a single column group.
    59        An alternative would be to define the continuous border as
    60          [table? + row group + row] for horizontal
    61          [table? + col group + col] for vertical
    62        This makes it easier to line up backgrounds across elements
    63        despite varying border widths, but it does not give much
    64        flexibility in aligning /to/ those border widths.
    65 */
    68 /* ~*~ TableBackgroundPainter ~*~
    70    The TableBackgroundPainter is created and destroyed in one painting call.
    71    Its principal function is PaintTable, which paints all table element
    72    backgrounds. The initial code in that method sets up an array of column
    73    data that caches the background styles and the border sizes for the
    74    columns and colgroups in TableBackgroundData structs in mCols. Data for
    75    BC borders are calculated and stashed in a synthesized border style struct
    76    in the data struct since collapsed borders aren't the same width as style-
    77    assigned borders. The data struct optimizes by only doing this if there's
    78    an image background; otherwise we don't care. //XXX should also check background-origin
    79    The class then loops through the row groups, rows, and cells. It uses
    80    the mRowGroup and mRow TableBackgroundData structs to cache data for
    81    the current frame in the loop. At the cell level, it paints the backgrounds,
    82    one over the other, inside the cell rect.
    84    The exception to this pattern is when a table element creates a (pseudo)
    85    stacking context. Elements with stacking contexts (e.g., 'opacity' applied)
    86    are <dfn>passed through</dfn>, which means their data (and their
    87    descendants' data) are not cached. The full loop is still executed, however,
    88    so that underlying layers can get painted at the cell level.
    90    The TableBackgroundPainter is then destroyed.
    92    Elements with stacking contexts set up their own painter to finish the
    93    painting process, since they were skipped. They call the appropriate
    94    sub-part of the loop (e.g. PaintRow) which will paint the frame and
    95    descendants. Note that it is permissible according to CSS2.1 to ignore'
    96    'position:relative' (and implicitly, 'opacity') on table parts so that
    97    table parts can never create stacking contexts; if we want to, we can
    98    implement that, and then we won't have to deal with TableBackgroundPainter
    99    being used anywhere but from the nsTableFrame.
   101    XXX views are going 
   102  */
   104 TableBackgroundPainter::TableBackgroundData::TableBackgroundData()
   105   : mFrame(nullptr),
   106     mVisible(false),
   107     mBorder(nullptr),
   108     mSynthBorder(nullptr)
   109 {
   110   MOZ_COUNT_CTOR(TableBackgroundData);
   111 }
   113 TableBackgroundPainter::TableBackgroundData::~TableBackgroundData()
   114 {
   115   NS_ASSERTION(!mSynthBorder, "must call Destroy before dtor");
   116   MOZ_COUNT_DTOR(TableBackgroundData);
   117 }
   119 void
   120 TableBackgroundPainter::TableBackgroundData::Destroy(nsPresContext* aPresContext)
   121 {
   122   NS_PRECONDITION(aPresContext, "null prescontext");
   123   if (mSynthBorder) {
   124     mSynthBorder->Destroy(aPresContext);
   125     mSynthBorder = nullptr;
   126   }
   127 }
   129 void
   130 TableBackgroundPainter::TableBackgroundData::Clear()
   131 {
   132   mRect.SetEmpty();
   133   mFrame = nullptr;
   134   mBorder = nullptr;
   135   mVisible = false;
   136 }
   138 void
   139 TableBackgroundPainter::TableBackgroundData::SetFrame(nsIFrame* aFrame)
   140 {
   141   NS_PRECONDITION(aFrame, "null frame");
   142   mFrame = aFrame;
   143   mRect = aFrame->GetRect();
   144 }
   146 void
   147 TableBackgroundPainter::TableBackgroundData::SetData()
   148 {
   149   NS_PRECONDITION(mFrame, "null frame");
   150   if (mFrame->IsVisibleForPainting()) {
   151     mVisible = true;
   152     mBorder = mFrame->StyleBorder();
   153   }
   154 }
   156 void
   157 TableBackgroundPainter::TableBackgroundData::SetFull(nsIFrame* aFrame)
   158 {
   159   NS_PRECONDITION(aFrame, "null frame");
   160   SetFrame(aFrame);
   161   SetData();
   162 }
   164 inline bool
   165 TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder()
   166 {
   167   /* we only need accurate border data when positioning background images*/
   168   if (!mVisible) {
   169     return false;
   170   }
   172   const nsStyleBackground *bg = mFrame->StyleBackground();
   173   NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
   174     if (!bg->mLayers[i].mImage.IsEmpty())
   175       return true;
   176   }
   177   return false;
   178 }
   180 nsresult
   181 TableBackgroundPainter::TableBackgroundData::SetBCBorder(nsMargin& aBorder,
   182                                                          TableBackgroundPainter* aPainter)
   183 {
   184   NS_PRECONDITION(aPainter, "null painter");
   185   if (!mSynthBorder) {
   186     mSynthBorder = new (aPainter->mPresContext)
   187                         nsStyleBorder(aPainter->mZeroBorder);
   188     if (!mSynthBorder) return NS_ERROR_OUT_OF_MEMORY;
   189   }
   191   NS_FOR_CSS_SIDES(side) {
   192     mSynthBorder->SetBorderWidth(side, aBorder.Side(side));
   193   }
   195   mBorder = mSynthBorder;
   196   return NS_OK;
   197 }
   199 TableBackgroundPainter::TableBackgroundPainter(nsTableFrame*        aTableFrame,
   200                                                Origin               aOrigin,
   201                                                nsPresContext*       aPresContext,
   202                                                nsRenderingContext& aRenderingContext,
   203                                                const nsRect&        aDirtyRect,
   204                                                const nsPoint&       aRenderPt,
   205                                                uint32_t             aBGPaintFlags)
   206   : mPresContext(aPresContext),
   207     mRenderingContext(aRenderingContext),
   208     mRenderPt(aRenderPt),
   209     mDirtyRect(aDirtyRect),
   210     mOrigin(aOrigin),
   211     mCols(nullptr),
   212     mZeroBorder(aPresContext),
   213     mBGPaintFlags(aBGPaintFlags)
   214 {
   215   MOZ_COUNT_CTOR(TableBackgroundPainter);
   217   NS_FOR_CSS_SIDES(side) {
   218     mZeroBorder.SetBorderStyle(side, NS_STYLE_BORDER_STYLE_SOLID);
   219     mZeroBorder.SetBorderWidth(side, 0);
   220   }
   222   mIsBorderCollapse = aTableFrame->IsBorderCollapse();
   223 #ifdef DEBUG
   224   mCompatMode = mPresContext->CompatibilityMode();
   225 #endif
   226   mNumCols = aTableFrame->GetColCount();
   227 }
   229 TableBackgroundPainter::~TableBackgroundPainter()
   230 {
   231   if (mCols) {
   232     TableBackgroundData* lastColGroup = nullptr;
   233     for (uint32_t i = 0; i < mNumCols; i++) {
   234       if (mCols[i].mColGroup != lastColGroup) {
   235         lastColGroup = mCols[i].mColGroup;
   236         NS_ASSERTION(mCols[i].mColGroup, "colgroup data should not be null - bug 237421");
   237         // we need to wallpaper a over zero pointer deref, bug 237421 will have the real fix
   238         if(lastColGroup)
   239           lastColGroup->Destroy(mPresContext);
   240         delete lastColGroup;
   241       }
   242       mCols[i].mColGroup = nullptr;
   243       mCols[i].mCol.Destroy(mPresContext);
   244     }
   245     delete [] mCols;
   246   }
   247   mRowGroup.Destroy(mPresContext);
   248   mRow.Destroy(mPresContext);
   249   MOZ_COUNT_DTOR(TableBackgroundPainter);
   250 }
   252 nsresult
   253 TableBackgroundPainter::PaintTableFrame(nsTableFrame*         aTableFrame,
   254                                         nsTableRowGroupFrame* aFirstRowGroup,
   255                                         nsTableRowGroupFrame* aLastRowGroup,
   256                                         const nsMargin&       aDeflate)
   257 {
   258   NS_PRECONDITION(aTableFrame, "null frame");
   259   TableBackgroundData tableData;
   260   tableData.SetFull(aTableFrame);
   261   tableData.mRect.MoveTo(0,0); //using table's coords
   262   tableData.mRect.Deflate(aDeflate);
   263   if (mIsBorderCollapse && tableData.ShouldSetBCBorder()) {
   264     if (aFirstRowGroup && aLastRowGroup && mNumCols > 0) {
   265       //only handle non-degenerate tables; we need a more robust BC model
   266       //to make degenerate tables' borders reasonable to deal with
   267       nsMargin border, tempBorder;
   268       nsTableColFrame* colFrame = aTableFrame->GetColFrame(mNumCols - 1);
   269       if (colFrame) {
   270         colFrame->GetContinuousBCBorderWidth(tempBorder);
   271       }
   272       border.right = tempBorder.right;
   274       aLastRowGroup->GetContinuousBCBorderWidth(tempBorder);
   275       border.bottom = tempBorder.bottom;
   277       nsTableRowFrame* rowFrame = aFirstRowGroup->GetFirstRow();
   278       if (rowFrame) {
   279         rowFrame->GetContinuousBCBorderWidth(tempBorder);
   280         border.top = tempBorder.top;
   281       }
   283       border.left = aTableFrame->GetContinuousLeftBCBorderWidth();
   285       nsresult rv = tableData.SetBCBorder(border, this);
   286       if (NS_FAILED(rv)) {
   287         tableData.Destroy(mPresContext);
   288         return rv;
   289       }
   290     }
   291   }
   292   if (tableData.IsVisible()) {
   293     nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
   294                                           tableData.mFrame, mDirtyRect,
   295                                           tableData.mRect + mRenderPt,
   296                                           tableData.mFrame->StyleContext(),
   297                                           *tableData.mBorder,
   298                                           mBGPaintFlags);
   299   }
   300   tableData.Destroy(mPresContext);
   301   return NS_OK;
   302 }
   304 void
   305 TableBackgroundPainter::TranslateContext(nscoord aDX,
   306                                          nscoord aDY)
   307 {
   308   mRenderPt += nsPoint(aDX, aDY);
   309   if (mCols) {
   310     TableBackgroundData* lastColGroup = nullptr;
   311     for (uint32_t i = 0; i < mNumCols; i++) {
   312       mCols[i].mCol.mRect.MoveBy(-aDX, -aDY);
   313       if (lastColGroup != mCols[i].mColGroup) {
   314         NS_ASSERTION(mCols[i].mColGroup, "colgroup data should not be null - bug 237421");
   315         // we need to wallpaper a over zero pointer deref, bug 237421 will have the real fix
   316         if (!mCols[i].mColGroup)
   317           return;
   318         mCols[i].mColGroup->mRect.MoveBy(-aDX, -aDY);
   319         lastColGroup = mCols[i].mColGroup;
   320       }
   321     }
   322   }
   323 }
   325 nsresult
   326 TableBackgroundPainter::PaintTable(nsTableFrame*   aTableFrame,
   327                                    const nsMargin& aDeflate,
   328                                    bool            aPaintTableBackground)
   329 {
   330   NS_PRECONDITION(aTableFrame, "null table frame");
   332   nsTableFrame::RowGroupArray rowGroups;
   333   aTableFrame->OrderRowGroups(rowGroups);
   335   if (rowGroups.Length() < 1) { //degenerate case
   336     if (aPaintTableBackground) {
   337       PaintTableFrame(aTableFrame, nullptr, nullptr, nsMargin(0,0,0,0));
   338     }
   339     /* No cells; nothing else to paint */
   340     return NS_OK;
   341   }
   343   if (aPaintTableBackground) {
   344     PaintTableFrame(aTableFrame, rowGroups[0], rowGroups[rowGroups.Length() - 1],
   345                     aDeflate);
   346   }
   348   /*Set up column background/border data*/
   349   if (mNumCols > 0) {
   350     nsFrameList& colGroupList = aTableFrame->GetColGroups();
   351     NS_ASSERTION(colGroupList.FirstChild(), "table should have at least one colgroup");
   353     mCols = new ColData[mNumCols];
   354     if (!mCols) return NS_ERROR_OUT_OF_MEMORY;
   356     TableBackgroundData* cgData = nullptr;
   357     nsMargin border;
   358     /* BC left borders aren't stored on cols, but the previous column's
   359        right border is the next one's left border.*/
   360     //Start with table's left border.
   361     nscoord lastLeftBorder = aTableFrame->GetContinuousLeftBCBorderWidth();
   362     for (nsTableColGroupFrame* cgFrame = static_cast<nsTableColGroupFrame*>(colGroupList.FirstChild());
   363          cgFrame; cgFrame = static_cast<nsTableColGroupFrame*>(cgFrame->GetNextSibling())) {
   365       if (cgFrame->GetColCount() < 1) {
   366         //No columns, no cells, so no need for data
   367         continue;
   368       }
   370       /*Create data struct for column group*/
   371       cgData = new TableBackgroundData;
   372       if (!cgData) return NS_ERROR_OUT_OF_MEMORY;
   373       cgData->SetFull(cgFrame);
   374       if (mIsBorderCollapse && cgData->ShouldSetBCBorder()) {
   375         border.left = lastLeftBorder;
   376         cgFrame->GetContinuousBCBorderWidth(border);
   377         nsresult rv = cgData->SetBCBorder(border, this);
   378         if (NS_FAILED(rv)) {
   379           cgData->Destroy(mPresContext);
   380           delete cgData;
   381           return rv;
   382         }
   383       }
   385       // Boolean that indicates whether mCols took ownership of cgData
   386       bool cgDataOwnershipTaken = false;
   388       /*Loop over columns in this colgroup*/
   389       for (nsTableColFrame* col = cgFrame->GetFirstColumn(); col;
   390            col = static_cast<nsTableColFrame*>(col->GetNextSibling())) {
   391         /*Create data struct for column*/
   392         uint32_t colIndex = col->GetColIndex();
   393         NS_ASSERTION(colIndex < mNumCols, "prevent array boundary violation");
   394         if (mNumCols <= colIndex)
   395           break;
   396         mCols[colIndex].mCol.SetFull(col);
   397         //Bring column mRect into table's coord system
   398         mCols[colIndex].mCol.mRect.MoveBy(cgData->mRect.x, cgData->mRect.y);
   399         //link to parent colgroup's data
   400         mCols[colIndex].mColGroup = cgData;
   401         cgDataOwnershipTaken = true;
   402         if (mIsBorderCollapse) {
   403           border.left = lastLeftBorder;
   404           lastLeftBorder = col->GetContinuousBCBorderWidth(border);
   405           if (mCols[colIndex].mCol.ShouldSetBCBorder()) {
   406             nsresult rv = mCols[colIndex].mCol.SetBCBorder(border, this);
   407             if (NS_FAILED(rv)) return rv;
   408           }
   409         }
   410       }
   412       if (!cgDataOwnershipTaken) {
   413         cgData->Destroy(mPresContext);
   414         delete cgData;
   415       }
   416     }
   417   }
   419   for (uint32_t i = 0; i < rowGroups.Length(); i++) {
   420     nsTableRowGroupFrame* rg = rowGroups[i];
   421     mRowGroup.SetFrame(rg);
   422     // Need to compute the right rect via GetOffsetTo, since the row
   423     // group may not be a child of the table.
   424     mRowGroup.mRect.MoveTo(rg->GetOffsetTo(aTableFrame));
   425     if (mRowGroup.mRect.Intersects(mDirtyRect - mRenderPt)) {
   426       nsresult rv = PaintRowGroup(rg, rg->IsPseudoStackingContextFromStyle());
   427       if (NS_FAILED(rv)) return rv;
   428     }
   429   }
   430   return NS_OK;
   431 }
   433 nsresult
   434 TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
   435                                       bool                  aPassThrough)
   436 {
   437   NS_PRECONDITION(aFrame, "null frame");
   439   if (!mRowGroup.mFrame) {
   440     mRowGroup.SetFrame(aFrame);
   441   }
   443   nsTableRowFrame* firstRow = aFrame->GetFirstRow();
   445   /* Load row group data */
   446   if (!aPassThrough) {
   447     mRowGroup.SetData();
   448     if (mIsBorderCollapse && mRowGroup.ShouldSetBCBorder()) {
   449       nsMargin border;
   450       if (firstRow) {
   451         //pick up first row's top border (= rg top border)
   452         firstRow->GetContinuousBCBorderWidth(border);
   453         /* (row group doesn't store its top border) */
   454       }
   455       //overwrite sides+bottom borders with rg's own
   456       aFrame->GetContinuousBCBorderWidth(border);
   457       nsresult res = mRowGroup.SetBCBorder(border, this);
   458       if (!NS_SUCCEEDED(res)) {
   459         return res;
   460       }
   461     }
   462     aPassThrough = !mRowGroup.IsVisible();
   463   }
   465   /* translate everything into row group coord system*/
   466   if (eOrigin_TableRowGroup != mOrigin) {
   467     TranslateContext(mRowGroup.mRect.x, mRowGroup.mRect.y);
   468   }
   469   nsRect rgRect = mRowGroup.mRect;
   470   mRowGroup.mRect.MoveTo(0, 0);
   472   /* Find the right row to start with */
   473   nscoord ignored; // We don't care about overflow above, since what we really
   474                    // care about are backgrounds and overflow above doesn't
   475                    // correspond to backgrounds, since cells can't span up from
   476                    // their originating row.  We do care about overflow below,
   477                    // however, since that can be due to rowspans.
   479   // Note that mDirtyRect  - mRenderPt is guaranteed to be in the row
   480   // group's coordinate system here, so passing its .y to
   481   // GetFirstRowContaining is ok.
   482   nsIFrame* cursor = aFrame->GetFirstRowContaining(mDirtyRect.y - mRenderPt.y, &ignored);
   484   // Sadly, it seems like there may be non-row frames in there... or something?
   485   // There are certainly null-checks in GetFirstRow() and GetNextRow().  :(
   486   while (cursor && cursor->GetType() != nsGkAtoms::tableRowFrame) {
   487     cursor = cursor->GetNextSibling();
   488   }
   490   // It's OK if cursor is null here.
   491   nsTableRowFrame* row = static_cast<nsTableRowFrame*>(cursor);  
   492   if (!row) {
   493     // No useful cursor; just start at the top.  Don't bother to set up a
   494     // cursor; if we've gotten this far then we've already built the display
   495     // list for the rowgroup, so not having a cursor means that there's some
   496     // good reason we don't have a cursor and we shouldn't create one here.
   497     row = firstRow;
   498   }
   500   /* Finally paint */
   501   for (; row; row = row->GetNextRow()) {
   502     mRow.SetFrame(row);
   503     if (mDirtyRect.YMost() - mRenderPt.y < mRow.mRect.y) { // Intersect wouldn't handle
   504                                              // rowspans.
   506       // All done; cells originating in later rows can't intersect mDirtyRect.
   507       break;
   508     }
   510     nsresult rv = PaintRow(row, aPassThrough || row->IsPseudoStackingContextFromStyle());
   511     if (NS_FAILED(rv)) return rv;
   512   }
   514   /* translate back into table coord system */
   515   if (eOrigin_TableRowGroup != mOrigin) {
   516     TranslateContext(-rgRect.x, -rgRect.y);
   517   }
   519   /* unload rg data */
   520   mRowGroup.Clear();
   522   return NS_OK;
   523 }
   525 nsresult
   526 TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame,
   527                                  bool             aPassThrough)
   528 {
   529   NS_PRECONDITION(aFrame, "null frame");
   531   if (!mRow.mFrame) {
   532     mRow.SetFrame(aFrame);
   533   }
   535   /* Load row data */
   536   if (!aPassThrough) {
   537     mRow.SetData();
   538     if (mIsBorderCollapse && mRow.ShouldSetBCBorder()) {
   539       nsMargin border;
   540       nsTableRowFrame* nextRow = aFrame->GetNextRow();
   541       if (nextRow) { //outer top below us is inner bottom for us
   542         border.bottom = nextRow->GetOuterTopContBCBorderWidth();
   543       }
   544       else { //acquire rg's bottom border
   545         nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame->GetParent());
   546         rowGroup->GetContinuousBCBorderWidth(border);
   547       }
   548       //get the rest of the borders; will overwrite all but bottom
   549       aFrame->GetContinuousBCBorderWidth(border);
   551       nsresult res = mRow.SetBCBorder(border, this);
   552       if (!NS_SUCCEEDED(res)) {
   553         return res;
   554       }
   555     }
   556     aPassThrough = !mRow.IsVisible();
   557   }
   559   /* Translate */
   560   if (eOrigin_TableRow == mOrigin) {
   561     /* If we originate from the row, then make the row the origin. */
   562     mRow.mRect.MoveTo(0, 0);
   563   }
   564   //else: Use row group's coord system -> no translation necessary
   566   for (nsTableCellFrame* cell = aFrame->GetFirstCell(); cell; cell = cell->GetNextCell()) {
   567     //Translate to use the same coord system as mRow.
   568     mCellRect = cell->GetRect() + mRow.mRect.TopLeft() + mRenderPt;
   569     if (mCellRect.Intersects(mDirtyRect)) {
   570       nsresult rv = PaintCell(cell, aPassThrough || cell->IsPseudoStackingContextFromStyle());
   571       if (NS_FAILED(rv)) return rv;
   572     }
   573   }
   575   /* Unload row data */
   576   mRow.Clear();
   577   return NS_OK;
   578 }
   580 nsresult
   581 TableBackgroundPainter::PaintCell(nsTableCellFrame* aCell,
   582                                   bool aPassSelf)
   583 {
   584   NS_PRECONDITION(aCell, "null frame");
   586   const nsStyleTableBorder* cellTableStyle;
   587   cellTableStyle = aCell->StyleTableBorder();
   588   if (!(NS_STYLE_TABLE_EMPTY_CELLS_SHOW == cellTableStyle->mEmptyCells ||
   589         NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND == cellTableStyle->mEmptyCells)
   590       && aCell->GetContentEmpty() && !mIsBorderCollapse) {
   591     return NS_OK;
   592   }
   594   int32_t colIndex;
   595   aCell->GetColIndex(colIndex);
   596   NS_ASSERTION(colIndex < int32_t(mNumCols), "prevent array boundary violation");
   597   if (int32_t(mNumCols) <= colIndex)
   598     return NS_OK;
   600   //Paint column group background
   601   if (mCols && mCols[colIndex].mColGroup && mCols[colIndex].mColGroup->IsVisible()) {
   602     nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
   603                                           mCols[colIndex].mColGroup->mFrame, mDirtyRect,
   604                                           mCols[colIndex].mColGroup->mRect + mRenderPt,
   605                                           mCols[colIndex].mColGroup->mFrame->StyleContext(),
   606                                           *mCols[colIndex].mColGroup->mBorder,
   607                                           mBGPaintFlags, &mCellRect);
   608   }
   610   //Paint column background
   611   if (mCols && mCols[colIndex].mCol.IsVisible()) {
   612     nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
   613                                           mCols[colIndex].mCol.mFrame, mDirtyRect,
   614                                           mCols[colIndex].mCol.mRect + mRenderPt,
   615                                           mCols[colIndex].mCol.mFrame->StyleContext(),
   616                                           *mCols[colIndex].mCol.mBorder,
   617                                           mBGPaintFlags, &mCellRect);
   618   }
   620   //Paint row group background
   621   if (mRowGroup.IsVisible()) {
   622     nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
   623                                           mRowGroup.mFrame, mDirtyRect,
   624                                           mRowGroup.mRect + mRenderPt,
   625                                           mRowGroup.mFrame->StyleContext(),
   626                                           *mRowGroup.mBorder,
   627                                           mBGPaintFlags, &mCellRect);
   628   }
   630   //Paint row background
   631   if (mRow.IsVisible()) {
   632     nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
   633                                           mRow.mFrame, mDirtyRect,
   634                                           mRow.mRect + mRenderPt,
   635                                           mRow.mFrame->StyleContext(),
   636                                           *mRow.mBorder,
   637                                           mBGPaintFlags, &mCellRect);
   638   }
   640   //Paint cell background in border-collapse unless we're just passing
   641   if (mIsBorderCollapse && !aPassSelf) {
   642     aCell->PaintCellBackground(mRenderingContext, mDirtyRect,
   643                                mCellRect.TopLeft(), mBGPaintFlags);
   644   }
   646   return NS_OK;
   647 }

mercurial