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