Renderers should receive their style at construction.
[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 "StylePropertySet.h"
37 #include "TransformState.h"
38 #include <wtf/StackStats.h>
39
40 #if ENABLE(MATHML)
41 #include "MathMLElement.h"
42 #include "MathMLNames.h"
43 #endif
44
45 using namespace std;
46
47 namespace WebCore {
48
49 using namespace HTMLNames;
50
51 struct SameSizeAsRenderTableCell : public RenderBlockFlow {
52     unsigned bitfields;
53     int paddings[2];
54 };
55
56 COMPILE_ASSERT(sizeof(RenderTableCell) == sizeof(SameSizeAsRenderTableCell), RenderTableCell_should_stay_small);
57 COMPILE_ASSERT(sizeof(CollapsedBorderValue) == 8, CollapsedBorderValue_should_stay_small);
58
59 RenderTableCell::RenderTableCell(Element& element, PassRef<RenderStyle> style)
60     : RenderBlockFlow(element, std::move(style))
61     , m_column(unsetColumnIndex)
62     , m_cellWidthChanged(false)
63     , m_intrinsicPaddingBefore(0)
64     , m_intrinsicPaddingAfter(0)
65 {
66     // We only update the flags when notified of DOM changes in colSpanOrRowSpanChanged()
67     // so we need to set their initial values here in case something asks for colSpan()/rowSpan() before then.
68     updateColAndRowSpanFlags();
69 }
70
71 RenderTableCell::RenderTableCell(Document& document, PassRef<RenderStyle> style)
72     : RenderBlockFlow(document, std::move(style))
73     , m_column(unsetColumnIndex)
74     , m_cellWidthChanged(false)
75     , m_hasColSpan(false)
76     , m_hasRowSpan(false)
77     , m_intrinsicPaddingBefore(0)
78     , m_intrinsicPaddingAfter(0)
79 {
80 }
81
82 void RenderTableCell::willBeRemovedFromTree()
83 {
84     RenderBlockFlow::willBeRemovedFromTree();
85
86     section()->setNeedsCellRecalc();
87     section()->removeCachedCollapsedBorders(this);
88 }
89
90 unsigned RenderTableCell::parseColSpanFromDOM() const
91 {
92     ASSERT(element());
93     if (element()->hasTagName(tdTag) || element()->hasTagName(thTag))
94         return min<unsigned>(toHTMLTableCellElement(element())->colSpan(), maxColumnIndex);
95 #if ENABLE(MATHML)
96     if (element()->hasTagName(MathMLNames::mtdTag))
97         return min<unsigned>(toMathMLElement(element())->colSpan(), maxColumnIndex);
98 #endif
99     return 1;
100 }
101
102 unsigned RenderTableCell::parseRowSpanFromDOM() const
103 {
104     ASSERT(element());
105     if (element()->hasTagName(tdTag) || element()->hasTagName(thTag))
106         return min<unsigned>(toHTMLTableCellElement(element())->rowSpan(), maxRowIndex);
107 #if ENABLE(MATHML)
108     if (element()->hasTagName(MathMLNames::mtdTag))
109         return min<unsigned>(toMathMLElement(element())->rowSpan(), maxRowIndex);
110 #endif
111     return 1;
112 }
113
114 void RenderTableCell::updateColAndRowSpanFlags()
115 {
116     // The vast majority of table cells do not have a colspan or rowspan,
117     // so we keep a bool to know if we need to bother reading from the DOM.
118     m_hasColSpan = element() && parseColSpanFromDOM() != 1;
119     m_hasRowSpan = element() && parseRowSpanFromDOM() != 1;
120 }
121
122 void RenderTableCell::colSpanOrRowSpanChanged()
123 {
124     ASSERT(element());
125 #if ENABLE(MATHML)
126     ASSERT(element()->hasTagName(tdTag) || element()->hasTagName(thTag) || element()->hasTagName(MathMLNames::mtdTag));
127 #else
128     ASSERT(element()->hasTagName(tdTag) || element()->hasTagName(thTag));
129 #endif
130
131     updateColAndRowSpanFlags();
132
133     // FIXME: I suspect that we could return early here if !m_hasColSpan && !m_hasRowSpan.
134
135     setNeedsLayoutAndPrefWidthsRecalc();
136     if (parent() && section())
137         section()->setNeedsCellRecalc();
138 }
139
140 Length RenderTableCell::logicalWidthFromColumns(RenderTableCol* firstColForThisCell, Length widthFromStyle) const
141 {
142     ASSERT(firstColForThisCell && firstColForThisCell == table()->colElement(col()));
143     RenderTableCol* tableCol = firstColForThisCell;
144
145     unsigned colSpanCount = colSpan();
146     int colWidthSum = 0;
147     for (unsigned i = 1; i <= colSpanCount; i++) {
148         Length colWidth = tableCol->style()->logicalWidth();
149
150         // Percentage value should be returned only for colSpan == 1.
151         // Otherwise we return original width for the cell.
152         if (!colWidth.isFixed()) {
153             if (colSpanCount > 1)
154                 return widthFromStyle;
155             return colWidth;
156         }
157
158         colWidthSum += colWidth.value();
159         tableCol = tableCol->nextColumn();
160         // If no next <col> tag found for the span we just return what we have for now.
161         if (!tableCol)
162             break;
163     }
164
165     // Column widths specified on <col> apply to the border box of the cell, see bug 8126.
166     // FIXME: Why is border/padding ignored in the negative width case?
167     if (colWidthSum > 0)
168         return Length(max(0, colWidthSum - borderAndPaddingLogicalWidth().ceil()), Fixed);
169     return Length(colWidthSum, Fixed);
170 }
171
172 void RenderTableCell::computePreferredLogicalWidths()
173 {
174     // 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
175     // cells are added, but relayout can cause the cells to be freed, leaving stale pointers in the sections'
176     // grids.  We must refresh those grids before the child cells try to use them.
177     table()->recalcSectionsIfNeeded();
178
179     RenderBlockFlow::computePreferredLogicalWidths();
180     if (element() && style()->autoWrap()) {
181         // See if nowrap was set.
182         Length w = styleOrColLogicalWidth();
183         String nowrap = element()->getAttribute(nowrapAttr);
184         if (!nowrap.isNull() && w.isFixed())
185             // Nowrap is set, but we didn't actually use it because of the
186             // fixed width set on the cell.  Even so, it is a WinIE/Moz trait
187             // to make the minwidth of the cell into the fixed width.  They do this
188             // even in strict mode, so do not make this a quirk.  Affected the top
189             // of hiptop.com.
190             m_minPreferredLogicalWidth = max<LayoutUnit>(w.value(), m_minPreferredLogicalWidth);
191     }
192 }
193
194 void RenderTableCell::computeIntrinsicPadding(int rowHeight)
195 {
196     int oldIntrinsicPaddingBefore = intrinsicPaddingBefore();
197     int oldIntrinsicPaddingAfter = intrinsicPaddingAfter();
198     int logicalHeightWithoutIntrinsicPadding = pixelSnappedLogicalHeight() - oldIntrinsicPaddingBefore - oldIntrinsicPaddingAfter;
199
200     int intrinsicPaddingBefore = 0;
201     switch (style()->verticalAlign()) {
202     case SUB:
203     case SUPER:
204     case TEXT_TOP:
205     case TEXT_BOTTOM:
206     case LENGTH:
207     case BASELINE: {
208         LayoutUnit baseline = cellBaselinePosition();
209         if (baseline > borderAndPaddingBefore())
210             intrinsicPaddingBefore = section()->rowBaseline(rowIndex()) - (baseline - oldIntrinsicPaddingBefore);
211         break;
212     }
213     case TOP:
214         break;
215     case MIDDLE:
216         intrinsicPaddingBefore = (rowHeight - logicalHeightWithoutIntrinsicPadding) / 2;
217         break;
218     case BOTTOM:
219         intrinsicPaddingBefore = rowHeight - logicalHeightWithoutIntrinsicPadding;
220         break;
221     case BASELINE_MIDDLE:
222         break;
223     }
224
225     int intrinsicPaddingAfter = rowHeight - logicalHeightWithoutIntrinsicPadding - intrinsicPaddingBefore;
226     setIntrinsicPaddingBefore(intrinsicPaddingBefore);
227     setIntrinsicPaddingAfter(intrinsicPaddingAfter);
228
229     // FIXME: Changing an intrinsic padding shouldn't trigger a relayout as it only shifts the cell inside the row but
230     // doesn't change the logical height.
231     if (intrinsicPaddingBefore != oldIntrinsicPaddingBefore || intrinsicPaddingAfter != oldIntrinsicPaddingAfter)
232         setNeedsLayout(MarkOnlyThis);
233 }
234
235 void RenderTableCell::updateLogicalWidth()
236 {
237 }
238
239 void RenderTableCell::setCellLogicalWidth(int tableLayoutLogicalWidth)
240 {
241     if (tableLayoutLogicalWidth == logicalWidth())
242         return;
243
244     setNeedsLayout(MarkOnlyThis);
245     row()->setChildNeedsLayout(MarkOnlyThis);
246
247     if (!table()->selfNeedsLayout() && checkForRepaintDuringLayout())
248         repaint();
249
250     setLogicalWidth(tableLayoutLogicalWidth);
251     setCellWidthChanged(true);
252 }
253
254 void RenderTableCell::layout()
255 {
256     StackStats::LayoutCheckPoint layoutCheckPoint;
257     updateFirstLetter();
258
259     int oldCellBaseline = cellBaselinePosition();
260     layoutBlock(cellWidthChanged());
261
262     // If we have replaced content, the intrinsic height of our content may have changed since the last time we laid out. If that's the case the intrinsic padding we used
263     // for layout (the padding required to push the contents of the cell down to the row's baseline) is included in our new height and baseline and makes both
264     // of them wrong. So if our content's intrinsic height has changed push the new content up into the intrinsic padding and relayout so that the rest of
265     // table and row layout can use the correct baseline and height for this cell.
266     if (isBaselineAligned() && section()->rowBaseline(rowIndex()) && cellBaselinePosition() > section()->rowBaseline(rowIndex())) {
267         int newIntrinsicPaddingBefore = max<LayoutUnit>(0, intrinsicPaddingBefore() - max<LayoutUnit>(0, cellBaselinePosition() - oldCellBaseline));
268         setIntrinsicPaddingBefore(newIntrinsicPaddingBefore);
269         setNeedsLayout(MarkOnlyThis);
270         layoutBlock(cellWidthChanged());
271     }
272
273     setCellWidthChanged(false);
274 }
275
276 LayoutUnit RenderTableCell::paddingTop() const
277 {
278     int result = computedCSSPaddingTop();
279     if (!isHorizontalWritingMode())
280         return result;
281     return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter());
282 }
283
284 LayoutUnit RenderTableCell::paddingBottom() const
285 {
286     int result = computedCSSPaddingBottom();
287     if (!isHorizontalWritingMode())
288         return result;
289     return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore());
290 }
291
292 LayoutUnit RenderTableCell::paddingLeft() const
293 {
294     int result = computedCSSPaddingLeft();
295     if (isHorizontalWritingMode())
296         return result;
297     return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter());
298 }
299
300 LayoutUnit RenderTableCell::paddingRight() const
301 {   
302     int result = computedCSSPaddingRight();
303     if (isHorizontalWritingMode())
304         return result;
305     return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore());
306 }
307
308 LayoutUnit RenderTableCell::paddingBefore() const
309 {
310     return static_cast<int>(computedCSSPaddingBefore()) + intrinsicPaddingBefore();
311 }
312
313 LayoutUnit RenderTableCell::paddingAfter() const
314 {
315     return static_cast<int>(computedCSSPaddingAfter()) + intrinsicPaddingAfter();
316 }
317
318 void RenderTableCell::setOverrideLogicalContentHeightFromRowHeight(LayoutUnit rowHeight)
319 {
320     clearIntrinsicPadding();
321     setOverrideLogicalContentHeight(max<LayoutUnit>(0, rowHeight - borderAndPaddingLogicalHeight()));
322 }
323
324 LayoutSize RenderTableCell::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
325 {
326     ASSERT(o == container());
327
328     LayoutSize offset = RenderBlockFlow::offsetFromContainer(o, point, offsetDependsOnPoint);
329     if (parent())
330         offset -= parentBox()->locationOffset();
331
332     return offset;
333 }
334
335 LayoutRect RenderTableCell::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
336 {
337     // If the table grid is dirty, we cannot get reliable information about adjoining cells,
338     // so we ignore outside borders. This should not be a problem because it means that
339     // the table is going to recalculate the grid, relayout and repaint its current rect, which
340     // includes any outside borders of this cell.
341     if (!table()->collapseBorders() || table()->needsSectionRecalc())
342         return RenderBlockFlow::clippedOverflowRectForRepaint(repaintContainer);
343
344     bool rtl = !styleForCellFlow()->isLeftToRightDirection();
345     int outlineSize = style()->outlineSize();
346     int left = max(borderHalfLeft(true), outlineSize);
347     int right = max(borderHalfRight(true), outlineSize);
348     int top = max(borderHalfTop(true), outlineSize);
349     int bottom = max(borderHalfBottom(true), outlineSize);
350     if ((left && !rtl) || (right && rtl)) {
351         if (RenderTableCell* before = table()->cellBefore(this)) {
352             top = max(top, before->borderHalfTop(true));
353             bottom = max(bottom, before->borderHalfBottom(true));
354         }
355     }
356     if ((left && rtl) || (right && !rtl)) {
357         if (RenderTableCell* after = table()->cellAfter(this)) {
358             top = max(top, after->borderHalfTop(true));
359             bottom = max(bottom, after->borderHalfBottom(true));
360         }
361     }
362     if (top) {
363         if (RenderTableCell* above = table()->cellAbove(this)) {
364             left = max(left, above->borderHalfLeft(true));
365             right = max(right, above->borderHalfRight(true));
366         }
367     }
368     if (bottom) {
369         if (RenderTableCell* below = table()->cellBelow(this)) {
370             left = max(left, below->borderHalfLeft(true));
371             right = max(right, below->borderHalfRight(true));
372         }
373     }
374     LayoutPoint location(max<LayoutUnit>(left, -visualOverflowRect().x()), max<LayoutUnit>(top, -visualOverflowRect().y()));
375     LayoutRect r(-location.x(), -location.y(), location.x() + max(width() + right, visualOverflowRect().maxX()), location.y() + max(height() + bottom, visualOverflowRect().maxY()));
376
377     // FIXME: layoutDelta needs to be applied in parts before/after transforms and
378     // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
379     r.move(view().layoutDelta());
380
381     computeRectForRepaint(repaintContainer, r);
382     return r;
383 }
384
385 void RenderTableCell::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& r, bool fixed) const
386 {
387     if (repaintContainer == this)
388         return;
389     r.setY(r.y());
390     if ((!view().layoutStateEnabled() || repaintContainer) && parent())
391         r.moveBy(-parentBox()->location()); // Rows are in the same coordinate space, so don't add their offset in.
392     RenderBlockFlow::computeRectForRepaint(repaintContainer, r, fixed);
393 }
394
395 LayoutUnit RenderTableCell::cellBaselinePosition() const
396 {
397     // <http://www.w3.org/TR/2007/CR-CSS21-20070719/tables.html#height-layout>: The baseline of a cell is the baseline of
398     // the first in-flow line box in the cell, or the first in-flow table-row in the cell, whichever comes first. If there
399     // is no such line box or table-row, the baseline is the bottom of content edge of the cell box.
400     LayoutUnit baseline = firstLineBaseline();
401     if (baseline != -1)
402         return baseline;
403     return borderAndPaddingBefore() + contentLogicalHeight();
404 }
405
406 void RenderTableCell::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
407 {
408     ASSERT(style()->display() == TABLE_CELL);
409     ASSERT(!row() || row()->rowIndexWasSet());
410
411     RenderBlockFlow::styleDidChange(diff, oldStyle);
412     setHasBoxDecorations(true);
413
414     if (parent() && section() && oldStyle && style()->height() != oldStyle->height())
415         section()->rowLogicalHeightChanged(rowIndex());
416
417     // Our intrinsic padding pushes us down to align with the baseline of other cells on the row. If our vertical-align
418     // has changed then so will the padding needed to align with other cells - clear it so we can recalculate it from scratch.
419     if (oldStyle && style()->verticalAlign() != oldStyle->verticalAlign())
420         clearIntrinsicPadding();
421
422     // If border was changed, notify table.
423     if (parent()) {
424         RenderTable* table = this->table();
425         if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout()&& oldStyle && oldStyle->border() != style()->border())
426             table->invalidateCollapsedBorders();
427     }
428 }
429
430 // The following rules apply for resolving conflicts and figuring out which border
431 // to use.
432 // (1) Borders with the 'border-style' of 'hidden' take precedence over all other conflicting 
433 // borders. Any border with this value suppresses all borders at this location.
434 // (2) Borders with a style of 'none' have the lowest priority. Only if the border properties of all 
435 // the elements meeting at this edge are 'none' will the border be omitted (but note that 'none' is 
436 // the default value for the border style.)
437 // (3) If none of the styles are 'hidden' and at least one of them is not 'none', then narrow borders 
438 // are discarded in favor of wider ones. If several have the same 'border-width' then styles are preferred 
439 // in this order: 'double', 'solid', 'dashed', 'dotted', 'ridge', 'outset', 'groove', and the lowest: 'inset'.
440 // (4) If border styles differ only in color, then a style set on a cell wins over one on a row, 
441 // which wins over a row group, column, column group and, lastly, table. It is undefined which color 
442 // is used when two elements of the same type disagree.
443 static int compareBorders(const CollapsedBorderValue& border1, const CollapsedBorderValue& border2)
444 {
445     // Sanity check the values passed in. The null border have lowest priority.
446     if (!border2.exists()) {
447         if (!border1.exists())
448             return 0;
449         return 1;
450     }
451     if (!border1.exists())
452         return -1;
453
454     // Rule #1 above.
455     if (border2.style() == BHIDDEN) {
456         if (border1.style() == BHIDDEN)
457             return 0;
458         return -1;
459     }
460     if (border1.style() == BHIDDEN)
461         return 1;
462     
463     // Rule #2 above.  A style of 'none' has lowest priority and always loses to any other border.
464     if (border2.style() == BNONE) {
465         if (border1.style() == BNONE)
466             return 0;
467         return 1;
468     }
469     if (border1.style() == BNONE)
470         return -1;
471
472     // The first part of rule #3 above. Wider borders win.
473     if (border1.width() != border2.width())
474         return border1.width() < border2.width() ? -1 : 1;
475     
476     // The borders have equal width.  Sort by border style.
477     if (border1.style() != border2.style())
478         return border1.style() < border2.style() ? -1 : 1;
479     
480     // The border have the same width and style.  Rely on precedence (cell over row over row group, etc.)
481     if (border1.precedence() == border2.precedence())
482         return 0;
483     return border1.precedence() < border2.precedence() ? -1 : 1;
484 }
485
486 static CollapsedBorderValue chooseBorder(const CollapsedBorderValue& border1, const CollapsedBorderValue& border2)
487 {
488     const CollapsedBorderValue& border = compareBorders(border1, border2) < 0 ? border2 : border1;
489     return border.style() == BHIDDEN ? CollapsedBorderValue() : border;
490 }
491
492 bool RenderTableCell::hasStartBorderAdjoiningTable() const
493 {
494     bool isStartColumn = !col();
495     bool isEndColumn = table()->colToEffCol(col() + colSpan() - 1) == table()->numEffCols() - 1;
496     bool hasSameDirectionAsTable = hasSameDirectionAs(section());
497
498     // The table direction determines the row direction. In mixed directionality, we cannot guarantee that
499     // we have a common border with the table (think a ltr table with rtl start cell).
500     return (isStartColumn && hasSameDirectionAsTable) || (isEndColumn && !hasSameDirectionAsTable);
501 }
502
503 bool RenderTableCell::hasEndBorderAdjoiningTable() const
504 {
505     bool isStartColumn = !col();
506     bool isEndColumn = table()->colToEffCol(col() + colSpan() - 1) == table()->numEffCols() - 1;
507     bool hasSameDirectionAsTable = hasSameDirectionAs(section());
508
509     // The table direction determines the row direction. In mixed directionality, we cannot guarantee that
510     // we have a common border with the table (think a ltr table with ltr end cell).
511     return (isStartColumn && !hasSameDirectionAsTable) || (isEndColumn && hasSameDirectionAsTable);
512 }
513
514 CollapsedBorderValue RenderTableCell::collapsedStartBorder(IncludeBorderColorOrNot includeColor) const
515 {
516     CollapsedBorderValue result = computeCollapsedStartBorder(includeColor);
517     if (includeColor)
518         section()->setCachedCollapsedBorder(this, CBSStart, result);
519     return result;
520 }
521
522 CollapsedBorderValue RenderTableCell::computeCollapsedStartBorder(IncludeBorderColorOrNot includeColor) const
523 {
524     RenderTable* table = this->table();
525
526     // For the start border, we need to check, in order of precedence:
527     // (1) Our start border.
528     int startColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderStartColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
529     int endColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderEndColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
530     CollapsedBorderValue result(style()->borderStart(), includeColor ? style()->visitedDependentColor(startColorProperty) : Color(), BCELL);
531
532     // (2) The end border of the preceding cell.
533     RenderTableCell* cellBefore = table->cellBefore(this);
534     if (cellBefore) {
535         CollapsedBorderValue cellBeforeAdjoiningBorder = CollapsedBorderValue(cellBefore->borderAdjoiningCellAfter(this), includeColor ? cellBefore->style()->visitedDependentColor(endColorProperty) : Color(), BCELL);
536         // |result| should be the 2nd argument as |cellBefore| should win in case of equality per CSS 2.1 (Border conflict resolution, point 4).
537         result = chooseBorder(cellBeforeAdjoiningBorder, result);
538         if (!result.exists())
539             return result;
540     }
541
542     bool startBorderAdjoinsTable = hasStartBorderAdjoiningTable();
543     if (startBorderAdjoinsTable) {
544         // (3) Our row's start border.
545         result = chooseBorder(result, CollapsedBorderValue(row()->borderAdjoiningStartCell(this), includeColor ? parent()->style()->visitedDependentColor(startColorProperty) : Color(), BROW));
546         if (!result.exists())
547             return result;
548
549         // (4) Our row group's start border.
550         result = chooseBorder(result, CollapsedBorderValue(section()->borderAdjoiningStartCell(this), includeColor ? section()->style()->visitedDependentColor(startColorProperty) : Color(), BROWGROUP));
551         if (!result.exists())
552             return result;
553     }
554     
555     // (5) Our column and column group's start borders.
556     bool startColEdge;
557     bool endColEdge;
558     if (RenderTableCol* colElt = table->colElement(col(), &startColEdge, &endColEdge)) {
559         if (colElt->isTableColumnGroup() && startColEdge) {
560             // The |colElt| is a column group and is also the first colgroup (in case of spanned colgroups).
561             result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellStartBorder(this), includeColor ? colElt->style()->visitedDependentColor(startColorProperty) : Color(), BCOLGROUP));
562             if (!result.exists())
563                 return result;
564         } else if (!colElt->isTableColumnGroup()) {
565             // We first consider the |colElt| and irrespective of whether it is a spanned col or not, we apply
566             // its start border. This is as per HTML5 which states that: "For the purposes of the CSS table model,
567             // the col element is expected to be treated as if it was present as many times as its span attribute specifies".
568             result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellStartBorder(this), includeColor ? colElt->style()->visitedDependentColor(startColorProperty) : Color(), BCOL));
569             if (!result.exists())
570                 return result;
571             // Next, apply the start border of the enclosing colgroup but only if it is adjacent to the cell's edge.
572             if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroupIfAdjacentBefore()) {
573                 result = chooseBorder(result, CollapsedBorderValue(enclosingColumnGroup->borderAdjoiningCellStartBorder(this), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(startColorProperty) : Color(), BCOLGROUP));
574                 if (!result.exists())
575                     return result;
576             }
577         }
578     }
579     
580     // (6) The end border of the preceding column.
581     if (cellBefore) {
582         if (RenderTableCol* colElt = table->colElement(col() - 1, &startColEdge, &endColEdge)) {
583             if (colElt->isTableColumnGroup() && endColEdge) {
584                 // The element is a colgroup and is also the last colgroup (in case of spanned colgroups).
585                 result = chooseBorder(CollapsedBorderValue(colElt->borderAdjoiningCellAfter(this), includeColor ? colElt->style()->visitedDependentColor(endColorProperty) : Color(), BCOLGROUP), result);
586                 if (!result.exists())
587                     return result;
588             } else if (colElt->isTableColumn()) {
589                 // Resolve the collapsing border against the col's border ignoring any 'span' as per HTML5.
590                 result = chooseBorder(CollapsedBorderValue(colElt->borderAdjoiningCellAfter(this), includeColor ? colElt->style()->visitedDependentColor(endColorProperty) : Color(), BCOL), result);
591                 if (!result.exists())
592                     return result;
593                 // Next, if the previous col has a parent colgroup then its end border should be applied
594                 // but only if it is adjacent to the cell's edge.
595                 if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroupIfAdjacentAfter()) {
596                     result = chooseBorder(CollapsedBorderValue(enclosingColumnGroup->borderAdjoiningCellEndBorder(this), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(endColorProperty) : Color(), BCOLGROUP), result);
597                     if (!result.exists())
598                         return result;
599                 }
600             }
601         }
602     }
603
604     if (startBorderAdjoinsTable) {
605         // (7) The table's start border.
606         result = chooseBorder(result, CollapsedBorderValue(table->tableStartBorderAdjoiningCell(this), includeColor ? table->style()->visitedDependentColor(startColorProperty) : Color(), BTABLE));
607         if (!result.exists())
608             return result;
609     }
610     
611     return result;
612 }
613
614 CollapsedBorderValue RenderTableCell::collapsedEndBorder(IncludeBorderColorOrNot includeColor) const
615 {
616     CollapsedBorderValue result = computeCollapsedEndBorder(includeColor);
617     if (includeColor)
618         section()->setCachedCollapsedBorder(this, CBSEnd, result);
619     return result;
620 }
621
622 CollapsedBorderValue RenderTableCell::computeCollapsedEndBorder(IncludeBorderColorOrNot includeColor) const
623 {
624     RenderTable* table = this->table();
625     // Note: We have to use the effective column information instead of whether we have a cell after as a table doesn't
626     // have to be regular (any row can have less cells than the total cell count).
627     bool isEndColumn = table->colToEffCol(col() + colSpan() - 1) == table->numEffCols() - 1;
628
629     // For end border, we need to check, in order of precedence:
630     // (1) Our end border.
631     int startColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderStartColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
632     int endColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderEndColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
633     CollapsedBorderValue result = CollapsedBorderValue(style()->borderEnd(), includeColor ? style()->visitedDependentColor(endColorProperty) : Color(), BCELL);
634     
635     // (2) The start border of the following cell.
636     if (!isEndColumn) {
637         if (RenderTableCell* cellAfter = table->cellAfter(this)) {
638             CollapsedBorderValue cellAfterAdjoiningBorder = CollapsedBorderValue(cellAfter->borderAdjoiningCellBefore(this), includeColor ? cellAfter->style()->visitedDependentColor(startColorProperty) : Color(), BCELL);
639             result = chooseBorder(result, cellAfterAdjoiningBorder);
640             if (!result.exists())
641                 return result;
642         }
643     }
644
645     bool endBorderAdjoinsTable = hasEndBorderAdjoiningTable();
646     if (endBorderAdjoinsTable) {
647         // (3) Our row's end border.
648         result = chooseBorder(result, CollapsedBorderValue(row()->borderAdjoiningEndCell(this), includeColor ? parent()->style()->visitedDependentColor(endColorProperty) : Color(), BROW));
649         if (!result.exists())
650             return result;
651         
652         // (4) Our row group's end border.
653         result = chooseBorder(result, CollapsedBorderValue(section()->borderAdjoiningEndCell(this), includeColor ? section()->style()->visitedDependentColor(endColorProperty) : Color(), BROWGROUP));
654         if (!result.exists())
655             return result;
656     }
657     
658     // (5) Our column and column group's end borders.
659     bool startColEdge;
660     bool endColEdge;
661     if (RenderTableCol* colElt = table->colElement(col() + colSpan() - 1, &startColEdge, &endColEdge)) {
662         if (colElt->isTableColumnGroup() && endColEdge) {
663             // The element is a colgroup and is also the last colgroup (in case of spanned colgroups).
664             result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellEndBorder(this), includeColor ? colElt->style()->visitedDependentColor(endColorProperty) : Color(), BCOLGROUP));
665             if (!result.exists())
666                 return result;
667         } else if (!colElt->isTableColumnGroup()) {
668             // First apply the end border of the column irrespective of whether it is spanned or not. This is as per
669             // HTML5 which states that: "For the purposes of the CSS table model, the col element is expected to be
670             // treated as if it was present as many times as its span attribute specifies".
671             result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellEndBorder(this), includeColor ? colElt->style()->visitedDependentColor(endColorProperty) : Color(), BCOL));
672             if (!result.exists())
673                 return result;
674             // Next, if it has a parent colgroup then we apply its end border but only if it is adjacent to the cell.
675             if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroupIfAdjacentAfter()) {
676                 result = chooseBorder(result, CollapsedBorderValue(enclosingColumnGroup->borderAdjoiningCellEndBorder(this), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(endColorProperty) : Color(), BCOLGROUP));
677                 if (!result.exists())
678                     return result;
679             }
680         }
681     }
682     
683     // (6) The start border of the next column.
684     if (!isEndColumn) {
685         if (RenderTableCol* colElt = table->colElement(col() + colSpan(), &startColEdge, &endColEdge)) {
686             if (colElt->isTableColumnGroup() && startColEdge) {
687                 // This case is a colgroup without any col, we only compute it if it is adjacent to the cell's edge.
688                 result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellBefore(this), includeColor ? colElt->style()->visitedDependentColor(startColorProperty) : Color(), BCOLGROUP));
689                 if (!result.exists())
690                     return result;
691             } else if (colElt->isTableColumn()) {
692                 // Resolve the collapsing border against the col's border ignoring any 'span' as per HTML5.
693                 result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellBefore(this), includeColor ? colElt->style()->visitedDependentColor(startColorProperty) : Color(), BCOL));
694                 if (!result.exists())
695                     return result;
696                 // If we have a parent colgroup, resolve the border only if it is adjacent to the cell.
697                 if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroupIfAdjacentBefore()) {
698                     result = chooseBorder(result, CollapsedBorderValue(enclosingColumnGroup->borderAdjoiningCellStartBorder(this), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(startColorProperty) : Color(), BCOLGROUP));
699                     if (!result.exists())
700                         return result;
701                 }
702             }
703         }
704     }
705
706     if (endBorderAdjoinsTable) {
707         // (7) The table's end border.
708         result = chooseBorder(result, CollapsedBorderValue(table->tableEndBorderAdjoiningCell(this), includeColor ? table->style()->visitedDependentColor(endColorProperty) : Color(), BTABLE));
709         if (!result.exists())
710             return result;
711     }
712     
713     return result;
714 }
715
716 CollapsedBorderValue RenderTableCell::collapsedBeforeBorder(IncludeBorderColorOrNot includeColor) const
717 {
718     CollapsedBorderValue result = computeCollapsedBeforeBorder(includeColor);
719     if (includeColor)
720         section()->setCachedCollapsedBorder(this, CBSBefore, result);
721     return result;
722 }
723
724 CollapsedBorderValue RenderTableCell::computeCollapsedBeforeBorder(IncludeBorderColorOrNot includeColor) const
725 {
726     RenderTable* table = this->table();
727
728     // For before border, we need to check, in order of precedence:
729     // (1) Our before border.
730     int beforeColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderBeforeColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
731     int afterColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderAfterColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
732     CollapsedBorderValue result = CollapsedBorderValue(style()->borderBefore(), includeColor ? style()->visitedDependentColor(beforeColorProperty) : Color(), BCELL);
733     
734     RenderTableCell* prevCell = table->cellAbove(this);
735     if (prevCell) {
736         // (2) A before cell's after border.
737         result = chooseBorder(CollapsedBorderValue(prevCell->style()->borderAfter(), includeColor ? prevCell->style()->visitedDependentColor(afterColorProperty) : Color(), BCELL), result);
738         if (!result.exists())
739             return result;
740     }
741     
742     // (3) Our row's before border.
743     result = chooseBorder(result, CollapsedBorderValue(parent()->style()->borderBefore(), includeColor ? parent()->style()->visitedDependentColor(beforeColorProperty) : Color(), BROW));
744     if (!result.exists())
745         return result;
746     
747     // (4) The previous row's after border.
748     if (prevCell) {
749         RenderObject* prevRow = 0;
750         if (prevCell->section() == section())
751             prevRow = parent()->previousSibling();
752         else
753             prevRow = prevCell->section()->lastRow();
754     
755         if (prevRow) {
756             result = chooseBorder(CollapsedBorderValue(prevRow->style()->borderAfter(), includeColor ? prevRow->style()->visitedDependentColor(afterColorProperty) : Color(), BROW), result);
757             if (!result.exists())
758                 return result;
759         }
760     }
761     
762     // Now check row groups.
763     RenderTableSection* currSection = section();
764     if (!rowIndex()) {
765         // (5) Our row group's before border.
766         result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderBefore(), includeColor ? currSection->style()->visitedDependentColor(beforeColorProperty) : Color(), BROWGROUP));
767         if (!result.exists())
768             return result;
769         
770         // (6) Previous row group's after border.
771         currSection = table->sectionAbove(currSection, SkipEmptySections);
772         if (currSection) {
773             result = chooseBorder(CollapsedBorderValue(currSection->style()->borderAfter(), includeColor ? currSection->style()->visitedDependentColor(afterColorProperty) : Color(), BROWGROUP), result);
774             if (!result.exists())
775                 return result;
776         }
777     }
778     
779     if (!currSection) {
780         // (8) Our column and column group's before borders.
781         RenderTableCol* colElt = table->colElement(col());
782         if (colElt) {
783             result = chooseBorder(result, CollapsedBorderValue(colElt->style()->borderBefore(), includeColor ? colElt->style()->visitedDependentColor(beforeColorProperty) : Color(), BCOL));
784             if (!result.exists())
785                 return result;
786             if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroup()) {
787                 result = chooseBorder(result, CollapsedBorderValue(enclosingColumnGroup->style()->borderBefore(), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(beforeColorProperty) : Color(), BCOLGROUP));
788                 if (!result.exists())
789                     return result;
790             }
791         }
792         
793         // (9) The table's before border.
794         result = chooseBorder(result, CollapsedBorderValue(table->style()->borderBefore(), includeColor ? table->style()->visitedDependentColor(beforeColorProperty) : Color(), BTABLE));
795         if (!result.exists())
796             return result;
797     }
798     
799     return result;
800 }
801
802 CollapsedBorderValue RenderTableCell::collapsedAfterBorder(IncludeBorderColorOrNot includeColor) const
803 {
804     CollapsedBorderValue result = computeCollapsedAfterBorder(includeColor);
805     if (includeColor)
806         section()->setCachedCollapsedBorder(this, CBSAfter, result);
807     return result;
808 }
809
810 CollapsedBorderValue RenderTableCell::computeCollapsedAfterBorder(IncludeBorderColorOrNot includeColor) const
811 {
812     RenderTable* table = this->table();
813
814     // For after border, we need to check, in order of precedence:
815     // (1) Our after border.
816     int beforeColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderBeforeColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
817     int afterColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderAfterColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
818     CollapsedBorderValue result = CollapsedBorderValue(style()->borderAfter(), includeColor ? style()->visitedDependentColor(afterColorProperty) : Color(), BCELL);
819     
820     RenderTableCell* nextCell = table->cellBelow(this);
821     if (nextCell) {
822         // (2) An after cell's before border.
823         result = chooseBorder(result, CollapsedBorderValue(nextCell->style()->borderBefore(), includeColor ? nextCell->style()->visitedDependentColor(beforeColorProperty) : Color(), BCELL));
824         if (!result.exists())
825             return result;
826     }
827     
828     // (3) Our row's after border. (FIXME: Deal with rowspan!)
829     result = chooseBorder(result, CollapsedBorderValue(parent()->style()->borderAfter(), includeColor ? parent()->style()->visitedDependentColor(afterColorProperty) : Color(), BROW));
830     if (!result.exists())
831         return result;
832     
833     // (4) The next row's before border.
834     if (nextCell) {
835         result = chooseBorder(result, CollapsedBorderValue(nextCell->parent()->style()->borderBefore(), includeColor ? nextCell->parent()->style()->visitedDependentColor(beforeColorProperty) : Color(), BROW));
836         if (!result.exists())
837             return result;
838     }
839     
840     // Now check row groups.
841     RenderTableSection* currSection = section();
842     if (rowIndex() + rowSpan() >= currSection->numRows()) {
843         // (5) Our row group's after border.
844         result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderAfter(), includeColor ? currSection->style()->visitedDependentColor(afterColorProperty) : Color(), BROWGROUP));
845         if (!result.exists())
846             return result;
847         
848         // (6) Following row group's before border.
849         currSection = table->sectionBelow(currSection, SkipEmptySections);
850         if (currSection) {
851             result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderBefore(), includeColor ? currSection->style()->visitedDependentColor(beforeColorProperty) : Color(), BROWGROUP));
852             if (!result.exists())
853                 return result;
854         }
855     }
856     
857     if (!currSection) {
858         // (8) Our column and column group's after borders.
859         RenderTableCol* colElt = table->colElement(col());
860         if (colElt) {
861             result = chooseBorder(result, CollapsedBorderValue(colElt->style()->borderAfter(), includeColor ? colElt->style()->visitedDependentColor(afterColorProperty) : Color(), BCOL));
862             if (!result.exists()) return result;
863             if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroup()) {
864                 result = chooseBorder(result, CollapsedBorderValue(enclosingColumnGroup->style()->borderAfter(), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(afterColorProperty) : Color(), BCOLGROUP));
865                 if (!result.exists())
866                     return result;
867             }
868         }
869         
870         // (9) The table's after border.
871         result = chooseBorder(result, CollapsedBorderValue(table->style()->borderAfter(), includeColor ? table->style()->visitedDependentColor(afterColorProperty) : Color(), BTABLE));
872         if (!result.exists())
873             return result;
874     }
875     
876     return result;    
877 }
878
879 inline CollapsedBorderValue RenderTableCell::cachedCollapsedLeftBorder(const RenderStyle* styleForCellFlow) const
880 {
881     if (styleForCellFlow->isHorizontalWritingMode())
882         return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSStart) : section()->cachedCollapsedBorder(this, CBSEnd);
883     return styleForCellFlow->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSAfter) : section()->cachedCollapsedBorder(this, CBSBefore);
884 }
885
886 inline CollapsedBorderValue RenderTableCell::cachedCollapsedRightBorder(const RenderStyle* styleForCellFlow) const
887 {
888     if (styleForCellFlow->isHorizontalWritingMode())
889         return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSEnd) : section()->cachedCollapsedBorder(this, CBSStart);
890     return styleForCellFlow->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSBefore) : section()->cachedCollapsedBorder(this, CBSAfter);
891 }
892
893 inline CollapsedBorderValue RenderTableCell::cachedCollapsedTopBorder(const RenderStyle* styleForCellFlow) const
894 {
895     if (styleForCellFlow->isHorizontalWritingMode())
896         return styleForCellFlow->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSAfter) : section()->cachedCollapsedBorder(this, CBSBefore);
897     return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSStart) : section()->cachedCollapsedBorder(this, CBSEnd);
898 }
899
900 inline CollapsedBorderValue RenderTableCell::cachedCollapsedBottomBorder(const RenderStyle* styleForCellFlow) const
901 {
902     if (styleForCellFlow->isHorizontalWritingMode())
903         return styleForCellFlow->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSBefore) : section()->cachedCollapsedBorder(this, CBSAfter);
904     return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSEnd) : section()->cachedCollapsedBorder(this, CBSStart);
905 }
906
907 inline RenderTableCell* RenderTableCell::cellAtLeft(const RenderStyle* styleForCellFlow) const
908 {
909     if (styleForCellFlow->isHorizontalWritingMode())
910         return styleForCellFlow->isLeftToRightDirection() ? table()->cellBefore(this) : table()->cellAfter(this);
911     return styleForCellFlow->isFlippedBlocksWritingMode() ? table()->cellBelow(this) : table()->cellAbove(this);
912 }
913
914 inline RenderTableCell* RenderTableCell::cellAtRight(const RenderStyle* styleForCellFlow) const
915 {
916     if (styleForCellFlow->isHorizontalWritingMode())
917         return styleForCellFlow->isLeftToRightDirection() ? table()->cellAfter(this) : table()->cellBefore(this);
918     return styleForCellFlow->isFlippedBlocksWritingMode() ? table()->cellAbove(this) : table()->cellBelow(this);
919 }
920
921 inline RenderTableCell* RenderTableCell::cellAtTop(const RenderStyle* styleForCellFlow) const
922 {
923     if (styleForCellFlow->isHorizontalWritingMode())
924         return styleForCellFlow->isFlippedBlocksWritingMode() ? table()->cellBelow(this) : table()->cellAbove(this);
925     return styleForCellFlow->isLeftToRightDirection() ? table()->cellBefore(this) : table()->cellAfter(this);
926 }
927
928 inline RenderTableCell* RenderTableCell::cellAtBottom(const RenderStyle* styleForCellFlow) const
929 {
930     if (styleForCellFlow->isHorizontalWritingMode())
931         return styleForCellFlow->isFlippedBlocksWritingMode() ? table()->cellAbove(this) : table()->cellBelow(this);
932     return styleForCellFlow->isLeftToRightDirection() ? table()->cellAfter(this) : table()->cellBefore(this);
933 }
934
935 int RenderTableCell::borderLeft() const
936 {
937     return table()->collapseBorders() ? borderHalfLeft(false) : RenderBlockFlow::borderLeft();
938 }
939
940 int RenderTableCell::borderRight() const
941 {
942     return table()->collapseBorders() ? borderHalfRight(false) : RenderBlockFlow::borderRight();
943 }
944
945 int RenderTableCell::borderTop() const
946 {
947     return table()->collapseBorders() ? borderHalfTop(false) : RenderBlockFlow::borderTop();
948 }
949
950 int RenderTableCell::borderBottom() const
951 {
952     return table()->collapseBorders() ? borderHalfBottom(false) : RenderBlockFlow::borderBottom();
953 }
954
955 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=46191, make the collapsed border drawing
956 // work with different block flow values instead of being hard-coded to top-to-bottom.
957 int RenderTableCell::borderStart() const
958 {
959     return table()->collapseBorders() ? borderHalfStart(false) : RenderBlockFlow::borderStart();
960 }
961
962 int RenderTableCell::borderEnd() const
963 {
964     return table()->collapseBorders() ? borderHalfEnd(false) : RenderBlockFlow::borderEnd();
965 }
966
967 int RenderTableCell::borderBefore() const
968 {
969     return table()->collapseBorders() ? borderHalfBefore(false) : RenderBlockFlow::borderBefore();
970 }
971
972 int RenderTableCell::borderAfter() const
973 {
974     return table()->collapseBorders() ? borderHalfAfter(false) : RenderBlockFlow::borderAfter();
975 }
976
977 int RenderTableCell::borderHalfLeft(bool outer) const
978 {
979     const RenderStyle* styleForCellFlow = this->styleForCellFlow();
980     if (styleForCellFlow->isHorizontalWritingMode())
981         return styleForCellFlow->isLeftToRightDirection() ? borderHalfStart(outer) : borderHalfEnd(outer);
982     return styleForCellFlow->isFlippedBlocksWritingMode() ? borderHalfAfter(outer) : borderHalfBefore(outer);
983 }
984
985 int RenderTableCell::borderHalfRight(bool outer) const
986 {
987     const RenderStyle* styleForCellFlow = this->styleForCellFlow();
988     if (styleForCellFlow->isHorizontalWritingMode())
989         return styleForCellFlow->isLeftToRightDirection() ? borderHalfEnd(outer) : borderHalfStart(outer);
990     return styleForCellFlow->isFlippedBlocksWritingMode() ? borderHalfBefore(outer) : borderHalfAfter(outer);
991 }
992
993 int RenderTableCell::borderHalfTop(bool outer) const
994 {
995     const RenderStyle* styleForCellFlow = this->styleForCellFlow();
996     if (styleForCellFlow->isHorizontalWritingMode())
997         return styleForCellFlow->isFlippedBlocksWritingMode() ? borderHalfAfter(outer) : borderHalfBefore(outer);
998     return styleForCellFlow->isLeftToRightDirection() ? borderHalfStart(outer) : borderHalfEnd(outer);
999 }
1000
1001 int RenderTableCell::borderHalfBottom(bool outer) const
1002 {
1003     const RenderStyle* styleForCellFlow = this->styleForCellFlow();
1004     if (styleForCellFlow->isHorizontalWritingMode())
1005         return styleForCellFlow->isFlippedBlocksWritingMode() ? borderHalfBefore(outer) : borderHalfAfter(outer);
1006     return styleForCellFlow->isLeftToRightDirection() ? borderHalfEnd(outer) : borderHalfStart(outer);
1007 }
1008
1009 int RenderTableCell::borderHalfStart(bool outer) const
1010 {
1011     CollapsedBorderValue border = collapsedStartBorder(DoNotIncludeBorderColor);
1012     if (border.exists())
1013         return (border.width() + ((styleForCellFlow()->isLeftToRightDirection() ^ outer) ? 1 : 0)) / 2; // Give the extra pixel to top and left.
1014     return 0;
1015 }
1016     
1017 int RenderTableCell::borderHalfEnd(bool outer) const
1018 {
1019     CollapsedBorderValue border = collapsedEndBorder(DoNotIncludeBorderColor);
1020     if (border.exists())
1021         return (border.width() + ((styleForCellFlow()->isLeftToRightDirection() ^ outer) ? 0 : 1)) / 2;
1022     return 0;
1023 }
1024
1025 int RenderTableCell::borderHalfBefore(bool outer) const
1026 {
1027     CollapsedBorderValue border = collapsedBeforeBorder(DoNotIncludeBorderColor);
1028     if (border.exists())
1029         return (border.width() + ((styleForCellFlow()->isFlippedBlocksWritingMode() ^ outer) ? 0 : 1)) / 2; // Give the extra pixel to top and left.
1030     return 0;
1031 }
1032
1033 int RenderTableCell::borderHalfAfter(bool outer) const
1034 {
1035     CollapsedBorderValue border = collapsedAfterBorder(DoNotIncludeBorderColor);
1036     if (border.exists())
1037         return (border.width() + ((styleForCellFlow()->isFlippedBlocksWritingMode() ^ outer) ? 1 : 0)) / 2;
1038     return 0;
1039 }
1040
1041 void RenderTableCell::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1042 {
1043     ASSERT(paintInfo.phase != PaintPhaseCollapsedTableBorders);
1044     RenderBlockFlow::paint(paintInfo, paintOffset);
1045 }
1046
1047 static EBorderStyle collapsedBorderStyle(EBorderStyle style)
1048 {
1049     if (style == OUTSET)
1050         return GROOVE;
1051     if (style == INSET)
1052         return RIDGE;
1053     return style;
1054 }
1055
1056 struct CollapsedBorder {
1057     CollapsedBorderValue borderValue;
1058     BoxSide side;
1059     bool shouldPaint;
1060     int x1;
1061     int y1;
1062     int x2;
1063     int y2;
1064     EBorderStyle style;
1065 };
1066
1067 class CollapsedBorders {
1068 public:
1069     CollapsedBorders()
1070         : m_count(0)
1071     {
1072     }
1073     
1074     void addBorder(const CollapsedBorderValue& borderValue, BoxSide borderSide, bool shouldPaint,
1075                    int x1, int y1, int x2, int y2, EBorderStyle borderStyle)
1076     {
1077         if (borderValue.exists() && shouldPaint) {
1078             m_borders[m_count].borderValue = borderValue;
1079             m_borders[m_count].side = borderSide;
1080             m_borders[m_count].shouldPaint = shouldPaint;
1081             m_borders[m_count].x1 = x1;
1082             m_borders[m_count].x2 = x2;
1083             m_borders[m_count].y1 = y1;
1084             m_borders[m_count].y2 = y2;
1085             m_borders[m_count].style = borderStyle;
1086             m_count++;
1087         }
1088     }
1089
1090     CollapsedBorder* nextBorder()
1091     {
1092         for (unsigned i = 0; i < m_count; i++) {
1093             if (m_borders[i].borderValue.exists() && m_borders[i].shouldPaint) {
1094                 m_borders[i].shouldPaint = false;
1095                 return &m_borders[i];
1096             }
1097         }
1098         
1099         return 0;
1100     }
1101     
1102     CollapsedBorder m_borders[4];
1103     unsigned m_count;
1104 };
1105
1106 static void addBorderStyle(RenderTable::CollapsedBorderValues& borderValues,
1107                            CollapsedBorderValue borderValue)
1108 {
1109     if (!borderValue.exists())
1110         return;
1111     size_t count = borderValues.size();
1112     for (size_t i = 0; i < count; ++i)
1113         if (borderValues[i].isSameIgnoringColor(borderValue))
1114             return;
1115     borderValues.append(borderValue);
1116 }
1117
1118 void RenderTableCell::collectBorderValues(RenderTable::CollapsedBorderValues& borderValues) const
1119 {
1120     addBorderStyle(borderValues, collapsedStartBorder());
1121     addBorderStyle(borderValues, collapsedEndBorder());
1122     addBorderStyle(borderValues, collapsedBeforeBorder());
1123     addBorderStyle(borderValues, collapsedAfterBorder());
1124 }
1125
1126 static int compareBorderValuesForQSort(const void* pa, const void* pb)
1127 {
1128     const CollapsedBorderValue* a = static_cast<const CollapsedBorderValue*>(pa);
1129     const CollapsedBorderValue* b = static_cast<const CollapsedBorderValue*>(pb);
1130     if (a->isSameIgnoringColor(*b))
1131         return 0;
1132     return compareBorders(*a, *b);
1133 }
1134
1135 void RenderTableCell::sortBorderValues(RenderTable::CollapsedBorderValues& borderValues)
1136 {
1137     qsort(borderValues.data(), borderValues.size(), sizeof(CollapsedBorderValue),
1138         compareBorderValuesForQSort);
1139 }
1140
1141 bool RenderTableCell::alignLeftRightBorderPaintRect(int& leftXOffset, int& rightXOffset)
1142 {
1143     const RenderStyle* styleForTopCell = styleForCellFlow();
1144     int left = cachedCollapsedLeftBorder(styleForTopCell).width();
1145     int right = cachedCollapsedRightBorder(styleForTopCell).width();
1146     leftXOffset = max<int>(leftXOffset, left);
1147     rightXOffset = max<int>(rightXOffset, right);
1148     if (colSpan() > 1)
1149         return false;
1150     return true;
1151 }
1152
1153 bool RenderTableCell::alignTopBottomBorderPaintRect(int& topYOffset, int& bottomYOffset)
1154 {
1155     const RenderStyle* styleForBottomCell = styleForCellFlow();
1156     int top = cachedCollapsedTopBorder(styleForBottomCell).width();
1157     int bottom = cachedCollapsedBottomBorder(styleForBottomCell).width();
1158     topYOffset = max<int>(topYOffset, top);
1159     bottomYOffset = max<int>(bottomYOffset, bottom);
1160     if (rowSpan() > 1)
1161         return false;
1162     return true;
1163 }
1164
1165
1166 void RenderTableCell::paintCollapsedBorders(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1167 {
1168     ASSERT(paintInfo.phase == PaintPhaseCollapsedTableBorders);
1169
1170     if (!paintInfo.shouldPaintWithinRoot(*this) || style()->visibility() != VISIBLE)
1171         return;
1172
1173     LayoutRect localRepaintRect = paintInfo.rect;
1174     localRepaintRect.inflate(maximalOutlineSize(paintInfo.phase));
1175
1176     LayoutRect paintRect = LayoutRect(paintOffset + location(), pixelSnappedSize());
1177     if (paintRect.y() - table()->outerBorderTop() >= localRepaintRect.maxY())
1178         return;
1179
1180     if (paintRect.maxY() + table()->outerBorderBottom() <= localRepaintRect.y())
1181         return;
1182
1183     GraphicsContext* graphicsContext = paintInfo.context;
1184     if (!table()->currentBorderValue() || graphicsContext->paintingDisabled())
1185         return;
1186
1187     const RenderStyle* styleForCellFlow = this->styleForCellFlow();
1188     CollapsedBorderValue leftVal = cachedCollapsedLeftBorder(styleForCellFlow);
1189     CollapsedBorderValue rightVal = cachedCollapsedRightBorder(styleForCellFlow);
1190     CollapsedBorderValue topVal = cachedCollapsedTopBorder(styleForCellFlow);
1191     CollapsedBorderValue bottomVal = cachedCollapsedBottomBorder(styleForCellFlow);
1192      
1193     // Adjust our x/y/width/height so that we paint the collapsed borders at the correct location.
1194     int topWidth = topVal.width();
1195     int bottomWidth = bottomVal.width();
1196     int leftWidth = leftVal.width();
1197     int rightWidth = rightVal.width();
1198
1199     int leftXOffsetTop = leftWidth;
1200     int leftXOffsetBottom = leftWidth;
1201     int rightXOffsetTop = rightWidth;
1202     int rightXOffsetBottom = rightWidth;
1203     int topYOffsetLeft = topWidth;
1204     int topYOffsetRight = topWidth;
1205     int bottomYOffsetLeft = bottomWidth;
1206     int bottomYOffsetRight = bottomWidth;
1207
1208     // We use the direction/writing-mode given by the section here because we want to know if we're
1209     // at the section's edge.
1210     bool shouldDrawTopBorder = !cellAtTop(section()->style());
1211     bool shouldDrawLeftBorder = !cellAtLeft(section()->style());
1212     bool shouldDrawRightBorder = true;
1213
1214     if (RenderTableCell* top = cellAtTop(styleForCellFlow)) {
1215         shouldDrawTopBorder = shouldDrawTopBorder && top->alignLeftRightBorderPaintRect(leftXOffsetTop, rightXOffsetTop);
1216         if (this->colSpan() > 1)
1217             shouldDrawTopBorder = false;
1218     }
1219
1220     if (RenderTableCell* bottom = cellAtBottom(styleForCellFlow))
1221         bottom->alignLeftRightBorderPaintRect(leftXOffsetBottom, rightXOffsetBottom);
1222
1223     if (RenderTableCell* left = cellAtLeft(styleForCellFlow))
1224         shouldDrawLeftBorder = shouldDrawLeftBorder && left->alignTopBottomBorderPaintRect(topYOffsetLeft, bottomYOffsetLeft);
1225
1226     if (RenderTableCell* right = cellAtRight(styleForCellFlow))
1227         shouldDrawRightBorder = right->alignTopBottomBorderPaintRect(topYOffsetRight, bottomYOffsetRight);
1228
1229     IntRect cellRect = pixelSnappedIntRect(paintRect.x(), paintRect.y(), paintRect.width(), paintRect.height());
1230
1231     IntRect borderRect = pixelSnappedIntRect(paintRect.x() - leftWidth / 2,
1232         paintRect.y() - topWidth / 2,
1233         paintRect.width() + leftWidth / 2 + (rightWidth + 1) / 2,
1234         paintRect.height() + topWidth / 2 + (bottomWidth + 1) / 2);
1235
1236     EBorderStyle topStyle = collapsedBorderStyle(topVal.style());
1237     EBorderStyle bottomStyle = collapsedBorderStyle(bottomVal.style());
1238     EBorderStyle leftStyle = collapsedBorderStyle(leftVal.style());
1239     EBorderStyle rightStyle = collapsedBorderStyle(rightVal.style());
1240     
1241     bool renderTop = topStyle > BHIDDEN && !topVal.isTransparent() && shouldDrawTopBorder;
1242     bool renderBottom = bottomStyle > BHIDDEN && !bottomVal.isTransparent();
1243     bool renderLeft = leftStyle > BHIDDEN && !leftVal.isTransparent() && shouldDrawLeftBorder;
1244     bool renderRight = rightStyle > BHIDDEN && !rightVal.isTransparent() && shouldDrawRightBorder;
1245
1246     // We never paint diagonals at the joins.  We simply let the border with the highest
1247     // precedence paint on top of borders with lower precedence.  
1248     CollapsedBorders borders;
1249     if (topVal.style() == DOTTED)
1250         borders.addBorder(topVal, BSTop, renderTop, cellRect.x() - leftXOffsetTop / 2, cellRect.y() - topWidth / 2, cellRect.maxX() + rightXOffsetTop / 2, cellRect.y() + topWidth / 2 + topWidth % 2, topStyle);
1251     else
1252         borders.addBorder(topVal, BSTop, renderTop, borderRect.x(), borderRect.y(), borderRect.maxX(), borderRect.y() + topWidth, topStyle);
1253
1254     if (bottomVal.style() == DOTTED)
1255         borders.addBorder(bottomVal, BSBottom, renderBottom, cellRect.x() - leftXOffsetBottom / 2, cellRect.maxY() - bottomWidth / 2, cellRect.maxX() + rightXOffsetBottom / 2, cellRect.maxY() + bottomWidth / 2 + bottomWidth % 2, bottomStyle);
1256     else
1257         borders.addBorder(bottomVal, BSBottom, renderBottom, borderRect.x(), borderRect.maxY() - bottomWidth, borderRect.maxX(), borderRect.maxY(), bottomStyle);
1258
1259     if (leftVal.style() == DOTTED)
1260         borders.addBorder(leftVal, BSLeft, renderLeft, cellRect.x() - leftWidth / 2, cellRect.y() - topYOffsetLeft / 2, cellRect.x() + leftWidth / 2 + leftWidth % 2, cellRect.maxY() + bottomYOffsetLeft / 2 + bottomYOffsetLeft % 2, leftStyle);
1261     else
1262         borders.addBorder(leftVal, BSLeft, renderLeft, borderRect.x(), borderRect.y(), borderRect.x() + leftWidth, borderRect.maxY(), leftStyle);
1263
1264     if (rightVal.style() == DOTTED)
1265         borders.addBorder(rightVal, BSRight, renderRight, cellRect.maxX() - rightWidth / 2, cellRect.y()  - topYOffsetRight / 2, cellRect.maxX() + rightWidth / 2 + rightWidth % 2, cellRect.maxY()  + bottomYOffsetRight / 2 + bottomYOffsetRight % 2, rightStyle);
1266     else
1267         borders.addBorder(rightVal, BSRight, renderRight, borderRect.maxX() - rightWidth, borderRect.y(), borderRect.maxX(), borderRect.maxY(), rightStyle);
1268
1269     bool antialias = shouldAntialiasLines(graphicsContext);
1270     
1271     for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) {
1272         if (border->borderValue.isSameIgnoringColor(*table()->currentBorderValue()))
1273             drawLineForBoxSide(graphicsContext, border->x1, border->y1, border->x2, border->y2, border->side, 
1274                 border->borderValue.color(), border->style, 0, 0, antialias);
1275     }
1276 }
1277
1278 void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, const LayoutPoint& paintOffset, RenderElement* backgroundObject)
1279 {
1280     if (!paintInfo.shouldPaintWithinRoot(*this))
1281         return;
1282
1283     if (!backgroundObject)
1284         return;
1285
1286     if (style()->visibility() != VISIBLE)
1287         return;
1288
1289     RenderTable* tableElt = table();
1290     if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
1291         return;
1292
1293     LayoutPoint adjustedPaintOffset = paintOffset;
1294     if (backgroundObject != this)
1295         adjustedPaintOffset.moveBy(location());
1296
1297     Color c = backgroundObject->style()->visitedDependentColor(CSSPropertyBackgroundColor);
1298     const FillLayer* bgLayer = backgroundObject->style()->backgroundLayers();
1299
1300     if (bgLayer->hasImage() || c.isValid()) {
1301         // We have to clip here because the background would paint
1302         // on top of the borders otherwise.  This only matters for cells and rows.
1303         bool shouldClip = backgroundObject->hasLayer() && (backgroundObject == this || backgroundObject == parent()) && tableElt->collapseBorders();
1304         GraphicsContextStateSaver stateSaver(*paintInfo.context, shouldClip);
1305         if (shouldClip) {
1306             LayoutRect clipRect(adjustedPaintOffset.x() + borderLeft(), adjustedPaintOffset.y() + borderTop(),
1307                 width() - borderLeft() - borderRight(), height() - borderTop() - borderBottom());
1308             paintInfo.context->clip(clipRect);
1309         }
1310         paintFillLayers(paintInfo, c, bgLayer, LayoutRect(adjustedPaintOffset, pixelSnappedSize()), BackgroundBleedNone, CompositeSourceOver, backgroundObject);
1311     }
1312 }
1313
1314 void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1315 {
1316     if (!paintInfo.shouldPaintWithinRoot(*this))
1317         return;
1318
1319     RenderTable* tableElt = table();
1320     if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
1321         return;
1322
1323     LayoutRect paintRect = LayoutRect(paintOffset, pixelSnappedSize());
1324     paintBoxShadow(paintInfo, paintRect, style(), Normal);
1325     
1326     // Paint our cell background.
1327     paintBackgroundsBehindCell(paintInfo, paintOffset, this);
1328
1329     paintBoxShadow(paintInfo, paintRect, style(), Inset);
1330
1331     if (!style()->hasBorder() || tableElt->collapseBorders())
1332         return;
1333
1334     paintBorder(paintInfo, paintRect, style());
1335 }
1336
1337 void RenderTableCell::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1338 {
1339     if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
1340         return;
1341
1342     RenderTable* tableElt = table();
1343     if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
1344         return;
1345    
1346     paintMaskImages(paintInfo, LayoutRect(paintOffset, pixelSnappedSize()));
1347 }
1348
1349 bool RenderTableCell::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const
1350 {
1351     return false;
1352 }
1353
1354 void RenderTableCell::scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged)
1355 {
1356     LayoutUnit scrollbarHeight = scrollbarLogicalHeight();
1357     if (!scrollbarHeight)
1358         return; // Not sure if we should be doing something when a scrollbar goes away or not.
1359     
1360     // We only care if the scrollbar that affects our intrinsic padding has been added.
1361     if ((isHorizontalWritingMode() && !horizontalScrollbarChanged) ||
1362         (!isHorizontalWritingMode() && !verticalScrollbarChanged))
1363         return;
1364
1365     // Shrink our intrinsic padding as much as possible to accommodate the scrollbar.
1366     if (style()->verticalAlign() == MIDDLE) {
1367         LayoutUnit totalHeight = logicalHeight();
1368         LayoutUnit heightWithoutIntrinsicPadding = totalHeight - intrinsicPaddingBefore() - intrinsicPaddingAfter();
1369         totalHeight -= scrollbarHeight;
1370         LayoutUnit newBeforePadding = (totalHeight - heightWithoutIntrinsicPadding) / 2;
1371         LayoutUnit newAfterPadding = totalHeight - heightWithoutIntrinsicPadding - newBeforePadding;
1372         setIntrinsicPaddingBefore(newBeforePadding);
1373         setIntrinsicPaddingAfter(newAfterPadding);
1374     } else
1375         setIntrinsicPaddingAfter(intrinsicPaddingAfter() - scrollbarHeight);
1376 }
1377
1378 RenderTableCell* RenderTableCell::createAnonymousWithParentRenderer(const RenderObject* parent)
1379 {
1380     auto cell = new RenderTableCell(parent->document(), RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE_CELL));
1381     cell->initializeStyle();
1382     return cell;
1383 }
1384
1385 } // namespace WebCore