LCOV - code coverage report
Current view: directory - layout/tables - nsTablePainter.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 278 0 0.0 %
Date: 2012-06-02 Functions: 17 0 0.0 %

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

Generated by: LCOV version 1.7