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