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