Have is<>(T*) function do a null check on the pointer argument
[WebKit-https.git] / Source / WebCore / rendering / RenderTable.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, 2010, 2014 Apple Inc. All rights reserved.
8  * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "RenderTable.h"
28
29 #include "AutoTableLayout.h"
30 #include "CollapsedBorderValue.h"
31 #include "Document.h"
32 #include "FixedTableLayout.h"
33 #include "FrameView.h"
34 #include "HitTestResult.h"
35 #include "HTMLNames.h"
36 #include "HTMLTableElement.h"
37 #include "LayoutRepainter.h"
38 #include "RenderIterator.h"
39 #include "RenderLayer.h"
40 #include "RenderNamedFlowFragment.h"
41 #include "RenderTableCaption.h"
42 #include "RenderTableCell.h"
43 #include "RenderTableCol.h"
44 #include "RenderTableSection.h"
45 #include "RenderView.h"
46 #include "StyleInheritedData.h"
47 #include <wtf/StackStats.h>
48
49 namespace WebCore {
50
51 using namespace HTMLNames;
52
53 RenderTable::RenderTable(Element& element, PassRef<RenderStyle> style)
54     : RenderBlock(element, WTF::move(style), 0)
55     , m_head(nullptr)
56     , m_foot(nullptr)
57     , m_firstBody(nullptr)
58     , m_currentBorder(nullptr)
59     , m_collapsedBordersValid(false)
60     , m_hasColElements(false)
61     , m_needsSectionRecalc(false)
62     , m_columnLogicalWidthChanged(false)
63     , m_columnRenderersValid(false)
64     , m_hasCellColspanThatDeterminesTableWidth(false)
65     , m_hSpacing(0)
66     , m_vSpacing(0)
67     , m_borderStart(0)
68     , m_borderEnd(0)
69     , m_columnOffsetTop(-1)
70     , m_columnOffsetHeight(-1)
71 {
72     setChildrenInline(false);
73     m_columnPos.fill(0, 1);
74 }
75
76 RenderTable::RenderTable(Document& document, PassRef<RenderStyle> style)
77     : RenderBlock(document, WTF::move(style), 0)
78     , m_head(nullptr)
79     , m_foot(nullptr)
80     , m_firstBody(nullptr)
81     , m_currentBorder(nullptr)
82     , m_collapsedBordersValid(false)
83     , m_hasColElements(false)
84     , m_needsSectionRecalc(false)
85     , m_columnLogicalWidthChanged(false)
86     , m_columnRenderersValid(false)
87     , m_hasCellColspanThatDeterminesTableWidth(false)
88     , m_hSpacing(0)
89     , m_vSpacing(0)
90     , m_borderStart(0)
91     , m_borderEnd(0)
92 {
93     setChildrenInline(false);
94     m_columnPos.fill(0, 1);
95 }
96
97 RenderTable::~RenderTable()
98 {
99 }
100
101 void RenderTable::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
102 {
103     RenderBlock::styleDidChange(diff, oldStyle);
104     propagateStyleToAnonymousChildren(PropagateToAllChildren);
105
106     ETableLayout oldTableLayout = oldStyle ? oldStyle->tableLayout() : TAUTO;
107
108     // In the collapsed border model, there is no cell spacing.
109     m_hSpacing = collapseBorders() ? 0 : style().horizontalBorderSpacing();
110     m_vSpacing = collapseBorders() ? 0 : style().verticalBorderSpacing();
111     m_columnPos[0] = m_hSpacing;
112
113     if (!m_tableLayout || style().tableLayout() != oldTableLayout) {
114         // According to the CSS2 spec, you only use fixed table layout if an
115         // explicit width is specified on the table.  Auto width implies auto table layout.
116         if (style().tableLayout() == TFIXED && !style().logicalWidth().isAuto())
117             m_tableLayout = std::make_unique<FixedTableLayout>(this);
118         else
119             m_tableLayout = std::make_unique<AutoTableLayout>(this);
120     }
121
122     // If border was changed, invalidate collapsed borders cache.
123     if (!needsLayout() && oldStyle && oldStyle->border() != style().border())
124         invalidateCollapsedBorders();
125 }
126
127 static inline void resetSectionPointerIfNotBefore(RenderTableSection*& ptr, RenderObject* before)
128 {
129     if (!before || !ptr)
130         return;
131     RenderObject* o = before->previousSibling();
132     while (o && o != ptr)
133         o = o->previousSibling();
134     if (!o)
135         ptr = 0;
136 }
137
138 void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
139 {
140     bool wrapInAnonymousSection = !child->isOutOfFlowPositioned();
141
142     if (child->isTableCaption())
143         wrapInAnonymousSection = false;
144     else if (child->isRenderTableCol()) {
145         m_hasColElements = true;
146         wrapInAnonymousSection = false;
147     } else if (child->isTableSection()) {
148         switch (child->style().display()) {
149             case TABLE_HEADER_GROUP:
150                 resetSectionPointerIfNotBefore(m_head, beforeChild);
151                 if (!m_head) {
152                     m_head = toRenderTableSection(child);
153                 } else {
154                     resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
155                     if (!m_firstBody) 
156                         m_firstBody = toRenderTableSection(child);
157                 }
158                 wrapInAnonymousSection = false;
159                 break;
160             case TABLE_FOOTER_GROUP:
161                 resetSectionPointerIfNotBefore(m_foot, beforeChild);
162                 if (!m_foot) {
163                     m_foot = toRenderTableSection(child);
164                     wrapInAnonymousSection = false;
165                     break;
166                 }
167                 FALLTHROUGH;
168             case TABLE_ROW_GROUP:
169                 resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
170                 if (!m_firstBody)
171                     m_firstBody = toRenderTableSection(child);
172                 wrapInAnonymousSection = false;
173                 break;
174             default:
175                 ASSERT_NOT_REACHED();
176         }
177     } else if (child->isTableCell() || child->isTableRow())
178         wrapInAnonymousSection = true;
179     else
180         wrapInAnonymousSection = true;
181
182     if (child->isTableSection())
183         setNeedsSectionRecalc();
184
185     if (!wrapInAnonymousSection) {
186         if (beforeChild && beforeChild->parent() != this)
187             beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
188
189         RenderBox::addChild(child, beforeChild);
190         return;
191     }
192
193     if (!beforeChild && lastChild() && lastChild()->isTableSection() && lastChild()->isAnonymous() && !lastChild()->isBeforeContent()) {
194         toRenderTableSection(lastChild())->addChild(child);
195         return;
196     }
197
198     if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
199         RenderObject* section = beforeChild->previousSibling();
200         if (section && section->isTableSection() && section->isAnonymous()) {
201             toRenderTableSection(section)->addChild(child);
202             return;
203         }
204     }
205
206     RenderObject* lastBox = beforeChild;
207     while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableSection() && lastBox->style().display() != TABLE_CAPTION && lastBox->style().display() != TABLE_COLUMN_GROUP)
208         lastBox = lastBox->parent();
209     if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox) && lastBox->isTableSection()) {
210         RenderTableSection* section = toRenderTableSection(lastBox);
211         if (beforeChild == section)
212             beforeChild = section->firstRow();
213         section->addChild(child, beforeChild);
214         return;
215     }
216
217     if (beforeChild && !beforeChild->isTableSection() && beforeChild->style().display() != TABLE_CAPTION && beforeChild->style().display() != TABLE_COLUMN_GROUP)
218         beforeChild = 0;
219
220     RenderTableSection* section = RenderTableSection::createAnonymousWithParentRenderer(this);
221     addChild(section, beforeChild);
222     section->addChild(child);
223 }
224
225 void RenderTable::addCaption(const RenderTableCaption* caption)
226 {
227     ASSERT(m_captions.find(caption) == notFound);
228     m_captions.append(const_cast<RenderTableCaption*>(caption));
229 }
230
231 void RenderTable::removeCaption(const RenderTableCaption* oldCaption)
232 {
233     size_t index = m_captions.find(oldCaption);
234     ASSERT(index != notFound);
235     if (index == notFound)
236         return;
237
238     m_captions.remove(index);
239 }
240
241 void RenderTable::invalidateCachedColumns()
242 {
243     m_columnRenderersValid = false;
244     m_columnRenderers.resize(0);
245     m_effectiveColumnIndexMap.clear();
246 }
247
248 void RenderTable::invalidateCachedColumnOffsets()
249 {
250     m_columnOffsetTop = -1;
251     m_columnOffsetHeight = -1;
252 }
253
254 void RenderTable::addColumn(const RenderTableCol*)
255 {
256     invalidateCachedColumns();
257 }
258
259 void RenderTable::removeColumn(const RenderTableCol*)
260 {
261     invalidateCachedColumns();
262     // We don't really need to recompute our sections, but we need to update our
263     // column count and whether we have a column. Currently, we only have one
264     // size-fit-all flag but we may have to consider splitting it.
265     setNeedsSectionRecalc();
266 }
267
268 void RenderTable::updateLogicalWidth()
269 {
270     recalcSectionsIfNeeded();
271
272     if (isOutOfFlowPositioned()) {
273         LogicalExtentComputedValues computedValues;
274         computePositionedLogicalWidth(computedValues);
275         setLogicalWidth(computedValues.m_extent);
276         setLogicalLeft(computedValues.m_position);
277         setMarginStart(computedValues.m_margins.m_start);
278         setMarginEnd(computedValues.m_margins.m_end);
279     }
280
281     RenderBlock* cb = containingBlock();
282
283     LayoutUnit availableLogicalWidth = containingBlockLogicalWidthForContent();
284     bool hasPerpendicularContainingBlock = cb->style().isHorizontalWritingMode() != style().isHorizontalWritingMode();
285     LayoutUnit containerWidthInInlineDirection = hasPerpendicularContainingBlock ? perpendicularContainingBlockLogicalHeight() : availableLogicalWidth;
286
287     Length styleLogicalWidth = style().logicalWidth();
288     if ((styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive()) || styleLogicalWidth.isIntrinsic())
289         setLogicalWidth(convertStyleLogicalWidthToComputedWidth(styleLogicalWidth, containerWidthInInlineDirection));
290     else {
291         // Subtract out any fixed margins from our available width for auto width tables.
292         LayoutUnit marginStart = minimumValueForLength(style().marginStart(), availableLogicalWidth);
293         LayoutUnit marginEnd = minimumValueForLength(style().marginEnd(), availableLogicalWidth);
294         LayoutUnit marginTotal = marginStart + marginEnd;
295
296         // Subtract out our margins to get the available content width.
297         LayoutUnit availableContentLogicalWidth = std::max<LayoutUnit>(0, containerWidthInInlineDirection - marginTotal);
298         if (shrinkToAvoidFloats() && cb->containsFloats() && !hasPerpendicularContainingBlock) {
299             // FIXME: Work with regions someday.
300             availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, 0);
301         }
302
303         // Ensure we aren't bigger than our available width.
304         setLogicalWidth(std::min<int>(availableContentLogicalWidth, maxPreferredLogicalWidth()));
305     }
306
307     // Ensure we aren't smaller than our min preferred width.
308     setLogicalWidth(std::max<int>(logicalWidth(), minPreferredLogicalWidth()));
309
310     
311     // Ensure we aren't bigger than our max-width style.
312     Length styleMaxLogicalWidth = style().logicalMaxWidth();
313     if ((styleMaxLogicalWidth.isSpecified() && !styleMaxLogicalWidth.isNegative()) || styleMaxLogicalWidth.isIntrinsic()) {
314         LayoutUnit computedMaxLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMaxLogicalWidth, availableLogicalWidth);
315         setLogicalWidth(std::min<int>(logicalWidth(), computedMaxLogicalWidth));
316     }
317
318     // Ensure we aren't smaller than our min-width style.
319     Length styleMinLogicalWidth = style().logicalMinWidth();
320     if ((styleMinLogicalWidth.isSpecified() && !styleMinLogicalWidth.isNegative()) || styleMinLogicalWidth.isIntrinsic()) {
321         LayoutUnit computedMinLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMinLogicalWidth, availableLogicalWidth);
322         setLogicalWidth(std::max<int>(logicalWidth(), computedMinLogicalWidth));
323     }
324
325     // Finally, with our true width determined, compute our margins for real.
326     setMarginStart(0);
327     setMarginEnd(0);
328     if (!hasPerpendicularContainingBlock) {
329         LayoutUnit containerLogicalWidthForAutoMargins = availableLogicalWidth;
330         if (avoidsFloats() && cb->containsFloats())
331             containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(0); // FIXME: Work with regions someday.
332         ComputedMarginValues marginValues;
333         bool hasInvertedDirection =  cb->style().isLeftToRightDirection() == style().isLeftToRightDirection();
334         computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth(),
335             hasInvertedDirection ? marginValues.m_start : marginValues.m_end,
336             hasInvertedDirection ? marginValues.m_end : marginValues.m_start);
337         setMarginStart(marginValues.m_start);
338         setMarginEnd(marginValues.m_end);
339     } else {
340         setMarginStart(minimumValueForLength(style().marginStart(), availableLogicalWidth));
341         setMarginEnd(minimumValueForLength(style().marginEnd(), availableLogicalWidth));
342     }
343 }
344
345 // This method takes a RenderStyle's logical width, min-width, or max-width length and computes its actual value.
346 LayoutUnit RenderTable::convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth)
347 {
348     if (styleLogicalWidth.isIntrinsic())
349         return computeIntrinsicLogicalWidthUsing(styleLogicalWidth, availableWidth, bordersPaddingAndSpacingInRowDirection());
350
351     // HTML tables' width styles already include borders and paddings, but CSS tables' width styles do not.
352     LayoutUnit borders = 0;
353     bool isCSSTable = !is<HTMLTableElement>(element());
354     if (isCSSTable && styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive() && style().boxSizing() == CONTENT_BOX)
355         borders = borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd());
356
357     return minimumValueForLength(styleLogicalWidth, availableWidth) + borders;
358 }
359
360 LayoutUnit RenderTable::convertStyleLogicalHeightToComputedHeight(const Length& styleLogicalHeight)
361 {
362     LayoutUnit computedLogicalHeight = 0;
363     if (styleLogicalHeight.isFixed()) {
364         // HTML tables size as though CSS height includes border/padding, CSS tables do not.
365         LayoutUnit borders = LayoutUnit();
366         // FIXME: We cannot apply box-sizing: content-box on <table> which other browsers allow.
367         if (is<HTMLTableElement>(element()) || style().boxSizing() == BORDER_BOX) {
368             LayoutUnit borderAndPaddingBefore = borderBefore() + (collapseBorders() ? LayoutUnit() : paddingBefore());
369             LayoutUnit borderAndPaddingAfter = borderAfter() + (collapseBorders() ? LayoutUnit() : paddingAfter());
370             borders = borderAndPaddingBefore + borderAndPaddingAfter;
371         }
372         computedLogicalHeight = styleLogicalHeight.value() - borders;
373     } else if (styleLogicalHeight.isPercent())
374         computedLogicalHeight = computePercentageLogicalHeight(styleLogicalHeight);
375     else
376         ASSERT_NOT_REACHED();
377     return std::max<LayoutUnit>(0, computedLogicalHeight);
378 }
379
380 void RenderTable::layoutCaption(RenderTableCaption* caption)
381 {
382     LayoutRect captionRect(caption->frameRect());
383
384     if (caption->needsLayout()) {
385         // The margins may not be available but ensure the caption is at least located beneath any previous sibling caption
386         // so that it does not mistakenly think any floats in the previous caption intrude into it.
387         caption->setLogicalLocation(LayoutPoint(caption->marginStart(), caption->marginBefore() + logicalHeight()));
388         // If RenderTableCaption ever gets a layout() function, use it here.
389         caption->layoutIfNeeded();
390     }
391     // Apply the margins to the location now that they are definitely available from layout
392     caption->setLogicalLocation(LayoutPoint(caption->marginStart(), caption->marginBefore() + logicalHeight()));
393
394     if (!selfNeedsLayout() && caption->checkForRepaintDuringLayout())
395         caption->repaintDuringLayoutIfMoved(captionRect);
396
397     setLogicalHeight(logicalHeight() + caption->logicalHeight() + caption->marginBefore() + caption->marginAfter());
398 }
399
400 void RenderTable::distributeExtraLogicalHeight(int extraLogicalHeight)
401 {
402     if (extraLogicalHeight <= 0)
403         return;
404
405     // FIXME: Distribute the extra logical height between all table sections instead of giving it all to the first one.
406     if (RenderTableSection* section = firstBody())
407         extraLogicalHeight -= section->distributeExtraLogicalHeightToRows(extraLogicalHeight);
408
409     // FIXME: We really would like to enable this ASSERT to ensure that all the extra space has been distributed.
410     // However our current distribution algorithm does not round properly and thus we can have some remaining height.
411     // ASSERT(!topSection() || !extraLogicalHeight);
412 }
413
414 void RenderTable::simplifiedNormalFlowLayout()
415 {
416     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
417         section->layoutIfNeeded();
418         section->computeOverflowFromCells();
419     }
420 }
421
422 void RenderTable::layout()
423 {
424     StackStats::LayoutCheckPoint layoutCheckPoint;
425     ASSERT(needsLayout());
426
427     if (simplifiedLayout())
428         return;
429
430     recalcSectionsIfNeeded();
431     // FIXME: We should do this recalc lazily in borderStart/borderEnd so that we don't have to make sure
432     // to call this before we call borderStart/borderEnd to avoid getting a stale value.
433     recalcBordersInRowDirection();
434         
435     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
436     LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
437
438     setLogicalHeight(0);
439     
440     LayoutUnit oldLogicalWidth = logicalWidth();
441     updateLogicalWidth();
442
443     if (logicalWidth() != oldLogicalWidth) {
444         for (unsigned i = 0; i < m_captions.size(); i++)
445             m_captions[i]->setNeedsLayout(MarkOnlyThis);
446     }
447     // FIXME: The optimisation below doesn't work since the internal table
448     // layout could have changed.  we need to add a flag to the table
449     // layout that tells us if something has changed in the min max
450     // calculations to do it correctly.
451 //     if ( oldWidth != width() || columns.size() + 1 != columnPos.size() )
452     m_tableLayout->layout();
453
454     LayoutUnit totalSectionLogicalHeight = 0;
455     LayoutUnit oldTableLogicalTop = 0;
456     for (unsigned i = 0; i < m_captions.size(); i++)
457         oldTableLogicalTop += m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
458
459     bool collapsing = collapseBorders();
460
461     for (auto& child : childrenOfType<RenderElement>(*this)) {
462         if (child.isTableSection()) {
463             RenderTableSection& section = toRenderTableSection(child);
464             if (m_columnLogicalWidthChanged)
465                 section.setChildNeedsLayout(MarkOnlyThis);
466             section.layoutIfNeeded();
467             totalSectionLogicalHeight += section.calcRowLogicalHeight();
468             if (collapsing)
469                 section.recalcOuterBorder();
470             ASSERT(!section.needsLayout());
471         } else if (child.isRenderTableCol()) {
472             toRenderTableCol(child).layoutIfNeeded();
473             ASSERT(!child.needsLayout());
474         }
475     }
476
477     // If any table section moved vertically, we will just repaint everything from that
478     // section down (it is quite unlikely that any of the following sections
479     // did not shift).
480     bool sectionMoved = false;
481     LayoutUnit movedSectionLogicalTop = 0;
482
483     // FIXME: Collapse caption margin.
484     if (!m_captions.isEmpty()) {
485         for (unsigned i = 0; i < m_captions.size(); i++) {
486             if (m_captions[i]->style().captionSide() == CAPBOTTOM)
487                 continue;
488             layoutCaption(m_captions[i]);
489         }
490         if (logicalHeight() != oldTableLogicalTop) {
491             sectionMoved = true;
492             movedSectionLogicalTop = std::min(logicalHeight(), oldTableLogicalTop);
493         }
494     }
495
496     LayoutUnit borderAndPaddingBefore = borderBefore() + (collapsing ? LayoutUnit() : paddingBefore());
497     LayoutUnit borderAndPaddingAfter = borderAfter() + (collapsing ? LayoutUnit() : paddingAfter());
498
499     setLogicalHeight(logicalHeight() + borderAndPaddingBefore);
500
501     if (!isOutOfFlowPositioned())
502         updateLogicalHeight();
503
504     LayoutUnit computedLogicalHeight = 0;
505     
506     Length logicalHeightLength = style().logicalHeight();
507     if (logicalHeightLength.isSpecified() && logicalHeightLength.isPositive())
508         computedLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalHeightLength);
509     
510     Length logicalMaxHeightLength = style().logicalMaxHeight();
511     if (logicalMaxHeightLength.isSpecified() && !logicalMaxHeightLength.isNegative()) {
512         LayoutUnit computedMaxLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMaxHeightLength);
513         computedLogicalHeight = std::min(computedLogicalHeight, computedMaxLogicalHeight);
514     }
515
516     Length logicalMinHeightLength = style().logicalMinHeight();
517     if (logicalMinHeightLength.isSpecified() && !logicalMinHeightLength.isNegative()) {
518         LayoutUnit computedMinLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMinHeightLength);
519         computedLogicalHeight = std::max(computedLogicalHeight, computedMinLogicalHeight);
520     }
521
522     distributeExtraLogicalHeight(floorToInt(computedLogicalHeight - totalSectionLogicalHeight));
523
524     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
525         section->layoutRows();
526
527     if (!topSection() && computedLogicalHeight > totalSectionLogicalHeight && !document().inQuirksMode()) {
528         // Completely empty tables (with no sections or anything) should at least honor specified height
529         // in strict mode.
530         setLogicalHeight(logicalHeight() + computedLogicalHeight);
531     }
532
533     LayoutUnit sectionLogicalLeft = style().isLeftToRightDirection() ? borderStart() : borderEnd();
534     if (!collapsing)
535         sectionLogicalLeft += style().isLeftToRightDirection() ? paddingStart() : paddingEnd();
536
537     // position the table sections
538     RenderTableSection* section = topSection();
539     while (section) {
540         if (!sectionMoved && section->logicalTop() != logicalHeight()) {
541             sectionMoved = true;
542             movedSectionLogicalTop = std::min(logicalHeight(), section->logicalTop()) + (style().isHorizontalWritingMode() ? section->visualOverflowRect().y() : section->visualOverflowRect().x());
543         }
544         section->setLogicalLocation(LayoutPoint(sectionLogicalLeft, logicalHeight()));
545
546         setLogicalHeight(logicalHeight() + section->logicalHeight());
547         section = sectionBelow(section);
548     }
549
550     setLogicalHeight(logicalHeight() + borderAndPaddingAfter);
551
552     for (unsigned i = 0; i < m_captions.size(); i++) {
553         if (m_captions[i]->style().captionSide() != CAPBOTTOM)
554             continue;
555         layoutCaption(m_captions[i]);
556     }
557
558     if (isOutOfFlowPositioned())
559         updateLogicalHeight();
560
561     // table can be containing block of positioned elements.
562     // FIXME: Only pass true if width or height changed.
563     layoutPositionedObjects(true);
564
565     updateLayerTransform();
566
567     // Layout was changed, so probably borders too.
568     invalidateCollapsedBorders();
569
570     // The location or height of one or more sections may have changed.
571     invalidateCachedColumnOffsets();
572
573     computeOverflow(clientLogicalBottom());
574
575     statePusher.pop();
576
577     if (view().layoutState()->pageLogicalHeight())
578         setPageLogicalOffset(view().layoutState()->pageLogicalOffset(this, logicalTop()));
579
580     bool didFullRepaint = repainter.repaintAfterLayout();
581     // Repaint with our new bounds if they are different from our old bounds.
582     if (!didFullRepaint && sectionMoved) {
583         if (style().isHorizontalWritingMode())
584             repaintRectangle(LayoutRect(visualOverflowRect().x(), movedSectionLogicalTop, visualOverflowRect().width(), visualOverflowRect().maxY() - movedSectionLogicalTop));
585         else
586             repaintRectangle(LayoutRect(movedSectionLogicalTop, visualOverflowRect().y(), visualOverflowRect().maxX() - movedSectionLogicalTop, visualOverflowRect().height()));
587     }
588
589     m_columnLogicalWidthChanged = false;
590     clearNeedsLayout();
591 }
592
593 // Collect all the unique border values that we want to paint in a sorted list.
594 void RenderTable::recalcCollapsedBorders()
595 {
596     if (m_collapsedBordersValid)
597         return;
598     m_collapsedBordersValid = true;
599     m_collapsedBorders.clear();
600
601     for (auto& section : childrenOfType<RenderTableSection>(*this)) {
602         for (RenderTableRow* row = section.firstRow(); row; row = row->nextRow()) {
603             for (RenderTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) {
604                 ASSERT(cell->table() == this);
605                 cell->collectBorderValues(m_collapsedBorders);
606             }
607         }
608     }
609     RenderTableCell::sortBorderValues(m_collapsedBorders);
610 }
611
612
613 void RenderTable::addOverflowFromChildren()
614 {
615     // Add overflow from borders.
616     // Technically it's odd that we are incorporating the borders into layout overflow, which is only supposed to be about overflow from our
617     // descendant objects, but since tables don't support overflow:auto, this works out fine.
618     if (collapseBorders()) {
619         int rightBorderOverflow = width() + outerBorderRight() - borderRight();
620         int leftBorderOverflow = borderLeft() - outerBorderLeft();
621         int bottomBorderOverflow = height() + outerBorderBottom() - borderBottom();
622         int topBorderOverflow = borderTop() - outerBorderTop();
623         IntRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow);
624         if (borderOverflowRect != pixelSnappedBorderBoxRect()) {
625             addLayoutOverflow(borderOverflowRect);
626             addVisualOverflow(borderOverflowRect);
627         }
628     }
629
630     // Add overflow from our caption.
631     for (unsigned i = 0; i < m_captions.size(); i++) 
632         addOverflowFromChild(m_captions[i]);
633
634     // Add overflow from our sections.
635     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
636         addOverflowFromChild(section);
637 }
638
639 void RenderTable::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
640 {
641     LayoutPoint adjustedPaintOffset = paintOffset + location();
642
643     PaintPhase paintPhase = paintInfo.phase;
644
645     if (!isRoot()) {
646         LayoutRect overflowBox = visualOverflowRect();
647         flipForWritingMode(overflowBox);
648         overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
649         overflowBox.moveBy(adjustedPaintOffset);
650         if (!overflowBox.intersects(paintInfo.rect))
651             return;
652     }
653
654     bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
655     paintObject(paintInfo, adjustedPaintOffset);
656     if (pushedClip)
657         popContentsClip(paintInfo, paintPhase, adjustedPaintOffset);
658 }
659
660 void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
661 {
662     PaintPhase paintPhase = paintInfo.phase;
663     if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style().visibility() == VISIBLE)
664         paintBoxDecorations(paintInfo, paintOffset);
665
666     if (paintPhase == PaintPhaseMask) {
667         paintMask(paintInfo, paintOffset);
668         return;
669     }
670
671     // We're done.  We don't bother painting any children.
672     if (paintPhase == PaintPhaseBlockBackground)
673         return;
674     
675     // We don't paint our own background, but we do let the kids paint their backgrounds.
676     if (paintPhase == PaintPhaseChildBlockBackgrounds)
677         paintPhase = PaintPhaseChildBlockBackground;
678
679     PaintInfo info(paintInfo);
680     info.phase = paintPhase;
681     info.updateSubtreePaintRootForChildren(this);
682
683     for (auto& box : childrenOfType<RenderBox>(*this)) {
684         if (!box.hasSelfPaintingLayer() && (box.isTableSection() || box.isTableCaption())) {
685             LayoutPoint childPoint = flipForWritingModeForChild(&box, paintOffset);
686             box.paint(info, childPoint);
687         }
688     }
689     
690     if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style().visibility() == VISIBLE) {
691         recalcCollapsedBorders();
692         // Using our cached sorted styles, we then do individual passes,
693         // painting each style of border from lowest precedence to highest precedence.
694         info.phase = PaintPhaseCollapsedTableBorders;
695         size_t count = m_collapsedBorders.size();
696         for (size_t i = 0; i < count; ++i) {
697             m_currentBorder = &m_collapsedBorders[i];
698             for (RenderTableSection* section = bottomSection(); section; section = sectionAbove(section)) {
699                 LayoutPoint childPoint = flipForWritingModeForChild(section, paintOffset);
700                 section->paint(info, childPoint);
701             }
702         }
703         m_currentBorder = 0;
704     }
705
706     // Paint outline.
707     if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style().visibility() == VISIBLE)
708         paintOutline(paintInfo, LayoutRect(paintOffset, size()));
709 }
710
711 void RenderTable::subtractCaptionRect(LayoutRect& rect) const
712 {
713     for (unsigned i = 0; i < m_captions.size(); i++) {
714         LayoutUnit captionLogicalHeight = m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
715         bool captionIsBefore = (m_captions[i]->style().captionSide() != CAPBOTTOM) ^ style().isFlippedBlocksWritingMode();
716         if (style().isHorizontalWritingMode()) {
717             rect.setHeight(rect.height() - captionLogicalHeight);
718             if (captionIsBefore)
719                 rect.move(0, captionLogicalHeight);
720         } else {
721             rect.setWidth(rect.width() - captionLogicalHeight);
722             if (captionIsBefore)
723                 rect.move(captionLogicalHeight, 0);
724         }
725     }
726 }
727
728 void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
729 {
730     if (!paintInfo.shouldPaintWithinRoot(*this))
731         return;
732
733     LayoutRect rect(paintOffset, size());
734     subtractCaptionRect(rect);
735
736     BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
737     if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance))
738         paintBoxShadow(paintInfo, rect, style(), Normal);
739     paintBackground(paintInfo, rect, bleedAvoidance);
740     paintBoxShadow(paintInfo, rect, style(), Inset);
741
742     if (style().hasBorder() && !collapseBorders())
743         paintBorder(paintInfo, rect, style());
744 }
745
746 void RenderTable::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
747 {
748     if (style().visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
749         return;
750
751     LayoutRect rect(paintOffset, size());
752     subtractCaptionRect(rect);
753
754     paintMaskImages(paintInfo, rect);
755 }
756
757 void RenderTable::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) const
758 {
759     recalcSectionsIfNeeded();
760     // FIXME: Do the recalc in borderStart/borderEnd and make those const_cast this call.
761     // Then m_borderStart/m_borderEnd will be transparent a cache and it removes the possibility
762     // of reading out stale values.
763     const_cast<RenderTable*>(this)->recalcBordersInRowDirection();
764     // FIXME: Restructure the table layout code so that we can make this method const.
765     const_cast<RenderTable*>(this)->m_tableLayout->computeIntrinsicLogicalWidths(minWidth, maxWidth);
766
767     // FIXME: We should include captions widths here like we do in computePreferredLogicalWidths.
768 }
769
770 void RenderTable::computePreferredLogicalWidths()
771 {
772     ASSERT(preferredLogicalWidthsDirty());
773
774     computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
775
776     int bordersPaddingAndSpacing = bordersPaddingAndSpacingInRowDirection();
777     m_minPreferredLogicalWidth += bordersPaddingAndSpacing;
778     m_maxPreferredLogicalWidth += bordersPaddingAndSpacing;
779
780     m_tableLayout->applyPreferredLogicalWidthQuirks(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
781
782     for (unsigned i = 0; i < m_captions.size(); i++)
783         m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, m_captions[i]->minPreferredLogicalWidth());
784
785     RenderStyle& styleToUse = style();
786     // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for min-width.
787     if (styleToUse.logicalMinWidth().isFixed() && styleToUse.logicalMinWidth().value() > 0) {
788         m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
789         m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
790     }
791
792     // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for maxWidth.
793     if (styleToUse.logicalMaxWidth().isFixed()) {
794         m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
795         m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
796     }
797
798     // FIXME: We should be adding borderAndPaddingLogicalWidth here, but m_tableLayout->computePreferredLogicalWidths already does,
799     // so a bunch of tests break doing this naively.
800     setPreferredLogicalWidthsDirty(false);
801 }
802
803 RenderTableSection* RenderTable::topNonEmptySection() const
804 {
805     RenderTableSection* section = topSection();
806     if (section && !section->numRows())
807         section = sectionBelow(section, SkipEmptySections);
808     return section;
809 }
810
811 void RenderTable::splitColumn(unsigned position, unsigned firstSpan)
812 {
813     // We split the column at "position", taking "firstSpan" cells from the span.
814     ASSERT(m_columns[position].span > firstSpan);
815     m_columns.insert(position, ColumnStruct(firstSpan));
816     m_columns[position + 1].span -= firstSpan;
817
818     // Propagate the change in our columns representation to the sections that don't need
819     // cell recalc. If they do, they will be synced up directly with m_columns later.
820     for (auto& section : childrenOfType<RenderTableSection>(*this)) {
821         if (section.needsCellRecalc())
822             continue;
823
824         section.splitColumn(position, firstSpan);
825     }
826
827     m_columnPos.grow(numEffCols() + 1);
828 }
829
830 void RenderTable::appendColumn(unsigned span)
831 {
832     unsigned newColumnIndex = m_columns.size();
833     m_columns.append(ColumnStruct(span));
834
835     // Unless the table has cell(s) with colspan that exceed the number of columns afforded
836     // by the other rows in the table we can use the fast path when mapping columns to effective columns.
837     m_hasCellColspanThatDeterminesTableWidth = m_hasCellColspanThatDeterminesTableWidth || span > 1;
838
839     // Propagate the change in our columns representation to the sections that don't need
840     // cell recalc. If they do, they will be synced up directly with m_columns later.
841     for (auto& section : childrenOfType<RenderTableSection>(*this)) {
842         if (section.needsCellRecalc())
843             continue;
844
845         section.appendColumn(newColumnIndex);
846     }
847
848     m_columnPos.grow(numEffCols() + 1);
849 }
850
851 RenderTableCol* RenderTable::firstColumn() const
852 {
853     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
854         if (child->isRenderTableCol())
855             return toRenderTableCol(child);
856
857         // We allow only table-captions before columns or column-groups.
858         if (!child->isTableCaption())
859             return 0;
860     }
861
862     return 0;
863 }
864
865 void RenderTable::updateColumnCache() const
866 {
867     ASSERT(m_hasColElements);
868     ASSERT(m_columnRenderers.isEmpty());
869     ASSERT(m_effectiveColumnIndexMap.isEmpty());
870     ASSERT(!m_columnRenderersValid);
871
872     unsigned columnIndex = 0;
873     for (RenderTableCol* columnRenderer = firstColumn(); columnRenderer; columnRenderer = columnRenderer->nextColumn()) {
874         if (columnRenderer->isTableColumnGroupWithColumnChildren())
875             continue;
876         m_columnRenderers.append(columnRenderer);
877         // FIXME: We should look to compute the effective column index successively from previous values instead of
878         // calling colToEffCol(), which is in O(numEffCols()). Although it's unlikely that this is a hot function.
879         m_effectiveColumnIndexMap.add(columnRenderer, colToEffCol(columnIndex));
880         columnIndex += columnRenderer->span();
881     }
882     m_columnRenderersValid = true;
883 }
884
885 unsigned RenderTable::effectiveIndexOfColumn(const RenderTableCol& column) const
886 {
887     if (!m_columnRenderersValid)
888         updateColumnCache();
889     const RenderTableCol* columnToUse = &column;
890     if (columnToUse->isTableColumnGroupWithColumnChildren())
891         columnToUse = columnToUse->nextColumn(); // First column in column-group
892     auto it = m_effectiveColumnIndexMap.find(columnToUse);
893     ASSERT(it != m_effectiveColumnIndexMap.end());
894     if (it == m_effectiveColumnIndexMap.end())
895         return std::numeric_limits<unsigned>::max();
896     return it->value;
897 }
898
899 LayoutUnit RenderTable::offsetTopForColumn(const RenderTableCol& column) const
900 {
901     if (effectiveIndexOfColumn(column) >= numEffCols())
902         return 0;
903     if (m_columnOffsetTop >= 0) {
904         ASSERT(!needsLayout());
905         return m_columnOffsetTop;
906     }
907     RenderTableSection* section = topNonEmptySection();
908     return m_columnOffsetTop = section ? section->offsetTop() : LayoutUnit(0);
909 }
910
911 LayoutUnit RenderTable::offsetLeftForColumn(const RenderTableCol& column) const
912 {
913     unsigned columnIndex = effectiveIndexOfColumn(column);
914     if (columnIndex >= numEffCols())
915         return 0;
916     return m_columnPos[columnIndex] + m_hSpacing + borderLeft();
917 }
918
919 LayoutUnit RenderTable::offsetWidthForColumn(const RenderTableCol& column) const
920 {
921     const RenderTableCol* currentColumn = &column;
922     bool hasColumnChildren;
923     if ((hasColumnChildren = currentColumn->isTableColumnGroupWithColumnChildren()))
924         currentColumn = currentColumn->nextColumn(); // First column in column-group
925     unsigned numberOfEffectiveColumns = numEffCols();
926     ASSERT_WITH_SECURITY_IMPLICATION(m_columnPos.size() >= numberOfEffectiveColumns + 1);
927     unsigned width = 0;
928     while (currentColumn) {
929         unsigned columnIndex = effectiveIndexOfColumn(*currentColumn);
930         unsigned span = currentColumn->span();
931         while (span && columnIndex < numberOfEffectiveColumns) {
932             width += m_columnPos[columnIndex + 1] - m_columnPos[columnIndex] - m_hSpacing;
933             span -= m_columns[columnIndex].span;
934             ++columnIndex;
935             if (span)
936                 width += m_hSpacing;
937         }
938         if (!hasColumnChildren)
939             break;
940         currentColumn = currentColumn->nextColumn();
941         if (!currentColumn || currentColumn->isTableColumnGroup())
942             break;
943         width += m_hSpacing;
944     }
945     return width;
946 }
947
948 LayoutUnit RenderTable::offsetHeightForColumn(const RenderTableCol& column) const
949 {
950     if (effectiveIndexOfColumn(column) >= numEffCols())
951         return 0;
952     if (m_columnOffsetHeight >= 0) {
953         ASSERT(!needsLayout());
954         return m_columnOffsetHeight;
955     }
956     LayoutUnit height = 0;
957     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
958         height += section->offsetHeight();
959     m_columnOffsetHeight = height;
960     return m_columnOffsetHeight;
961 }
962
963 RenderTableCol* RenderTable::slowColElement(unsigned col, bool* startEdge, bool* endEdge) const
964 {
965     ASSERT(m_hasColElements);
966
967     if (!m_columnRenderersValid)
968         updateColumnCache();
969
970     unsigned columnCount = 0;
971     for (unsigned i = 0; i < m_columnRenderers.size(); i++) {
972         RenderTableCol* columnRenderer = m_columnRenderers[i];
973         unsigned span = columnRenderer->span();
974         unsigned startCol = columnCount;
975         ASSERT(span >= 1);
976         unsigned endCol = columnCount + span - 1;
977         columnCount += span;
978         if (columnCount > col) {
979             if (startEdge)
980                 *startEdge = startCol == col;
981             if (endEdge)
982                 *endEdge = endCol == col;
983             return columnRenderer;
984         }
985     }
986     return 0;
987 }
988
989 void RenderTable::recalcSections() const
990 {
991     ASSERT(m_needsSectionRecalc);
992
993     m_head = 0;
994     m_foot = 0;
995     m_firstBody = 0;
996     m_hasColElements = false;
997     m_hasCellColspanThatDeterminesTableWidth = hasCellColspanThatDeterminesTableWidth();
998
999     // We need to get valid pointers to caption, head, foot and first body again
1000     RenderObject* nextSibling;
1001     for (RenderObject* child = firstChild(); child; child = nextSibling) {
1002         nextSibling = child->nextSibling();
1003         switch (child->style().display()) {
1004         case TABLE_COLUMN:
1005         case TABLE_COLUMN_GROUP:
1006             m_hasColElements = true;
1007             break;
1008         case TABLE_HEADER_GROUP:
1009             if (child->isTableSection()) {
1010                 RenderTableSection* section = toRenderTableSection(child);
1011                 if (!m_head)
1012                     m_head = section;
1013                 else if (!m_firstBody)
1014                     m_firstBody = section;
1015                 section->recalcCellsIfNeeded();
1016             }
1017             break;
1018         case TABLE_FOOTER_GROUP:
1019             if (child->isTableSection()) {
1020                 RenderTableSection* section = toRenderTableSection(child);
1021                 if (!m_foot)
1022                     m_foot = section;
1023                 else if (!m_firstBody)
1024                     m_firstBody = section;
1025                 section->recalcCellsIfNeeded();
1026             }
1027             break;
1028         case TABLE_ROW_GROUP:
1029             if (child->isTableSection()) {
1030                 RenderTableSection* section = toRenderTableSection(child);
1031                 if (!m_firstBody)
1032                     m_firstBody = section;
1033                 section->recalcCellsIfNeeded();
1034             }
1035             break;
1036         default:
1037             break;
1038         }
1039     }
1040
1041     // repair column count (addChild can grow it too much, because it always adds elements to the last row of a section)
1042     unsigned maxCols = 0;
1043     for (auto& section : childrenOfType<RenderTableSection>(*this)) {
1044         unsigned sectionCols = section.numColumns();
1045         if (sectionCols > maxCols)
1046             maxCols = sectionCols;
1047     }
1048     
1049     m_columns.resize(maxCols);
1050     m_columnPos.resize(maxCols + 1);
1051
1052     ASSERT(selfNeedsLayout());
1053
1054     m_needsSectionRecalc = false;
1055 }
1056
1057 int RenderTable::calcBorderStart() const
1058 {
1059     if (!collapseBorders())
1060         return RenderBlock::borderStart();
1061
1062     // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2.
1063     if (!numEffCols())
1064         return 0;
1065
1066     float borderWidth = 0;
1067
1068     const BorderValue& tableStartBorder = style().borderStart();
1069     if (tableStartBorder.style() == BHIDDEN)
1070         return 0;
1071     if (tableStartBorder.style() > BHIDDEN)
1072         borderWidth = tableStartBorder.width();
1073
1074     if (RenderTableCol* column = colElement(0)) {
1075         // FIXME: We don't account for direction on columns and column groups.
1076         const BorderValue& columnAdjoiningBorder = column->style().borderStart();
1077         if (columnAdjoiningBorder.style() == BHIDDEN)
1078             return 0;
1079         if (columnAdjoiningBorder.style() > BHIDDEN)
1080             borderWidth = std::max(borderWidth, columnAdjoiningBorder.width());
1081         // FIXME: This logic doesn't properly account for the first column in the first column-group case.
1082     }
1083
1084     if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) {
1085         const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableStart();
1086         if (sectionAdjoiningBorder.style() == BHIDDEN)
1087             return 0;
1088
1089         if (sectionAdjoiningBorder.style() > BHIDDEN)
1090             borderWidth = std::max(borderWidth, sectionAdjoiningBorder.width());
1091
1092         if (const RenderTableCell* adjoiningStartCell = topNonEmptySection->firstRowCellAdjoiningTableStart()) {
1093             // FIXME: Make this work with perpendicular and flipped cells.
1094             const BorderValue& startCellAdjoiningBorder = adjoiningStartCell->borderAdjoiningTableStart();
1095             if (startCellAdjoiningBorder.style() == BHIDDEN)
1096                 return 0;
1097
1098             const BorderValue& firstRowAdjoiningBorder = adjoiningStartCell->row()->borderAdjoiningTableStart();
1099             if (firstRowAdjoiningBorder.style() == BHIDDEN)
1100                 return 0;
1101
1102             if (startCellAdjoiningBorder.style() > BHIDDEN)
1103                 borderWidth = std::max(borderWidth, startCellAdjoiningBorder.width());
1104             if (firstRowAdjoiningBorder.style() > BHIDDEN)
1105                 borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width());
1106         }
1107     }
1108     return (borderWidth + (style().isLeftToRightDirection() ? 0 : 1)) / 2;
1109 }
1110
1111 int RenderTable::calcBorderEnd() const
1112 {
1113     if (!collapseBorders())
1114         return RenderBlock::borderEnd();
1115
1116     // Determined by the last cell of the first row. See the CSS 2.1 spec, section 17.6.2.
1117     if (!numEffCols())
1118         return 0;
1119
1120     float borderWidth = 0;
1121
1122     const BorderValue& tableEndBorder = style().borderEnd();
1123     if (tableEndBorder.style() == BHIDDEN)
1124         return 0;
1125     if (tableEndBorder.style() > BHIDDEN)
1126         borderWidth = tableEndBorder.width();
1127
1128     unsigned endColumn = numEffCols() - 1;
1129     if (RenderTableCol* column = colElement(endColumn)) {
1130         // FIXME: We don't account for direction on columns and column groups.
1131         const BorderValue& columnAdjoiningBorder = column->style().borderEnd();
1132         if (columnAdjoiningBorder.style() == BHIDDEN)
1133             return 0;
1134         if (columnAdjoiningBorder.style() > BHIDDEN)
1135             borderWidth = std::max(borderWidth, columnAdjoiningBorder.width());
1136         // FIXME: This logic doesn't properly account for the last column in the last column-group case.
1137     }
1138
1139     if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) {
1140         const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableEnd();
1141         if (sectionAdjoiningBorder.style() == BHIDDEN)
1142             return 0;
1143
1144         if (sectionAdjoiningBorder.style() > BHIDDEN)
1145             borderWidth = std::max(borderWidth, sectionAdjoiningBorder.width());
1146
1147         if (const RenderTableCell* adjoiningEndCell = topNonEmptySection->firstRowCellAdjoiningTableEnd()) {
1148             // FIXME: Make this work with perpendicular and flipped cells.
1149             const BorderValue& endCellAdjoiningBorder = adjoiningEndCell->borderAdjoiningTableEnd();
1150             if (endCellAdjoiningBorder.style() == BHIDDEN)
1151                 return 0;
1152
1153             const BorderValue& firstRowAdjoiningBorder = adjoiningEndCell->row()->borderAdjoiningTableEnd();
1154             if (firstRowAdjoiningBorder.style() == BHIDDEN)
1155                 return 0;
1156
1157             if (endCellAdjoiningBorder.style() > BHIDDEN)
1158                 borderWidth = std::max(borderWidth, endCellAdjoiningBorder.width());
1159             if (firstRowAdjoiningBorder.style() > BHIDDEN)
1160                 borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width());
1161         }
1162     }
1163     return (borderWidth + (style().isLeftToRightDirection() ? 1 : 0)) / 2;
1164 }
1165
1166 void RenderTable::recalcBordersInRowDirection()
1167 {
1168     // FIXME: We need to compute the collapsed before / after borders in the same fashion.
1169     m_borderStart = calcBorderStart();
1170     m_borderEnd = calcBorderEnd();
1171 }
1172
1173 LayoutUnit RenderTable::borderBefore() const
1174 {
1175     if (collapseBorders()) {
1176         recalcSectionsIfNeeded();
1177         return outerBorderBefore();
1178     }
1179     return RenderBlock::borderBefore();
1180 }
1181
1182 LayoutUnit RenderTable::borderAfter() const
1183 {
1184     if (collapseBorders()) {
1185         recalcSectionsIfNeeded();
1186         return outerBorderAfter();
1187     }
1188     return RenderBlock::borderAfter();
1189 }
1190
1191 int RenderTable::outerBorderBefore() const
1192 {
1193     if (!collapseBorders())
1194         return 0;
1195     int borderWidth = 0;
1196     if (RenderTableSection* topSection = this->topSection()) {
1197         borderWidth = topSection->outerBorderBefore();
1198         if (borderWidth < 0)
1199             return 0;   // Overridden by hidden
1200     }
1201     const BorderValue& tb = style().borderBefore();
1202     if (tb.style() == BHIDDEN)
1203         return 0;
1204     if (tb.style() > BHIDDEN)
1205         borderWidth = std::max<int>(borderWidth, tb.width() / 2);
1206     return borderWidth;
1207 }
1208
1209 int RenderTable::outerBorderAfter() const
1210 {
1211     if (!collapseBorders())
1212         return 0;
1213     int borderWidth = 0;
1214
1215     if (RenderTableSection* section = bottomSection()) {
1216         borderWidth = section->outerBorderAfter();
1217         if (borderWidth < 0)
1218             return 0; // Overridden by hidden
1219     }
1220     const BorderValue& tb = style().borderAfter();
1221     if (tb.style() == BHIDDEN)
1222         return 0;
1223     if (tb.style() > BHIDDEN)
1224         borderWidth = std::max<int>(borderWidth, (tb.width() + 1) / 2);
1225     return borderWidth;
1226 }
1227
1228 int RenderTable::outerBorderStart() const
1229 {
1230     if (!collapseBorders())
1231         return 0;
1232
1233     int borderWidth = 0;
1234
1235     const BorderValue& tb = style().borderStart();
1236     if (tb.style() == BHIDDEN)
1237         return 0;
1238     if (tb.style() > BHIDDEN)
1239         borderWidth = (tb.width() + (style().isLeftToRightDirection() ? 0 : 1)) / 2;
1240
1241     bool allHidden = true;
1242     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
1243         int sw = section->outerBorderStart();
1244         if (sw < 0)
1245             continue;
1246         allHidden = false;
1247         borderWidth = std::max(borderWidth, sw);
1248     }
1249     if (allHidden)
1250         return 0;
1251
1252     return borderWidth;
1253 }
1254
1255 int RenderTable::outerBorderEnd() const
1256 {
1257     if (!collapseBorders())
1258         return 0;
1259
1260     int borderWidth = 0;
1261
1262     const BorderValue& tb = style().borderEnd();
1263     if (tb.style() == BHIDDEN)
1264         return 0;
1265     if (tb.style() > BHIDDEN)
1266         borderWidth = (tb.width() + (style().isLeftToRightDirection() ? 1 : 0)) / 2;
1267
1268     bool allHidden = true;
1269     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
1270         int sw = section->outerBorderEnd();
1271         if (sw < 0)
1272             continue;
1273         allHidden = false;
1274         borderWidth = std::max(borderWidth, sw);
1275     }
1276     if (allHidden)
1277         return 0;
1278
1279     return borderWidth;
1280 }
1281
1282 RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section, SkipEmptySectionsValue skipEmptySections) const
1283 {
1284     recalcSectionsIfNeeded();
1285
1286     if (section == m_head)
1287         return 0;
1288
1289     RenderObject* prevSection = section == m_foot ? lastChild() : section->previousSibling();
1290     while (prevSection) {
1291         if (prevSection->isTableSection() && prevSection != m_head && prevSection != m_foot && (skipEmptySections == DoNotSkipEmptySections || toRenderTableSection(prevSection)->numRows()))
1292             break;
1293         prevSection = prevSection->previousSibling();
1294     }
1295     if (!prevSection && m_head && (skipEmptySections == DoNotSkipEmptySections || m_head->numRows()))
1296         prevSection = m_head;
1297     return toRenderTableSection(prevSection);
1298 }
1299
1300 RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, SkipEmptySectionsValue skipEmptySections) const
1301 {
1302     recalcSectionsIfNeeded();
1303
1304     if (section == m_foot)
1305         return 0;
1306
1307     RenderObject* nextSection = section == m_head ? firstChild() : section->nextSibling();
1308     while (nextSection) {
1309         if (nextSection->isTableSection() && nextSection != m_head && nextSection != m_foot && (skipEmptySections  == DoNotSkipEmptySections || toRenderTableSection(nextSection)->numRows()))
1310             break;
1311         nextSection = nextSection->nextSibling();
1312     }
1313     if (!nextSection && m_foot && (skipEmptySections == DoNotSkipEmptySections || m_foot->numRows()))
1314         nextSection = m_foot;
1315     return toRenderTableSection(nextSection);
1316 }
1317
1318 RenderTableSection* RenderTable::bottomSection() const
1319 {
1320     recalcSectionsIfNeeded();
1321
1322     if (m_foot)
1323         return m_foot;
1324
1325     for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
1326         if (child->isTableSection())
1327             return toRenderTableSection(child);
1328     }
1329
1330     return 0;
1331 }
1332
1333 RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
1334 {
1335     recalcSectionsIfNeeded();
1336
1337     // Find the section and row to look in
1338     unsigned r = cell->rowIndex();
1339     RenderTableSection* section = 0;
1340     unsigned rAbove = 0;
1341     if (r > 0) {
1342         // cell is not in the first row, so use the above row in its own section
1343         section = cell->section();
1344         rAbove = r - 1;
1345     } else {
1346         section = sectionAbove(cell->section(), SkipEmptySections);
1347         if (section) {
1348             ASSERT(section->numRows());
1349             rAbove = section->numRows() - 1;
1350         }
1351     }
1352
1353     // Look up the cell in the section's grid, which requires effective col index
1354     if (section) {
1355         unsigned effCol = colToEffCol(cell->col());
1356         RenderTableSection::CellStruct& aboveCell = section->cellAt(rAbove, effCol);
1357         return aboveCell.primaryCell();
1358     } else
1359         return 0;
1360 }
1361
1362 RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
1363 {
1364     recalcSectionsIfNeeded();
1365
1366     // Find the section and row to look in
1367     unsigned r = cell->rowIndex() + cell->rowSpan() - 1;
1368     RenderTableSection* section = 0;
1369     unsigned rBelow = 0;
1370     if (r < cell->section()->numRows() - 1) {
1371         // The cell is not in the last row, so use the next row in the section.
1372         section = cell->section();
1373         rBelow = r + 1;
1374     } else {
1375         section = sectionBelow(cell->section(), SkipEmptySections);
1376         if (section)
1377             rBelow = 0;
1378     }
1379
1380     // Look up the cell in the section's grid, which requires effective col index
1381     if (section) {
1382         unsigned effCol = colToEffCol(cell->col());
1383         RenderTableSection::CellStruct& belowCell = section->cellAt(rBelow, effCol);
1384         return belowCell.primaryCell();
1385     } else
1386         return 0;
1387 }
1388
1389 RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
1390 {
1391     recalcSectionsIfNeeded();
1392
1393     RenderTableSection* section = cell->section();
1394     unsigned effCol = colToEffCol(cell->col());
1395     if (!effCol)
1396         return 0;
1397     
1398     // If we hit a colspan back up to a real cell.
1399     RenderTableSection::CellStruct& prevCell = section->cellAt(cell->rowIndex(), effCol - 1);
1400     return prevCell.primaryCell();
1401 }
1402
1403 RenderTableCell* RenderTable::cellAfter(const RenderTableCell* cell) const
1404 {
1405     recalcSectionsIfNeeded();
1406
1407     unsigned effCol = colToEffCol(cell->col() + cell->colSpan());
1408     if (effCol >= numEffCols())
1409         return 0;
1410     return cell->section()->primaryCellAt(cell->rowIndex(), effCol);
1411 }
1412
1413 RenderBlock* RenderTable::firstLineBlock() const
1414 {
1415     return 0;
1416 }
1417
1418 void RenderTable::updateFirstLetter()
1419 {
1420 }
1421
1422 int RenderTable::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
1423 {
1424     LayoutUnit baseline = firstLineBaseline();
1425     if (baseline != -1)
1426         return baseline;
1427
1428     return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
1429 }
1430
1431 int RenderTable::inlineBlockBaseline(LineDirectionMode) const
1432 {
1433     // Tables are skipped when computing an inline-block's baseline.
1434     return -1;
1435 }
1436
1437 int RenderTable::firstLineBaseline() const
1438 {
1439     // The baseline of a 'table' is the same as the 'inline-table' baseline per CSS 3 Flexbox (CSS 2.1
1440     // doesn't define the baseline of a 'table' only an 'inline-table').
1441     // This is also needed to properly determine the baseline of a cell if it has a table child.
1442
1443     if (isWritingModeRoot())
1444         return -1;
1445
1446     recalcSectionsIfNeeded();
1447
1448     const RenderTableSection* topNonEmptySection = this->topNonEmptySection();
1449     if (!topNonEmptySection)
1450         return -1;
1451
1452     int baseline = topNonEmptySection->firstLineBaseline();
1453     if (baseline > 0)
1454         return topNonEmptySection->logicalTop() + baseline;
1455
1456     // FIXME: A table row always has a baseline per CSS 2.1. Will this return the right value?
1457     return -1;
1458 }
1459
1460 LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy, PaintPhase phase)
1461 {
1462     LayoutRect rect;
1463     // Don't clip out the table's side of the collapsed borders if we're in the paint phase that will ask the sections to paint them.
1464     // Likewise, if we're self-painting we avoid clipping them out as the clip rect that will be passed down to child layers from RenderLayer will do that instead.
1465     if (phase == PaintPhaseChildBlockBackgrounds || layer()->isSelfPaintingLayer()) {
1466         rect = borderBoxRectInRegion(region);
1467         rect.setLocation(location + rect.location());
1468     } else
1469         rect = RenderBox::overflowClipRect(location, region, relevancy);
1470     
1471     // If we have a caption, expand the clip to include the caption.
1472     // FIXME: Technically this is wrong, but it's virtually impossible to fix this
1473     // for real until captions have been re-written.
1474     // FIXME: This code assumes (like all our other caption code) that only top/bottom are
1475     // supported.  When we actually support left/right and stop mapping them to top/bottom,
1476     // we might have to hack this code first (depending on what order we do these bug fixes in).
1477     if (!m_captions.isEmpty()) {
1478         if (style().isHorizontalWritingMode()) {
1479             rect.setHeight(height());
1480             rect.setY(location.y());
1481         } else {
1482             rect.setWidth(width());
1483             rect.setX(location.x());
1484         }
1485     }
1486
1487     return rect;
1488 }
1489
1490 bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
1491 {
1492     LayoutPoint adjustedLocation = accumulatedOffset + location();
1493
1494     // Check kids first.
1495     if (!hasOverflowClip() || locationInContainer.intersects(overflowClipRect(adjustedLocation, currentRenderNamedFlowFragment()))) {
1496         for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
1497             if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
1498                 LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), adjustedLocation);
1499                 if (child->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
1500                     updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
1501                     return true;
1502                 }
1503             }
1504         }
1505     }
1506
1507     // Check our bounds next.
1508     LayoutRect boundsRect(adjustedLocation, size());
1509     if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && locationInContainer.intersects(boundsRect)) {
1510         updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(adjustedLocation)));
1511         if (!result.addNodeToRectBasedTestResult(element(), request, locationInContainer, boundsRect))
1512             return true;
1513     }
1514
1515     return false;
1516 }
1517
1518 RenderTable* RenderTable::createAnonymousWithParentRenderer(const RenderObject* parent)
1519 {
1520     auto table = new RenderTable(parent->document(), RenderStyle::createAnonymousStyleWithDisplay(&parent->style(), TABLE));
1521     table->initializeStyle();
1522     return table;
1523 }
1524
1525 const BorderValue& RenderTable::tableStartBorderAdjoiningCell(const RenderTableCell* cell) const
1526 {
1527     ASSERT(cell->isFirstOrLastCellInRow());
1528     if (hasSameDirectionAs(cell->row()))
1529         return style().borderStart();
1530
1531     return style().borderEnd();
1532 }
1533
1534 const BorderValue& RenderTable::tableEndBorderAdjoiningCell(const RenderTableCell* cell) const
1535 {
1536     ASSERT(cell->isFirstOrLastCellInRow());
1537     if (hasSameDirectionAs(cell->row()))
1538         return style().borderEnd();
1539
1540     return style().borderStart();
1541 }
1542
1543 }