Revert borders to integers for subpixel layout
[WebKit-https.git] / Source / WebCore / rendering / RenderTableCell.cpp
1 /*
2  * Copyright (C) 1997 Martin Jones (mjones@kde.org)
3  *           (C) 1997 Torben Weis (weis@kde.org)
4  *           (C) 1998 Waldo Bastian (bastian@kde.org)
5  *           (C) 1999 Lars Knoll (knoll@kde.org)
6  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
7  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #include "config.h"
26 #include "RenderTableCell.h"
27
28 #include "CollapsedBorderValue.h"
29 #include "FloatQuad.h"
30 #include "GraphicsContext.h"
31 #include "HTMLNames.h"
32 #include "HTMLTableCellElement.h"
33 #include "PaintInfo.h"
34 #include "RenderTableCol.h"
35 #include "RenderView.h"
36 #include "TransformState.h"
37
38 using namespace std;
39
40 namespace WebCore {
41
42 using namespace HTMLNames;
43
44 RenderTableCell::RenderTableCell(Node* node)
45     : RenderBlock(node)
46     , m_row(unsetRowIndex)
47     , m_cellWidthChanged(false)
48     , m_column(unsetColumnIndex)
49     , m_hasAssociatedTableCellElement(node && (node->hasTagName(tdTag) || node->hasTagName(thTag)))
50     , m_intrinsicPaddingBefore(0)
51     , m_intrinsicPaddingAfter(0)
52 {
53 }
54
55 void RenderTableCell::willBeDestroyed()
56 {
57     RenderTableSection* recalcSection = parent() ? section() : 0;
58
59     RenderBlock::willBeDestroyed();
60
61     if (recalcSection) {
62         recalcSection->setNeedsCellRecalc();
63         recalcSection->removeCachedCollapsedBorders(this);
64     }
65 }
66
67 unsigned RenderTableCell::colSpan() const
68 {
69     if (UNLIKELY(!m_hasAssociatedTableCellElement))
70         return 1;
71
72     return toHTMLTableCellElement(node())->colSpan();
73 }
74
75 unsigned RenderTableCell::rowSpan() const
76 {
77     if (UNLIKELY(!m_hasAssociatedTableCellElement))
78         return 1;
79
80     return toHTMLTableCellElement(node())->rowSpan();
81 }
82
83 void RenderTableCell::colSpanOrRowSpanChanged()
84 {
85     ASSERT(m_hasAssociatedTableCellElement);
86     ASSERT(node());
87     ASSERT(node()->hasTagName(tdTag) || node()->hasTagName(thTag));
88
89     setNeedsLayoutAndPrefWidthsRecalc();
90     if (parent() && section())
91         section()->setNeedsCellRecalc();
92 }
93
94 LayoutUnit RenderTableCell::logicalHeightForRowSizing() const
95 {
96     LayoutUnit adjustedLogicalHeight = logicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter());
97
98     LayoutUnit styleLogicalHeight = style()->logicalHeight().calcValue(0);
99     if (document()->inQuirksMode() || style()->boxSizing() == BORDER_BOX) {
100         // Explicit heights use the border box in quirks mode.
101         // Don't adjust height.
102     } else {
103         // In strict mode, box-sizing: content-box do the right
104         // thing and actually add in the border and padding.
105         LayoutUnit adjustedPaddingBefore = paddingBefore() - intrinsicPaddingBefore();
106         LayoutUnit adjustedPaddingAfter = paddingAfter() - intrinsicPaddingAfter();
107         styleLogicalHeight += adjustedPaddingBefore + adjustedPaddingAfter + borderBefore() + borderAfter();
108     }
109
110     return max(styleLogicalHeight, adjustedLogicalHeight);
111 }
112
113 Length RenderTableCell::styleOrColLogicalWidth() const
114 {
115     Length w = style()->logicalWidth();
116     if (!w.isAuto())
117         return w;
118
119     if (RenderTableCol* tableCol = table()->colElement(col())) {
120         unsigned colSpanCount = colSpan();
121
122         Length colWidthSum = Length(0, Fixed);
123         for (unsigned i = 1; i <= colSpanCount; i++) {
124             Length colWidth = tableCol->style()->logicalWidth();
125
126             // Percentage value should be returned only for colSpan == 1.
127             // Otherwise we return original width for the cell.
128             if (!colWidth.isFixed()) {
129                 if (colSpanCount > 1)
130                     return w;
131                 return colWidth;
132             }
133
134             colWidthSum = Length(colWidthSum.value() + colWidth.value(), Fixed);
135
136             tableCol = table()->nextColElement(tableCol);
137             // If no next <col> tag found for the span we just return what we have for now.
138             if (!tableCol)
139                 break;
140         }
141
142         // Column widths specified on <col> apply to the border box of the cell.
143         // Percentages don't need to be handled since they're always treated this way (even when specified on the cells).
144         // See Bugzilla bug 8126 for details.
145         if (colWidthSum.isFixed() && colWidthSum.value() > 0)
146             colWidthSum = Length(max<LayoutUnit>(0, colWidthSum.value() - borderAndPaddingLogicalWidth()), Fixed);
147         return colWidthSum;
148     }
149
150     return w;
151 }
152
153 void RenderTableCell::computePreferredLogicalWidths()
154 {
155     // The child cells rely on the grids up in the sections to do their computePreferredLogicalWidths work.  Normally the sections are set up early, as table
156     // cells are added, but relayout can cause the cells to be freed, leaving stale pointers in the sections'
157     // grids.  We must refresh those grids before the child cells try to use them.
158     table()->recalcSectionsIfNeeded();
159
160     RenderBlock::computePreferredLogicalWidths();
161     if (node() && style()->autoWrap()) {
162         // See if nowrap was set.
163         Length w = styleOrColLogicalWidth();
164         String nowrap = static_cast<Element*>(node())->getAttribute(nowrapAttr);
165         if (!nowrap.isNull() && w.isFixed())
166             // Nowrap is set, but we didn't actually use it because of the
167             // fixed width set on the cell.  Even so, it is a WinIE/Moz trait
168             // to make the minwidth of the cell into the fixed width.  They do this
169             // even in strict mode, so do not make this a quirk.  Affected the top
170             // of hiptop.com.
171             m_minPreferredLogicalWidth = max<LayoutUnit>(w.value(), m_minPreferredLogicalWidth);
172     }
173 }
174
175 void RenderTableCell::computeLogicalWidth()
176 {
177 }
178
179 void RenderTableCell::updateLogicalWidth(LayoutUnit w)
180 {
181     if (w == logicalWidth())
182         return;
183
184     setLogicalWidth(w);
185     setCellWidthChanged(true);
186 }
187
188 void RenderTableCell::layout()
189 {
190     layoutBlock(cellWidthChanged());
191     setCellWidthChanged(false);
192 }
193
194 LayoutUnit RenderTableCell::paddingTop(bool includeIntrinsicPadding) const
195 {
196     LayoutUnit result = RenderBlock::paddingTop();
197     if (!includeIntrinsicPadding || !isHorizontalWritingMode())
198         return result;
199     return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter());
200 }
201
202 LayoutUnit RenderTableCell::paddingBottom(bool includeIntrinsicPadding) const
203 {
204     LayoutUnit result = RenderBlock::paddingBottom();
205     if (!includeIntrinsicPadding || !isHorizontalWritingMode())
206         return result;
207     return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore());
208 }
209
210 LayoutUnit RenderTableCell::paddingLeft(bool includeIntrinsicPadding) const
211 {
212     LayoutUnit result = RenderBlock::paddingLeft();
213     if (!includeIntrinsicPadding || isHorizontalWritingMode())
214         return result;
215     return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter());
216     
217 }
218
219 LayoutUnit RenderTableCell::paddingRight(bool includeIntrinsicPadding) const
220 {   
221     LayoutUnit result = RenderBlock::paddingRight();
222     if (!includeIntrinsicPadding || isHorizontalWritingMode())
223         return result;
224     return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore());
225 }
226
227 LayoutUnit RenderTableCell::paddingBefore(bool includeIntrinsicPadding) const
228 {
229     LayoutUnit result = RenderBlock::paddingBefore();
230     if (!includeIntrinsicPadding)
231         return result;
232     return result + intrinsicPaddingBefore();
233 }
234
235 LayoutUnit RenderTableCell::paddingAfter(bool includeIntrinsicPadding) const
236 {
237     LayoutUnit result = RenderBlock::paddingAfter();
238     if (!includeIntrinsicPadding)
239         return result;
240     return result + intrinsicPaddingAfter();
241 }
242
243 void RenderTableCell::setOverrideHeightFromRowHeight(LayoutUnit rowHeight)
244 {
245     clearIntrinsicPadding();
246     RenderBlock::setOverrideHeight(max<LayoutUnit>(0, rowHeight - borderBefore() - paddingBefore() - borderAfter() - paddingAfter()));
247 }
248
249 LayoutSize RenderTableCell::offsetFromContainer(RenderObject* o, const LayoutPoint& point) const
250 {
251     ASSERT(o == container());
252
253     LayoutSize offset = RenderBlock::offsetFromContainer(o, point);
254     if (parent())
255         offset.expand(-parentBox()->x(), -parentBox()->y());
256
257     return offset;
258 }
259
260 LayoutRect RenderTableCell::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const
261 {
262     // If the table grid is dirty, we cannot get reliable information about adjoining cells,
263     // so we ignore outside borders. This should not be a problem because it means that
264     // the table is going to recalculate the grid, relayout and repaint its current rect, which
265     // includes any outside borders of this cell.
266     if (!table()->collapseBorders() || table()->needsSectionRecalc())
267         return RenderBlock::clippedOverflowRectForRepaint(repaintContainer);
268
269     bool rtl = !table()->style()->isLeftToRightDirection();
270     int outlineSize = style()->outlineSize();
271     int left = max(borderHalfLeft(true), outlineSize);
272     int right = max(borderHalfRight(true), outlineSize);
273     int top = max(borderHalfTop(true), outlineSize);
274     int bottom = max(borderHalfBottom(true), outlineSize);
275     if ((left && !rtl) || (right && rtl)) {
276         if (RenderTableCell* before = table()->cellBefore(this)) {
277             top = max(top, before->borderHalfTop(true));
278             bottom = max(bottom, before->borderHalfBottom(true));
279         }
280     }
281     if ((left && rtl) || (right && !rtl)) {
282         if (RenderTableCell* after = table()->cellAfter(this)) {
283             top = max(top, after->borderHalfTop(true));
284             bottom = max(bottom, after->borderHalfBottom(true));
285         }
286     }
287     if (top) {
288         if (RenderTableCell* above = table()->cellAbove(this)) {
289             left = max(left, above->borderHalfLeft(true));
290             right = max(right, above->borderHalfRight(true));
291         }
292     }
293     if (bottom) {
294         if (RenderTableCell* below = table()->cellBelow(this)) {
295             left = max(left, below->borderHalfLeft(true));
296             right = max(right, below->borderHalfRight(true));
297         }
298     }
299     left = max(left, -minXVisualOverflow());
300     top = max(top, -minYVisualOverflow());
301     LayoutRect r(-left, - top, left + max(width() + right, maxXVisualOverflow()), top + max(height() + bottom, maxYVisualOverflow()));
302
303     if (RenderView* v = view()) {
304         // FIXME: layoutDelta needs to be applied in parts before/after transforms and
305         // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
306         r.move(v->layoutDelta());
307     }
308     computeRectForRepaint(repaintContainer, r);
309     return r;
310 }
311
312 void RenderTableCell::computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect& r, bool fixed) const
313 {
314     if (repaintContainer == this)
315         return;
316     r.setY(r.y());
317     RenderView* v = view();
318     if ((!v || !v->layoutStateEnabled() || repaintContainer) && parent())
319         r.moveBy(-parentBox()->location()); // Rows are in the same coordinate space, so don't add their offset in.
320     RenderBlock::computeRectForRepaint(repaintContainer, r, fixed);
321 }
322
323 LayoutUnit RenderTableCell::cellBaselinePosition() const
324 {
325     // <http://www.w3.org/TR/2007/CR-CSS21-20070719/tables.html#height-layout>: The baseline of a cell is the baseline of
326     // the first in-flow line box in the cell, or the first in-flow table-row in the cell, whichever comes first. If there
327     // is no such line box or table-row, the baseline is the bottom of content edge of the cell box.
328     LayoutUnit firstLineBaseline = firstLineBoxBaseline();
329     if (firstLineBaseline != -1)
330         return firstLineBaseline;
331     return paddingBefore() + borderBefore() + contentLogicalHeight();
332 }
333
334 void RenderTableCell::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
335 {
336     ASSERT(style()->display() == TABLE_CELL);
337
338     RenderBlock::styleDidChange(diff, oldStyle);
339     setHasBoxDecorations(true);
340
341     if (parent() && section() && oldStyle && style()->height() != oldStyle->height() && rowWasSet())
342         section()->rowLogicalHeightChanged(row());
343
344     // If border was changed, notify table.
345     if (parent()) {
346         RenderTable* table = this->table();
347         if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout()&& oldStyle && oldStyle->border() != style()->border())
348             table->invalidateCollapsedBorders();
349     }
350 }
351
352 // The following rules apply for resolving conflicts and figuring out which border
353 // to use.
354 // (1) Borders with the 'border-style' of 'hidden' take precedence over all other conflicting 
355 // borders. Any border with this value suppresses all borders at this location.
356 // (2) Borders with a style of 'none' have the lowest priority. Only if the border properties of all 
357 // the elements meeting at this edge are 'none' will the border be omitted (but note that 'none' is 
358 // the default value for the border style.)
359 // (3) If none of the styles are 'hidden' and at least one of them is not 'none', then narrow borders 
360 // are discarded in favor of wider ones. If several have the same 'border-width' then styles are preferred 
361 // in this order: 'double', 'solid', 'dashed', 'dotted', 'ridge', 'outset', 'groove', and the lowest: 'inset'.
362 // (4) If border styles differ only in color, then a style set on a cell wins over one on a row, 
363 // which wins over a row group, column, column group and, lastly, table. It is undefined which color 
364 // is used when two elements of the same type disagree.
365 static int compareBorders(const CollapsedBorderValue& border1, const CollapsedBorderValue& border2)
366 {
367     // Sanity check the values passed in. The null border have lowest priority.
368     if (!border2.exists()) {
369         if (!border1.exists())
370             return 0;
371         return 1;
372     }
373     if (!border1.exists())
374         return -1;
375
376     // Rule #1 above.
377     if (border2.style() == BHIDDEN) {
378         if (border1.style() == BHIDDEN)
379             return 0;
380         return -1;
381     }
382     if (border1.style() == BHIDDEN)
383         return 1;
384     
385     // Rule #2 above.  A style of 'none' has lowest priority and always loses to any other border.
386     if (border2.style() == BNONE) {
387         if (border1.style() == BNONE)
388             return 0;
389         return 1;
390     }
391     if (border1.style() == BNONE)
392         return -1;
393
394     // The first part of rule #3 above. Wider borders win.
395     if (border1.width() != border2.width())
396         return border1.width() < border2.width() ? -1 : 1;
397     
398     // The borders have equal width.  Sort by border style.
399     if (border1.style() != border2.style())
400         return border1.style() < border2.style() ? -1 : 1;
401     
402     // The border have the same width and style.  Rely on precedence (cell over row over row group, etc.)
403     if (border1.precedence() == border2.precedence())
404         return 0;
405     return border1.precedence() < border2.precedence() ? -1 : 1;
406 }
407
408 static CollapsedBorderValue chooseBorder(const CollapsedBorderValue& border1, const CollapsedBorderValue& border2)
409 {
410     const CollapsedBorderValue& border = compareBorders(border1, border2) < 0 ? border2 : border1;
411     return border.style() == BHIDDEN ? CollapsedBorderValue() : border;
412 }
413
414 CollapsedBorderValue RenderTableCell::collapsedStartBorder(IncludeBorderColorOrNot includeColor) const
415 {
416     CollapsedBorderValue result = computeCollapsedStartBorder(includeColor);
417     if (includeColor)
418         section()->setCachedCollapsedBorder(this, CBSStart, result);
419     return result;
420 }
421
422 CollapsedBorderValue RenderTableCell::computeCollapsedStartBorder(IncludeBorderColorOrNot includeColor) const
423 {
424     RenderTable* table = this->table();
425     bool isStartColumn = col() == 0;
426
427     // For the start border, we need to check, in order of precedence:
428     // (1) Our start border.
429     int startColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderStartColor, table->style()->direction(), table->style()->writingMode()) : 0;
430     int endColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderEndColor, table->style()->direction(), table->style()->writingMode()) : 0;
431     CollapsedBorderValue result(style()->borderStart(), includeColor ? style()->visitedDependentColor(startColorProperty) : Color(), BCELL);
432
433     // (2) The end border of the preceding cell.
434     if (RenderTableCell* prevCell = table->cellBefore(this)) {
435         CollapsedBorderValue prevCellBorder = CollapsedBorderValue(prevCell->style()->borderEnd(), includeColor ? prevCell->style()->visitedDependentColor(endColorProperty) : Color(), BCELL);
436         result = chooseBorder(prevCellBorder, result);
437         if (!result.exists())
438             return result;
439     } else if (isStartColumn) {
440         // (3) Our row's start border.
441         result = chooseBorder(result, CollapsedBorderValue(parent()->style()->borderStart(), includeColor ? parent()->style()->visitedDependentColor(startColorProperty) : Color(), BROW));
442         if (!result.exists())
443             return result;
444         
445         // (4) Our row group's start border.
446         result = chooseBorder(result, CollapsedBorderValue(section()->style()->borderStart(), includeColor ? section()->style()->visitedDependentColor(startColorProperty) : Color(), BROWGROUP));
447         if (!result.exists())
448             return result;
449     }
450     
451     // (5) Our column and column group's start borders.
452     bool startColEdge;
453     bool endColEdge;
454     RenderTableCol* colElt = table->colElement(col(), &startColEdge, &endColEdge);
455     if (colElt && startColEdge) {
456         result = chooseBorder(result, CollapsedBorderValue(colElt->style()->borderStart(), includeColor ? colElt->style()->visitedDependentColor(startColorProperty) : Color(), BCOL));
457         if (!result.exists())
458             return result;
459         if (colElt->parent()->isTableCol() && !colElt->previousSibling()) {
460             result = chooseBorder(result, CollapsedBorderValue(colElt->parent()->style()->borderStart(), includeColor ? colElt->parent()->style()->visitedDependentColor(startColorProperty) : Color(), BCOLGROUP));
461             if (!result.exists())
462                 return result;
463         }
464     }
465     
466     // (6) The end border of the preceding column.
467     if (!isStartColumn) {
468         colElt = table->colElement(col() -1, &startColEdge, &endColEdge);
469         if (colElt && endColEdge) {
470             CollapsedBorderValue endBorder = CollapsedBorderValue(colElt->style()->borderEnd(), includeColor ? colElt->style()->visitedDependentColor(endColorProperty) : Color(), BCOL);
471             result = chooseBorder(endBorder, result);
472             if (!result.exists())
473                 return result;
474         }
475     } else {
476         // (7) The table's start border.
477         result = chooseBorder(result, CollapsedBorderValue(table->style()->borderStart(), includeColor ? table->style()->visitedDependentColor(startColorProperty) : Color(), BTABLE));
478         if (!result.exists())
479             return result;
480     }
481     
482     return result;
483 }
484
485 CollapsedBorderValue RenderTableCell::collapsedEndBorder(IncludeBorderColorOrNot includeColor) const
486 {
487     CollapsedBorderValue result = computeCollapsedEndBorder(includeColor);
488     if (includeColor)
489         section()->setCachedCollapsedBorder(this, CBSEnd, result);
490     return result;
491 }
492
493 CollapsedBorderValue RenderTableCell::computeCollapsedEndBorder(IncludeBorderColorOrNot includeColor) const
494 {
495     RenderTable* table = this->table();
496     bool isEndColumn = table->colToEffCol(col() + colSpan() - 1) == table->numEffCols() - 1;
497
498     // For end border, we need to check, in order of precedence:
499     // (1) Our end border.
500     int startColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderStartColor, table->style()->direction(), table->style()->writingMode()) : 0;
501     int endColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderEndColor, table->style()->direction(), table->style()->writingMode()) : 0;
502     CollapsedBorderValue result = CollapsedBorderValue(style()->borderEnd(), includeColor ? style()->visitedDependentColor(endColorProperty) : Color(), BCELL);
503     
504     // (2) The start border of the following cell.
505     if (!isEndColumn) {
506         RenderTableCell* nextCell = table->cellAfter(this);
507         if (nextCell && nextCell->style()) {
508             CollapsedBorderValue startBorder = CollapsedBorderValue(nextCell->style()->borderStart(), includeColor ? nextCell->style()->visitedDependentColor(startColorProperty) : Color(), BCELL);
509             result = chooseBorder(result, startBorder);
510             if (!result.exists())
511                 return result;
512         }
513     } else {
514         // (3) Our row's end border.
515         result = chooseBorder(result, CollapsedBorderValue(parent()->style()->borderEnd(), includeColor ? parent()->style()->visitedDependentColor(endColorProperty) : Color(), BROW));
516         if (!result.exists())
517             return result;
518         
519         // (4) Our row group's end border.
520         result = chooseBorder(result, CollapsedBorderValue(section()->style()->borderEnd(), includeColor ? section()->style()->visitedDependentColor(endColorProperty) : Color(), BROWGROUP));
521         if (!result.exists())
522             return result;
523     }
524     
525     // (5) Our column and column group's end borders.
526     bool startColEdge;
527     bool endColEdge;
528     RenderTableCol* colElt = table->colElement(col() + colSpan() - 1, &startColEdge, &endColEdge);
529     if (colElt && endColEdge) {
530         result = chooseBorder(result, CollapsedBorderValue(colElt->style()->borderEnd(), includeColor ? colElt->style()->visitedDependentColor(endColorProperty) : Color(), BCOL));
531         if (!result.exists())
532             return result;
533         if (colElt->parent()->isTableCol() && !colElt->nextSibling()) {
534             result = chooseBorder(result, CollapsedBorderValue(colElt->parent()->style()->borderEnd(), includeColor ? colElt->parent()->style()->visitedDependentColor(endColorProperty) : Color(), BCOLGROUP));
535             if (!result.exists())
536                 return result;
537         }
538     }
539     
540     // (6) The start border of the next column.
541     if (!isEndColumn) {
542         colElt = table->colElement(col() + colSpan(), &startColEdge, &endColEdge);
543         if (colElt && startColEdge) {
544             CollapsedBorderValue startBorder = CollapsedBorderValue(colElt->style()->borderStart(), includeColor ? colElt->style()->visitedDependentColor(startColorProperty) : Color(), BCOL);
545             result = chooseBorder(result, startBorder);
546             if (!result.exists())
547                 return result;
548         }
549     } else {
550         // (7) The table's end border.
551         result = chooseBorder(result, CollapsedBorderValue(table->style()->borderEnd(), includeColor ? table->style()->visitedDependentColor(endColorProperty) : Color(), BTABLE));
552         if (!result.exists())
553             return result;
554     }
555     
556     return result;
557 }
558
559 CollapsedBorderValue RenderTableCell::collapsedBeforeBorder(IncludeBorderColorOrNot includeColor) const
560 {
561     CollapsedBorderValue result = computeCollapsedBeforeBorder(includeColor);
562     if (includeColor)
563         section()->setCachedCollapsedBorder(this, CBSBefore, result);
564     return result;
565 }
566
567 CollapsedBorderValue RenderTableCell::computeCollapsedBeforeBorder(IncludeBorderColorOrNot includeColor) const
568 {
569     RenderTable* table = this->table();
570
571     // For before border, we need to check, in order of precedence:
572     // (1) Our before border.
573     int beforeColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderBeforeColor, table->style()->direction(), table->style()->writingMode()) : 0;
574     int afterColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderAfterColor, table->style()->direction(), table->style()->writingMode()) : 0;
575     CollapsedBorderValue result = CollapsedBorderValue(style()->borderBefore(), includeColor ? style()->visitedDependentColor(beforeColorProperty) : Color(), BCELL);
576     
577     RenderTableCell* prevCell = table->cellAbove(this);
578     if (prevCell) {
579         // (2) A before cell's after border.
580         result = chooseBorder(CollapsedBorderValue(prevCell->style()->borderAfter(), includeColor ? prevCell->style()->visitedDependentColor(afterColorProperty) : Color(), BCELL), result);
581         if (!result.exists())
582             return result;
583     }
584     
585     // (3) Our row's before border.
586     result = chooseBorder(result, CollapsedBorderValue(parent()->style()->borderBefore(), includeColor ? parent()->style()->visitedDependentColor(beforeColorProperty) : Color(), BROW));
587     if (!result.exists())
588         return result;
589     
590     // (4) The previous row's after border.
591     if (prevCell) {
592         RenderObject* prevRow = 0;
593         if (prevCell->section() == section())
594             prevRow = parent()->previousSibling();
595         else
596             prevRow = prevCell->section()->lastChild();
597     
598         if (prevRow) {
599             result = chooseBorder(CollapsedBorderValue(prevRow->style()->borderAfter(), includeColor ? prevRow->style()->visitedDependentColor(afterColorProperty) : Color(), BROW), result);
600             if (!result.exists())
601                 return result;
602         }
603     }
604     
605     // Now check row groups.
606     RenderTableSection* currSection = section();
607     if (!row()) {
608         // (5) Our row group's before border.
609         result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderBefore(), includeColor ? currSection->style()->visitedDependentColor(beforeColorProperty) : Color(), BROWGROUP));
610         if (!result.exists())
611             return result;
612         
613         // (6) Previous row group's after border.
614         currSection = table->sectionAbove(currSection);
615         if (currSection) {
616             result = chooseBorder(CollapsedBorderValue(currSection->style()->borderAfter(), includeColor ? currSection->style()->visitedDependentColor(afterColorProperty) : Color(), BROWGROUP), result);
617             if (!result.exists())
618                 return result;
619         }
620     }
621     
622     if (!currSection) {
623         // (8) Our column and column group's before borders.
624         RenderTableCol* colElt = table->colElement(col());
625         if (colElt) {
626             result = chooseBorder(result, CollapsedBorderValue(colElt->style()->borderBefore(), includeColor ? colElt->style()->visitedDependentColor(beforeColorProperty) : Color(), BCOL));
627             if (!result.exists())
628                 return result;
629             if (colElt->parent()->isTableCol()) {
630                 result = chooseBorder(result, CollapsedBorderValue(colElt->parent()->style()->borderBefore(), includeColor ? colElt->parent()->style()->visitedDependentColor(beforeColorProperty) : Color(), BCOLGROUP));
631                 if (!result.exists())
632                     return result;
633             }
634         }
635         
636         // (9) The table's before border.
637         result = chooseBorder(result, CollapsedBorderValue(table->style()->borderBefore(), includeColor ? table->style()->visitedDependentColor(beforeColorProperty) : Color(), BTABLE));
638         if (!result.exists())
639             return result;
640     }
641     
642     return result;
643 }
644
645 CollapsedBorderValue RenderTableCell::collapsedAfterBorder(IncludeBorderColorOrNot includeColor) const
646 {
647     CollapsedBorderValue result = computeCollapsedAfterBorder(includeColor);
648     if (includeColor)
649         section()->setCachedCollapsedBorder(this, CBSAfter, result);
650     return result;
651 }
652
653 CollapsedBorderValue RenderTableCell::computeCollapsedAfterBorder(IncludeBorderColorOrNot includeColor) const
654 {
655     RenderTable* table = this->table();
656
657     // For after border, we need to check, in order of precedence:
658     // (1) Our after border.
659     int beforeColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderBeforeColor, table->style()->direction(), table->style()->writingMode()) : 0;
660     int afterColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderAfterColor, table->style()->direction(), table->style()->writingMode()) : 0;
661     CollapsedBorderValue result = CollapsedBorderValue(style()->borderAfter(), includeColor ? style()->visitedDependentColor(afterColorProperty) : Color(), BCELL);
662     
663     RenderTableCell* nextCell = table->cellBelow(this);
664     if (nextCell) {
665         // (2) An after cell's before border.
666         result = chooseBorder(result, CollapsedBorderValue(nextCell->style()->borderBefore(), includeColor ? nextCell->style()->visitedDependentColor(beforeColorProperty) : Color(), BCELL));
667         if (!result.exists())
668             return result;
669     }
670     
671     // (3) Our row's after border. (FIXME: Deal with rowspan!)
672     result = chooseBorder(result, CollapsedBorderValue(parent()->style()->borderAfter(), includeColor ? parent()->style()->visitedDependentColor(afterColorProperty) : Color(), BROW));
673     if (!result.exists())
674         return result;
675     
676     // (4) The next row's before border.
677     if (nextCell) {
678         result = chooseBorder(result, CollapsedBorderValue(nextCell->parent()->style()->borderBefore(), includeColor ? nextCell->parent()->style()->visitedDependentColor(beforeColorProperty) : Color(), BROW));
679         if (!result.exists())
680             return result;
681     }
682     
683     // Now check row groups.
684     RenderTableSection* currSection = section();
685     if (row() + rowSpan() >= currSection->numRows()) {
686         // (5) Our row group's after border.
687         result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderAfter(), includeColor ? currSection->style()->visitedDependentColor(afterColorProperty) : Color(), BROWGROUP));
688         if (!result.exists())
689             return result;
690         
691         // (6) Following row group's before border.
692         currSection = table->sectionBelow(currSection);
693         if (currSection) {
694             result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderBefore(), includeColor ? currSection->style()->visitedDependentColor(beforeColorProperty) : Color(), BROWGROUP));
695             if (!result.exists())
696                 return result;
697         }
698     }
699     
700     if (!currSection) {
701         // (8) Our column and column group's after borders.
702         RenderTableCol* colElt = table->colElement(col());
703         if (colElt) {
704             result = chooseBorder(result, CollapsedBorderValue(colElt->style()->borderAfter(), includeColor ? colElt->style()->visitedDependentColor(afterColorProperty) : Color(), BCOL));
705             if (!result.exists()) return result;
706             if (colElt->parent()->isTableCol()) {
707                 result = chooseBorder(result, CollapsedBorderValue(colElt->parent()->style()->borderAfter(), includeColor ? colElt->parent()->style()->visitedDependentColor(afterColorProperty) : Color(), BCOLGROUP));
708                 if (!result.exists())
709                     return result;
710             }
711         }
712         
713         // (9) The table's after border.
714         result = chooseBorder(result, CollapsedBorderValue(table->style()->borderAfter(), includeColor ? table->style()->visitedDependentColor(afterColorProperty) : Color(), BTABLE));
715         if (!result.exists())
716             return result;
717     }
718     
719     return result;    
720 }
721
722 inline CollapsedBorderValue RenderTableCell::cachedCollapsedLeftBorder(RenderStyle* tableStyle) const
723 {
724     if (tableStyle->isHorizontalWritingMode())
725         return tableStyle->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSStart) : section()->cachedCollapsedBorder(this, CBSEnd);
726     return tableStyle->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSAfter) : section()->cachedCollapsedBorder(this, CBSBefore);
727 }
728
729 inline CollapsedBorderValue RenderTableCell::cachedCollapsedRightBorder(RenderStyle* tableStyle) const
730 {
731     if (tableStyle->isHorizontalWritingMode())
732         return tableStyle->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSEnd) : section()->cachedCollapsedBorder(this, CBSStart);
733     return tableStyle->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSBefore) : section()->cachedCollapsedBorder(this, CBSAfter);
734 }
735
736 inline CollapsedBorderValue RenderTableCell::cachedCollapsedTopBorder(RenderStyle* tableStyle) const
737 {
738     if (tableStyle->isHorizontalWritingMode())
739         return tableStyle->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSAfter) : section()->cachedCollapsedBorder(this, CBSBefore);
740     return tableStyle->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSStart) : section()->cachedCollapsedBorder(this, CBSEnd);
741 }
742
743 inline CollapsedBorderValue RenderTableCell::cachedCollapsedBottomBorder(RenderStyle* tableStyle) const
744 {
745     if (tableStyle->isHorizontalWritingMode())
746         return tableStyle->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSBefore) : section()->cachedCollapsedBorder(this, CBSAfter);
747     return tableStyle->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSEnd) : section()->cachedCollapsedBorder(this, CBSStart);
748 }
749
750 int RenderTableCell::borderLeft() const
751 {
752     return table()->collapseBorders() ? borderHalfLeft(false) : RenderBlock::borderLeft();
753 }
754
755 int RenderTableCell::borderRight() const
756 {
757     return table()->collapseBorders() ? borderHalfRight(false) : RenderBlock::borderRight();
758 }
759
760 int RenderTableCell::borderTop() const
761 {
762     return table()->collapseBorders() ? borderHalfTop(false) : RenderBlock::borderTop();
763 }
764
765 int RenderTableCell::borderBottom() const
766 {
767     return table()->collapseBorders() ? borderHalfBottom(false) : RenderBlock::borderBottom();
768 }
769
770 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=46191, make the collapsed border drawing
771 // work with different block flow values instead of being hard-coded to top-to-bottom.
772 int RenderTableCell::borderStart() const
773 {
774     return table()->collapseBorders() ? borderHalfStart(false) : RenderBlock::borderStart();
775 }
776
777 int RenderTableCell::borderEnd() const
778 {
779     return table()->collapseBorders() ? borderHalfEnd(false) : RenderBlock::borderEnd();
780 }
781
782 int RenderTableCell::borderBefore() const
783 {
784     return table()->collapseBorders() ? borderHalfBefore(false) : RenderBlock::borderBefore();
785 }
786
787 int RenderTableCell::borderAfter() const
788 {
789     return table()->collapseBorders() ? borderHalfAfter(false) : RenderBlock::borderAfter();
790 }
791
792 int RenderTableCell::borderHalfLeft(bool outer) const
793 {
794     RenderStyle* tableStyle = table()->style();
795     if (tableStyle->isHorizontalWritingMode())
796         return tableStyle->isLeftToRightDirection() ? borderHalfStart(outer) : borderHalfEnd(outer);
797     return tableStyle->isFlippedBlocksWritingMode() ? borderHalfAfter(outer) : borderHalfBefore(outer);
798 }
799
800 int RenderTableCell::borderHalfRight(bool outer) const
801 {
802     RenderStyle* tableStyle = table()->style();
803     if (tableStyle->isHorizontalWritingMode())
804         return tableStyle->isLeftToRightDirection() ? borderHalfEnd(outer) : borderHalfStart(outer);
805     return tableStyle->isFlippedBlocksWritingMode() ? borderHalfBefore(outer) : borderHalfAfter(outer);
806 }
807
808 int RenderTableCell::borderHalfTop(bool outer) const
809 {
810     RenderStyle* tableStyle = table()->style();
811     if (tableStyle->isHorizontalWritingMode())
812         return tableStyle->isFlippedBlocksWritingMode() ? borderHalfAfter(outer) : borderHalfBefore(outer);
813     return tableStyle->isLeftToRightDirection() ? borderHalfStart(outer) : borderHalfEnd(outer);
814 }
815
816 int RenderTableCell::borderHalfBottom(bool outer) const
817 {
818     RenderStyle* tableStyle = table()->style();
819     if (tableStyle->isHorizontalWritingMode())
820         return tableStyle->isFlippedBlocksWritingMode() ? borderHalfBefore(outer) : borderHalfAfter(outer);
821     return tableStyle->isLeftToRightDirection() ? borderHalfEnd(outer) : borderHalfStart(outer);
822 }
823
824 int RenderTableCell::borderHalfStart(bool outer) const
825 {
826     CollapsedBorderValue border = collapsedStartBorder(DoNotIncludeBorderColor);
827     if (border.exists())
828         return (border.width() + ((table()->style()->isLeftToRightDirection() ^ outer) ? 1 : 0)) / 2; // Give the extra pixel to top and left.
829     return 0;
830 }
831     
832 int RenderTableCell::borderHalfEnd(bool outer) const
833 {
834     CollapsedBorderValue border = collapsedEndBorder(DoNotIncludeBorderColor);
835     if (border.exists())
836         return (border.width() + ((table()->style()->isLeftToRightDirection() ^ outer) ? 0 : 1)) / 2;
837     return 0;
838 }
839
840 int RenderTableCell::borderHalfBefore(bool outer) const
841 {
842     CollapsedBorderValue border = collapsedBeforeBorder(DoNotIncludeBorderColor);
843     if (border.exists())
844         return (border.width() + ((table()->style()->isFlippedBlocksWritingMode() ^ outer) ? 0 : 1)) / 2; // Give the extra pixel to top and left.
845     return 0;
846 }
847
848 int RenderTableCell::borderHalfAfter(bool outer) const
849 {
850     CollapsedBorderValue border = collapsedAfterBorder(DoNotIncludeBorderColor);
851     if (border.exists())
852         return (border.width() + ((table()->style()->isFlippedBlocksWritingMode() ^ outer) ? 1 : 0)) / 2;
853     return 0;
854 }
855
856 void RenderTableCell::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
857 {
858     ASSERT(paintInfo.phase != PaintPhaseCollapsedTableBorders);
859     RenderBlock::paint(paintInfo, paintOffset);
860 }
861
862 static EBorderStyle collapsedBorderStyle(EBorderStyle style)
863 {
864     if (style == OUTSET)
865         return GROOVE;
866     if (style == INSET)
867         return RIDGE;
868     return style;
869 }
870
871 struct CollapsedBorder {
872     CollapsedBorderValue borderValue;
873     BoxSide side;
874     bool shouldPaint;
875     int x1;
876     int y1;
877     int x2;
878     int y2;
879     EBorderStyle style;
880 };
881
882 class CollapsedBorders {
883 public:
884     CollapsedBorders()
885         : m_count(0)
886     {
887     }
888     
889     void addBorder(const CollapsedBorderValue& borderValue, BoxSide borderSide, bool shouldPaint,
890                    int x1, int y1, int x2, int y2, EBorderStyle borderStyle)
891     {
892         if (borderValue.exists() && shouldPaint) {
893             m_borders[m_count].borderValue = borderValue;
894             m_borders[m_count].side = borderSide;
895             m_borders[m_count].shouldPaint = shouldPaint;
896             m_borders[m_count].x1 = x1;
897             m_borders[m_count].x2 = x2;
898             m_borders[m_count].y1 = y1;
899             m_borders[m_count].y2 = y2;
900             m_borders[m_count].style = borderStyle;
901             m_count++;
902         }
903     }
904
905     CollapsedBorder* nextBorder()
906     {
907         for (unsigned i = 0; i < m_count; i++) {
908             if (m_borders[i].borderValue.exists() && m_borders[i].shouldPaint) {
909                 m_borders[i].shouldPaint = false;
910                 return &m_borders[i];
911             }
912         }
913         
914         return 0;
915     }
916     
917     CollapsedBorder m_borders[4];
918     unsigned m_count;
919 };
920
921 static void addBorderStyle(RenderTable::CollapsedBorderValues& borderValues,
922                            CollapsedBorderValue borderValue)
923 {
924     if (!borderValue.exists())
925         return;
926     size_t count = borderValues.size();
927     for (size_t i = 0; i < count; ++i)
928         if (borderValues[i].isSameIgnoringColor(borderValue))
929             return;
930     borderValues.append(borderValue);
931 }
932
933 void RenderTableCell::collectBorderValues(RenderTable::CollapsedBorderValues& borderValues) const
934 {
935     addBorderStyle(borderValues, collapsedStartBorder());
936     addBorderStyle(borderValues, collapsedEndBorder());
937     addBorderStyle(borderValues, collapsedBeforeBorder());
938     addBorderStyle(borderValues, collapsedAfterBorder());
939 }
940
941 static int compareBorderValuesForQSort(const void* pa, const void* pb)
942 {
943     const CollapsedBorderValue* a = static_cast<const CollapsedBorderValue*>(pa);
944     const CollapsedBorderValue* b = static_cast<const CollapsedBorderValue*>(pb);
945     if (a->isSameIgnoringColor(*b))
946         return 0;
947     return compareBorders(*a, *b);
948 }
949
950 void RenderTableCell::sortBorderValues(RenderTable::CollapsedBorderValues& borderValues)
951 {
952     qsort(borderValues.data(), borderValues.size(), sizeof(CollapsedBorderValue),
953         compareBorderValuesForQSort);
954 }
955
956 void RenderTableCell::paintCollapsedBorders(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
957 {
958     ASSERT(paintInfo.phase == PaintPhaseCollapsedTableBorders);
959
960     if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE)
961         return;
962
963     LayoutRect localRepaintRect = paintInfo.rect;
964     localRepaintRect.inflate(maximalOutlineSize(paintInfo.phase));
965
966     LayoutRect paintRect = LayoutRect(paintOffset + location(), size());
967     if (paintRect.y() - table()->outerBorderTop() >= localRepaintRect.maxY())
968         return;
969
970     if (paintRect.maxY() + table()->outerBorderBottom() <= localRepaintRect.y())
971         return;
972
973     GraphicsContext* graphicsContext = paintInfo.context;
974     if (!table()->currentBorderValue() || graphicsContext->paintingDisabled())
975         return;
976
977     RenderStyle* tableStyle = table()->style();
978     CollapsedBorderValue leftVal = cachedCollapsedLeftBorder(tableStyle);
979     CollapsedBorderValue rightVal = cachedCollapsedRightBorder(tableStyle);
980     CollapsedBorderValue topVal = cachedCollapsedTopBorder(tableStyle);
981     CollapsedBorderValue bottomVal = cachedCollapsedBottomBorder(tableStyle);
982      
983     // Adjust our x/y/width/height so that we paint the collapsed borders at the correct location.
984     int topWidth = topVal.width();
985     int bottomWidth = bottomVal.width();
986     int leftWidth = leftVal.width();
987     int rightWidth = rightVal.width();
988
989     IntRect borderRect = pixelSnappedIntRect(paintRect.x() - leftWidth / 2,
990             paintRect.y() - topWidth / 2,
991             paintRect.width() + leftWidth / 2 + (rightWidth + 1) / 2,
992             paintRect.height() + topWidth / 2 + (bottomWidth + 1) / 2);
993
994     EBorderStyle topStyle = collapsedBorderStyle(topVal.style());
995     EBorderStyle bottomStyle = collapsedBorderStyle(bottomVal.style());
996     EBorderStyle leftStyle = collapsedBorderStyle(leftVal.style());
997     EBorderStyle rightStyle = collapsedBorderStyle(rightVal.style());
998     
999     bool renderTop = topStyle > BHIDDEN && !topVal.isTransparent();
1000     bool renderBottom = bottomStyle > BHIDDEN && !bottomVal.isTransparent();
1001     bool renderLeft = leftStyle > BHIDDEN && !leftVal.isTransparent();
1002     bool renderRight = rightStyle > BHIDDEN && !rightVal.isTransparent();
1003
1004     // We never paint diagonals at the joins.  We simply let the border with the highest
1005     // precedence paint on top of borders with lower precedence.  
1006     CollapsedBorders borders;
1007     borders.addBorder(topVal, BSTop, renderTop, borderRect.x(), borderRect.y(), borderRect.maxX(), borderRect.y() + topWidth, topStyle);
1008     borders.addBorder(bottomVal, BSBottom, renderBottom, borderRect.x(), borderRect.maxY() - bottomWidth, borderRect.maxX(), borderRect.maxY(), bottomStyle);
1009     borders.addBorder(leftVal, BSLeft, renderLeft, borderRect.x(), borderRect.y(), borderRect.x() + leftWidth, borderRect.maxY(), leftStyle);
1010     borders.addBorder(rightVal, BSRight, renderRight, borderRect.maxX() - rightWidth, borderRect.y(), borderRect.maxX(), borderRect.maxY(), rightStyle);
1011
1012     bool antialias = shouldAntialiasLines(graphicsContext);
1013     
1014     for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) {
1015         if (border->borderValue.isSameIgnoringColor(*table()->currentBorderValue()))
1016             drawLineForBoxSide(graphicsContext, border->x1, border->y1, border->x2, border->y2, border->side, 
1017                                border->borderValue.color(), border->style, 0, 0, antialias);
1018     }
1019 }
1020
1021 void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, const LayoutPoint& paintOffset, RenderObject* backgroundObject)
1022 {
1023     if (!paintInfo.shouldPaintWithinRoot(this))
1024         return;
1025
1026     if (!backgroundObject)
1027         return;
1028
1029     if (style()->visibility() != VISIBLE)
1030         return;
1031
1032     RenderTable* tableElt = table();
1033     if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
1034         return;
1035
1036     LayoutPoint adjustedPaintOffset = paintOffset;
1037     if (backgroundObject != this)
1038         adjustedPaintOffset.moveBy(location());
1039
1040     Color c = backgroundObject->style()->visitedDependentColor(CSSPropertyBackgroundColor);
1041     const FillLayer* bgLayer = backgroundObject->style()->backgroundLayers();
1042
1043     if (bgLayer->hasImage() || c.isValid()) {
1044         // We have to clip here because the background would paint
1045         // on top of the borders otherwise.  This only matters for cells and rows.
1046         bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == this || backgroundObject == parent()) && tableElt->collapseBorders();
1047         GraphicsContextStateSaver stateSaver(*paintInfo.context, shouldClip);
1048         if (shouldClip) {
1049             LayoutRect clipRect(adjustedPaintOffset.x() + borderLeft(), adjustedPaintOffset.y() + borderTop(),
1050                 width() - borderLeft() - borderRight(), height() - borderTop() - borderBottom());
1051             paintInfo.context->clip(clipRect);
1052         }
1053         paintFillLayers(paintInfo, c, bgLayer, LayoutRect(adjustedPaintOffset, size()), BackgroundBleedNone, CompositeSourceOver, backgroundObject);
1054     }
1055 }
1056
1057 void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1058 {
1059     if (!paintInfo.shouldPaintWithinRoot(this))
1060         return;
1061
1062     RenderTable* tableElt = table();
1063     if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
1064         return;
1065
1066     LayoutRect paintRect = LayoutRect(paintOffset, size());
1067     paintBoxShadow(paintInfo, paintRect, style(), Normal);
1068     
1069     // Paint our cell background.
1070     paintBackgroundsBehindCell(paintInfo, paintOffset, this);
1071
1072     paintBoxShadow(paintInfo, paintRect, style(), Inset);
1073
1074     if (!style()->hasBorder() || tableElt->collapseBorders())
1075         return;
1076
1077     paintBorder(paintInfo, paintRect, style());
1078 }
1079
1080 void RenderTableCell::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1081 {
1082     if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
1083         return;
1084
1085     RenderTable* tableElt = table();
1086     if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
1087         return;
1088    
1089     paintMaskImages(paintInfo, LayoutRect(paintOffset, size()));
1090 }
1091
1092 bool RenderTableCell::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const
1093 {
1094     return false;
1095 }
1096
1097 void RenderTableCell::scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged)
1098 {
1099     LayoutUnit scrollbarHeight = scrollbarLogicalHeight();
1100     if (!scrollbarHeight)
1101         return; // Not sure if we should be doing something when a scrollbar goes away or not.
1102     
1103     // We only care if the scrollbar that affects our intrinsic padding has been added.
1104     if ((isHorizontalWritingMode() && !horizontalScrollbarChanged) ||
1105         (!isHorizontalWritingMode() && !verticalScrollbarChanged))
1106         return;
1107
1108     // Shrink our intrinsic padding as much as possible to accommodate the scrollbar.
1109     if (style()->verticalAlign() == MIDDLE) {
1110         LayoutUnit totalHeight = logicalHeight();
1111         LayoutUnit heightWithoutIntrinsicPadding = totalHeight - intrinsicPaddingBefore() - intrinsicPaddingAfter();
1112         totalHeight -= scrollbarHeight;
1113         LayoutUnit newBeforePadding = (totalHeight - heightWithoutIntrinsicPadding) / 2;
1114         LayoutUnit newAfterPadding = totalHeight - heightWithoutIntrinsicPadding - newBeforePadding;
1115         setIntrinsicPaddingBefore(newBeforePadding);
1116         setIntrinsicPaddingAfter(newAfterPadding);
1117     } else
1118         setIntrinsicPaddingAfter(intrinsicPaddingAfter() - scrollbarHeight);
1119 }
1120
1121 } // namespace WebCore