Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / core / layout / LayoutTable.cpp
blob7c2d93c430b137b2dd321e4d7d5b62279b97195b
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, 2013 Apple Inc. All rights reserved.
8 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
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.
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.
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.
26 #include "config.h"
27 #include "core/layout/LayoutTable.h"
29 #include "core/HTMLNames.h"
30 #include "core/dom/Document.h"
31 #include "core/frame/FrameView.h"
32 #include "core/html/HTMLTableElement.h"
33 #include "core/layout/HitTestResult.h"
34 #include "core/layout/LayoutAnalyzer.h"
35 #include "core/layout/LayoutTableCaption.h"
36 #include "core/layout/LayoutTableCell.h"
37 #include "core/layout/LayoutTableCol.h"
38 #include "core/layout/LayoutTableSection.h"
39 #include "core/layout/LayoutView.h"
40 #include "core/layout/SubtreeLayoutScope.h"
41 #include "core/layout/TableLayoutAlgorithmAuto.h"
42 #include "core/layout/TableLayoutAlgorithmFixed.h"
43 #include "core/layout/TextAutosizer.h"
44 #include "core/paint/BoxPainter.h"
45 #include "core/paint/DeprecatedPaintLayer.h"
46 #include "core/paint/TablePainter.h"
47 #include "core/style/StyleInheritedData.h"
49 namespace blink {
51 using namespace HTMLNames;
53 LayoutTable::LayoutTable(Element* element)
54 : LayoutBlock(element)
55 , m_head(nullptr)
56 , m_foot(nullptr)
57 , m_firstBody(nullptr)
58 , m_currentBorder(nullptr)
59 , m_collapsedBordersValid(false)
60 , m_hasColElements(false)
61 , m_needsSectionRecalc(false)
62 , m_columnLogicalWidthChanged(false)
63 , m_columnLayoutObjectsValid(false)
64 , m_hasCellColspanThatDeterminesTableWidth(false)
65 , m_hSpacing(0)
66 , m_vSpacing(0)
67 , m_borderStart(0)
68 , m_borderEnd(0)
70 ASSERT(!childrenInline());
71 m_columnPos.fill(0, 1);
74 LayoutTable::~LayoutTable()
78 void LayoutTable::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
80 LayoutBlock::styleDidChange(diff, oldStyle);
81 propagateStyleToAnonymousChildren();
83 bool oldFixedTableLayout = oldStyle ? oldStyle->isFixedTableLayout() : false;
85 // In the collapsed border model, there is no cell spacing.
86 m_hSpacing = collapseBorders() ? 0 : style()->horizontalBorderSpacing();
87 m_vSpacing = collapseBorders() ? 0 : style()->verticalBorderSpacing();
88 m_columnPos[0] = m_hSpacing;
90 if (!m_tableLayout || style()->isFixedTableLayout() != oldFixedTableLayout) {
91 if (m_tableLayout)
92 m_tableLayout->willChangeTableLayout();
94 // According to the CSS2 spec, you only use fixed table layout if an
95 // explicit width is specified on the table. Auto width implies auto table layout.
96 if (style()->isFixedTableLayout())
97 m_tableLayout = adoptPtr(new TableLayoutAlgorithmFixed(this));
98 else
99 m_tableLayout = adoptPtr(new TableLayoutAlgorithmAuto(this));
102 // If border was changed, invalidate collapsed borders cache.
103 if (!needsLayout() && oldStyle && oldStyle->border() != style()->border())
104 invalidateCollapsedBorders();
107 static inline void resetSectionPointerIfNotBefore(LayoutTableSection*& ptr, LayoutObject* before)
109 if (!before || !ptr)
110 return;
111 LayoutObject* o = before->previousSibling();
112 while (o && o != ptr)
113 o = o->previousSibling();
114 if (!o)
115 ptr = 0;
118 static inline bool needsTableSection(LayoutObject* object)
120 // Return true if 'object' can't exist in an anonymous table without being
121 // wrapped in a table section box.
122 EDisplay display = object->style()->display();
123 return display != TABLE_CAPTION && display != TABLE_COLUMN_GROUP && display != TABLE_COLUMN;
126 void LayoutTable::addChild(LayoutObject* child, LayoutObject* beforeChild)
128 bool wrapInAnonymousSection = !child->isOutOfFlowPositioned();
130 if (child->isTableCaption()) {
131 wrapInAnonymousSection = false;
132 } else if (child->isLayoutTableCol()) {
133 m_hasColElements = true;
134 wrapInAnonymousSection = false;
135 } else if (child->isTableSection()) {
136 switch (child->style()->display()) {
137 case TABLE_HEADER_GROUP:
138 resetSectionPointerIfNotBefore(m_head, beforeChild);
139 if (!m_head) {
140 m_head = toLayoutTableSection(child);
141 } else {
142 resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
143 if (!m_firstBody)
144 m_firstBody = toLayoutTableSection(child);
146 wrapInAnonymousSection = false;
147 break;
148 case TABLE_FOOTER_GROUP:
149 resetSectionPointerIfNotBefore(m_foot, beforeChild);
150 if (!m_foot) {
151 m_foot = toLayoutTableSection(child);
152 wrapInAnonymousSection = false;
153 break;
155 // Fall through.
156 case TABLE_ROW_GROUP:
157 resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
158 if (!m_firstBody)
159 m_firstBody = toLayoutTableSection(child);
160 wrapInAnonymousSection = false;
161 break;
162 default:
163 ASSERT_NOT_REACHED();
165 } else {
166 wrapInAnonymousSection = true;
169 if (child->isTableSection())
170 setNeedsSectionRecalc();
172 if (!wrapInAnonymousSection) {
173 if (beforeChild && beforeChild->parent() != this)
174 beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
176 LayoutBox::addChild(child, beforeChild);
177 return;
180 if (!beforeChild && lastChild() && lastChild()->isTableSection() && lastChild()->isAnonymous() && !lastChild()->isBeforeContent()) {
181 lastChild()->addChild(child);
182 return;
185 if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
186 LayoutObject* section = beforeChild->previousSibling();
187 if (section && section->isTableSection() && section->isAnonymous()) {
188 section->addChild(child);
189 return;
193 LayoutObject* lastBox = beforeChild;
194 while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableSection() && needsTableSection(lastBox))
195 lastBox = lastBox->parent();
196 if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox)) {
197 if (beforeChild == lastBox)
198 beforeChild = lastBox->slowFirstChild();
199 lastBox->addChild(child, beforeChild);
200 return;
203 if (beforeChild && !beforeChild->isTableSection() && needsTableSection(beforeChild))
204 beforeChild = 0;
206 LayoutTableSection* section = LayoutTableSection::createAnonymousWithParent(this);
207 addChild(section, beforeChild);
208 section->addChild(child);
211 void LayoutTable::addChildIgnoringContinuation(LayoutObject* newChild, LayoutObject* beforeChild)
213 // We need to bypass the LayoutBlock implementation and instead do a normal addChild() (or we
214 // won't get there at all), so that any missing anonymous table part layoutObjects are
215 // inserted. Otherwise we might end up with an insane layout tree with inlines or blocks as
216 // direct children of a table, which will break assumptions made all over the code, which may
217 // lead to crashers and security issues.
218 addChild(newChild, beforeChild);
221 void LayoutTable::addCaption(const LayoutTableCaption* caption)
223 ASSERT(m_captions.find(caption) == kNotFound);
224 m_captions.append(const_cast<LayoutTableCaption*>(caption));
227 void LayoutTable::removeCaption(const LayoutTableCaption* oldCaption)
229 size_t index = m_captions.find(oldCaption);
230 ASSERT(index != kNotFound);
231 if (index == kNotFound)
232 return;
234 m_captions.remove(index);
237 void LayoutTable::invalidateCachedColumns()
239 m_columnLayoutObjectsValid = false;
240 m_columnLayoutObjects.resize(0);
243 void LayoutTable::addColumn(const LayoutTableCol*)
245 invalidateCachedColumns();
248 void LayoutTable::removeColumn(const LayoutTableCol*)
250 invalidateCachedColumns();
251 // We don't really need to recompute our sections, but we need to update our
252 // column count and whether we have a column. Currently, we only have one
253 // size-fit-all flag but we may have to consider splitting it.
254 setNeedsSectionRecalc();
257 void LayoutTable::updateLogicalWidth()
259 recalcSectionsIfNeeded();
261 if (isOutOfFlowPositioned()) {
262 LogicalExtentComputedValues computedValues;
263 computePositionedLogicalWidth(computedValues);
264 setLogicalWidth(computedValues.m_extent);
265 setLogicalLeft(computedValues.m_position);
266 setMarginStart(computedValues.m_margins.m_start);
267 setMarginEnd(computedValues.m_margins.m_end);
270 LayoutBlock* cb = containingBlock();
272 LayoutUnit availableLogicalWidth = containingBlockLogicalWidthForContent() + (isOutOfFlowPositioned() ? cb->paddingLogicalWidth() : LayoutUnit());
273 bool hasPerpendicularContainingBlock = cb->style()->isHorizontalWritingMode() != style()->isHorizontalWritingMode();
274 LayoutUnit containerWidthInInlineDirection = hasPerpendicularContainingBlock ? perpendicularContainingBlockLogicalHeight() : availableLogicalWidth;
276 Length styleLogicalWidth = style()->logicalWidth();
277 if ((styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive()) || styleLogicalWidth.isIntrinsic()) {
278 setLogicalWidth(convertStyleLogicalWidthToComputedWidth(styleLogicalWidth, containerWidthInInlineDirection));
279 } else {
280 // Subtract out any fixed margins from our available width for auto width tables.
281 LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth);
282 LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth);
283 LayoutUnit marginTotal = marginStart + marginEnd;
285 // Subtract out our margins to get the available content width.
286 LayoutUnit availableContentLogicalWidth = std::max<LayoutUnit>(0, containerWidthInInlineDirection - marginTotal);
287 if (shrinkToAvoidFloats() && cb->isLayoutBlockFlow() && toLayoutBlockFlow(cb)->containsFloats() && !hasPerpendicularContainingBlock)
288 availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, toLayoutBlockFlow(cb));
290 // Ensure we aren't bigger than our available width.
291 setLogicalWidth(std::min<int>(availableContentLogicalWidth, maxPreferredLogicalWidth()));
294 // Ensure we aren't bigger than our max-width style.
295 Length styleMaxLogicalWidth = style()->logicalMaxWidth();
296 if ((styleMaxLogicalWidth.isSpecified() && !styleMaxLogicalWidth.isNegative()) || styleMaxLogicalWidth.isIntrinsic()) {
297 LayoutUnit computedMaxLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMaxLogicalWidth, availableLogicalWidth);
298 setLogicalWidth(std::min<int>(logicalWidth(), computedMaxLogicalWidth));
301 // Ensure we aren't smaller than our min preferred width. This MUST be done after 'max-width' as
302 // we ignore it if it means we wouldn't accomodate our content.
303 setLogicalWidth(std::max<int>(logicalWidth(), minPreferredLogicalWidth()));
305 // Ensure we aren't smaller than our min-width style.
306 Length styleMinLogicalWidth = style()->logicalMinWidth();
307 if ((styleMinLogicalWidth.isSpecified() && !styleMinLogicalWidth.isNegative()) || styleMinLogicalWidth.isIntrinsic()) {
308 LayoutUnit computedMinLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMinLogicalWidth, availableLogicalWidth);
309 setLogicalWidth(std::max<int>(logicalWidth(), computedMinLogicalWidth));
312 // Finally, with our true width determined, compute our margins for real.
313 ComputedMarginValues marginValues;
314 computeMarginsForDirection(InlineDirection, cb, availableLogicalWidth, logicalWidth(), marginValues.m_start, marginValues.m_end, style()->marginStart(), style()->marginEnd());
315 setMarginStart(marginValues.m_start);
316 setMarginEnd(marginValues.m_end);
318 // We should NEVER shrink the table below the min-content logical width, or else the table can't accomodate
319 // its own content which doesn't match CSS nor what authors expect.
320 // FIXME: When we convert to sub-pixel layout for tables we can remove the int conversion
321 // https://code.google.com/p/chromium/issues/detail?id=241198
322 ASSERT(logicalWidth().toInt() >= minPreferredLogicalWidth().toInt());
325 // This method takes a ComputedStyle's logical width, min-width, or max-width length and computes its actual value.
326 LayoutUnit LayoutTable::convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth)
328 if (styleLogicalWidth.isIntrinsic())
329 return computeIntrinsicLogicalWidthUsing(styleLogicalWidth, availableWidth, bordersPaddingAndSpacingInRowDirection());
331 // HTML tables' width styles already include borders and paddings, but CSS tables' width styles do not.
332 LayoutUnit borders = 0;
333 bool isCSSTable = !isHTMLTableElement(node());
334 if (isCSSTable && styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive() && style()->boxSizing() == CONTENT_BOX)
335 borders = borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd());
337 return minimumValueForLength(styleLogicalWidth, availableWidth) + borders;
340 LayoutUnit LayoutTable::convertStyleLogicalHeightToComputedHeight(const Length& styleLogicalHeight)
342 LayoutUnit borderAndPaddingBefore = borderBefore() + (collapseBorders() ? LayoutUnit() : paddingBefore());
343 LayoutUnit borderAndPaddingAfter = borderAfter() + (collapseBorders() ? LayoutUnit() : paddingAfter());
344 LayoutUnit borderAndPadding = borderAndPaddingBefore + borderAndPaddingAfter;
345 LayoutUnit computedLogicalHeight = 0;
346 if (styleLogicalHeight.isFixed()) {
347 // HTML tables size as though CSS height includes border/padding, CSS tables do not.
348 LayoutUnit borders = LayoutUnit();
349 // FIXME: We cannot apply box-sizing: content-box on <table> which other browsers allow.
350 if (isHTMLTableElement(node()) || style()->boxSizing() == BORDER_BOX) {
351 borders = borderAndPadding;
353 computedLogicalHeight = styleLogicalHeight.value() - borders;
354 } else if (styleLogicalHeight.hasPercent()) {
355 computedLogicalHeight = computePercentageLogicalHeight(styleLogicalHeight);
356 } else if (styleLogicalHeight.isIntrinsic()) {
357 computedLogicalHeight = computeIntrinsicLogicalContentHeightUsing(styleLogicalHeight, logicalHeight() - borderAndPadding, borderAndPadding);
358 } else {
359 ASSERT_NOT_REACHED();
361 return std::max<LayoutUnit>(0, computedLogicalHeight);
364 void LayoutTable::layoutCaption(LayoutTableCaption& caption)
366 if (caption.needsLayout()) {
367 // The margins may not be available but ensure the caption is at least located beneath any previous sibling caption
368 // so that it does not mistakenly think any floats in the previous caption intrude into it.
369 caption.setLogicalLocation(LayoutPoint(caption.marginStart(), collapsedMarginBeforeForChild(caption) + logicalHeight()));
370 // If LayoutTableCaption ever gets a layout() function, use it here.
371 caption.layoutIfNeeded();
373 // Apply the margins to the location now that they are definitely available from layout
374 LayoutUnit captionLogicalTop = collapsedMarginBeforeForChild(caption) + logicalHeight();
375 if (view()->layoutState()->isPaginated()) {
376 captionLogicalTop += caption.paginationStrut();
377 caption.setPaginationStrut(0);
379 caption.setLogicalLocation(LayoutPoint(caption.marginStart(), captionLogicalTop));
381 if (!selfNeedsLayout())
382 caption.setMayNeedPaintInvalidation();
384 setLogicalHeight(logicalHeight() + caption.logicalHeight() + collapsedMarginBeforeForChild(caption) + collapsedMarginAfterForChild(caption));
387 void LayoutTable::distributeExtraLogicalHeight(int extraLogicalHeight)
389 if (extraLogicalHeight <= 0)
390 return;
392 // FIXME: Distribute the extra logical height between all table sections instead of giving it all to the first one.
393 if (LayoutTableSection* section = firstBody())
394 extraLogicalHeight -= section->distributeExtraLogicalHeightToRows(extraLogicalHeight);
396 // FIXME: We really would like to enable this ASSERT to ensure that all the extra space has been distributed.
397 // However our current distribution algorithm does not round properly and thus we can have some remaining height.
398 // ASSERT(!topSection() || !extraLogicalHeight);
401 void LayoutTable::simplifiedNormalFlowLayout()
403 // FIXME: We should walk through the items in the tree in tree order to do the layout here
404 // instead of walking through individual parts of the tree. crbug.com/442737
405 for (auto& caption : m_captions)
406 caption->layoutIfNeeded();
408 for (LayoutTableSection* section = topSection(); section; section = sectionBelow(section)) {
409 section->layoutIfNeeded();
410 section->layoutRows();
411 section->computeOverflowFromCells();
412 section->updateLayerTransformAfterLayout();
413 section->addVisualEffectOverflow();
417 void LayoutTable::layout()
419 ASSERT(needsLayout());
420 LayoutAnalyzer::Scope analyzer(*this);
422 if (simplifiedLayout())
423 return;
425 // Note: LayoutTable is handled differently than other LayoutBlocks and the LayoutScope
426 // must be created before the table begins laying out.
427 TextAutosizer::LayoutScope textAutosizerLayoutScope(this);
429 recalcSectionsIfNeeded();
430 // FIXME: We should do this recalc lazily in borderStart/borderEnd so that we don't have to make sure
431 // to call this before we call borderStart/borderEnd to avoid getting a stale value.
432 recalcBordersInRowDirection();
434 SubtreeLayoutScope layouter(*this);
436 // If any table section moved vertically, we will just issue paint invalidations for everything from that
437 // section down (it is quite unlikely that any of the following sections
438 // did not shift).
439 bool sectionMoved = false;
441 LayoutState state(*this, locationOffset());
442 LayoutUnit oldLogicalWidth = logicalWidth();
443 LayoutUnit oldLogicalHeight = logicalHeight();
445 setLogicalHeight(0);
446 updateLogicalWidth();
448 if (logicalWidth() != oldLogicalWidth) {
449 for (unsigned i = 0; i < m_captions.size(); i++)
450 layouter.setNeedsLayout(m_captions[i], LayoutInvalidationReason::TableChanged);
452 // FIXME: The optimisation below doesn't work since the internal table
453 // layout could have changed. We need to add a flag to the table
454 // layout that tells us if something has changed in the min max
455 // calculations to do it correctly.
456 // if ( oldWidth != width() || columns.size() + 1 != columnPos.size() )
457 m_tableLayout->layout();
459 LayoutUnit totalSectionLogicalHeight = 0;
460 LayoutUnit oldTableLogicalTop = 0;
461 for (unsigned i = 0; i < m_captions.size(); i++)
462 oldTableLogicalTop += m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
464 bool collapsing = collapseBorders();
466 for (LayoutObject* child = firstChild(); child; child = child->nextSibling()) {
467 if (!child->needsLayout() && child->isBox())
468 toLayoutBox(child)->markForPaginationRelayoutIfNeeded(layouter);
469 if (child->isTableSection()) {
470 LayoutTableSection* section = toLayoutTableSection(child);
471 if (m_columnLogicalWidthChanged)
472 layouter.setChildNeedsLayout(section);
473 section->layoutIfNeeded();
474 totalSectionLogicalHeight += section->calcRowLogicalHeight();
475 if (collapsing)
476 section->recalcOuterBorder();
477 ASSERT(!section->needsLayout());
478 } else if (child->isLayoutTableCol()) {
479 child->layoutIfNeeded();
480 ASSERT(!child->needsLayout());
481 } else {
482 // FIXME: We should never have other type of children (they should be wrapped in an
483 // anonymous table section) but our code is too crazy and this can happen in practice.
484 // Until this is fixed, let's make sure we don't leave non laid out children in the tree.
485 child->layoutIfNeeded();
489 // FIXME: Collapse caption margin.
490 if (!m_captions.isEmpty()) {
491 for (unsigned i = 0; i < m_captions.size(); i++) {
492 if (m_captions[i]->style()->captionSide() == CAPBOTTOM)
493 continue;
494 layoutCaption(*m_captions[i]);
496 sectionMoved = logicalHeight() != oldTableLogicalTop;
499 LayoutUnit borderAndPaddingBefore = borderBefore() + (collapsing ? LayoutUnit() : paddingBefore());
500 LayoutUnit borderAndPaddingAfter = borderAfter() + (collapsing ? LayoutUnit() : paddingAfter());
502 setLogicalHeight(logicalHeight() + borderAndPaddingBefore);
504 LayoutUnit computedLogicalHeight = 0;
506 Length logicalHeightLength = style()->logicalHeight();
507 if (logicalHeightLength.isIntrinsic() || (logicalHeightLength.isSpecified() && logicalHeightLength.isPositive()))
508 computedLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalHeightLength);
510 Length logicalMaxHeightLength = style()->logicalMaxHeight();
511 if (logicalMaxHeightLength.isIntrinsic() || (logicalMaxHeightLength.isSpecified() && !logicalMaxHeightLength.isNegative())) {
512 LayoutUnit computedMaxLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMaxHeightLength);
513 computedLogicalHeight = std::min(computedLogicalHeight, computedMaxLogicalHeight);
516 Length logicalMinHeightLength = style()->logicalMinHeight();
517 if (logicalMinHeightLength.isIntrinsic() || (logicalMinHeightLength.isSpecified() && !logicalMinHeightLength.isNegative())) {
518 LayoutUnit computedMinLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMinHeightLength);
519 computedLogicalHeight = std::max(computedLogicalHeight, computedMinLogicalHeight);
522 distributeExtraLogicalHeight(floorToInt(computedLogicalHeight - totalSectionLogicalHeight));
524 for (LayoutTableSection* section = topSection(); section; section = sectionBelow(section))
525 section->layoutRows();
527 if (!topSection() && computedLogicalHeight > totalSectionLogicalHeight && !document().inQuirksMode()) {
528 // Completely empty tables (with no sections or anything) should at least honor specified height
529 // in strict mode.
530 setLogicalHeight(logicalHeight() + computedLogicalHeight);
533 LayoutUnit sectionLogicalLeft = style()->isLeftToRightDirection() ? borderStart() : borderEnd();
534 if (!collapsing)
535 sectionLogicalLeft += style()->isLeftToRightDirection() ? paddingStart() : paddingEnd();
537 // position the table sections
538 LayoutTableSection* section = topSection();
539 while (section) {
540 if (!sectionMoved && section->logicalTop() != logicalHeight())
541 sectionMoved = true;
542 section->setLogicalLocation(LayoutPoint(sectionLogicalLeft, logicalHeight()));
544 // As we may skip invalidation on the table, we need to ensure that sections are invalidated when they moved.
545 if (sectionMoved && !section->selfNeedsLayout())
546 section->setMayNeedPaintInvalidation();
548 setLogicalHeight(logicalHeight() + section->logicalHeight());
550 section->updateLayerTransformAfterLayout();
551 section->addVisualEffectOverflow();
553 section = sectionBelow(section);
556 setLogicalHeight(logicalHeight() + borderAndPaddingAfter);
558 for (unsigned i = 0; i < m_captions.size(); i++) {
559 if (m_captions[i]->style()->captionSide() != CAPBOTTOM)
560 continue;
561 layoutCaption(*m_captions[i]);
564 updateLogicalHeight();
566 // table can be containing block of positioned elements.
567 bool dimensionChanged = oldLogicalWidth != logicalWidth() || oldLogicalHeight != logicalHeight();
568 layoutPositionedObjects(dimensionChanged);
570 updateLayerTransformAfterLayout();
572 // Layout was changed, so probably borders too.
573 invalidateCollapsedBorders();
575 computeOverflow(clientLogicalBottom());
576 updateScrollInfoAfterLayout();
579 // FIXME: This value isn't the intrinsic content logical height, but we need
580 // to update the value as its used by flexbox layout. crbug.com/367324
581 setIntrinsicContentLogicalHeight(contentLogicalHeight());
583 if (view()->layoutState()->pageLogicalHeight())
584 setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(*this, logicalTop()));
586 m_columnLogicalWidthChanged = false;
587 clearNeedsLayout();
590 void LayoutTable::invalidateCollapsedBorders()
592 m_collapsedBorders.clear();
593 if (!collapseBorders())
594 return;
596 m_collapsedBordersValid = false;
597 setMayNeedPaintInvalidation();
600 // Collect all the unique border values that we want to paint in a sorted list.
601 // During the collection, each cell saves its recalculated borders into the cache
602 // of its containing section, and invalidates itself if any border changes.
603 // This method doesn't affect layout.
604 void LayoutTable::recalcCollapsedBordersIfNeeded()
606 if (m_collapsedBordersValid || !collapseBorders())
607 return;
608 m_collapsedBordersValid = true;
609 m_collapsedBorders.clear();
610 for (LayoutObject* section = firstChild(); section; section = section->nextSibling()) {
611 if (!section->isTableSection())
612 continue;
613 for (LayoutTableRow* row = toLayoutTableSection(section)->firstRow(); row; row = row->nextRow()) {
614 for (LayoutTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) {
615 ASSERT(cell->table() == this);
616 cell->collectBorderValues(m_collapsedBorders);
620 LayoutTableCell::sortBorderValues(m_collapsedBorders);
623 void LayoutTable::addOverflowFromChildren()
625 // Add overflow from borders.
626 // Technically it's odd that we are incorporating the borders into layout overflow, which is only supposed to be about overflow from our
627 // descendant objects, but since tables don't support overflow:auto, this works out fine.
628 if (collapseBorders()) {
629 int rightBorderOverflow = size().width() + outerBorderRight() - borderRight();
630 int leftBorderOverflow = borderLeft() - outerBorderLeft();
631 int bottomBorderOverflow = size().height() + outerBorderBottom() - borderBottom();
632 int topBorderOverflow = borderTop() - outerBorderTop();
633 IntRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow);
634 if (borderOverflowRect != pixelSnappedBorderBoxRect()) {
635 LayoutRect borderLayoutRect(borderOverflowRect);
636 addLayoutOverflow(borderLayoutRect);
637 addVisualOverflow(borderLayoutRect);
641 // Add overflow from our caption.
642 for (unsigned i = 0; i < m_captions.size(); i++)
643 addOverflowFromChild(m_captions[i]);
645 // Add overflow from our sections.
646 for (LayoutTableSection* section = topSection(); section; section = sectionBelow(section))
647 addOverflowFromChild(section);
650 void LayoutTable::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
652 TablePainter(*this).paintObject(paintInfo, paintOffset);
655 void LayoutTable::subtractCaptionRect(LayoutRect& rect) const
657 for (unsigned i = 0; i < m_captions.size(); i++) {
658 LayoutUnit captionLogicalHeight = m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
659 bool captionIsBefore = (m_captions[i]->style()->captionSide() != CAPBOTTOM) ^ style()->isFlippedBlocksWritingMode();
660 if (style()->isHorizontalWritingMode()) {
661 rect.setHeight(rect.height() - captionLogicalHeight);
662 if (captionIsBefore)
663 rect.move(0, captionLogicalHeight);
664 } else {
665 rect.setWidth(rect.width() - captionLogicalHeight);
666 if (captionIsBefore)
667 rect.move(captionLogicalHeight, 0);
672 void LayoutTable::paintBoxDecorationBackground(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
674 TablePainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset);
677 void LayoutTable::paintMask(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
679 TablePainter(*this).paintMask(paintInfo, paintOffset);
682 void LayoutTable::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) const
684 recalcSectionsIfNeeded();
685 // FIXME: Do the recalc in borderStart/borderEnd and make those const_cast this call.
686 // Then m_borderStart/m_borderEnd will be transparent a cache and it removes the possibility
687 // of reading out stale values.
688 const_cast<LayoutTable*>(this)->recalcBordersInRowDirection();
689 // FIXME: Restructure the table layout code so that we can make this method const.
690 const_cast<LayoutTable*>(this)->m_tableLayout->computeIntrinsicLogicalWidths(minWidth, maxWidth);
692 // FIXME: We should include captions widths here like we do in computePreferredLogicalWidths.
695 void LayoutTable::computePreferredLogicalWidths()
697 ASSERT(preferredLogicalWidthsDirty());
699 computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
701 int bordersPaddingAndSpacing = bordersPaddingAndSpacingInRowDirection();
702 m_minPreferredLogicalWidth += bordersPaddingAndSpacing;
703 m_maxPreferredLogicalWidth += bordersPaddingAndSpacing;
705 m_tableLayout->applyPreferredLogicalWidthQuirks(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
707 for (unsigned i = 0; i < m_captions.size(); i++)
708 m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, m_captions[i]->minPreferredLogicalWidth());
710 const ComputedStyle& styleToUse = styleRef();
711 // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for min-width.
712 if (styleToUse.logicalMinWidth().isFixed() && styleToUse.logicalMinWidth().value() > 0) {
713 m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
714 m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
717 // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for maxWidth.
718 if (styleToUse.logicalMaxWidth().isFixed()) {
719 // We don't constrain m_minPreferredLogicalWidth as the table should be at least the size of its min-content, regardless of 'max-width'.
720 m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
721 m_maxPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
724 // FIXME: We should be adding borderAndPaddingLogicalWidth here, but m_tableLayout->computePreferredLogicalWidths already does,
725 // so a bunch of tests break doing this naively.
726 clearPreferredLogicalWidthsDirty();
729 LayoutTableSection* LayoutTable::topNonEmptySection() const
731 LayoutTableSection* section = topSection();
732 if (section && !section->numRows())
733 section = sectionBelow(section, SkipEmptySections);
734 return section;
737 void LayoutTable::splitColumn(unsigned position, unsigned firstSpan)
739 // We split the column at "position", taking "firstSpan" cells from the span.
740 ASSERT(m_columns[position].span > firstSpan);
741 m_columns.insert(position, ColumnStruct(firstSpan));
742 m_columns[position + 1].span -= firstSpan;
744 // Propagate the change in our columns representation to the sections that don't need
745 // cell recalc. If they do, they will be synced up directly with m_columns later.
746 for (LayoutObject* child = firstChild(); child; child = child->nextSibling()) {
747 if (!child->isTableSection())
748 continue;
750 LayoutTableSection* section = toLayoutTableSection(child);
751 if (section->needsCellRecalc())
752 continue;
754 section->splitColumn(position, firstSpan);
757 m_columnPos.grow(numEffCols() + 1);
760 void LayoutTable::appendColumn(unsigned span)
762 unsigned newColumnIndex = m_columns.size();
763 m_columns.append(ColumnStruct(span));
765 // Unless the table has cell(s) with colspan that exceed the number of columns afforded
766 // by the other rows in the table we can use the fast path when mapping columns to effective columns.
767 m_hasCellColspanThatDeterminesTableWidth = m_hasCellColspanThatDeterminesTableWidth || span > 1;
769 // Propagate the change in our columns representation to the sections that don't need
770 // cell recalc. If they do, they will be synced up directly with m_columns later.
771 for (LayoutObject* child = firstChild(); child; child = child->nextSibling()) {
772 if (!child->isTableSection())
773 continue;
775 LayoutTableSection* section = toLayoutTableSection(child);
776 if (section->needsCellRecalc())
777 continue;
779 section->appendColumn(newColumnIndex);
782 m_columnPos.grow(numEffCols() + 1);
785 LayoutTableCol* LayoutTable::firstColumn() const
787 for (LayoutObject* child = firstChild(); child; child = child->nextSibling()) {
788 if (child->isLayoutTableCol())
789 return toLayoutTableCol(child);
792 return nullptr;
795 void LayoutTable::updateColumnCache() const
797 ASSERT(m_hasColElements);
798 ASSERT(m_columnLayoutObjects.isEmpty());
799 ASSERT(!m_columnLayoutObjectsValid);
801 for (LayoutTableCol* columnLayoutObject = firstColumn(); columnLayoutObject; columnLayoutObject = columnLayoutObject->nextColumn()) {
802 if (columnLayoutObject->isTableColumnGroupWithColumnChildren())
803 continue;
804 m_columnLayoutObjects.append(columnLayoutObject);
806 m_columnLayoutObjectsValid = true;
809 LayoutTableCol* LayoutTable::slowColElement(unsigned col, bool* startEdge, bool* endEdge) const
811 ASSERT(m_hasColElements);
813 if (!m_columnLayoutObjectsValid)
814 updateColumnCache();
816 unsigned columnCount = 0;
817 for (unsigned i = 0; i < m_columnLayoutObjects.size(); i++) {
818 LayoutTableCol* columnLayoutObject = m_columnLayoutObjects[i];
819 unsigned span = columnLayoutObject->span();
820 unsigned startCol = columnCount;
821 ASSERT(span >= 1);
822 unsigned endCol = columnCount + span - 1;
823 columnCount += span;
824 if (columnCount > col) {
825 if (startEdge)
826 *startEdge = startCol == col;
827 if (endEdge)
828 *endEdge = endCol == col;
829 return columnLayoutObject;
832 return nullptr;
835 void LayoutTable::recalcSections() const
837 ASSERT(m_needsSectionRecalc);
839 m_head = nullptr;
840 m_foot = nullptr;
841 m_firstBody = nullptr;
842 m_hasColElements = false;
843 m_hasCellColspanThatDeterminesTableWidth = hasCellColspanThatDeterminesTableWidth();
845 // We need to get valid pointers to caption, head, foot and first body again
846 LayoutObject* nextSibling;
847 for (LayoutObject* child = firstChild(); child; child = nextSibling) {
848 nextSibling = child->nextSibling();
849 switch (child->style()->display()) {
850 case TABLE_COLUMN:
851 case TABLE_COLUMN_GROUP:
852 m_hasColElements = true;
853 break;
854 case TABLE_HEADER_GROUP:
855 if (child->isTableSection()) {
856 LayoutTableSection* section = toLayoutTableSection(child);
857 if (!m_head)
858 m_head = section;
859 else if (!m_firstBody)
860 m_firstBody = section;
861 section->recalcCellsIfNeeded();
863 break;
864 case TABLE_FOOTER_GROUP:
865 if (child->isTableSection()) {
866 LayoutTableSection* section = toLayoutTableSection(child);
867 if (!m_foot)
868 m_foot = section;
869 else if (!m_firstBody)
870 m_firstBody = section;
871 section->recalcCellsIfNeeded();
873 break;
874 case TABLE_ROW_GROUP:
875 if (child->isTableSection()) {
876 LayoutTableSection* section = toLayoutTableSection(child);
877 if (!m_firstBody)
878 m_firstBody = section;
879 section->recalcCellsIfNeeded();
881 break;
882 default:
883 break;
887 // repair column count (addChild can grow it too much, because it always adds elements to the last row of a section)
888 unsigned maxCols = 0;
889 for (LayoutObject* child = firstChild(); child; child = child->nextSibling()) {
890 if (child->isTableSection()) {
891 LayoutTableSection* section = toLayoutTableSection(child);
892 unsigned sectionCols = section->numColumns();
893 if (sectionCols > maxCols)
894 maxCols = sectionCols;
898 m_columns.resize(maxCols);
899 m_columnPos.resize(maxCols + 1);
901 ASSERT(selfNeedsLayout());
903 m_needsSectionRecalc = false;
906 int LayoutTable::calcBorderStart() const
908 if (!collapseBorders())
909 return LayoutBlock::borderStart();
911 // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2.
912 if (!numEffCols())
913 return 0;
915 int borderWidth = 0;
917 const BorderValue& tableStartBorder = style()->borderStart();
918 if (tableStartBorder.style() == BHIDDEN)
919 return 0;
920 if (tableStartBorder.style() > BHIDDEN)
921 borderWidth = tableStartBorder.width();
923 if (LayoutTableCol* column = colElement(0)) {
924 // FIXME: We don't account for direction on columns and column groups.
925 const BorderValue& columnAdjoiningBorder = column->style()->borderStart();
926 if (columnAdjoiningBorder.style() == BHIDDEN)
927 return 0;
928 if (columnAdjoiningBorder.style() > BHIDDEN)
929 borderWidth = std::max(borderWidth, columnAdjoiningBorder.width());
930 // FIXME: This logic doesn't properly account for the first column in the first column-group case.
933 if (const LayoutTableSection* topNonEmptySection = this->topNonEmptySection()) {
934 const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableStart();
935 if (sectionAdjoiningBorder.style() == BHIDDEN)
936 return 0;
938 if (sectionAdjoiningBorder.style() > BHIDDEN)
939 borderWidth = std::max(borderWidth, sectionAdjoiningBorder.width());
941 if (const LayoutTableCell* adjoiningStartCell = topNonEmptySection->firstRowCellAdjoiningTableStart()) {
942 // FIXME: Make this work with perpendicular and flipped cells.
943 const BorderValue& startCellAdjoiningBorder = adjoiningStartCell->borderAdjoiningTableStart();
944 if (startCellAdjoiningBorder.style() == BHIDDEN)
945 return 0;
947 const BorderValue& firstRowAdjoiningBorder = adjoiningStartCell->row()->borderAdjoiningTableStart();
948 if (firstRowAdjoiningBorder.style() == BHIDDEN)
949 return 0;
951 if (startCellAdjoiningBorder.style() > BHIDDEN)
952 borderWidth = std::max(borderWidth, startCellAdjoiningBorder.width());
953 if (firstRowAdjoiningBorder.style() > BHIDDEN)
954 borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width());
957 return (borderWidth + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
960 int LayoutTable::calcBorderEnd() const
962 if (!collapseBorders())
963 return LayoutBlock::borderEnd();
965 // Determined by the last cell of the first row. See the CSS 2.1 spec, section 17.6.2.
966 if (!numEffCols())
967 return 0;
969 int borderWidth = 0;
971 const BorderValue& tableEndBorder = style()->borderEnd();
972 if (tableEndBorder.style() == BHIDDEN)
973 return 0;
974 if (tableEndBorder.style() > BHIDDEN)
975 borderWidth = tableEndBorder.width();
977 unsigned endColumn = numEffCols() - 1;
978 if (LayoutTableCol* column = colElement(endColumn)) {
979 // FIXME: We don't account for direction on columns and column groups.
980 const BorderValue& columnAdjoiningBorder = column->style()->borderEnd();
981 if (columnAdjoiningBorder.style() == BHIDDEN)
982 return 0;
983 if (columnAdjoiningBorder.style() > BHIDDEN)
984 borderWidth = std::max(borderWidth, columnAdjoiningBorder.width());
985 // FIXME: This logic doesn't properly account for the last column in the last column-group case.
988 if (const LayoutTableSection* topNonEmptySection = this->topNonEmptySection()) {
989 const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableEnd();
990 if (sectionAdjoiningBorder.style() == BHIDDEN)
991 return 0;
993 if (sectionAdjoiningBorder.style() > BHIDDEN)
994 borderWidth = std::max(borderWidth, sectionAdjoiningBorder.width());
996 if (const LayoutTableCell* adjoiningEndCell = topNonEmptySection->firstRowCellAdjoiningTableEnd()) {
997 // FIXME: Make this work with perpendicular and flipped cells.
998 const BorderValue& endCellAdjoiningBorder = adjoiningEndCell->borderAdjoiningTableEnd();
999 if (endCellAdjoiningBorder.style() == BHIDDEN)
1000 return 0;
1002 const BorderValue& firstRowAdjoiningBorder = adjoiningEndCell->row()->borderAdjoiningTableEnd();
1003 if (firstRowAdjoiningBorder.style() == BHIDDEN)
1004 return 0;
1006 if (endCellAdjoiningBorder.style() > BHIDDEN)
1007 borderWidth = std::max(borderWidth, endCellAdjoiningBorder.width());
1008 if (firstRowAdjoiningBorder.style() > BHIDDEN)
1009 borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width());
1012 return (borderWidth + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
1015 void LayoutTable::recalcBordersInRowDirection()
1017 // FIXME: We need to compute the collapsed before / after borders in the same fashion.
1018 m_borderStart = calcBorderStart();
1019 m_borderEnd = calcBorderEnd();
1022 int LayoutTable::borderBefore() const
1024 if (collapseBorders()) {
1025 recalcSectionsIfNeeded();
1026 return outerBorderBefore();
1028 return LayoutBlock::borderBefore();
1031 int LayoutTable::borderAfter() const
1033 if (collapseBorders()) {
1034 recalcSectionsIfNeeded();
1035 return outerBorderAfter();
1037 return LayoutBlock::borderAfter();
1040 int LayoutTable::outerBorderBefore() const
1042 if (!collapseBorders())
1043 return 0;
1044 int borderWidth = 0;
1045 if (LayoutTableSection* topSection = this->topSection()) {
1046 borderWidth = topSection->outerBorderBefore();
1047 if (borderWidth < 0)
1048 return 0; // Overridden by hidden
1050 const BorderValue& tb = style()->borderBefore();
1051 if (tb.style() == BHIDDEN)
1052 return 0;
1053 if (tb.style() > BHIDDEN)
1054 borderWidth = std::max<int>(borderWidth, tb.width() / 2);
1055 return borderWidth;
1058 int LayoutTable::outerBorderAfter() const
1060 if (!collapseBorders())
1061 return 0;
1062 int borderWidth = 0;
1064 if (LayoutTableSection* section = bottomSection()) {
1065 borderWidth = section->outerBorderAfter();
1066 if (borderWidth < 0)
1067 return 0; // Overridden by hidden
1069 const BorderValue& tb = style()->borderAfter();
1070 if (tb.style() == BHIDDEN)
1071 return 0;
1072 if (tb.style() > BHIDDEN)
1073 borderWidth = std::max<int>(borderWidth, (tb.width() + 1) / 2);
1074 return borderWidth;
1077 int LayoutTable::outerBorderStart() const
1079 if (!collapseBorders())
1080 return 0;
1082 int borderWidth = 0;
1084 const BorderValue& tb = style()->borderStart();
1085 if (tb.style() == BHIDDEN)
1086 return 0;
1087 if (tb.style() > BHIDDEN)
1088 borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
1090 bool allHidden = true;
1091 for (LayoutTableSection* section = topSection(); section; section = sectionBelow(section)) {
1092 int sw = section->outerBorderStart();
1093 if (sw < 0)
1094 continue;
1095 allHidden = false;
1096 borderWidth = std::max(borderWidth, sw);
1098 if (allHidden)
1099 return 0;
1101 return borderWidth;
1104 int LayoutTable::outerBorderEnd() const
1106 if (!collapseBorders())
1107 return 0;
1109 int borderWidth = 0;
1111 const BorderValue& tb = style()->borderEnd();
1112 if (tb.style() == BHIDDEN)
1113 return 0;
1114 if (tb.style() > BHIDDEN)
1115 borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
1117 bool allHidden = true;
1118 for (LayoutTableSection* section = topSection(); section; section = sectionBelow(section)) {
1119 int sw = section->outerBorderEnd();
1120 if (sw < 0)
1121 continue;
1122 allHidden = false;
1123 borderWidth = std::max(borderWidth, sw);
1125 if (allHidden)
1126 return 0;
1128 return borderWidth;
1131 LayoutTableSection* LayoutTable::sectionAbove(const LayoutTableSection* section, SkipEmptySectionsValue skipEmptySections) const
1133 recalcSectionsIfNeeded();
1135 if (section == m_head)
1136 return 0;
1138 LayoutObject* prevSection = section == m_foot ? lastChild() : section->previousSibling();
1139 while (prevSection) {
1140 if (prevSection->isTableSection() && prevSection != m_head && prevSection != m_foot && (skipEmptySections == DoNotSkipEmptySections || toLayoutTableSection(prevSection)->numRows()))
1141 break;
1142 prevSection = prevSection->previousSibling();
1144 if (!prevSection && m_head && (skipEmptySections == DoNotSkipEmptySections || m_head->numRows()))
1145 prevSection = m_head;
1146 return toLayoutTableSection(prevSection);
1149 LayoutTableSection* LayoutTable::sectionBelow(const LayoutTableSection* section, SkipEmptySectionsValue skipEmptySections) const
1151 recalcSectionsIfNeeded();
1153 if (section == m_foot)
1154 return nullptr;
1156 LayoutObject* nextSection = section == m_head ? firstChild() : section->nextSibling();
1157 while (nextSection) {
1158 if (nextSection->isTableSection() && nextSection != m_head && nextSection != m_foot && (skipEmptySections == DoNotSkipEmptySections || toLayoutTableSection(nextSection)->numRows()))
1159 break;
1160 nextSection = nextSection->nextSibling();
1162 if (!nextSection && m_foot && (skipEmptySections == DoNotSkipEmptySections || m_foot->numRows()))
1163 nextSection = m_foot;
1164 return toLayoutTableSection(nextSection);
1167 LayoutTableSection* LayoutTable::bottomSection() const
1169 recalcSectionsIfNeeded();
1171 if (m_foot)
1172 return m_foot;
1174 for (LayoutObject* child = lastChild(); child; child = child->previousSibling()) {
1175 if (child->isTableSection())
1176 return toLayoutTableSection(child);
1179 return nullptr;
1182 LayoutTableCell* LayoutTable::cellAbove(const LayoutTableCell* cell) const
1184 recalcSectionsIfNeeded();
1186 // Find the section and row to look in
1187 unsigned r = cell->rowIndex();
1188 LayoutTableSection* section = nullptr;
1189 unsigned rAbove = 0;
1190 if (r > 0) {
1191 // cell is not in the first row, so use the above row in its own section
1192 section = cell->section();
1193 rAbove = r - 1;
1194 } else {
1195 section = sectionAbove(cell->section(), SkipEmptySections);
1196 if (section) {
1197 ASSERT(section->numRows());
1198 rAbove = section->numRows() - 1;
1202 // Look up the cell in the section's grid, which requires effective col index
1203 if (section) {
1204 unsigned effCol = colToEffCol(cell->col());
1205 LayoutTableSection::CellStruct& aboveCell = section->cellAt(rAbove, effCol);
1206 return aboveCell.primaryCell();
1208 return nullptr;
1211 LayoutTableCell* LayoutTable::cellBelow(const LayoutTableCell* cell) const
1213 recalcSectionsIfNeeded();
1215 // Find the section and row to look in
1216 unsigned r = cell->rowIndex() + cell->rowSpan() - 1;
1217 LayoutTableSection* section = nullptr;
1218 unsigned rBelow = 0;
1219 if (r < cell->section()->numRows() - 1) {
1220 // The cell is not in the last row, so use the next row in the section.
1221 section = cell->section();
1222 rBelow = r + 1;
1223 } else {
1224 section = sectionBelow(cell->section(), SkipEmptySections);
1225 if (section)
1226 rBelow = 0;
1229 // Look up the cell in the section's grid, which requires effective col index
1230 if (section) {
1231 unsigned effCol = colToEffCol(cell->col());
1232 LayoutTableSection::CellStruct& belowCell = section->cellAt(rBelow, effCol);
1233 return belowCell.primaryCell();
1235 return nullptr;
1238 LayoutTableCell* LayoutTable::cellBefore(const LayoutTableCell* cell) const
1240 recalcSectionsIfNeeded();
1242 LayoutTableSection* section = cell->section();
1243 unsigned effCol = colToEffCol(cell->col());
1244 if (!effCol)
1245 return nullptr;
1247 // If we hit a colspan back up to a real cell.
1248 LayoutTableSection::CellStruct& prevCell = section->cellAt(cell->rowIndex(), effCol - 1);
1249 return prevCell.primaryCell();
1252 LayoutTableCell* LayoutTable::cellAfter(const LayoutTableCell* cell) const
1254 recalcSectionsIfNeeded();
1256 unsigned effCol = colToEffCol(cell->col() + cell->colSpan());
1257 if (effCol >= numEffCols())
1258 return nullptr;
1259 return cell->section()->primaryCellAt(cell->rowIndex(), effCol);
1262 int LayoutTable::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
1264 ASSERT(linePositionMode == PositionOnContainingLine);
1265 int baseline = firstLineBoxBaseline();
1266 if (baseline != -1) {
1267 if (isInline())
1268 return beforeMarginInLineDirection(direction) + baseline;
1269 return baseline;
1272 return LayoutBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
1275 int LayoutTable::inlineBlockBaseline(LineDirectionMode) const
1277 // Tables are skipped when computing an inline-block's baseline.
1278 return -1;
1281 int LayoutTable::firstLineBoxBaseline() const
1283 // The baseline of a 'table' is the same as the 'inline-table' baseline per CSS 3 Flexbox (CSS 2.1
1284 // doesn't define the baseline of a 'table' only an 'inline-table').
1285 // This is also needed to properly determine the baseline of a cell if it has a table child.
1287 if (isWritingModeRoot())
1288 return -1;
1290 recalcSectionsIfNeeded();
1292 const LayoutTableSection* topNonEmptySection = this->topNonEmptySection();
1293 if (!topNonEmptySection)
1294 return -1;
1296 int baseline = topNonEmptySection->firstLineBoxBaseline();
1297 if (baseline >= 0)
1298 return topNonEmptySection->logicalTop() + baseline;
1300 // FF, Presto and IE use the top of the section as the baseline if its first row is empty of cells or content.
1301 // The baseline of an empty row isn't specified by CSS 2.1.
1302 if (topNonEmptySection->firstRow() && !topNonEmptySection->firstRow()->firstCell())
1303 return topNonEmptySection->logicalTop();
1305 return -1;
1308 LayoutRect LayoutTable::overflowClipRect(const LayoutPoint& location, OverlayScrollbarSizeRelevancy relevancy) const
1310 LayoutRect rect = LayoutBlock::overflowClipRect(location, relevancy);
1312 // If we have a caption, expand the clip to include the caption.
1313 // FIXME: Technically this is wrong, but it's virtually impossible to fix this
1314 // for real until captions have been re-written.
1315 // FIXME: This code assumes (like all our other caption code) that only top/bottom are
1316 // supported. When we actually support left/right and stop mapping them to top/bottom,
1317 // we might have to hack this code first (depending on what order we do these bug fixes in).
1318 if (!m_captions.isEmpty()) {
1319 if (style()->isHorizontalWritingMode()) {
1320 rect.setHeight(size().height());
1321 rect.setY(location.y());
1322 } else {
1323 rect.setWidth(size().width());
1324 rect.setX(location.x());
1328 return rect;
1331 bool LayoutTable::nodeAtPoint(HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
1333 LayoutPoint adjustedLocation = accumulatedOffset + location();
1335 // Check kids first.
1336 if (!hasOverflowClip() || locationInContainer.intersects(overflowClipRect(adjustedLocation))) {
1337 for (LayoutObject* child = lastChild(); child; child = child->previousSibling()) {
1338 if (child->isBox() && !toLayoutBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
1339 LayoutPoint childPoint = flipForWritingModeForChild(toLayoutBox(child), adjustedLocation);
1340 if (child->nodeAtPoint(result, locationInContainer, childPoint, action)) {
1341 updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
1342 return true;
1348 // Check our bounds next.
1349 LayoutRect boundsRect(adjustedLocation, size());
1350 if (visibleToHitTestRequest(result.hitTestRequest()) && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && locationInContainer.intersects(boundsRect)) {
1351 updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(adjustedLocation)));
1352 if (!result.addNodeToListBasedTestResult(node(), locationInContainer, boundsRect))
1353 return true;
1356 return false;
1359 LayoutTable* LayoutTable::createAnonymousWithParent(const LayoutObject* parent)
1361 RefPtr<ComputedStyle> newStyle = ComputedStyle::createAnonymousStyleWithDisplay(parent->styleRef(), TABLE);
1362 LayoutTable* newTable = new LayoutTable(nullptr);
1363 newTable->setDocumentForAnonymous(&parent->document());
1364 newTable->setStyle(newStyle.release());
1365 return newTable;
1368 const BorderValue& LayoutTable::tableStartBorderAdjoiningCell(const LayoutTableCell* cell) const
1370 ASSERT(cell->isFirstOrLastCellInRow());
1371 if (hasSameDirectionAs(cell->row()))
1372 return style()->borderStart();
1374 return style()->borderEnd();
1377 const BorderValue& LayoutTable::tableEndBorderAdjoiningCell(const LayoutTableCell* cell) const
1379 ASSERT(cell->isFirstOrLastCellInRow());
1380 if (hasSameDirectionAs(cell->row()))
1381 return style()->borderEnd();
1383 return style()->borderStart();
1386 PaintInvalidationReason LayoutTable::invalidatePaintIfNeeded(PaintInvalidationState& paintInvalidationState, const LayoutBoxModelObject& paintInvalidationContainer)
1388 // Information of collapsed borders doesn't affect layout and are for painting only.
1389 // Do it now instead of during painting to invalidate table cells if needed.
1390 recalcCollapsedBordersIfNeeded();
1391 return LayoutBlock::invalidatePaintIfNeeded(paintInvalidationState, paintInvalidationContainer);
1394 void LayoutTable::invalidatePaintOfSubtreesIfNeeded(PaintInvalidationState& childPaintInvalidationState)
1396 // Table cells paint background from the containing column group, column, section and row.
1397 // If background of any of them changed, we need to invalidate all affected cells.
1398 // Here use shouldDoFullPaintInvalidation() as a broader condition of background change.
1399 for (LayoutObject* section = firstChild(); section; section = section->nextSibling()) {
1400 if (!section->isTableSection())
1401 continue;
1402 for (LayoutTableRow* row = toLayoutTableSection(section)->firstRow(); row; row = row->nextRow()) {
1403 for (LayoutTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) {
1404 LayoutTableCol* column = colElement(cell->col());
1405 LayoutTableCol* columnGroup = column ? column->enclosingColumnGroup() : 0;
1406 if ((columnGroup && columnGroup->shouldDoFullPaintInvalidation())
1407 || (column && column->shouldDoFullPaintInvalidation())
1408 || section->shouldDoFullPaintInvalidation()
1409 || row->shouldDoFullPaintInvalidation())
1410 cell->invalidateDisplayItemClient(*cell);
1415 LayoutBlock::invalidatePaintOfSubtreesIfNeeded(childPaintInvalidationState);