5a4ae706e8bfcb801fcf4551e41a0fb8f32cc32e
[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, Ref<RenderStyle>&& style)
54     : RenderBlock(element, WTFMove(style), 0)
55     , m_head(nullptr)
56     , m_foot(nullptr)
57     , m_firstBody(nullptr)
58     , m_currentBorder(nullptr)
59     , m_collapsedBordersValid(false)
60     , m_collapsedEmptyBorderIsPresent(false)
61     , m_hasColElements(false)
62     , m_needsSectionRecalc(false)
63     , m_columnLogicalWidthChanged(false)
64     , m_columnRenderersValid(false)
65     , m_hasCellColspanThatDeterminesTableWidth(false)
66     , m_hSpacing(0)
67     , m_vSpacing(0)
68     , m_borderStart(0)
69     , m_borderEnd(0)
70     , m_columnOffsetTop(-1)
71     , m_columnOffsetHeight(-1)
72 {
73     setChildrenInline(false);
74     m_columnPos.fill(0, 1);
75 }
76
77 RenderTable::RenderTable(Document& document, Ref<RenderStyle>&& style)
78     : RenderBlock(document, WTFMove(style), 0)
79     , m_head(nullptr)
80     , m_foot(nullptr)
81     , m_firstBody(nullptr)
82     , m_currentBorder(nullptr)
83     , m_collapsedBordersValid(false)
84     , m_collapsedEmptyBorderIsPresent(false)
85     , m_hasColElements(false)
86     , m_needsSectionRecalc(false)
87     , m_columnLogicalWidthChanged(false)
88     , m_columnRenderersValid(false)
89     , m_hasCellColspanThatDeterminesTableWidth(false)
90     , m_hSpacing(0)
91     , m_vSpacing(0)
92     , m_borderStart(0)
93     , m_borderEnd(0)
94 {
95     setChildrenInline(false);
96     m_columnPos.fill(0, 1);
97 }
98
99 RenderTable::~RenderTable()
100 {
101 }
102
103 void RenderTable::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
104 {
105     RenderBlock::styleDidChange(diff, oldStyle);
106     propagateStyleToAnonymousChildren(PropagateToAllChildren);
107
108     ETableLayout oldTableLayout = oldStyle ? oldStyle->tableLayout() : TAUTO;
109
110     // In the collapsed border model, there is no cell spacing.
111     m_hSpacing = collapseBorders() ? 0 : style().horizontalBorderSpacing();
112     m_vSpacing = collapseBorders() ? 0 : style().verticalBorderSpacing();
113     m_columnPos[0] = m_hSpacing;
114
115     if (!m_tableLayout || style().tableLayout() != oldTableLayout) {
116         // According to the CSS2 spec, you only use fixed table layout if an
117         // explicit width is specified on the table.  Auto width implies auto table layout.
118         if (style().tableLayout() == TFIXED && !style().logicalWidth().isAuto())
119             m_tableLayout = std::make_unique<FixedTableLayout>(this);
120         else
121             m_tableLayout = std::make_unique<AutoTableLayout>(this);
122     }
123
124     // If border was changed, invalidate collapsed borders cache.
125     if (oldStyle && oldStyle->border() != style().border())
126         invalidateCollapsedBorders();
127 }
128
129 static inline void resetSectionPointerIfNotBefore(RenderTableSection*& ptr, RenderObject* before)
130 {
131     if (!before || !ptr)
132         return;
133     RenderObject* o = before->previousSibling();
134     while (o && o != ptr)
135         o = o->previousSibling();
136     if (!o)
137         ptr = 0;
138 }
139
140 void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
141 {
142     bool wrapInAnonymousSection = !child->isOutOfFlowPositioned();
143
144     if (is<RenderTableCaption>(*child))
145         wrapInAnonymousSection = false;
146     else if (is<RenderTableCol>(*child)) {
147         m_hasColElements = true;
148         wrapInAnonymousSection = false;
149     } else if (is<RenderTableSection>(*child)) {
150         switch (child->style().display()) {
151             case TABLE_HEADER_GROUP:
152                 resetSectionPointerIfNotBefore(m_head, beforeChild);
153                 if (!m_head) {
154                     m_head = downcast<RenderTableSection>(child);
155                 } else {
156                     resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
157                     if (!m_firstBody) 
158                         m_firstBody = downcast<RenderTableSection>(child);
159                 }
160                 wrapInAnonymousSection = false;
161                 break;
162             case TABLE_FOOTER_GROUP:
163                 resetSectionPointerIfNotBefore(m_foot, beforeChild);
164                 if (!m_foot) {
165                     m_foot = downcast<RenderTableSection>(child);
166                     wrapInAnonymousSection = false;
167                     break;
168                 }
169                 FALLTHROUGH;
170             case TABLE_ROW_GROUP:
171                 resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
172                 if (!m_firstBody)
173                     m_firstBody = downcast<RenderTableSection>(child);
174                 wrapInAnonymousSection = false;
175                 break;
176             default:
177                 ASSERT_NOT_REACHED();
178         }
179     } else if (is<RenderTableCell>(*child) || is<RenderTableRow>(*child))
180         wrapInAnonymousSection = true;
181     else
182         wrapInAnonymousSection = true;
183
184     if (is<RenderTableSection>(*child))
185         setNeedsSectionRecalc();
186
187     if (!wrapInAnonymousSection) {
188         if (beforeChild && beforeChild->parent() != this)
189             beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
190
191         RenderBox::addChild(child, beforeChild);
192         return;
193     }
194
195     if (!beforeChild && is<RenderTableSection>(lastChild()) && lastChild()->isAnonymous() && !lastChild()->isBeforeContent()) {
196         downcast<RenderTableSection>(*lastChild()).addChild(child);
197         return;
198     }
199
200     if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
201         RenderObject* section = beforeChild->previousSibling();
202         if (is<RenderTableSection>(section) && section->isAnonymous()) {
203             downcast<RenderTableSection>(*section).addChild(child);
204             return;
205         }
206     }
207
208     RenderObject* lastBox = beforeChild;
209     while (lastBox && lastBox->parent()->isAnonymous() && !is<RenderTableSection>(*lastBox) && lastBox->style().display() != TABLE_CAPTION && lastBox->style().display() != TABLE_COLUMN_GROUP)
210         lastBox = lastBox->parent();
211     if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox) && lastBox->isTableSection()) {
212         RenderTableSection& section = downcast<RenderTableSection>(*lastBox);
213         if (beforeChild == &section)
214             beforeChild = section.firstRow();
215         section.addChild(child, beforeChild);
216         return;
217     }
218
219     if (beforeChild && !is<RenderTableSection>(*beforeChild) && beforeChild->style().display() != TABLE_CAPTION && beforeChild->style().display() != TABLE_COLUMN_GROUP)
220         beforeChild = nullptr;
221
222     RenderTableSection* section = RenderTableSection::createAnonymousWithParentRenderer(this);
223     addChild(section, beforeChild);
224     section->addChild(child);
225 }
226
227 void RenderTable::addCaption(const RenderTableCaption* caption)
228 {
229     ASSERT(m_captions.find(caption) == notFound);
230     m_captions.append(const_cast<RenderTableCaption*>(caption));
231 }
232
233 void RenderTable::removeCaption(const RenderTableCaption* oldCaption)
234 {
235     bool removed = m_captions.removeFirst(oldCaption);
236     ASSERT_UNUSED(removed, removed);
237 }
238
239 void RenderTable::invalidateCachedColumns()
240 {
241     m_columnRenderersValid = false;
242     m_columnRenderers.resize(0);
243     m_effectiveColumnIndexMap.clear();
244 }
245
246 void RenderTable::invalidateCachedColumnOffsets()
247 {
248     m_columnOffsetTop = -1;
249     m_columnOffsetHeight = -1;
250 }
251
252 void RenderTable::addColumn(const RenderTableCol*)
253 {
254     invalidateCachedColumns();
255 }
256
257 void RenderTable::removeColumn(const RenderTableCol*)
258 {
259     invalidateCachedColumns();
260     // We don't really need to recompute our sections, but we need to update our
261     // column count and whether we have a column. Currently, we only have one
262     // size-fit-all flag but we may have to consider splitting it.
263     setNeedsSectionRecalc();
264 }
265
266 void RenderTable::updateLogicalWidth()
267 {
268     recalcSectionsIfNeeded();
269
270     if (isOutOfFlowPositioned()) {
271         LogicalExtentComputedValues computedValues;
272         computePositionedLogicalWidth(computedValues);
273         setLogicalWidth(computedValues.m_extent);
274         setLogicalLeft(computedValues.m_position);
275         setMarginStart(computedValues.m_margins.m_start);
276         setMarginEnd(computedValues.m_margins.m_end);
277     }
278
279     RenderBlock* cb = containingBlock();
280
281     LayoutUnit availableLogicalWidth = containingBlockLogicalWidthForContent();
282     bool hasPerpendicularContainingBlock = cb->style().isHorizontalWritingMode() != style().isHorizontalWritingMode();
283     LayoutUnit containerWidthInInlineDirection = hasPerpendicularContainingBlock ? perpendicularContainingBlockLogicalHeight() : availableLogicalWidth;
284
285     Length styleLogicalWidth = style().logicalWidth();
286     if ((styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive()) || styleLogicalWidth.isIntrinsic())
287         setLogicalWidth(convertStyleLogicalWidthToComputedWidth(styleLogicalWidth, containerWidthInInlineDirection));
288     else {
289         // Subtract out any fixed margins from our available width for auto width tables.
290         LayoutUnit marginStart = minimumValueForLength(style().marginStart(), availableLogicalWidth);
291         LayoutUnit marginEnd = minimumValueForLength(style().marginEnd(), availableLogicalWidth);
292         LayoutUnit marginTotal = marginStart + marginEnd;
293
294         // Subtract out our margins to get the available content width.
295         LayoutUnit availableContentLogicalWidth = std::max<LayoutUnit>(0, containerWidthInInlineDirection - marginTotal);
296         if (shrinkToAvoidFloats() && cb->containsFloats() && !hasPerpendicularContainingBlock) {
297             // FIXME: Work with regions someday.
298             availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, 0);
299         }
300
301         // Ensure we aren't bigger than our available width.
302         setLogicalWidth(std::min(availableContentLogicalWidth, maxPreferredLogicalWidth()));
303     }
304
305     // Ensure we aren't smaller than our min preferred width.
306     setLogicalWidth(std::max(logicalWidth(), minPreferredLogicalWidth()));
307
308     
309     // Ensure we aren't bigger than our max-width style.
310     Length styleMaxLogicalWidth = style().logicalMaxWidth();
311     if ((styleMaxLogicalWidth.isSpecified() && !styleMaxLogicalWidth.isNegative()) || styleMaxLogicalWidth.isIntrinsic()) {
312         LayoutUnit computedMaxLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMaxLogicalWidth, availableLogicalWidth);
313         setLogicalWidth(std::min(logicalWidth(), computedMaxLogicalWidth));
314     }
315
316     // Ensure we aren't smaller than our min-width style.
317     Length styleMinLogicalWidth = style().logicalMinWidth();
318     if ((styleMinLogicalWidth.isSpecified() && !styleMinLogicalWidth.isNegative()) || styleMinLogicalWidth.isIntrinsic()) {
319         LayoutUnit computedMinLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMinLogicalWidth, availableLogicalWidth);
320         setLogicalWidth(std::max(logicalWidth(), computedMinLogicalWidth));
321     }
322
323     // Finally, with our true width determined, compute our margins for real.
324     setMarginStart(0);
325     setMarginEnd(0);
326     if (!hasPerpendicularContainingBlock) {
327         LayoutUnit containerLogicalWidthForAutoMargins = availableLogicalWidth;
328         if (avoidsFloats() && cb->containsFloats())
329             containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(0); // FIXME: Work with regions someday.
330         ComputedMarginValues marginValues;
331         bool hasInvertedDirection =  cb->style().isLeftToRightDirection() == style().isLeftToRightDirection();
332         computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth(),
333             hasInvertedDirection ? marginValues.m_start : marginValues.m_end,
334             hasInvertedDirection ? marginValues.m_end : marginValues.m_start);
335         setMarginStart(marginValues.m_start);
336         setMarginEnd(marginValues.m_end);
337     } else {
338         setMarginStart(minimumValueForLength(style().marginStart(), availableLogicalWidth));
339         setMarginEnd(minimumValueForLength(style().marginEnd(), availableLogicalWidth));
340     }
341 }
342
343 // This method takes a RenderStyle's logical width, min-width, or max-width length and computes its actual value.
344 LayoutUnit RenderTable::convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth)
345 {
346     if (styleLogicalWidth.isIntrinsic())
347         return computeIntrinsicLogicalWidthUsing(styleLogicalWidth, availableWidth, bordersPaddingAndSpacingInRowDirection());
348
349     // HTML tables' width styles already include borders and paddings, but CSS tables' width styles do not.
350     LayoutUnit borders = 0;
351     bool isCSSTable = !is<HTMLTableElement>(element());
352     if (isCSSTable && styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive() && style().boxSizing() == CONTENT_BOX)
353         borders = borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd());
354
355     return minimumValueForLength(styleLogicalWidth, availableWidth) + borders;
356 }
357
358 LayoutUnit RenderTable::convertStyleLogicalHeightToComputedHeight(const Length& styleLogicalHeight)
359 {
360     LayoutUnit borderAndPaddingBefore = borderBefore() + (collapseBorders() ? LayoutUnit() : paddingBefore());
361     LayoutUnit borderAndPaddingAfter = borderAfter() + (collapseBorders() ? LayoutUnit() : paddingAfter());
362     LayoutUnit borderAndPadding = borderAndPaddingBefore + borderAndPaddingAfter;
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             borders = borderAndPadding;
369         }
370         return styleLogicalHeight.value() - borders;
371     } else if (styleLogicalHeight.isPercentOrCalculated())
372         return computePercentageLogicalHeight(styleLogicalHeight).valueOr(0);
373     else if (styleLogicalHeight.isIntrinsic())
374         return computeIntrinsicLogicalContentHeightUsing(styleLogicalHeight, logicalHeight() - borderAndPadding, borderAndPadding).valueOr(0);
375     else
376         ASSERT_NOT_REACHED();
377     return LayoutUnit();
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(LayoutUnit 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     LayoutUnit oldLogicalWidth = logicalWidth();
439     LayoutUnit oldLogicalHeight = logicalHeight();
440     setLogicalHeight(0);
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 (is<RenderTableSection>(child)) {
463             RenderTableSection& section = downcast<RenderTableSection>(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 (is<RenderTableCol>(child)) {
472             downcast<RenderTableCol>(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.isIntrinsic() || (logicalHeightLength.isSpecified() && logicalHeightLength.isPositive()))
508         computedLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalHeightLength);
509     
510     Length logicalMaxHeightLength = style().logicalMaxHeight();
511     if (logicalMaxHeightLength.isIntrinsic() || (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.isIntrinsic() || (logicalMinHeightLength.isSpecified() && !logicalMinHeightLength.isNegative())) {
518         LayoutUnit computedMinLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMinHeightLength);
519         computedLogicalHeight = std::max(computedLogicalHeight, computedMinLogicalHeight);
520     }
521
522     distributeExtraLogicalHeight(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     bool dimensionChanged = oldLogicalWidth != logicalWidth() || oldLogicalHeight != logicalHeight();
563     layoutPositionedObjects(dimensionChanged);
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 void RenderTable::invalidateCollapsedBorders()
594 {
595     m_collapsedBordersValid = false;
596     m_collapsedBorders.clear();
597     for (auto& section : childrenOfType<RenderTableSection>(*this)) {
598         section.clearCachedCollapsedBorders();
599         if (!m_collapsedEmptyBorderIsPresent)
600             continue;
601         for (auto* row = section.firstRow(); row; row = row->nextRow()) {
602             for (auto* cell = row->firstCell(); cell; cell = cell->nextCell()) {
603                 ASSERT(cell->table() == this);
604                 cell->invalidateHasEmptyCollapsedBorders();
605             }
606         }
607     }
608     m_collapsedEmptyBorderIsPresent = false;
609 }
610
611 // Collect all the unique border values that we want to paint in a sorted list.
612 void RenderTable::recalcCollapsedBorders()
613 {
614     if (m_collapsedBordersValid)
615         return;
616     m_collapsedBorders.clear();
617     for (auto& section : childrenOfType<RenderTableSection>(*this)) {
618         for (RenderTableRow* row = section.firstRow(); row; row = row->nextRow()) {
619             for (RenderTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) {
620                 ASSERT(cell->table() == this);
621                 cell->collectBorderValues(m_collapsedBorders);
622             }
623         }
624     }
625     RenderTableCell::sortBorderValues(m_collapsedBorders);
626     m_collapsedBordersValid = true;
627 }
628
629 void RenderTable::addOverflowFromChildren()
630 {
631     // Add overflow from borders.
632     // Technically it's odd that we are incorporating the borders into layout overflow, which is only supposed to be about overflow from our
633     // descendant objects, but since tables don't support overflow:auto, this works out fine.
634     if (collapseBorders()) {
635         LayoutUnit rightBorderOverflow = width() + outerBorderRight() - borderRight();
636         LayoutUnit leftBorderOverflow = borderLeft() - outerBorderLeft();
637         LayoutUnit bottomBorderOverflow = height() + outerBorderBottom() - borderBottom();
638         LayoutUnit topBorderOverflow = borderTop() - outerBorderTop();
639         LayoutRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow);
640         if (borderOverflowRect != borderBoxRect()) {
641             addLayoutOverflow(borderOverflowRect);
642             addVisualOverflow(borderOverflowRect);
643         }
644     }
645
646     // Add overflow from our caption.
647     for (unsigned i = 0; i < m_captions.size(); i++) 
648         addOverflowFromChild(m_captions[i]);
649
650     // Add overflow from our sections.
651     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
652         addOverflowFromChild(section);
653 }
654
655 void RenderTable::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
656 {
657     LayoutPoint adjustedPaintOffset = paintOffset + location();
658
659     PaintPhase paintPhase = paintInfo.phase;
660
661     if (!isDocumentElementRenderer()) {
662         LayoutRect overflowBox = visualOverflowRect();
663         adjustRectWithMaximumOutline(paintInfo.phase, overflowBox);
664         flipForWritingMode(overflowBox);
665         overflowBox.moveBy(adjustedPaintOffset);
666         if (!overflowBox.intersects(paintInfo.rect))
667             return;
668     }
669
670     bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
671     paintObject(paintInfo, adjustedPaintOffset);
672     if (pushedClip)
673         popContentsClip(paintInfo, paintPhase, adjustedPaintOffset);
674 }
675
676 void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
677 {
678     PaintPhase paintPhase = paintInfo.phase;
679     if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style().visibility() == VISIBLE)
680         paintBoxDecorations(paintInfo, paintOffset);
681
682     if (paintPhase == PaintPhaseMask) {
683         paintMask(paintInfo, paintOffset);
684         return;
685     }
686
687     // We're done.  We don't bother painting any children.
688     if (paintPhase == PaintPhaseBlockBackground)
689         return;
690     
691     // We don't paint our own background, but we do let the kids paint their backgrounds.
692     if (paintPhase == PaintPhaseChildBlockBackgrounds)
693         paintPhase = PaintPhaseChildBlockBackground;
694
695     PaintInfo info(paintInfo);
696     info.phase = paintPhase;
697     info.updateSubtreePaintRootForChildren(this);
698
699     for (auto& box : childrenOfType<RenderBox>(*this)) {
700         if (!box.hasSelfPaintingLayer() && (box.isTableSection() || box.isTableCaption())) {
701             LayoutPoint childPoint = flipForWritingModeForChild(&box, paintOffset);
702             box.paint(info, childPoint);
703         }
704     }
705     
706     if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style().visibility() == VISIBLE) {
707         recalcCollapsedBorders();
708         // Using our cached sorted styles, we then do individual passes,
709         // painting each style of border from lowest precedence to highest precedence.
710         info.phase = PaintPhaseCollapsedTableBorders;
711         size_t count = m_collapsedBorders.size();
712         for (size_t i = 0; i < count; ++i) {
713             m_currentBorder = &m_collapsedBorders[i];
714             for (RenderTableSection* section = bottomSection(); section; section = sectionAbove(section)) {
715                 LayoutPoint childPoint = flipForWritingModeForChild(section, paintOffset);
716                 section->paint(info, childPoint);
717             }
718         }
719         m_currentBorder = 0;
720     }
721
722     // Paint outline.
723     if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style().visibility() == VISIBLE)
724         paintOutline(paintInfo, LayoutRect(paintOffset, size()));
725 }
726
727 void RenderTable::subtractCaptionRect(LayoutRect& rect) const
728 {
729     for (unsigned i = 0; i < m_captions.size(); i++) {
730         LayoutUnit captionLogicalHeight = m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
731         bool captionIsBefore = (m_captions[i]->style().captionSide() != CAPBOTTOM) ^ style().isFlippedBlocksWritingMode();
732         if (style().isHorizontalWritingMode()) {
733             rect.setHeight(rect.height() - captionLogicalHeight);
734             if (captionIsBefore)
735                 rect.move(0, captionLogicalHeight);
736         } else {
737             rect.setWidth(rect.width() - captionLogicalHeight);
738             if (captionIsBefore)
739                 rect.move(captionLogicalHeight, 0);
740         }
741     }
742 }
743
744 void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
745 {
746     if (!paintInfo.shouldPaintWithinRoot(*this))
747         return;
748
749     LayoutRect rect(paintOffset, size());
750     subtractCaptionRect(rect);
751
752     BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context());
753     if (!boxShadowShouldBeAppliedToBackground(rect.location(), bleedAvoidance))
754         paintBoxShadow(paintInfo, rect, style(), Normal);
755     paintBackground(paintInfo, rect, bleedAvoidance);
756     paintBoxShadow(paintInfo, rect, style(), Inset);
757
758     if (style().hasBorderDecoration() && !collapseBorders())
759         paintBorder(paintInfo, rect, style());
760 }
761
762 void RenderTable::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
763 {
764     if (style().visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
765         return;
766
767     LayoutRect rect(paintOffset, size());
768     subtractCaptionRect(rect);
769
770     paintMaskImages(paintInfo, rect);
771 }
772
773 void RenderTable::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) const
774 {
775     recalcSectionsIfNeeded();
776     // FIXME: Do the recalc in borderStart/borderEnd and make those const_cast this call.
777     // Then m_borderStart/m_borderEnd will be transparent a cache and it removes the possibility
778     // of reading out stale values.
779     const_cast<RenderTable*>(this)->recalcBordersInRowDirection();
780     // FIXME: Restructure the table layout code so that we can make this method const.
781     const_cast<RenderTable*>(this)->m_tableLayout->computeIntrinsicLogicalWidths(minWidth, maxWidth);
782
783     // FIXME: We should include captions widths here like we do in computePreferredLogicalWidths.
784 }
785
786 void RenderTable::computePreferredLogicalWidths()
787 {
788     ASSERT(preferredLogicalWidthsDirty());
789
790     computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
791
792     LayoutUnit bordersPaddingAndSpacing = bordersPaddingAndSpacingInRowDirection();
793     m_minPreferredLogicalWidth += bordersPaddingAndSpacing;
794     m_maxPreferredLogicalWidth += bordersPaddingAndSpacing;
795
796     m_tableLayout->applyPreferredLogicalWidthQuirks(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
797
798     for (unsigned i = 0; i < m_captions.size(); i++)
799         m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, m_captions[i]->minPreferredLogicalWidth());
800
801     RenderStyle& styleToUse = style();
802     // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for min-width.
803     if (styleToUse.logicalMinWidth().isFixed() && styleToUse.logicalMinWidth().value() > 0) {
804         m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
805         m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
806     }
807
808     // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for maxWidth.
809     if (styleToUse.logicalMaxWidth().isFixed()) {
810         m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
811         m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
812     }
813
814     // FIXME: We should be adding borderAndPaddingLogicalWidth here, but m_tableLayout->computePreferredLogicalWidths already does,
815     // so a bunch of tests break doing this naively.
816     setPreferredLogicalWidthsDirty(false);
817 }
818
819 RenderTableSection* RenderTable::topNonEmptySection() const
820 {
821     RenderTableSection* section = topSection();
822     if (section && !section->numRows())
823         section = sectionBelow(section, SkipEmptySections);
824     return section;
825 }
826
827 void RenderTable::splitColumn(unsigned position, unsigned firstSpan)
828 {
829     // We split the column at "position", taking "firstSpan" cells from the span.
830     ASSERT(m_columns[position].span > firstSpan);
831     m_columns.insert(position, ColumnStruct(firstSpan));
832     m_columns[position + 1].span -= firstSpan;
833
834     // Propagate the change in our columns representation to the sections that don't need
835     // cell recalc. If they do, they will be synced up directly with m_columns later.
836     for (auto& section : childrenOfType<RenderTableSection>(*this)) {
837         if (section.needsCellRecalc())
838             continue;
839
840         section.splitColumn(position, firstSpan);
841     }
842
843     m_columnPos.grow(numEffCols() + 1);
844 }
845
846 void RenderTable::appendColumn(unsigned span)
847 {
848     unsigned newColumnIndex = m_columns.size();
849     m_columns.append(ColumnStruct(span));
850
851     // Unless the table has cell(s) with colspan that exceed the number of columns afforded
852     // by the other rows in the table we can use the fast path when mapping columns to effective columns.
853     m_hasCellColspanThatDeterminesTableWidth = m_hasCellColspanThatDeterminesTableWidth || span > 1;
854
855     // Propagate the change in our columns representation to the sections that don't need
856     // cell recalc. If they do, they will be synced up directly with m_columns later.
857     for (auto& section : childrenOfType<RenderTableSection>(*this)) {
858         if (section.needsCellRecalc())
859             continue;
860
861         section.appendColumn(newColumnIndex);
862     }
863
864     m_columnPos.grow(numEffCols() + 1);
865 }
866
867 RenderTableCol* RenderTable::firstColumn() const
868 {
869     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
870         if (is<RenderTableCol>(*child))
871             return downcast<RenderTableCol>(child);
872
873         // We allow only table-captions before columns or column-groups.
874         if (!is<RenderTableCaption>(*child))
875             return nullptr;
876     }
877
878     return nullptr;
879 }
880
881 void RenderTable::updateColumnCache() const
882 {
883     ASSERT(m_hasColElements);
884     ASSERT(m_columnRenderers.isEmpty());
885     ASSERT(m_effectiveColumnIndexMap.isEmpty());
886     ASSERT(!m_columnRenderersValid);
887
888     unsigned columnIndex = 0;
889     for (RenderTableCol* columnRenderer = firstColumn(); columnRenderer; columnRenderer = columnRenderer->nextColumn()) {
890         if (columnRenderer->isTableColumnGroupWithColumnChildren())
891             continue;
892         m_columnRenderers.append(columnRenderer);
893         // FIXME: We should look to compute the effective column index successively from previous values instead of
894         // calling colToEffCol(), which is in O(numEffCols()). Although it's unlikely that this is a hot function.
895         m_effectiveColumnIndexMap.add(columnRenderer, colToEffCol(columnIndex));
896         columnIndex += columnRenderer->span();
897     }
898     m_columnRenderersValid = true;
899 }
900
901 unsigned RenderTable::effectiveIndexOfColumn(const RenderTableCol& column) const
902 {
903     if (!m_columnRenderersValid)
904         updateColumnCache();
905     const RenderTableCol* columnToUse = &column;
906     if (columnToUse->isTableColumnGroupWithColumnChildren())
907         columnToUse = columnToUse->nextColumn(); // First column in column-group
908     auto it = m_effectiveColumnIndexMap.find(columnToUse);
909     ASSERT(it != m_effectiveColumnIndexMap.end());
910     if (it == m_effectiveColumnIndexMap.end())
911         return std::numeric_limits<unsigned>::max();
912     return it->value;
913 }
914
915 LayoutUnit RenderTable::offsetTopForColumn(const RenderTableCol& column) const
916 {
917     if (effectiveIndexOfColumn(column) >= numEffCols())
918         return 0;
919     if (m_columnOffsetTop >= 0) {
920         ASSERT(!needsLayout());
921         return m_columnOffsetTop;
922     }
923     RenderTableSection* section = topNonEmptySection();
924     return m_columnOffsetTop = section ? section->offsetTop() : LayoutUnit(0);
925 }
926
927 LayoutUnit RenderTable::offsetLeftForColumn(const RenderTableCol& column) const
928 {
929     unsigned columnIndex = effectiveIndexOfColumn(column);
930     if (columnIndex >= numEffCols())
931         return 0;
932     return m_columnPos[columnIndex] + LayoutUnit(m_hSpacing) + borderLeft();
933 }
934
935 LayoutUnit RenderTable::offsetWidthForColumn(const RenderTableCol& column) const
936 {
937     const RenderTableCol* currentColumn = &column;
938     bool hasColumnChildren;
939     if ((hasColumnChildren = currentColumn->isTableColumnGroupWithColumnChildren()))
940         currentColumn = currentColumn->nextColumn(); // First column in column-group
941     unsigned numberOfEffectiveColumns = numEffCols();
942     ASSERT_WITH_SECURITY_IMPLICATION(m_columnPos.size() >= numberOfEffectiveColumns + 1);
943     LayoutUnit width = 0;
944     LayoutUnit spacing = m_hSpacing;
945     while (currentColumn) {
946         unsigned columnIndex = effectiveIndexOfColumn(*currentColumn);
947         unsigned span = currentColumn->span();
948         while (span && columnIndex < numberOfEffectiveColumns) {
949             width += m_columnPos[columnIndex + 1] - m_columnPos[columnIndex] - spacing;
950             span -= m_columns[columnIndex].span;
951             ++columnIndex;
952             if (span)
953                 width += spacing;
954         }
955         if (!hasColumnChildren)
956             break;
957         currentColumn = currentColumn->nextColumn();
958         if (!currentColumn || currentColumn->isTableColumnGroup())
959             break;
960         width += spacing;
961     }
962     return width;
963 }
964
965 LayoutUnit RenderTable::offsetHeightForColumn(const RenderTableCol& column) const
966 {
967     if (effectiveIndexOfColumn(column) >= numEffCols())
968         return 0;
969     if (m_columnOffsetHeight >= 0) {
970         ASSERT(!needsLayout());
971         return m_columnOffsetHeight;
972     }
973     LayoutUnit height = 0;
974     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
975         height += section->offsetHeight();
976     m_columnOffsetHeight = height;
977     return m_columnOffsetHeight;
978 }
979
980 RenderTableCol* RenderTable::slowColElement(unsigned col, bool* startEdge, bool* endEdge) const
981 {
982     ASSERT(m_hasColElements);
983
984     if (!m_columnRenderersValid)
985         updateColumnCache();
986
987     unsigned columnCount = 0;
988     for (unsigned i = 0; i < m_columnRenderers.size(); i++) {
989         RenderTableCol* columnRenderer = m_columnRenderers[i];
990         unsigned span = columnRenderer->span();
991         unsigned startCol = columnCount;
992         ASSERT(span >= 1);
993         unsigned endCol = columnCount + span - 1;
994         columnCount += span;
995         if (columnCount > col) {
996             if (startEdge)
997                 *startEdge = startCol == col;
998             if (endEdge)
999                 *endEdge = endCol == col;
1000             return columnRenderer;
1001         }
1002     }
1003     return 0;
1004 }
1005
1006 void RenderTable::recalcSections() const
1007 {
1008     ASSERT(m_needsSectionRecalc);
1009
1010     m_head = 0;
1011     m_foot = 0;
1012     m_firstBody = 0;
1013     m_hasColElements = false;
1014     m_hasCellColspanThatDeterminesTableWidth = hasCellColspanThatDeterminesTableWidth();
1015
1016     // We need to get valid pointers to caption, head, foot and first body again
1017     RenderObject* nextSibling;
1018     for (RenderObject* child = firstChild(); child; child = nextSibling) {
1019         nextSibling = child->nextSibling();
1020         switch (child->style().display()) {
1021         case TABLE_COLUMN:
1022         case TABLE_COLUMN_GROUP:
1023             m_hasColElements = true;
1024             break;
1025         case TABLE_HEADER_GROUP:
1026             if (is<RenderTableSection>(*child)) {
1027                 RenderTableSection& section = downcast<RenderTableSection>(*child);
1028                 if (!m_head)
1029                     m_head = &section;
1030                 else if (!m_firstBody)
1031                     m_firstBody = &section;
1032                 section.recalcCellsIfNeeded();
1033             }
1034             break;
1035         case TABLE_FOOTER_GROUP:
1036             if (is<RenderTableSection>(*child)) {
1037                 RenderTableSection& section = downcast<RenderTableSection>(*child);
1038                 if (!m_foot)
1039                     m_foot = &section;
1040                 else if (!m_firstBody)
1041                     m_firstBody = &section;
1042                 section.recalcCellsIfNeeded();
1043             }
1044             break;
1045         case TABLE_ROW_GROUP:
1046             if (is<RenderTableSection>(*child)) {
1047                 RenderTableSection& section = downcast<RenderTableSection>(*child);
1048                 if (!m_firstBody)
1049                     m_firstBody = &section;
1050                 section.recalcCellsIfNeeded();
1051             }
1052             break;
1053         default:
1054             break;
1055         }
1056     }
1057
1058     // repair column count (addChild can grow it too much, because it always adds elements to the last row of a section)
1059     unsigned maxCols = 0;
1060     for (auto& section : childrenOfType<RenderTableSection>(*this)) {
1061         unsigned sectionCols = section.numColumns();
1062         if (sectionCols > maxCols)
1063             maxCols = sectionCols;
1064     }
1065     
1066     m_columns.resize(maxCols);
1067     m_columnPos.resize(maxCols + 1);
1068
1069     ASSERT(selfNeedsLayout());
1070
1071     m_needsSectionRecalc = false;
1072 }
1073
1074 LayoutUnit RenderTable::calcBorderStart() const
1075 {
1076     if (!collapseBorders())
1077         return RenderBlock::borderStart();
1078
1079     // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2.
1080     if (!numEffCols())
1081         return 0;
1082
1083     float borderWidth = 0;
1084
1085     const BorderValue& tableStartBorder = style().borderStart();
1086     if (tableStartBorder.style() == BHIDDEN)
1087         return 0;
1088     if (tableStartBorder.style() > BHIDDEN)
1089         borderWidth = tableStartBorder.width();
1090
1091     if (RenderTableCol* column = colElement(0)) {
1092         // FIXME: We don't account for direction on columns and column groups.
1093         const BorderValue& columnAdjoiningBorder = column->style().borderStart();
1094         if (columnAdjoiningBorder.style() == BHIDDEN)
1095             return 0;
1096         if (columnAdjoiningBorder.style() > BHIDDEN)
1097             borderWidth = std::max(borderWidth, columnAdjoiningBorder.width());
1098         // FIXME: This logic doesn't properly account for the first column in the first column-group case.
1099     }
1100
1101     if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) {
1102         const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableStart();
1103         if (sectionAdjoiningBorder.style() == BHIDDEN)
1104             return 0;
1105
1106         if (sectionAdjoiningBorder.style() > BHIDDEN)
1107             borderWidth = std::max(borderWidth, sectionAdjoiningBorder.width());
1108
1109         if (const RenderTableCell* adjoiningStartCell = topNonEmptySection->firstRowCellAdjoiningTableStart()) {
1110             // FIXME: Make this work with perpendicular and flipped cells.
1111             const BorderValue& startCellAdjoiningBorder = adjoiningStartCell->borderAdjoiningTableStart();
1112             if (startCellAdjoiningBorder.style() == BHIDDEN)
1113                 return 0;
1114
1115             const BorderValue& firstRowAdjoiningBorder = adjoiningStartCell->row()->borderAdjoiningTableStart();
1116             if (firstRowAdjoiningBorder.style() == BHIDDEN)
1117                 return 0;
1118
1119             if (startCellAdjoiningBorder.style() > BHIDDEN)
1120                 borderWidth = std::max(borderWidth, startCellAdjoiningBorder.width());
1121             if (firstRowAdjoiningBorder.style() > BHIDDEN)
1122                 borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width());
1123         }
1124     }
1125     return floorToInt((borderWidth + (style().isLeftToRightDirection() ? 0 : 1)) / 2);
1126 }
1127
1128 LayoutUnit RenderTable::calcBorderEnd() const
1129 {
1130     if (!collapseBorders())
1131         return RenderBlock::borderEnd();
1132
1133     // Determined by the last cell of the first row. See the CSS 2.1 spec, section 17.6.2.
1134     if (!numEffCols())
1135         return 0;
1136
1137     float borderWidth = 0;
1138
1139     const BorderValue& tableEndBorder = style().borderEnd();
1140     if (tableEndBorder.style() == BHIDDEN)
1141         return 0;
1142     if (tableEndBorder.style() > BHIDDEN)
1143         borderWidth = tableEndBorder.width();
1144
1145     unsigned endColumn = numEffCols() - 1;
1146     if (RenderTableCol* column = colElement(endColumn)) {
1147         // FIXME: We don't account for direction on columns and column groups.
1148         const BorderValue& columnAdjoiningBorder = column->style().borderEnd();
1149         if (columnAdjoiningBorder.style() == BHIDDEN)
1150             return 0;
1151         if (columnAdjoiningBorder.style() > BHIDDEN)
1152             borderWidth = std::max(borderWidth, columnAdjoiningBorder.width());
1153         // FIXME: This logic doesn't properly account for the last column in the last column-group case.
1154     }
1155
1156     if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) {
1157         const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableEnd();
1158         if (sectionAdjoiningBorder.style() == BHIDDEN)
1159             return 0;
1160
1161         if (sectionAdjoiningBorder.style() > BHIDDEN)
1162             borderWidth = std::max(borderWidth, sectionAdjoiningBorder.width());
1163
1164         if (const RenderTableCell* adjoiningEndCell = topNonEmptySection->firstRowCellAdjoiningTableEnd()) {
1165             // FIXME: Make this work with perpendicular and flipped cells.
1166             const BorderValue& endCellAdjoiningBorder = adjoiningEndCell->borderAdjoiningTableEnd();
1167             if (endCellAdjoiningBorder.style() == BHIDDEN)
1168                 return 0;
1169
1170             const BorderValue& firstRowAdjoiningBorder = adjoiningEndCell->row()->borderAdjoiningTableEnd();
1171             if (firstRowAdjoiningBorder.style() == BHIDDEN)
1172                 return 0;
1173
1174             if (endCellAdjoiningBorder.style() > BHIDDEN)
1175                 borderWidth = std::max(borderWidth, endCellAdjoiningBorder.width());
1176             if (firstRowAdjoiningBorder.style() > BHIDDEN)
1177                 borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width());
1178         }
1179     }
1180     return floorToInt((borderWidth + (style().isLeftToRightDirection() ? 1 : 0)) / 2);
1181 }
1182
1183 void RenderTable::recalcBordersInRowDirection()
1184 {
1185     // FIXME: We need to compute the collapsed before / after borders in the same fashion.
1186     m_borderStart = calcBorderStart();
1187     m_borderEnd = calcBorderEnd();
1188 }
1189
1190 LayoutUnit RenderTable::borderBefore() const
1191 {
1192     if (collapseBorders()) {
1193         recalcSectionsIfNeeded();
1194         return outerBorderBefore();
1195     }
1196     return RenderBlock::borderBefore();
1197 }
1198
1199 LayoutUnit RenderTable::borderAfter() const
1200 {
1201     if (collapseBorders()) {
1202         recalcSectionsIfNeeded();
1203         return outerBorderAfter();
1204     }
1205     return RenderBlock::borderAfter();
1206 }
1207
1208 LayoutUnit RenderTable::outerBorderBefore() const
1209 {
1210     if (!collapseBorders())
1211         return 0;
1212     LayoutUnit borderWidth = 0;
1213     if (RenderTableSection* topSection = this->topSection()) {
1214         borderWidth = topSection->outerBorderBefore();
1215         if (borderWidth < 0)
1216             return 0;   // Overridden by hidden
1217     }
1218     const BorderValue& tb = style().borderBefore();
1219     if (tb.style() == BHIDDEN)
1220         return 0;
1221     if (tb.style() > BHIDDEN)
1222         borderWidth = floorToInt(std::max<LayoutUnit>(borderWidth, tb.width() / 2));
1223     return borderWidth;
1224 }
1225
1226 LayoutUnit RenderTable::outerBorderAfter() const
1227 {
1228     if (!collapseBorders())
1229         return 0;
1230     LayoutUnit borderWidth = 0;
1231
1232     if (RenderTableSection* section = bottomSection()) {
1233         borderWidth = section->outerBorderAfter();
1234         if (borderWidth < 0)
1235             return 0; // Overridden by hidden
1236     }
1237     const BorderValue& tb = style().borderAfter();
1238     if (tb.style() == BHIDDEN)
1239         return 0;
1240     if (tb.style() > BHIDDEN)
1241         borderWidth = floorToInt(std::max<LayoutUnit>(borderWidth, (tb.width() + 1) / 2));
1242     return borderWidth;
1243 }
1244
1245 LayoutUnit RenderTable::outerBorderStart() const
1246 {
1247     if (!collapseBorders())
1248         return 0;
1249
1250     LayoutUnit borderWidth = 0;
1251
1252     const BorderValue& tb = style().borderStart();
1253     if (tb.style() == BHIDDEN)
1254         return 0;
1255     if (tb.style() > BHIDDEN)
1256         borderWidth = floorToInt((tb.width() + (style().isLeftToRightDirection() ? 0 : 1)) / 2);
1257
1258     bool allHidden = true;
1259     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
1260         LayoutUnit sw = section->outerBorderStart();
1261         if (sw < 0)
1262             continue;
1263         allHidden = false;
1264         borderWidth = std::max(borderWidth, sw);
1265     }
1266     if (allHidden)
1267         return 0;
1268
1269     return borderWidth;
1270 }
1271
1272 LayoutUnit RenderTable::outerBorderEnd() const
1273 {
1274     if (!collapseBorders())
1275         return 0;
1276
1277     LayoutUnit borderWidth = 0;
1278
1279     const BorderValue& tb = style().borderEnd();
1280     if (tb.style() == BHIDDEN)
1281         return 0;
1282     if (tb.style() > BHIDDEN)
1283         borderWidth = floorToInt((tb.width() + (style().isLeftToRightDirection() ? 1 : 0)) / 2);
1284
1285     bool allHidden = true;
1286     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
1287         LayoutUnit sw = section->outerBorderEnd();
1288         if (sw < 0)
1289             continue;
1290         allHidden = false;
1291         borderWidth = std::max(borderWidth, sw);
1292     }
1293     if (allHidden)
1294         return 0;
1295
1296     return borderWidth;
1297 }
1298
1299 RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section, SkipEmptySectionsValue skipEmptySections) const
1300 {
1301     recalcSectionsIfNeeded();
1302
1303     if (section == m_head)
1304         return nullptr;
1305
1306     RenderObject* prevSection = section == m_foot ? lastChild() : section->previousSibling();
1307     while (prevSection) {
1308         if (is<RenderTableSection>(*prevSection) && prevSection != m_head && prevSection != m_foot && (skipEmptySections == DoNotSkipEmptySections || downcast<RenderTableSection>(*prevSection).numRows()))
1309             break;
1310         prevSection = prevSection->previousSibling();
1311     }
1312     if (!prevSection && m_head && (skipEmptySections == DoNotSkipEmptySections || m_head->numRows()))
1313         prevSection = m_head;
1314     return downcast<RenderTableSection>(prevSection);
1315 }
1316
1317 RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, SkipEmptySectionsValue skipEmptySections) const
1318 {
1319     recalcSectionsIfNeeded();
1320
1321     if (section == m_foot)
1322         return nullptr;
1323
1324     RenderObject* nextSection = section == m_head ? firstChild() : section->nextSibling();
1325     while (nextSection) {
1326         if (is<RenderTableSection>(*nextSection) && nextSection != m_head && nextSection != m_foot && (skipEmptySections  == DoNotSkipEmptySections || downcast<RenderTableSection>(*nextSection).numRows()))
1327             break;
1328         nextSection = nextSection->nextSibling();
1329     }
1330     if (!nextSection && m_foot && (skipEmptySections == DoNotSkipEmptySections || m_foot->numRows()))
1331         nextSection = m_foot;
1332     return downcast<RenderTableSection>(nextSection);
1333 }
1334
1335 RenderTableSection* RenderTable::bottomSection() const
1336 {
1337     recalcSectionsIfNeeded();
1338
1339     if (m_foot)
1340         return m_foot;
1341
1342     for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
1343         if (is<RenderTableSection>(*child))
1344             return downcast<RenderTableSection>(child);
1345     }
1346
1347     return nullptr;
1348 }
1349
1350 RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
1351 {
1352     recalcSectionsIfNeeded();
1353
1354     // Find the section and row to look in
1355     unsigned r = cell->rowIndex();
1356     RenderTableSection* section = nullptr;
1357     unsigned rAbove = 0;
1358     if (r > 0) {
1359         // cell is not in the first row, so use the above row in its own section
1360         section = cell->section();
1361         rAbove = r - 1;
1362     } else {
1363         section = sectionAbove(cell->section(), SkipEmptySections);
1364         if (section) {
1365             ASSERT(section->numRows());
1366             rAbove = section->numRows() - 1;
1367         }
1368     }
1369
1370     // Look up the cell in the section's grid, which requires effective col index
1371     if (section) {
1372         unsigned effCol = colToEffCol(cell->col());
1373         RenderTableSection::CellStruct& aboveCell = section->cellAt(rAbove, effCol);
1374         return aboveCell.primaryCell();
1375     } else
1376         return nullptr;
1377 }
1378
1379 RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
1380 {
1381     recalcSectionsIfNeeded();
1382
1383     // Find the section and row to look in
1384     unsigned r = cell->rowIndex() + cell->rowSpan() - 1;
1385     RenderTableSection* section = nullptr;
1386     unsigned rBelow = 0;
1387     if (r < cell->section()->numRows() - 1) {
1388         // The cell is not in the last row, so use the next row in the section.
1389         section = cell->section();
1390         rBelow = r + 1;
1391     } else {
1392         section = sectionBelow(cell->section(), SkipEmptySections);
1393         if (section)
1394             rBelow = 0;
1395     }
1396
1397     // Look up the cell in the section's grid, which requires effective col index
1398     if (section) {
1399         unsigned effCol = colToEffCol(cell->col());
1400         RenderTableSection::CellStruct& belowCell = section->cellAt(rBelow, effCol);
1401         return belowCell.primaryCell();
1402     } else
1403         return nullptr;
1404 }
1405
1406 RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
1407 {
1408     recalcSectionsIfNeeded();
1409
1410     RenderTableSection* section = cell->section();
1411     unsigned effCol = colToEffCol(cell->col());
1412     if (!effCol)
1413         return nullptr;
1414     
1415     // If we hit a colspan back up to a real cell.
1416     RenderTableSection::CellStruct& prevCell = section->cellAt(cell->rowIndex(), effCol - 1);
1417     return prevCell.primaryCell();
1418 }
1419
1420 RenderTableCell* RenderTable::cellAfter(const RenderTableCell* cell) const
1421 {
1422     recalcSectionsIfNeeded();
1423
1424     unsigned effCol = colToEffCol(cell->col() + cell->colSpan());
1425     if (effCol >= numEffCols())
1426         return nullptr;
1427     return cell->section()->primaryCellAt(cell->rowIndex(), effCol);
1428 }
1429
1430 RenderBlock* RenderTable::firstLineBlock() const
1431 {
1432     return nullptr;
1433 }
1434
1435 void RenderTable::updateFirstLetter()
1436 {
1437 }
1438
1439 int RenderTable::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
1440 {
1441     return firstLineBaseline().valueOrCompute([&] {
1442         return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
1443     });
1444 }
1445
1446 Optional<int> RenderTable::inlineBlockBaseline(LineDirectionMode) const
1447 {
1448     // Tables are skipped when computing an inline-block's baseline.
1449     return Optional<int>();
1450 }
1451
1452 Optional<int> RenderTable::firstLineBaseline() const
1453 {
1454     // The baseline of a 'table' is the same as the 'inline-table' baseline per CSS 3 Flexbox (CSS 2.1
1455     // doesn't define the baseline of a 'table' only an 'inline-table').
1456     // This is also needed to properly determine the baseline of a cell if it has a table child.
1457
1458     if (isWritingModeRoot())
1459         return Optional<int>();
1460
1461     recalcSectionsIfNeeded();
1462
1463     const RenderTableSection* topNonEmptySection = this->topNonEmptySection();
1464     if (!topNonEmptySection)
1465         return Optional<int>();
1466
1467     if (Optional<int> baseline = topNonEmptySection->firstLineBaseline())
1468         return Optional<int>(topNonEmptySection->logicalTop() + baseline.value());
1469
1470     // FIXME: A table row always has a baseline per CSS 2.1. Will this return the right value?
1471     return Optional<int>();
1472 }
1473
1474 LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy, PaintPhase phase)
1475 {
1476     LayoutRect rect;
1477     // 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.
1478     // 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.
1479     if (phase == PaintPhaseChildBlockBackgrounds || layer()->isSelfPaintingLayer()) {
1480         rect = borderBoxRectInRegion(region);
1481         rect.setLocation(location + rect.location());
1482     } else
1483         rect = RenderBox::overflowClipRect(location, region, relevancy);
1484     
1485     // If we have a caption, expand the clip to include the caption.
1486     // FIXME: Technically this is wrong, but it's virtually impossible to fix this
1487     // for real until captions have been re-written.
1488     // FIXME: This code assumes (like all our other caption code) that only top/bottom are
1489     // supported.  When we actually support left/right and stop mapping them to top/bottom,
1490     // we might have to hack this code first (depending on what order we do these bug fixes in).
1491     if (!m_captions.isEmpty()) {
1492         if (style().isHorizontalWritingMode()) {
1493             rect.setHeight(height());
1494             rect.setY(location.y());
1495         } else {
1496             rect.setWidth(width());
1497             rect.setX(location.x());
1498         }
1499     }
1500
1501     return rect;
1502 }
1503
1504 bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
1505 {
1506     LayoutPoint adjustedLocation = accumulatedOffset + location();
1507
1508     // Check kids first.
1509     if (!hasOverflowClip() || locationInContainer.intersects(overflowClipRect(adjustedLocation, currentRenderNamedFlowFragment()))) {
1510         for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
1511             if (is<RenderBox>(*child) && !downcast<RenderBox>(*child).hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
1512                 LayoutPoint childPoint = flipForWritingModeForChild(downcast<RenderBox>(child), adjustedLocation);
1513                 if (child->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
1514                     updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
1515                     return true;
1516                 }
1517             }
1518         }
1519     }
1520
1521     // Check our bounds next.
1522     LayoutRect boundsRect(adjustedLocation, size());
1523     if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && locationInContainer.intersects(boundsRect)) {
1524         updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(adjustedLocation)));
1525         if (!result.addNodeToRectBasedTestResult(element(), request, locationInContainer, boundsRect))
1526             return true;
1527     }
1528
1529     return false;
1530 }
1531
1532 RenderTable* RenderTable::createAnonymousWithParentRenderer(const RenderObject* parent)
1533 {
1534     auto table = new RenderTable(parent->document(), RenderStyle::createAnonymousStyleWithDisplay(&parent->style(), parent->style().display() == INLINE ? INLINE_TABLE : TABLE));
1535     table->initializeStyle();
1536     return table;
1537 }
1538
1539 const BorderValue& RenderTable::tableStartBorderAdjoiningCell(const RenderTableCell* cell) const
1540 {
1541     ASSERT(cell->isFirstOrLastCellInRow());
1542     if (hasSameDirectionAs(cell->row()))
1543         return style().borderStart();
1544
1545     return style().borderEnd();
1546 }
1547
1548 const BorderValue& RenderTable::tableEndBorderAdjoiningCell(const RenderTableCell* cell) const
1549 {
1550     ASSERT(cell->isFirstOrLastCellInRow());
1551     if (hasSameDirectionAs(cell->row()))
1552         return style().borderEnd();
1553
1554     return style().borderStart();
1555 }
1556
1557 void RenderTable::markForPaginationRelayoutIfNeeded()
1558 {
1559     if (!view().layoutState()->isPaginated() || (!view().layoutState()->pageLogicalHeightChanged() && (!view().layoutState()->pageLogicalHeight() || view().layoutState()->pageLogicalOffset(this, logicalTop()) == pageLogicalOffset())))
1560         return;
1561     
1562     // When a table moves, we have to dirty all of the sections too.
1563     if (!needsLayout())
1564         setChildNeedsLayout(MarkOnlyThis);
1565     for (auto& child : childrenOfType<RenderTableSection>(*this)) {
1566         if (!child.needsLayout())
1567             child.setChildNeedsLayout(MarkOnlyThis);
1568     }
1569 }
1570
1571 }