~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/layout/html/table/src/nsTablePainter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
47
/* ~*~ Standards Mode Painting ~*~
 
48
 
 
49
   Background painting in Standards mode follows CSS2.1:17.5.1
 
50
   That section does not, however, describe the effect of
 
51
   borders on background image positioning. What we do is:
 
52
 
 
53
     - in separate borders, the borders are passed in so that
 
54
       their width figures in image positioning, even for rows/cols, which
 
55
       don't have visible borders. This is done to allow authors
 
56
       to position row backgrounds by, for example, aligning the
 
57
       top left corner with the top left padding corner of the
 
58
       top left table cell in the row in cases where all cells
 
59
       have consistent border widths. If we didn't honor these
 
60
       invisible borders, there would be no way to align
 
61
       backgrounds with the padding edges, and designs would be
 
62
       lost underneath the border.
 
63
 
 
64
     - in collapsing borders, because the borders collapse, we
 
65
       use the -continuous border- width to synthesize a border
 
66
       style and pass that in instead of using the element's
 
67
       assigned style directly.
 
68
 
 
69
       The continuous border on a given edge of an element is
 
70
       the collapse of all borders guaranteed to be continuous
 
71
       along that edge. Cell borders are ignored (because, for
 
72
       example, setting a thick border on the leftmost cell
 
73
       should not shift the row background over; this way a
 
74
       striped background set on <tr> will line up across rows
 
75
       even if the cells are assigned arbitrary border widths.
 
76
 
 
77
       For example, the continous border on the top edge of a
 
78
       row group is the collapse of any row group, row, and
 
79
       table borders involved. (The first row group's top would
 
80
       be [table-top + row group top + first row top]. It's bottom
 
81
       would be [row group bottom + last row bottom + next row
 
82
       top + next row group top].)
 
83
       The top edge of a column group likewise includes the
 
84
       table top, row group top, and first row top borders. However,
 
85
       it *also* includes its own top border, since that is guaranteed
 
86
       to be continuous. It does not include column borders because
 
87
       those are not guaranteed to be continuous: there may be two
 
88
       columns with different borders in a single column group.
 
89
 
 
90
       An alternative would be to define the continuous border as
 
91
         [table? + row group + row] for horizontal
 
92
         [table? + col group + col] for vertical
 
93
       This makes it easier to line up backgrounds across elements
 
94
       despite varying border widths, but it does not give much
 
95
       flexibility in aligning /to/ those border widths.
 
96
*/
 
97
 
 
98
/* ~*~ Quirks Table Background Painting ~*~
 
99
 
 
100
   Quirks inherits all backgrounds below the table level into the
 
101
   cells; we don't paint intermediate backgrounds.
 
102
*/
 
103
 
 
104
 
 
105
/* ~*~ TableBackgroundPainter ~*~
 
106
 
 
107
   The TableBackgroundPainter is created and destroyed in one painting call.
 
108
   Its principal function is PaintTable, which paints all table element
 
109
   backgrounds. The initial code in that method sets up an array of column
 
110
   data that caches the background styles and the border sizes for the
 
111
   columns and colgroups in TableBackgroundData structs in mCols. Data for
 
112
   BC borders are calculated and stashed in a synthesized border style struct
 
113
   in the data struct since collapsed borders aren't the same width as style-
 
114
   assigned borders. The data struct optimizes by only doing this if there's
 
115
   an image background; otherwise we don't care. //XXX should also check background-origin
 
116
   The class then loops through the row groups, rows, and cells. It uses
 
117
   the mRowGroup and mRow TableBackgroundData structs to cache data for
 
118
   the current frame in the loop. At the cell level, it paints the backgrounds,
 
119
   one over the other, inside the cell rect.
 
120
 
 
121
   The exception to this pattern is when a table element has a view.
 
122
   Elements with views are <dfn>passed through</dfn>, which means their data
 
123
   (and their descendants' data) are not cached. The full loop is still
 
124
   executed, however, so that underlying layers can get painted at the cell
 
125
   level.
 
126
 
 
127
   The TableBackgroundPainter is then destroyed.
 
128
 
 
129
   Elements with views set up their own painter to finish the painting
 
130
   process, since they were skipped. They call the appropriate sub-part
 
131
   of the loop (e.g. PaintRow) which will paint the frame and descendants.
 
132
 */
 
133
 
 
134
TableBackgroundPainter::TableBackgroundData::TableBackgroundData()
 
135
  : mFrame(nsnull),
 
136
    mBackground(nsnull),
 
137
    mBorder(nsnull),
 
138
    mSynthBorder(nsnull)
 
139
{
 
140
  MOZ_COUNT_CTOR(TableBackgroundData);
 
141
}
 
142
 
 
143
TableBackgroundPainter::TableBackgroundData::~TableBackgroundData()
 
144
{
 
145
  NS_ASSERTION(!mSynthBorder, "must call Destroy before dtor");
 
146
  MOZ_COUNT_DTOR(TableBackgroundData);
 
147
}
 
148
 
 
149
void
 
150
TableBackgroundPainter::TableBackgroundData::Destroy(nsIPresContext* aPresContext)
 
151
{
 
152
  NS_PRECONDITION(aPresContext, "null prescontext");
 
153
  if (mSynthBorder) {
 
154
    mSynthBorder->Destroy(aPresContext);
 
155
    mSynthBorder = nsnull;
 
156
  }
 
157
}
 
158
 
 
159
void
 
160
TableBackgroundPainter::TableBackgroundData::Clear()
 
161
{
 
162
  mRect.Empty();
 
163
  mFrame = nsnull;
 
164
  mBorder = nsnull;
 
165
  mBackground = nsnull;
 
166
}
 
167
 
 
168
void
 
169
TableBackgroundPainter::TableBackgroundData::SetFrame(nsIFrame* aFrame)
 
170
{
 
171
  NS_PRECONDITION(aFrame, "null frame");
 
172
  mFrame = aFrame;
 
173
  mRect = aFrame->GetRect();
 
174
}
 
175
 
 
176
void
 
177
TableBackgroundPainter::TableBackgroundData::SetFull(nsIPresContext*      aPresContext,
 
178
                                                     nsIRenderingContext& aRenderingContext,
 
179
                                                     nsIFrame*            aFrame)
 
180
{
 
181
  NS_PRECONDITION(aFrame, "null frame");
 
182
  mFrame = aFrame;
 
183
  mRect = aFrame->GetRect();
 
184
  /* IsVisibleForPainting doesn't use aRenderingContext except in nsTextFrames,
 
185
     so we're not going to bother translating.*/
 
186
  PRBool isVisible;
 
187
  nsresult rv = aFrame->IsVisibleForPainting(aPresContext, aRenderingContext,
 
188
                                             PR_TRUE, &isVisible);
 
189
  if (NS_SUCCEEDED(rv) && isVisible &&
 
190
      aFrame->GetStyleVisibility()->IsVisible()) {
 
191
    mBackground = aFrame->GetStyleBackground();
 
192
    mBorder = aFrame->GetStyleBorder();
 
193
  }
 
194
}
 
195
 
 
196
inline PRBool
 
197
TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder()
 
198
{
 
199
  /* we only need accurate border data when positioning background images*/
 
200
  return mBackground && !(mBackground->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE);
 
201
}
 
202
 
 
203
nsresult
 
204
TableBackgroundPainter::TableBackgroundData::SetBCBorder(nsMargin& aBorder,
 
205
                                                         TableBackgroundPainter* aPainter)
 
206
{
 
207
  NS_PRECONDITION(aPainter, "null painter");
 
208
  if (!mSynthBorder) {
 
209
    mSynthBorder = new (aPainter->mPresContext)
 
210
                        nsStyleBorder(aPainter->mZeroBorder);
 
211
    if (!mSynthBorder) return NS_ERROR_OUT_OF_MEMORY;
 
212
  }
 
213
 
 
214
  nsStyleCoord coord(aBorder.top);
 
215
  mSynthBorder->mBorder.SetTop(coord);
 
216
  coord.SetCoordValue(aBorder.right);
 
217
  mSynthBorder->mBorder.SetRight(coord);
 
218
  coord.SetCoordValue(aBorder.bottom);
 
219
  mSynthBorder->mBorder.SetBottom(coord);
 
220
  coord.SetCoordValue(aBorder.left);
 
221
  mSynthBorder->mBorder.SetLeft(coord);
 
222
  mSynthBorder->RecalcData();
 
223
 
 
224
  mBorder = mSynthBorder;
 
225
  return NS_OK;
 
226
}
 
227
 
 
228
TableBackgroundPainter::TableBackgroundPainter(nsTableFrame*        aTableFrame,
 
229
                                               Origin               aOrigin,
 
230
                                               nsIPresContext*      aPresContext,
 
231
                                               nsIRenderingContext& aRenderingContext,
 
232
                                               const nsRect&        aDirtyRect)
 
233
  : mPresContext(aPresContext),
 
234
    mRenderingContext(aRenderingContext),
 
235
    mDirtyRect(aDirtyRect),
 
236
    mOrigin(aOrigin),
 
237
    mCols(nsnull),
 
238
    mZeroBorder(aPresContext)
 
239
{
 
240
  MOZ_COUNT_CTOR(TableBackgroundPainter);
 
241
 
 
242
  mZeroBorder.SetBorderStyle(NS_SIDE_TOP, NS_STYLE_BORDER_STYLE_SOLID);
 
243
  mZeroBorder.SetBorderStyle(NS_SIDE_RIGHT, NS_STYLE_BORDER_STYLE_SOLID);
 
244
  mZeroBorder.SetBorderStyle(NS_SIDE_BOTTOM, NS_STYLE_BORDER_STYLE_SOLID);
 
245
  mZeroBorder.SetBorderStyle(NS_SIDE_LEFT, NS_STYLE_BORDER_STYLE_SOLID);
 
246
  nsStyleCoord coord(0);
 
247
  mZeroBorder.mBorder.SetTop(coord);
 
248
  mZeroBorder.mBorder.SetRight(coord);
 
249
  mZeroBorder.mBorder.SetBottom(coord);
 
250
  mZeroBorder.mBorder.SetLeft(coord);
 
251
  mZeroBorder.RecalcData();
 
252
 
 
253
  mZeroPadding.RecalcData();
 
254
 
 
255
  mPresContext->GetScaledPixelsToTwips(&mP2t);
 
256
  mIsBorderCollapse = aTableFrame->IsBorderCollapse();
 
257
#ifdef DEBUG
 
258
  mCompatMode = mPresContext->CompatibilityMode();
 
259
#endif
 
260
  mNumCols = aTableFrame->GetColCount();
 
261
}
 
262
 
 
263
TableBackgroundPainter::~TableBackgroundPainter()
 
264
{
 
265
  if (mCols) {
 
266
    TableBackgroundData* lastColGroup = nsnull;
 
267
    for (PRUint32 i = 0; i < mNumCols; i++) {
 
268
      if (mCols[i].mColGroup != lastColGroup) {
 
269
        lastColGroup = mCols[i].mColGroup;
 
270
        NS_ASSERTION(mCols[i].mColGroup, "colgroup data should not be null - bug 237421");
 
271
        // we need to wallpaper a over zero pointer deref, bug 237421 will have the real fix
 
272
        if(lastColGroup)
 
273
          lastColGroup->Destroy(mPresContext);
 
274
        delete lastColGroup;
 
275
      }
 
276
      mCols[i].mColGroup = nsnull;
 
277
      mCols[i].mCol.Destroy(mPresContext);
 
278
    }
 
279
    delete [] mCols;
 
280
  }
 
281
  mRowGroup.Destroy(mPresContext);
 
282
  mRow.Destroy(mPresContext);
 
283
  MOZ_COUNT_DTOR(TableBackgroundPainter);
 
284
}
 
285
 
 
286
nsresult
 
287
TableBackgroundPainter::PaintTableFrame(nsTableFrame*         aTableFrame,
 
288
                                        nsTableRowGroupFrame* aFirstRowGroup,
 
289
                                        nsTableRowGroupFrame* aLastRowGroup,
 
290
                                        nsMargin*             aDeflate)
 
291
{
 
292
  NS_PRECONDITION(aTableFrame, "null frame");
 
293
  TableBackgroundData tableData;
 
294
  tableData.SetFull(mPresContext, mRenderingContext, aTableFrame);
 
295
  tableData.mRect.MoveTo(0,0); //using table's coords
 
296
  if (aDeflate) {
 
297
    tableData.mRect.Deflate(*aDeflate);
 
298
  }
 
299
  if (mIsBorderCollapse && tableData.ShouldSetBCBorder()) {
 
300
    if (aFirstRowGroup && aLastRowGroup && mNumCols > 0) {
 
301
      //only handle non-degenerate tables; we need a more robust BC model
 
302
      //to make degenerate tables' borders reasonable to deal with
 
303
      nsMargin border, tempBorder;
 
304
      nsTableColFrame* colFrame = aTableFrame->GetColFrame(mNumCols - 1);
 
305
      if (colFrame) {
 
306
        colFrame->GetContinuousBCBorderWidth(mP2t, tempBorder);
 
307
      }
 
308
      border.right = tempBorder.right;
 
309
 
 
310
      aLastRowGroup->GetContinuousBCBorderWidth(mP2t, tempBorder);
 
311
      border.bottom = tempBorder.bottom;
 
312
 
 
313
      nsTableRowFrame* rowFrame = aFirstRowGroup->GetFirstRow();
 
314
      if (rowFrame) {
 
315
        rowFrame->GetContinuousBCBorderWidth(mP2t, tempBorder);
 
316
        border.top = tempBorder.top;
 
317
      }
 
318
 
 
319
      border.left = aTableFrame->GetContinuousLeftBCBorderWidth(mP2t);
 
320
 
 
321
      nsresult rv = tableData.SetBCBorder(border, this);
 
322
      if (NS_FAILED(rv)) {
 
323
        tableData.Destroy(mPresContext);
 
324
        return rv;
 
325
      }
 
326
    }
 
327
  }
 
328
  if (tableData.IsVisible()) {
 
329
    nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
 
330
                                          tableData.mFrame, mDirtyRect,
 
331
                                          tableData.mRect,
 
332
                                          *tableData.mBackground,
 
333
                                          *tableData.mBorder,
 
334
                                          mZeroPadding, PR_TRUE);
 
335
  }
 
336
  tableData.Destroy(mPresContext);
 
337
  return NS_OK;
 
338
}
 
339
 
 
340
void
 
341
TableBackgroundPainter::TranslateContext(nscoord aDX,
 
342
                                         nscoord aDY)
 
343
{
 
344
  mRenderingContext.Translate(aDX, aDY);
 
345
  mDirtyRect.MoveBy(-aDX, -aDY);
 
346
  if (mCols) {
 
347
    TableBackgroundData* lastColGroup = nsnull;
 
348
    for (PRUint32 i = 0; i < mNumCols; i++) {
 
349
      mCols[i].mCol.mRect.MoveBy(-aDX, -aDY);
 
350
      if (lastColGroup != mCols[i].mColGroup) {
 
351
        NS_ASSERTION(mCols[i].mColGroup, "colgroup data should not be null - bug 237421");
 
352
        // we need to wallpaper a over zero pointer deref, bug 237421 will have the real fix
 
353
        if (!mCols[i].mColGroup)
 
354
          return;
 
355
        mCols[i].mColGroup->mRect.MoveBy(-aDX, -aDY);
 
356
        lastColGroup = mCols[i].mColGroup;
 
357
      }
 
358
    }
 
359
  }
 
360
}
 
361
 
 
362
nsresult
 
363
TableBackgroundPainter::QuirksPaintTable(nsTableFrame* aTableFrame,
 
364
                                         nsMargin&     aDeflate)
 
365
{
 
366
  NS_PRECONDITION(aTableFrame, "null table frame");
 
367
  NS_PRECONDITION(eCompatibility_NavQuirks == mCompatMode,
 
368
                  "QuirksPaintTable called for non-Quirks");
 
369
 
 
370
  nsVoidArray rowGroups;
 
371
  PRUint32 numRowGroups;
 
372
  aTableFrame->OrderRowGroups(rowGroups, numRowGroups);
 
373
 
 
374
  if (numRowGroups < 1) { //degenerate case
 
375
    PaintTableFrame(aTableFrame,nsnull, nsnull, &aDeflate);
 
376
    /* No cells; nothing else to paint */
 
377
    return NS_OK;
 
378
  }
 
379
 
 
380
  PaintTableFrame(aTableFrame,
 
381
                  aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(0))),
 
382
                  aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(numRowGroups - 1))),
 
383
                  &aDeflate);
 
384
 
 
385
  if (mIsBorderCollapse) {
 
386
    /* This is a simple pass, so we'll just keep with the table coord system. */
 
387
 
 
388
    for (PRUint32 i = 0; i < numRowGroups; i++) {
 
389
      nsTableRowGroupFrame* rg = aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(i)));
 
390
      nsRect rgRect = rg->GetRect();
 
391
      if (rgRect.Intersects(mDirtyRect) && !rg->HasView()) {
 
392
        for (nsTableRowFrame* row = rg->GetFirstRow(); row; row = row->GetNextRow()) {
 
393
          nsRect rowRect = row->GetRect();
 
394
          rowRect.MoveBy(rgRect.x, rgRect.y);
 
395
          if (mDirtyRect.YMost() > rowRect.y && //Intersect won't handle rowspans
 
396
              !row->HasView()) {
 
397
            for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
 
398
              mCellRect = cell->GetRect();
 
399
              mCellRect.MoveBy(rowRect.x, rowRect.y);
 
400
              if (mCellRect.Intersects(mDirtyRect) && !cell->HasView()) {
 
401
                nsresult rv = PaintCell(cell, PR_FALSE);
 
402
                if (NS_FAILED(rv)) return rv;
 
403
              }
 
404
            }
 
405
          }
 
406
        }
 
407
      }
 
408
    }
 
409
  }
 
410
  return NS_OK;
 
411
}
 
412
 
 
413
nsresult
 
414
TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame)
 
415
{
 
416
  NS_PRECONDITION(aTableFrame, "null table frame");
 
417
  NS_PRECONDITION(eCompatibility_NavQuirks != mCompatMode,
 
418
                  "must call QuirksPaintTable in Quirks mode, not PaintTable");
 
419
 
 
420
  nsVoidArray rowGroups;
 
421
  PRUint32 numRowGroups;
 
422
  aTableFrame->OrderRowGroups(rowGroups, numRowGroups);
 
423
 
 
424
  if (numRowGroups < 1) { //degenerate case
 
425
    PaintTableFrame(aTableFrame,nsnull, nsnull, nsnull);
 
426
    /* No cells; nothing else to paint */
 
427
    return NS_OK;
 
428
  }
 
429
 
 
430
  PaintTableFrame(aTableFrame,
 
431
                  aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(0))),
 
432
                  aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(numRowGroups - 1))),
 
433
                  nsnull);
 
434
 
 
435
  /*Set up column background/border data*/
 
436
  if (mNumCols > 0) {
 
437
    nsFrameList& colGroupList = aTableFrame->GetColGroups();
 
438
    NS_ASSERTION(colGroupList.FirstChild(), "table should have at least one colgroup");
 
439
 
 
440
    mCols = new ColData[mNumCols];
 
441
    if (!mCols) return NS_ERROR_OUT_OF_MEMORY;
 
442
 
 
443
    TableBackgroundData* cgData = nsnull;
 
444
    nsMargin border;
 
445
    /* BC left borders aren't stored on cols, but the previous column's
 
446
       right border is the next one's left border.*/
 
447
    //Start with table's left border.
 
448
    nscoord lastLeftBorder = aTableFrame->GetContinuousLeftBCBorderWidth(mP2t);
 
449
    for (nsTableColGroupFrame* cgFrame = NS_STATIC_CAST(nsTableColGroupFrame*, colGroupList.FirstChild());
 
450
         cgFrame; cgFrame = NS_STATIC_CAST(nsTableColGroupFrame*, cgFrame->GetNextSibling())) {
 
451
 
 
452
      if (cgFrame->GetColCount() < 1) {
 
453
        //No columns, no cells, so no need for data
 
454
        continue;
 
455
      }
 
456
 
 
457
      /*Create data struct for column group*/
 
458
      cgData = new TableBackgroundData;
 
459
      if (!cgData) return NS_ERROR_OUT_OF_MEMORY;
 
460
      cgData->SetFull(mPresContext, mRenderingContext, cgFrame);
 
461
      if (mIsBorderCollapse && cgData->ShouldSetBCBorder()) {
 
462
        border.left = lastLeftBorder;
 
463
        cgFrame->GetContinuousBCBorderWidth(mP2t, border);
 
464
        nsresult rv = cgData->SetBCBorder(border, this);
 
465
        if (NS_FAILED(rv)) {
 
466
          cgData->Destroy(mPresContext);
 
467
          delete cgData;
 
468
          return rv;
 
469
        }
 
470
      }
 
471
 
 
472
      /*Loop over columns in this colgroup*/
 
473
      if (cgData->IsVisible()) {
 
474
        for (nsTableColFrame* col = cgFrame->GetFirstColumn(); col;
 
475
             col = NS_STATIC_CAST(nsTableColFrame*, col->GetNextSibling())) {
 
476
          /*Create data struct for column*/
 
477
          PRUint32 colIndex = col->GetColIndex();
 
478
          // please file a bug if you can reproduce the assertion below 
 
479
          // (see bug 240854)
 
480
          NS_ASSERTION(colIndex < mNumCols, "prevent array boundary violation");
 
481
          if (mNumCols <= colIndex)
 
482
            break;
 
483
          mCols[colIndex].mCol.SetFull(mPresContext, mRenderingContext, col);
 
484
          //Bring column mRect into table's coord system
 
485
          mCols[colIndex].mCol.mRect.MoveBy(cgData->mRect.x, cgData->mRect.y);
 
486
          //link to parent colgroup's data
 
487
          mCols[colIndex].mColGroup = cgData;
 
488
          if (mIsBorderCollapse) {
 
489
            border.left = lastLeftBorder;
 
490
            lastLeftBorder = col->GetContinuousBCBorderWidth(mP2t, border);
 
491
            if (mCols[colIndex].mCol.ShouldSetBCBorder()) {
 
492
              nsresult rv = mCols[colIndex].mCol.SetBCBorder(border, this);
 
493
              if (NS_FAILED(rv)) return rv;
 
494
            }
 
495
          }
 
496
        }
 
497
      }
 
498
    }
 
499
  }
 
500
 
 
501
  for (PRUint32 i = 0; i < numRowGroups; i++) {
 
502
    nsTableRowGroupFrame* rg = nsTableFrame::GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(i)));
 
503
    nsRect rgRect = rg->GetRect();
 
504
    if (rgRect.Intersects(mDirtyRect)) {
 
505
      nsresult rv = PaintRowGroup(rg, rg->HasView());
 
506
      if (NS_FAILED(rv)) return rv;
 
507
    }
 
508
  }
 
509
  return NS_OK;
 
510
}
 
511
 
 
512
nsresult
 
513
TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
 
514
                                      PRBool                aPassThrough)
 
515
{
 
516
  NS_PRECONDITION(aFrame, "null frame");
 
517
  NS_PRECONDITION(eCompatibility_NavQuirks != mCompatMode,
 
518
                  "must not call PaintRowGroup in Quirks mode");
 
519
 
 
520
  nsTableRowFrame* firstRow = aFrame->GetFirstRow();
 
521
 
 
522
  /* Load row group data */
 
523
  if (!aPassThrough) {
 
524
    mRowGroup.SetFull(mPresContext, mRenderingContext, aFrame);
 
525
    if (mIsBorderCollapse && mRowGroup.ShouldSetBCBorder()) {
 
526
      nsMargin border;
 
527
      if (firstRow) {
 
528
        //pick up first row's top border (= rg top border)
 
529
        firstRow->GetContinuousBCBorderWidth(mP2t, border);
 
530
        /* (row group doesn't store its top border) */
 
531
      }
 
532
      //overwrite sides+bottom borders with rg's own
 
533
      aFrame->GetContinuousBCBorderWidth(mP2t, border);
 
534
      nsresult res = mRowGroup.SetBCBorder(border, this);
 
535
      if (!NS_SUCCEEDED(res)) {
 
536
        return res;
 
537
      }
 
538
    }
 
539
    aPassThrough = !mRowGroup.IsVisible();
 
540
  }
 
541
  else {
 
542
    mRowGroup.SetFrame(aFrame);
 
543
  }
 
544
 
 
545
  /* translate everything into row group coord system*/
 
546
  if (eOrigin_TableRowGroup != mOrigin) {
 
547
    TranslateContext(mRowGroup.mRect.x, mRowGroup.mRect.y);
 
548
  }
 
549
  nsRect rgRect = mRowGroup.mRect;
 
550
  mRowGroup.mRect.MoveTo(0, 0);
 
551
 
 
552
  /* paint */
 
553
  for (nsTableRowFrame* row = firstRow; row; row = row->GetNextRow()) {
 
554
    nsRect rect = row->GetRect();
 
555
    if (mDirtyRect.YMost() >= rect.y) { //Intersect wouldn't handle rowspans
 
556
      nsresult rv = PaintRow(row, aPassThrough || row->HasView());
 
557
      if (NS_FAILED(rv)) return rv;
 
558
    }
 
559
  }
 
560
 
 
561
  /* translate back into table coord system */
 
562
  if (eOrigin_TableRowGroup != mOrigin) {
 
563
    TranslateContext(-rgRect.x, -rgRect.y);
 
564
  }
 
565
  
 
566
  /* unload rg data */
 
567
  mRowGroup.Clear();
 
568
 
 
569
  return NS_OK;
 
570
}
 
571
 
 
572
nsresult
 
573
TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame,
 
574
                                 PRBool           aPassThrough)
 
575
{
 
576
  NS_PRECONDITION(aFrame, "null frame");
 
577
  NS_PRECONDITION(eCompatibility_NavQuirks != mCompatMode,
 
578
                  "must not call PaintRow in Quirks mode");
 
579
  /* Load row data */
 
580
  if (!aPassThrough) {
 
581
    mRow.SetFull(mPresContext, mRenderingContext, aFrame);
 
582
    if (mIsBorderCollapse && mRow.ShouldSetBCBorder()) {
 
583
      nsMargin border;
 
584
      nsTableRowFrame* nextRow = aFrame->GetNextRow();
 
585
      if (nextRow) { //outer top below us is inner bottom for us
 
586
        border.bottom = nextRow->GetOuterTopContBCBorderWidth(mP2t);
 
587
      }
 
588
      else { //acquire rg's bottom border
 
589
        nsTableRowGroupFrame* rowGroup = NS_STATIC_CAST(nsTableRowGroupFrame*, aFrame->GetParent());
 
590
        rowGroup->GetContinuousBCBorderWidth(mP2t, border);
 
591
      }
 
592
      //get the rest of the borders; will overwrite all but bottom
 
593
      aFrame->GetContinuousBCBorderWidth(mP2t, border);
 
594
 
 
595
      nsresult res = mRow.SetBCBorder(border, this);
 
596
      if (!NS_SUCCEEDED(res)) {
 
597
        return res;
 
598
      }
 
599
    }
 
600
    aPassThrough = !mRow.IsVisible();
 
601
  }
 
602
  else {
 
603
    mRow.SetFrame(aFrame);
 
604
  }
 
605
 
 
606
  /* Translate */
 
607
  if (eOrigin_TableRow == mOrigin) {
 
608
    /* If we originate from the row, then make the row the origin. */
 
609
    mRow.mRect.MoveTo(0, 0);
 
610
  }
 
611
  //else: Use row group's coord system -> no translation necessary
 
612
 
 
613
  for (nsTableCellFrame* cell = aFrame->GetFirstCell(); cell; cell = cell->GetNextCell()) {
 
614
    mCellRect = cell->GetRect();
 
615
    //Translate to use the same coord system as mRow.
 
616
    mCellRect.MoveBy(mRow.mRect.x, mRow.mRect.y);
 
617
    if (mCellRect.Intersects(mDirtyRect)) {
 
618
      nsresult rv = PaintCell(cell, aPassThrough || cell->HasView());
 
619
      if (NS_FAILED(rv)) return rv;
 
620
    }
 
621
  }
 
622
 
 
623
  /* Unload row data */
 
624
  mRow.Clear();
 
625
  return NS_OK;
 
626
}
 
627
 
 
628
nsresult
 
629
TableBackgroundPainter::PaintCell(nsTableCellFrame* aCell,
 
630
                                  PRBool aPassSelf)
 
631
{
 
632
  NS_PRECONDITION(aCell, "null frame");
 
633
 
 
634
  const nsStyleTableBorder* cellTableStyle;
 
635
  cellTableStyle = aCell->GetStyleTableBorder();
 
636
  if (!(NS_STYLE_TABLE_EMPTY_CELLS_SHOW == cellTableStyle->mEmptyCells ||
 
637
        NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND == cellTableStyle->mEmptyCells)
 
638
      && aCell->GetContentEmpty()) {
 
639
    return NS_OK;
 
640
  }
 
641
 
 
642
  PRInt32 colIndex;
 
643
  aCell->GetColIndex(colIndex);
 
644
 
 
645
  //Paint column group background
 
646
  if (mCols && mCols[colIndex].mColGroup && mCols[colIndex].mColGroup->IsVisible()) {
 
647
    nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
 
648
                                          mCols[colIndex].mColGroup->mFrame, mDirtyRect,
 
649
                                          mCols[colIndex].mColGroup->mRect,
 
650
                                          *mCols[colIndex].mColGroup->mBackground,
 
651
                                          *mCols[colIndex].mColGroup->mBorder,
 
652
                                          mZeroPadding, PR_TRUE, &mCellRect);
 
653
  }
 
654
 
 
655
  //Paint column background
 
656
  if (mCols && mCols[colIndex].mCol.IsVisible()) {
 
657
    nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
 
658
                                          mCols[colIndex].mCol.mFrame, mDirtyRect,
 
659
                                          mCols[colIndex].mCol.mRect,
 
660
                                          *mCols[colIndex].mCol.mBackground,
 
661
                                          *mCols[colIndex].mCol.mBorder,
 
662
                                          mZeroPadding, PR_TRUE, &mCellRect);
 
663
  }
 
664
 
 
665
  //Paint row group background
 
666
  if (mRowGroup.IsVisible()) {
 
667
    nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
 
668
                                          mRowGroup.mFrame, mDirtyRect, mRowGroup.mRect,
 
669
                                          *mRowGroup.mBackground, *mRowGroup.mBorder,
 
670
                                          mZeroPadding, PR_TRUE, &mCellRect);
 
671
  }
 
672
 
 
673
  //Paint row background
 
674
  if (mRow.IsVisible()) {
 
675
    nsCSSRendering::PaintBackgroundWithSC(mPresContext, mRenderingContext,
 
676
                                          mRow.mFrame, mDirtyRect, mRow.mRect,
 
677
                                          *mRow.mBackground, *mRow.mBorder,
 
678
                                          mZeroPadding, PR_TRUE, &mCellRect);
 
679
  }
 
680
 
 
681
  //Paint cell background in border-collapse unless we're just passing
 
682
  if (mIsBorderCollapse && !aPassSelf) {
 
683
    mRenderingContext.PushState();
 
684
    mRenderingContext.Translate(mCellRect.x, mCellRect.y);
 
685
    mDirtyRect.MoveBy(-mCellRect.x, -mCellRect.y);
 
686
    aCell->Paint(mPresContext, mRenderingContext, mDirtyRect,
 
687
                 NS_FRAME_PAINT_LAYER_BACKGROUND,
 
688
                 NS_PAINT_FLAG_TABLE_BG_PAINT | NS_PAINT_FLAG_TABLE_CELL_BG_PASS);
 
689
    mDirtyRect.MoveBy(mCellRect.x, mCellRect.y);
 
690
    PRBool clipEmpty;
 
691
    mRenderingContext.PopState(clipEmpty);
 
692
  }
 
693
 
 
694
  return NS_OK;
 
695
}