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)
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 "core/rendering/RenderTable.h"
28
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/paint/BoxPainter.h"
34#include "core/paint/TablePainter.h"
35#include "core/rendering/AutoTableLayout.h"
36#include "core/rendering/FixedTableLayout.h"
37#include "core/rendering/GraphicsContextAnnotator.h"
38#include "core/rendering/HitTestResult.h"
39#include "core/rendering/RenderLayer.h"
40#include "core/rendering/RenderTableCaption.h"
41#include "core/rendering/RenderTableCell.h"
42#include "core/rendering/RenderTableCol.h"
43#include "core/rendering/RenderTableSection.h"
44#include "core/rendering/RenderView.h"
45#include "core/rendering/SubtreeLayoutScope.h"
46#include "core/rendering/TextAutosizer.h"
47#include "core/rendering/style/StyleInheritedData.h"
48#include "platform/graphics/GraphicsContextStateSaver.h"
49
50namespace blink {
51
52using namespace HTMLNames;
53
54RenderTable::RenderTable(Element* element)
55    : RenderBlock(element)
56    , m_head(0)
57    , m_foot(0)
58    , m_firstBody(0)
59    , m_currentBorder(0)
60    , m_collapsedBordersValid(false)
61    , m_hasColElements(false)
62    , m_needsSectionRecalc(false)
63    , m_columnLogicalWidthChanged(false)
64    , m_columnRenderersValid(false)
65    , m_hasCellColspanThatDeterminesTableWidth(false)
66    , m_hSpacing(0)
67    , m_vSpacing(0)
68    , m_borderStart(0)
69    , m_borderEnd(0)
70{
71    ASSERT(!childrenInline());
72    m_columnPos.fill(0, 1);
73}
74
75RenderTable::~RenderTable()
76{
77}
78
79void RenderTable::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
80{
81    RenderBlock::styleDidChange(diff, oldStyle);
82    propagateStyleToAnonymousChildren();
83
84    bool oldFixedTableLayout = oldStyle ? oldStyle->isFixedTableLayout() : false;
85
86    // In the collapsed border model, there is no cell spacing.
87    m_hSpacing = collapseBorders() ? 0 : style()->horizontalBorderSpacing();
88    m_vSpacing = collapseBorders() ? 0 : style()->verticalBorderSpacing();
89    m_columnPos[0] = m_hSpacing;
90
91    if (!m_tableLayout || style()->isFixedTableLayout() != oldFixedTableLayout) {
92        if (m_tableLayout)
93            m_tableLayout->willChangeTableLayout();
94
95        // According to the CSS2 spec, you only use fixed table layout if an
96        // explicit width is specified on the table.  Auto width implies auto table layout.
97        if (style()->isFixedTableLayout())
98            m_tableLayout = adoptPtr(new FixedTableLayout(this));
99        else
100            m_tableLayout = adoptPtr(new AutoTableLayout(this));
101    }
102
103    // If border was changed, invalidate collapsed borders cache.
104    if (!needsLayout() && oldStyle && oldStyle->border() != style()->border())
105        invalidateCollapsedBorders();
106}
107
108static inline void resetSectionPointerIfNotBefore(RenderTableSection*& ptr, RenderObject* before)
109{
110    if (!before || !ptr)
111        return;
112    RenderObject* o = before->previousSibling();
113    while (o && o != ptr)
114        o = o->previousSibling();
115    if (!o)
116        ptr = 0;
117}
118
119static inline bool needsTableSection(RenderObject* object)
120{
121    // Return true if 'object' can't exist in an anonymous table without being
122    // wrapped in a table section box.
123    EDisplay display = object->style()->display();
124    return display != TABLE_CAPTION && display != TABLE_COLUMN_GROUP && display != TABLE_COLUMN;
125}
126
127void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
128{
129    bool wrapInAnonymousSection = !child->isOutOfFlowPositioned();
130
131    if (child->isTableCaption())
132        wrapInAnonymousSection = false;
133    else if (child->isRenderTableCol()) {
134        m_hasColElements = true;
135        wrapInAnonymousSection = false;
136    } else if (child->isTableSection()) {
137        switch (child->style()->display()) {
138            case TABLE_HEADER_GROUP:
139                resetSectionPointerIfNotBefore(m_head, beforeChild);
140                if (!m_head) {
141                    m_head = toRenderTableSection(child);
142                } else {
143                    resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
144                    if (!m_firstBody)
145                        m_firstBody = toRenderTableSection(child);
146                }
147                wrapInAnonymousSection = false;
148                break;
149            case TABLE_FOOTER_GROUP:
150                resetSectionPointerIfNotBefore(m_foot, beforeChild);
151                if (!m_foot) {
152                    m_foot = toRenderTableSection(child);
153                    wrapInAnonymousSection = false;
154                    break;
155                }
156                // Fall through.
157            case TABLE_ROW_GROUP:
158                resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
159                if (!m_firstBody)
160                    m_firstBody = toRenderTableSection(child);
161                wrapInAnonymousSection = false;
162                break;
163            default:
164                ASSERT_NOT_REACHED();
165        }
166    } else
167        wrapInAnonymousSection = true;
168
169    if (child->isTableSection())
170        setNeedsSectionRecalc();
171
172    if (!wrapInAnonymousSection) {
173        if (beforeChild && beforeChild->parent() != this)
174            beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
175
176        RenderBox::addChild(child, beforeChild);
177        return;
178    }
179
180    if (!beforeChild && lastChild() && lastChild()->isTableSection() && lastChild()->isAnonymous() && !lastChild()->isBeforeContent()) {
181        lastChild()->addChild(child);
182        return;
183    }
184
185    if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
186        RenderObject* section = beforeChild->previousSibling();
187        if (section && section->isTableSection() && section->isAnonymous()) {
188            section->addChild(child);
189            return;
190        }
191    }
192
193    RenderObject* 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;
201    }
202
203    if (beforeChild && !beforeChild->isTableSection() && needsTableSection(beforeChild))
204        beforeChild = 0;
205
206    RenderTableSection* section = RenderTableSection::createAnonymousWithParentRenderer(this);
207    addChild(section, beforeChild);
208    section->addChild(child);
209}
210
211void RenderTable::addCaption(const RenderTableCaption* caption)
212{
213    ASSERT(m_captions.find(caption) == kNotFound);
214    m_captions.append(const_cast<RenderTableCaption*>(caption));
215}
216
217void RenderTable::removeCaption(const RenderTableCaption* oldCaption)
218{
219    size_t index = m_captions.find(oldCaption);
220    ASSERT(index != kNotFound);
221    if (index == kNotFound)
222        return;
223
224    m_captions.remove(index);
225}
226
227void RenderTable::invalidateCachedColumns()
228{
229    m_columnRenderersValid = false;
230    m_columnRenderers.resize(0);
231}
232
233void RenderTable::addColumn(const RenderTableCol*)
234{
235    invalidateCachedColumns();
236}
237
238void RenderTable::removeColumn(const RenderTableCol*)
239{
240    invalidateCachedColumns();
241    // We don't really need to recompute our sections, but we need to update our
242    // column count and whether we have a column. Currently, we only have one
243    // size-fit-all flag but we may have to consider splitting it.
244    setNeedsSectionRecalc();
245}
246
247void RenderTable::updateLogicalWidth()
248{
249    recalcSectionsIfNeeded();
250
251    if (isOutOfFlowPositioned()) {
252        LogicalExtentComputedValues computedValues;
253        computePositionedLogicalWidth(computedValues);
254        setLogicalWidth(computedValues.m_extent);
255        setLogicalLeft(computedValues.m_position);
256        setMarginStart(computedValues.m_margins.m_start);
257        setMarginEnd(computedValues.m_margins.m_end);
258    }
259
260    RenderBlock* cb = containingBlock();
261
262    LayoutUnit availableLogicalWidth = containingBlockLogicalWidthForContent() + (isOutOfFlowPositioned() ? cb->paddingLogicalWidth() : LayoutUnit(0));
263    bool hasPerpendicularContainingBlock = cb->style()->isHorizontalWritingMode() != style()->isHorizontalWritingMode();
264    LayoutUnit containerWidthInInlineDirection = hasPerpendicularContainingBlock ? perpendicularContainingBlockLogicalHeight() : availableLogicalWidth;
265
266    Length styleLogicalWidth = style()->logicalWidth();
267    if ((styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive()) || styleLogicalWidth.isIntrinsic())
268        setLogicalWidth(convertStyleLogicalWidthToComputedWidth(styleLogicalWidth, containerWidthInInlineDirection));
269    else {
270        // Subtract out any fixed margins from our available width for auto width tables.
271        LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth);
272        LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth);
273        LayoutUnit marginTotal = marginStart + marginEnd;
274
275        // Subtract out our margins to get the available content width.
276        LayoutUnit availableContentLogicalWidth = std::max<LayoutUnit>(0, containerWidthInInlineDirection - marginTotal);
277        if (shrinkToAvoidFloats() && cb->isRenderBlockFlow() && toRenderBlockFlow(cb)->containsFloats() && !hasPerpendicularContainingBlock)
278            availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, toRenderBlockFlow(cb));
279
280        // Ensure we aren't bigger than our available width.
281        setLogicalWidth(std::min<int>(availableContentLogicalWidth, maxPreferredLogicalWidth()));
282    }
283
284    // Ensure we aren't bigger than our max-width style.
285    Length styleMaxLogicalWidth = style()->logicalMaxWidth();
286    if ((styleMaxLogicalWidth.isSpecified() && !styleMaxLogicalWidth.isNegative()) || styleMaxLogicalWidth.isIntrinsic()) {
287        LayoutUnit computedMaxLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMaxLogicalWidth, availableLogicalWidth);
288        setLogicalWidth(std::min<int>(logicalWidth(), computedMaxLogicalWidth));
289    }
290
291    // Ensure we aren't smaller than our min preferred width. This MUST be done after 'max-width' as
292    // we ignore it if it means we wouldn't accomodate our content.
293    setLogicalWidth(std::max<int>(logicalWidth(), minPreferredLogicalWidth()));
294
295     // Ensure we aren't smaller than our min-width style.
296    Length styleMinLogicalWidth = style()->logicalMinWidth();
297    if ((styleMinLogicalWidth.isSpecified() && !styleMinLogicalWidth.isNegative()) || styleMinLogicalWidth.isIntrinsic()) {
298        LayoutUnit computedMinLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMinLogicalWidth, availableLogicalWidth);
299        setLogicalWidth(std::max<int>(logicalWidth(), computedMinLogicalWidth));
300    }
301
302    // Finally, with our true width determined, compute our margins for real.
303    ComputedMarginValues marginValues;
304    computeMarginsForDirection(InlineDirection, cb, availableLogicalWidth, logicalWidth(), marginValues.m_start, marginValues.m_end, style()->marginStart(), style()->marginEnd());
305    setMarginStart(marginValues.m_start);
306    setMarginEnd(marginValues.m_end);
307
308    // We should NEVER shrink the table below the min-content logical width, or else the table can't accomodate
309    // its own content which doesn't match CSS nor what authors expect.
310    // FIXME: When we convert to sub-pixel layout for tables we can remove the int conversion
311    // https://code.google.com/p/chromium/issues/detail?id=241198
312    ASSERT(logicalWidth().toInt() >= minPreferredLogicalWidth().toInt());
313}
314
315// This method takes a RenderStyle's logical width, min-width, or max-width length and computes its actual value.
316LayoutUnit RenderTable::convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth)
317{
318    if (styleLogicalWidth.isIntrinsic())
319        return computeIntrinsicLogicalWidthUsing(styleLogicalWidth, availableWidth, bordersPaddingAndSpacingInRowDirection());
320
321    // HTML tables' width styles already include borders and paddings, but CSS tables' width styles do not.
322    LayoutUnit borders = 0;
323    bool isCSSTable = !isHTMLTableElement(node());
324    if (isCSSTable && styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive() && style()->boxSizing() == CONTENT_BOX)
325        borders = borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd());
326
327    return minimumValueForLength(styleLogicalWidth, availableWidth) + borders;
328}
329
330LayoutUnit RenderTable::convertStyleLogicalHeightToComputedHeight(const Length& styleLogicalHeight)
331{
332    LayoutUnit borderAndPaddingBefore = borderBefore() + (collapseBorders() ? LayoutUnit() : paddingBefore());
333    LayoutUnit borderAndPaddingAfter = borderAfter() + (collapseBorders() ? LayoutUnit() : paddingAfter());
334    LayoutUnit borderAndPadding = borderAndPaddingBefore + borderAndPaddingAfter;
335    LayoutUnit computedLogicalHeight = 0;
336    if (styleLogicalHeight.isFixed()) {
337        // HTML tables size as though CSS height includes border/padding, CSS tables do not.
338        LayoutUnit borders = LayoutUnit();
339        // FIXME: We cannot apply box-sizing: content-box on <table> which other browsers allow.
340        if (isHTMLTableElement(node()) || style()->boxSizing() == BORDER_BOX) {
341            borders = borderAndPadding;
342        }
343        computedLogicalHeight = styleLogicalHeight.value() - borders;
344    } else if (styleLogicalHeight.isPercent())
345        computedLogicalHeight = computePercentageLogicalHeight(styleLogicalHeight);
346    else if (styleLogicalHeight.isIntrinsic())
347        computedLogicalHeight = computeIntrinsicLogicalContentHeightUsing(styleLogicalHeight, logicalHeight() - borderAndPadding, borderAndPadding);
348    else
349        ASSERT_NOT_REACHED();
350    return std::max<LayoutUnit>(0, computedLogicalHeight);
351}
352
353void RenderTable::layoutCaption(RenderTableCaption* caption)
354{
355    if (caption->needsLayout()) {
356        // The margins may not be available but ensure the caption is at least located beneath any previous sibling caption
357        // so that it does not mistakenly think any floats in the previous caption intrude into it.
358        caption->setLogicalLocation(LayoutPoint(caption->marginStart(), collapsedMarginBeforeForChild(caption) + logicalHeight()));
359        // If RenderTableCaption ever gets a layout() function, use it here.
360        caption->layoutIfNeeded();
361    }
362    // Apply the margins to the location now that they are definitely available from layout
363    LayoutUnit captionLogicalTop = collapsedMarginBeforeForChild(caption) + logicalHeight();
364    if (view()->layoutState()->isPaginated()) {
365        captionLogicalTop += caption->paginationStrut();
366        caption->setPaginationStrut(0);
367    }
368    caption->setLogicalLocation(LayoutPoint(caption->marginStart(), captionLogicalTop));
369
370    if (!selfNeedsLayout())
371        caption->setMayNeedPaintInvalidation(true);
372
373    setLogicalHeight(logicalHeight() + caption->logicalHeight() + collapsedMarginBeforeForChild(caption) + collapsedMarginAfterForChild(caption));
374}
375
376void RenderTable::distributeExtraLogicalHeight(int extraLogicalHeight)
377{
378    if (extraLogicalHeight <= 0)
379        return;
380
381    // FIXME: Distribute the extra logical height between all table sections instead of giving it all to the first one.
382    if (RenderTableSection* section = firstBody())
383        extraLogicalHeight -= section->distributeExtraLogicalHeightToRows(extraLogicalHeight);
384
385    // FIXME: We really would like to enable this ASSERT to ensure that all the extra space has been distributed.
386    // However our current distribution algorithm does not round properly and thus we can have some remaining height.
387    // ASSERT(!topSection() || !extraLogicalHeight);
388}
389
390void RenderTable::simplifiedNormalFlowLayout()
391{
392    for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
393        section->layoutIfNeeded();
394        section->computeOverflowFromCells();
395    }
396}
397
398void RenderTable::layout()
399{
400    ASSERT(needsLayout());
401
402    if (simplifiedLayout())
403        return;
404
405    // Note: RenderTable is handled differently than other RenderBlocks and the LayoutScope
406    //       must be created before the table begins laying out.
407    TextAutosizer::LayoutScope textAutosizerLayoutScope(this);
408
409    recalcSectionsIfNeeded();
410    // FIXME: We should do this recalc lazily in borderStart/borderEnd so that we don't have to make sure
411    // to call this before we call borderStart/borderEnd to avoid getting a stale value.
412    recalcBordersInRowDirection();
413
414    SubtreeLayoutScope layouter(*this);
415
416    // If any table section moved vertically, we will just issue paint invalidations for everything from that
417    // section down (it is quite unlikely that any of the following sections
418    // did not shift).
419    bool sectionMoved = false;
420    LayoutUnit movedSectionLogicalTop = 0;
421    {
422        LayoutState state(*this, locationOffset());
423
424        setLogicalHeight(0);
425
426        LayoutUnit oldLogicalWidth = logicalWidth();
427        updateLogicalWidth();
428
429        if (logicalWidth() != oldLogicalWidth) {
430            for (unsigned i = 0; i < m_captions.size(); i++)
431                layouter.setNeedsLayout(m_captions[i]);
432        }
433        // FIXME: The optimisation below doesn't work since the internal table
434        // layout could have changed. We need to add a flag to the table
435        // layout that tells us if something has changed in the min max
436        // calculations to do it correctly.
437        // if ( oldWidth != width() || columns.size() + 1 != columnPos.size() )
438        m_tableLayout->layout();
439
440        LayoutUnit totalSectionLogicalHeight = 0;
441        LayoutUnit oldTableLogicalTop = 0;
442        for (unsigned i = 0; i < m_captions.size(); i++)
443            oldTableLogicalTop += m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
444
445        bool collapsing = collapseBorders();
446
447        for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
448            if (child->isTableSection()) {
449                RenderTableSection* section = toRenderTableSection(child);
450                if (m_columnLogicalWidthChanged)
451                    layouter.setChildNeedsLayout(section);
452                section->layoutIfNeeded();
453                totalSectionLogicalHeight += section->calcRowLogicalHeight();
454                if (collapsing)
455                    section->recalcOuterBorder();
456                ASSERT(!section->needsLayout());
457            } else if (child->isRenderTableCol()) {
458                child->layoutIfNeeded();
459                ASSERT(!child->needsLayout());
460            } else {
461                // FIXME: We should never have other type of children (they should be wrapped in an
462                // anonymous table section) but our code is too crazy and this can happen in practice.
463                // Until this is fixed, let's make sure we don't leave non laid out children in the tree.
464                child->layoutIfNeeded();
465            }
466        }
467
468        // FIXME: Collapse caption margin.
469        if (!m_captions.isEmpty()) {
470            for (unsigned i = 0; i < m_captions.size(); i++) {
471                if (m_captions[i]->style()->captionSide() == CAPBOTTOM)
472                    continue;
473                layoutCaption(m_captions[i]);
474            }
475            if (logicalHeight() != oldTableLogicalTop) {
476                sectionMoved = true;
477                movedSectionLogicalTop = std::min(logicalHeight(), oldTableLogicalTop);
478            }
479        }
480
481        LayoutUnit borderAndPaddingBefore = borderBefore() + (collapsing ? LayoutUnit() : paddingBefore());
482        LayoutUnit borderAndPaddingAfter = borderAfter() + (collapsing ? LayoutUnit() : paddingAfter());
483
484        setLogicalHeight(logicalHeight() + borderAndPaddingBefore);
485
486        LayoutUnit computedLogicalHeight = 0;
487
488        Length logicalHeightLength = style()->logicalHeight();
489        if (logicalHeightLength.isIntrinsic() || (logicalHeightLength.isSpecified() && logicalHeightLength.isPositive()))
490            computedLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalHeightLength);
491
492        Length logicalMaxHeightLength = style()->logicalMaxHeight();
493        if (logicalMaxHeightLength.isIntrinsic() || (logicalMaxHeightLength.isSpecified() && !logicalMaxHeightLength.isNegative())) {
494            LayoutUnit computedMaxLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMaxHeightLength);
495            computedLogicalHeight = std::min(computedLogicalHeight, computedMaxLogicalHeight);
496        }
497
498        Length logicalMinHeightLength = style()->logicalMinHeight();
499        if (logicalMinHeightLength.isIntrinsic() || (logicalMinHeightLength.isSpecified() && !logicalMinHeightLength.isNegative())) {
500            LayoutUnit computedMinLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMinHeightLength);
501            computedLogicalHeight = std::max(computedLogicalHeight, computedMinLogicalHeight);
502        }
503
504        distributeExtraLogicalHeight(floorToInt(computedLogicalHeight - totalSectionLogicalHeight));
505
506        for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
507            section->layoutRows();
508
509        if (!topSection() && computedLogicalHeight > totalSectionLogicalHeight && !document().inQuirksMode()) {
510            // Completely empty tables (with no sections or anything) should at least honor specified height
511            // in strict mode.
512            setLogicalHeight(logicalHeight() + computedLogicalHeight);
513        }
514
515        LayoutUnit sectionLogicalLeft = style()->isLeftToRightDirection() ? borderStart() : borderEnd();
516        if (!collapsing)
517            sectionLogicalLeft += style()->isLeftToRightDirection() ? paddingStart() : paddingEnd();
518
519        // position the table sections
520        RenderTableSection* section = topSection();
521        while (section) {
522            if (!sectionMoved && section->logicalTop() != logicalHeight()) {
523                sectionMoved = true;
524                movedSectionLogicalTop = std::min(logicalHeight(), section->logicalTop()) + (style()->isHorizontalWritingMode() ? section->visualOverflowRect().y() : section->visualOverflowRect().x());
525            }
526            section->setLogicalLocation(LayoutPoint(sectionLogicalLeft, logicalHeight()));
527
528            // As we may skip invalidation on the table, we need to ensure that sections are invalidated when they moved.
529            if (sectionMoved && !section->selfNeedsLayout())
530                section->setMayNeedPaintInvalidation(true);
531
532            setLogicalHeight(logicalHeight() + section->logicalHeight());
533
534            section = sectionBelow(section);
535        }
536
537        setLogicalHeight(logicalHeight() + borderAndPaddingAfter);
538
539        for (unsigned i = 0; i < m_captions.size(); i++) {
540            if (m_captions[i]->style()->captionSide() != CAPBOTTOM)
541                continue;
542            layoutCaption(m_captions[i]);
543        }
544
545        updateLogicalHeight();
546
547        // table can be containing block of positioned elements.
548        // FIXME: Only pass true if width or height changed.
549        layoutPositionedObjects(true);
550
551        updateLayerTransformAfterLayout();
552
553        // Layout was changed, so probably borders too.
554        invalidateCollapsedBorders();
555
556        computeOverflow(clientLogicalBottom());
557    }
558
559    // FIXME: This value isn't the intrinsic content logical height, but we need
560    // to update the value as its used by flexbox layout. crbug.com/367324
561    updateIntrinsicContentLogicalHeight(contentLogicalHeight());
562
563    if (view()->layoutState()->pageLogicalHeight())
564        setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(*this, logicalTop()));
565
566    m_columnLogicalWidthChanged = false;
567    clearNeedsLayout();
568}
569
570// Collect all the unique border values that we want to paint in a sorted list.
571void RenderTable::recalcCollapsedBorders()
572{
573    if (m_collapsedBordersValid)
574        return;
575    m_collapsedBordersValid = true;
576    m_collapsedBorders.clear();
577    for (RenderObject* section = firstChild(); section; section = section->nextSibling()) {
578        if (!section->isTableSection())
579            continue;
580        for (RenderTableRow* row = toRenderTableSection(section)->firstRow(); row; row = row->nextRow()) {
581            for (RenderTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) {
582                ASSERT(cell->table() == this);
583                cell->collectBorderValues(m_collapsedBorders);
584            }
585        }
586    }
587    RenderTableCell::sortBorderValues(m_collapsedBorders);
588}
589
590void RenderTable::addOverflowFromChildren()
591{
592    // Add overflow from borders.
593    // Technically it's odd that we are incorporating the borders into layout overflow, which is only supposed to be about overflow from our
594    // descendant objects, but since tables don't support overflow:auto, this works out fine.
595    if (collapseBorders()) {
596        int rightBorderOverflow = width() + outerBorderRight() - borderRight();
597        int leftBorderOverflow = borderLeft() - outerBorderLeft();
598        int bottomBorderOverflow = height() + outerBorderBottom() - borderBottom();
599        int topBorderOverflow = borderTop() - outerBorderTop();
600        IntRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow);
601        if (borderOverflowRect != pixelSnappedBorderBoxRect()) {
602            addLayoutOverflow(borderOverflowRect);
603            addVisualOverflow(borderOverflowRect);
604        }
605    }
606
607    // Add overflow from our caption.
608    for (unsigned i = 0; i < m_captions.size(); i++)
609        addOverflowFromChild(m_captions[i]);
610
611    // Add overflow from our sections.
612    for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
613        addOverflowFromChild(section);
614}
615
616void RenderTable::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
617{
618    TablePainter(*this).paint(paintInfo, paintOffset);
619}
620
621void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
622{
623    TablePainter(*this).paintObject(paintInfo, paintOffset);
624}
625
626void RenderTable::subtractCaptionRect(LayoutRect& rect) const
627{
628    for (unsigned i = 0; i < m_captions.size(); i++) {
629        LayoutUnit captionLogicalHeight = m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
630        bool captionIsBefore = (m_captions[i]->style()->captionSide() != CAPBOTTOM) ^ style()->isFlippedBlocksWritingMode();
631        if (style()->isHorizontalWritingMode()) {
632            rect.setHeight(rect.height() - captionLogicalHeight);
633            if (captionIsBefore)
634                rect.move(0, captionLogicalHeight);
635        } else {
636            rect.setWidth(rect.width() - captionLogicalHeight);
637            if (captionIsBefore)
638                rect.move(captionLogicalHeight, 0);
639        }
640    }
641}
642
643void RenderTable::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
644{
645    TablePainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset);
646}
647
648void RenderTable::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
649{
650    TablePainter(*this).paintMask(paintInfo, paintOffset);
651}
652
653void RenderTable::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) const
654{
655    recalcSectionsIfNeeded();
656    // FIXME: Do the recalc in borderStart/borderEnd and make those const_cast this call.
657    // Then m_borderStart/m_borderEnd will be transparent a cache and it removes the possibility
658    // of reading out stale values.
659    const_cast<RenderTable*>(this)->recalcBordersInRowDirection();
660    // FIXME: Restructure the table layout code so that we can make this method const.
661    const_cast<RenderTable*>(this)->m_tableLayout->computeIntrinsicLogicalWidths(minWidth, maxWidth);
662
663    // FIXME: We should include captions widths here like we do in computePreferredLogicalWidths.
664}
665
666void RenderTable::computePreferredLogicalWidths()
667{
668    ASSERT(preferredLogicalWidthsDirty());
669
670    computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
671
672    int bordersPaddingAndSpacing = bordersPaddingAndSpacingInRowDirection();
673    m_minPreferredLogicalWidth += bordersPaddingAndSpacing;
674    m_maxPreferredLogicalWidth += bordersPaddingAndSpacing;
675
676    m_tableLayout->applyPreferredLogicalWidthQuirks(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
677
678    for (unsigned i = 0; i < m_captions.size(); i++)
679        m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, m_captions[i]->minPreferredLogicalWidth());
680
681    RenderStyle* styleToUse = style();
682    // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for min-width.
683    if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
684        m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
685        m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
686    }
687
688    // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for maxWidth.
689    if (styleToUse->logicalMaxWidth().isFixed()) {
690        // We don't constrain m_minPreferredLogicalWidth as the table should be at least the size of its min-content, regardless of 'max-width'.
691        m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
692        m_maxPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
693    }
694
695    // FIXME: We should be adding borderAndPaddingLogicalWidth here, but m_tableLayout->computePreferredLogicalWidths already does,
696    // so a bunch of tests break doing this naively.
697    clearPreferredLogicalWidthsDirty();
698}
699
700RenderTableSection* RenderTable::topNonEmptySection() const
701{
702    RenderTableSection* section = topSection();
703    if (section && !section->numRows())
704        section = sectionBelow(section, SkipEmptySections);
705    return section;
706}
707
708void RenderTable::splitColumn(unsigned position, unsigned firstSpan)
709{
710    // We split the column at "position", taking "firstSpan" cells from the span.
711    ASSERT(m_columns[position].span > firstSpan);
712    m_columns.insert(position, ColumnStruct(firstSpan));
713    m_columns[position + 1].span -= firstSpan;
714
715    // Propagate the change in our columns representation to the sections that don't need
716    // cell recalc. If they do, they will be synced up directly with m_columns later.
717    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
718        if (!child->isTableSection())
719            continue;
720
721        RenderTableSection* section = toRenderTableSection(child);
722        if (section->needsCellRecalc())
723            continue;
724
725        section->splitColumn(position, firstSpan);
726    }
727
728    m_columnPos.grow(numEffCols() + 1);
729}
730
731void RenderTable::appendColumn(unsigned span)
732{
733    unsigned newColumnIndex = m_columns.size();
734    m_columns.append(ColumnStruct(span));
735
736    // Unless the table has cell(s) with colspan that exceed the number of columns afforded
737    // by the other rows in the table we can use the fast path when mapping columns to effective columns.
738    m_hasCellColspanThatDeterminesTableWidth = m_hasCellColspanThatDeterminesTableWidth || span > 1;
739
740    // Propagate the change in our columns representation to the sections that don't need
741    // cell recalc. If they do, they will be synced up directly with m_columns later.
742    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
743        if (!child->isTableSection())
744            continue;
745
746        RenderTableSection* section = toRenderTableSection(child);
747        if (section->needsCellRecalc())
748            continue;
749
750        section->appendColumn(newColumnIndex);
751    }
752
753    m_columnPos.grow(numEffCols() + 1);
754}
755
756RenderTableCol* RenderTable::firstColumn() const
757{
758    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
759        if (child->isRenderTableCol())
760            return toRenderTableCol(child);
761    }
762
763    return 0;
764}
765
766void RenderTable::updateColumnCache() const
767{
768    ASSERT(m_hasColElements);
769    ASSERT(m_columnRenderers.isEmpty());
770    ASSERT(!m_columnRenderersValid);
771
772    for (RenderTableCol* columnRenderer = firstColumn(); columnRenderer; columnRenderer = columnRenderer->nextColumn()) {
773        if (columnRenderer->isTableColumnGroupWithColumnChildren())
774            continue;
775        m_columnRenderers.append(columnRenderer);
776    }
777    m_columnRenderersValid = true;
778}
779
780RenderTableCol* RenderTable::slowColElement(unsigned col, bool* startEdge, bool* endEdge) const
781{
782    ASSERT(m_hasColElements);
783
784    if (!m_columnRenderersValid)
785        updateColumnCache();
786
787    unsigned columnCount = 0;
788    for (unsigned i = 0; i < m_columnRenderers.size(); i++) {
789        RenderTableCol* columnRenderer = m_columnRenderers[i];
790        unsigned span = columnRenderer->span();
791        unsigned startCol = columnCount;
792        ASSERT(span >= 1);
793        unsigned endCol = columnCount + span - 1;
794        columnCount += span;
795        if (columnCount > col) {
796            if (startEdge)
797                *startEdge = startCol == col;
798            if (endEdge)
799                *endEdge = endCol == col;
800            return columnRenderer;
801        }
802    }
803    return 0;
804}
805
806void RenderTable::recalcSections() const
807{
808    ASSERT(m_needsSectionRecalc);
809
810    m_head = 0;
811    m_foot = 0;
812    m_firstBody = 0;
813    m_hasColElements = false;
814    m_hasCellColspanThatDeterminesTableWidth = hasCellColspanThatDeterminesTableWidth();
815
816    // We need to get valid pointers to caption, head, foot and first body again
817    RenderObject* nextSibling;
818    for (RenderObject* child = firstChild(); child; child = nextSibling) {
819        nextSibling = child->nextSibling();
820        switch (child->style()->display()) {
821        case TABLE_COLUMN:
822        case TABLE_COLUMN_GROUP:
823            m_hasColElements = true;
824            break;
825        case TABLE_HEADER_GROUP:
826            if (child->isTableSection()) {
827                RenderTableSection* section = toRenderTableSection(child);
828                if (!m_head)
829                    m_head = section;
830                else if (!m_firstBody)
831                    m_firstBody = section;
832                section->recalcCellsIfNeeded();
833            }
834            break;
835        case TABLE_FOOTER_GROUP:
836            if (child->isTableSection()) {
837                RenderTableSection* section = toRenderTableSection(child);
838                if (!m_foot)
839                    m_foot = section;
840                else if (!m_firstBody)
841                    m_firstBody = section;
842                section->recalcCellsIfNeeded();
843            }
844            break;
845        case TABLE_ROW_GROUP:
846            if (child->isTableSection()) {
847                RenderTableSection* section = toRenderTableSection(child);
848                if (!m_firstBody)
849                    m_firstBody = section;
850                section->recalcCellsIfNeeded();
851            }
852            break;
853        default:
854            break;
855        }
856    }
857
858    // repair column count (addChild can grow it too much, because it always adds elements to the last row of a section)
859    unsigned maxCols = 0;
860    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
861        if (child->isTableSection()) {
862            RenderTableSection* section = toRenderTableSection(child);
863            unsigned sectionCols = section->numColumns();
864            if (sectionCols > maxCols)
865                maxCols = sectionCols;
866        }
867    }
868
869    m_columns.resize(maxCols);
870    m_columnPos.resize(maxCols + 1);
871
872    ASSERT(selfNeedsLayout());
873
874    m_needsSectionRecalc = false;
875}
876
877int RenderTable::calcBorderStart() const
878{
879    if (!collapseBorders())
880        return RenderBlock::borderStart();
881
882    // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2.
883    if (!numEffCols())
884        return 0;
885
886    unsigned borderWidth = 0;
887
888    const BorderValue& tableStartBorder = style()->borderStart();
889    if (tableStartBorder.style() == BHIDDEN)
890        return 0;
891    if (tableStartBorder.style() > BHIDDEN)
892        borderWidth = tableStartBorder.width();
893
894    if (RenderTableCol* column = colElement(0)) {
895        // FIXME: We don't account for direction on columns and column groups.
896        const BorderValue& columnAdjoiningBorder = column->style()->borderStart();
897        if (columnAdjoiningBorder.style() == BHIDDEN)
898            return 0;
899        if (columnAdjoiningBorder.style() > BHIDDEN)
900            borderWidth = std::max(borderWidth, columnAdjoiningBorder.width());
901        // FIXME: This logic doesn't properly account for the first column in the first column-group case.
902    }
903
904    if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) {
905        const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableStart();
906        if (sectionAdjoiningBorder.style() == BHIDDEN)
907            return 0;
908
909        if (sectionAdjoiningBorder.style() > BHIDDEN)
910            borderWidth = std::max(borderWidth, sectionAdjoiningBorder.width());
911
912        if (const RenderTableCell* adjoiningStartCell = topNonEmptySection->firstRowCellAdjoiningTableStart()) {
913            // FIXME: Make this work with perpendicular and flipped cells.
914            const BorderValue& startCellAdjoiningBorder = adjoiningStartCell->borderAdjoiningTableStart();
915            if (startCellAdjoiningBorder.style() == BHIDDEN)
916                return 0;
917
918            const BorderValue& firstRowAdjoiningBorder = adjoiningStartCell->row()->borderAdjoiningTableStart();
919            if (firstRowAdjoiningBorder.style() == BHIDDEN)
920                return 0;
921
922            if (startCellAdjoiningBorder.style() > BHIDDEN)
923                borderWidth = std::max(borderWidth, startCellAdjoiningBorder.width());
924            if (firstRowAdjoiningBorder.style() > BHIDDEN)
925                borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width());
926        }
927    }
928    return (borderWidth + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
929}
930
931int RenderTable::calcBorderEnd() const
932{
933    if (!collapseBorders())
934        return RenderBlock::borderEnd();
935
936    // Determined by the last cell of the first row. See the CSS 2.1 spec, section 17.6.2.
937    if (!numEffCols())
938        return 0;
939
940    unsigned borderWidth = 0;
941
942    const BorderValue& tableEndBorder = style()->borderEnd();
943    if (tableEndBorder.style() == BHIDDEN)
944        return 0;
945    if (tableEndBorder.style() > BHIDDEN)
946        borderWidth = tableEndBorder.width();
947
948    unsigned endColumn = numEffCols() - 1;
949    if (RenderTableCol* column = colElement(endColumn)) {
950        // FIXME: We don't account for direction on columns and column groups.
951        const BorderValue& columnAdjoiningBorder = column->style()->borderEnd();
952        if (columnAdjoiningBorder.style() == BHIDDEN)
953            return 0;
954        if (columnAdjoiningBorder.style() > BHIDDEN)
955            borderWidth = std::max(borderWidth, columnAdjoiningBorder.width());
956        // FIXME: This logic doesn't properly account for the last column in the last column-group case.
957    }
958
959    if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) {
960        const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableEnd();
961        if (sectionAdjoiningBorder.style() == BHIDDEN)
962            return 0;
963
964        if (sectionAdjoiningBorder.style() > BHIDDEN)
965            borderWidth = std::max(borderWidth, sectionAdjoiningBorder.width());
966
967        if (const RenderTableCell* adjoiningEndCell = topNonEmptySection->firstRowCellAdjoiningTableEnd()) {
968            // FIXME: Make this work with perpendicular and flipped cells.
969            const BorderValue& endCellAdjoiningBorder = adjoiningEndCell->borderAdjoiningTableEnd();
970            if (endCellAdjoiningBorder.style() == BHIDDEN)
971                return 0;
972
973            const BorderValue& firstRowAdjoiningBorder = adjoiningEndCell->row()->borderAdjoiningTableEnd();
974            if (firstRowAdjoiningBorder.style() == BHIDDEN)
975                return 0;
976
977            if (endCellAdjoiningBorder.style() > BHIDDEN)
978                borderWidth = std::max(borderWidth, endCellAdjoiningBorder.width());
979            if (firstRowAdjoiningBorder.style() > BHIDDEN)
980                borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width());
981        }
982    }
983    return (borderWidth + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
984}
985
986void RenderTable::recalcBordersInRowDirection()
987{
988    // FIXME: We need to compute the collapsed before / after borders in the same fashion.
989    m_borderStart = calcBorderStart();
990    m_borderEnd = calcBorderEnd();
991}
992
993int RenderTable::borderBefore() const
994{
995    if (collapseBorders()) {
996        recalcSectionsIfNeeded();
997        return outerBorderBefore();
998    }
999    return RenderBlock::borderBefore();
1000}
1001
1002int RenderTable::borderAfter() const
1003{
1004    if (collapseBorders()) {
1005        recalcSectionsIfNeeded();
1006        return outerBorderAfter();
1007    }
1008    return RenderBlock::borderAfter();
1009}
1010
1011int RenderTable::outerBorderBefore() const
1012{
1013    if (!collapseBorders())
1014        return 0;
1015    int borderWidth = 0;
1016    if (RenderTableSection* topSection = this->topSection()) {
1017        borderWidth = topSection->outerBorderBefore();
1018        if (borderWidth < 0)
1019            return 0;   // Overridden by hidden
1020    }
1021    const BorderValue& tb = style()->borderBefore();
1022    if (tb.style() == BHIDDEN)
1023        return 0;
1024    if (tb.style() > BHIDDEN)
1025        borderWidth = std::max<int>(borderWidth, tb.width() / 2);
1026    return borderWidth;
1027}
1028
1029int RenderTable::outerBorderAfter() const
1030{
1031    if (!collapseBorders())
1032        return 0;
1033    int borderWidth = 0;
1034
1035    if (RenderTableSection* section = bottomSection()) {
1036        borderWidth = section->outerBorderAfter();
1037        if (borderWidth < 0)
1038            return 0; // Overridden by hidden
1039    }
1040    const BorderValue& tb = style()->borderAfter();
1041    if (tb.style() == BHIDDEN)
1042        return 0;
1043    if (tb.style() > BHIDDEN)
1044        borderWidth = std::max<int>(borderWidth, (tb.width() + 1) / 2);
1045    return borderWidth;
1046}
1047
1048int RenderTable::outerBorderStart() const
1049{
1050    if (!collapseBorders())
1051        return 0;
1052
1053    int borderWidth = 0;
1054
1055    const BorderValue& tb = style()->borderStart();
1056    if (tb.style() == BHIDDEN)
1057        return 0;
1058    if (tb.style() > BHIDDEN)
1059        borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
1060
1061    bool allHidden = true;
1062    for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
1063        int sw = section->outerBorderStart();
1064        if (sw < 0)
1065            continue;
1066        allHidden = false;
1067        borderWidth = std::max(borderWidth, sw);
1068    }
1069    if (allHidden)
1070        return 0;
1071
1072    return borderWidth;
1073}
1074
1075int RenderTable::outerBorderEnd() const
1076{
1077    if (!collapseBorders())
1078        return 0;
1079
1080    int borderWidth = 0;
1081
1082    const BorderValue& tb = style()->borderEnd();
1083    if (tb.style() == BHIDDEN)
1084        return 0;
1085    if (tb.style() > BHIDDEN)
1086        borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
1087
1088    bool allHidden = true;
1089    for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
1090        int sw = section->outerBorderEnd();
1091        if (sw < 0)
1092            continue;
1093        allHidden = false;
1094        borderWidth = std::max(borderWidth, sw);
1095    }
1096    if (allHidden)
1097        return 0;
1098
1099    return borderWidth;
1100}
1101
1102RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section, SkipEmptySectionsValue skipEmptySections) const
1103{
1104    recalcSectionsIfNeeded();
1105
1106    if (section == m_head)
1107        return 0;
1108
1109    RenderObject* prevSection = section == m_foot ? lastChild() : section->previousSibling();
1110    while (prevSection) {
1111        if (prevSection->isTableSection() && prevSection != m_head && prevSection != m_foot && (skipEmptySections == DoNotSkipEmptySections || toRenderTableSection(prevSection)->numRows()))
1112            break;
1113        prevSection = prevSection->previousSibling();
1114    }
1115    if (!prevSection && m_head && (skipEmptySections == DoNotSkipEmptySections || m_head->numRows()))
1116        prevSection = m_head;
1117    return toRenderTableSection(prevSection);
1118}
1119
1120RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, SkipEmptySectionsValue skipEmptySections) const
1121{
1122    recalcSectionsIfNeeded();
1123
1124    if (section == m_foot)
1125        return 0;
1126
1127    RenderObject* nextSection = section == m_head ? firstChild() : section->nextSibling();
1128    while (nextSection) {
1129        if (nextSection->isTableSection() && nextSection != m_head && nextSection != m_foot && (skipEmptySections  == DoNotSkipEmptySections || toRenderTableSection(nextSection)->numRows()))
1130            break;
1131        nextSection = nextSection->nextSibling();
1132    }
1133    if (!nextSection && m_foot && (skipEmptySections == DoNotSkipEmptySections || m_foot->numRows()))
1134        nextSection = m_foot;
1135    return toRenderTableSection(nextSection);
1136}
1137
1138RenderTableSection* RenderTable::bottomSection() const
1139{
1140    recalcSectionsIfNeeded();
1141
1142    if (m_foot)
1143        return m_foot;
1144
1145    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
1146        if (child->isTableSection())
1147            return toRenderTableSection(child);
1148    }
1149
1150    return 0;
1151}
1152
1153RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
1154{
1155    recalcSectionsIfNeeded();
1156
1157    // Find the section and row to look in
1158    unsigned r = cell->rowIndex();
1159    RenderTableSection* section = 0;
1160    unsigned rAbove = 0;
1161    if (r > 0) {
1162        // cell is not in the first row, so use the above row in its own section
1163        section = cell->section();
1164        rAbove = r - 1;
1165    } else {
1166        section = sectionAbove(cell->section(), SkipEmptySections);
1167        if (section) {
1168            ASSERT(section->numRows());
1169            rAbove = section->numRows() - 1;
1170        }
1171    }
1172
1173    // Look up the cell in the section's grid, which requires effective col index
1174    if (section) {
1175        unsigned effCol = colToEffCol(cell->col());
1176        RenderTableSection::CellStruct& aboveCell = section->cellAt(rAbove, effCol);
1177        return aboveCell.primaryCell();
1178    } else
1179        return 0;
1180}
1181
1182RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
1183{
1184    recalcSectionsIfNeeded();
1185
1186    // Find the section and row to look in
1187    unsigned r = cell->rowIndex() + cell->rowSpan() - 1;
1188    RenderTableSection* section = 0;
1189    unsigned rBelow = 0;
1190    if (r < cell->section()->numRows() - 1) {
1191        // The cell is not in the last row, so use the next row in the section.
1192        section = cell->section();
1193        rBelow = r + 1;
1194    } else {
1195        section = sectionBelow(cell->section(), SkipEmptySections);
1196        if (section)
1197            rBelow = 0;
1198    }
1199
1200    // Look up the cell in the section's grid, which requires effective col index
1201    if (section) {
1202        unsigned effCol = colToEffCol(cell->col());
1203        RenderTableSection::CellStruct& belowCell = section->cellAt(rBelow, effCol);
1204        return belowCell.primaryCell();
1205    } else
1206        return 0;
1207}
1208
1209RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
1210{
1211    recalcSectionsIfNeeded();
1212
1213    RenderTableSection* section = cell->section();
1214    unsigned effCol = colToEffCol(cell->col());
1215    if (!effCol)
1216        return 0;
1217
1218    // If we hit a colspan back up to a real cell.
1219    RenderTableSection::CellStruct& prevCell = section->cellAt(cell->rowIndex(), effCol - 1);
1220    return prevCell.primaryCell();
1221}
1222
1223RenderTableCell* RenderTable::cellAfter(const RenderTableCell* cell) const
1224{
1225    recalcSectionsIfNeeded();
1226
1227    unsigned effCol = colToEffCol(cell->col() + cell->colSpan());
1228    if (effCol >= numEffCols())
1229        return 0;
1230    return cell->section()->primaryCellAt(cell->rowIndex(), effCol);
1231}
1232
1233int RenderTable::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
1234{
1235    ASSERT(linePositionMode == PositionOnContainingLine);
1236    int baseline = firstLineBoxBaseline();
1237    if (baseline != -1) {
1238        if (isInline())
1239            return beforeMarginInLineDirection(direction) + baseline;
1240        return baseline;
1241    }
1242
1243    return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
1244}
1245
1246int RenderTable::inlineBlockBaseline(LineDirectionMode) const
1247{
1248    // Tables are skipped when computing an inline-block's baseline.
1249    return -1;
1250}
1251
1252int RenderTable::firstLineBoxBaseline() const
1253{
1254    // The baseline of a 'table' is the same as the 'inline-table' baseline per CSS 3 Flexbox (CSS 2.1
1255    // doesn't define the baseline of a 'table' only an 'inline-table').
1256    // This is also needed to properly determine the baseline of a cell if it has a table child.
1257
1258    if (isWritingModeRoot())
1259        return -1;
1260
1261    recalcSectionsIfNeeded();
1262
1263    const RenderTableSection* topNonEmptySection = this->topNonEmptySection();
1264    if (!topNonEmptySection)
1265        return -1;
1266
1267    int baseline = topNonEmptySection->firstLineBoxBaseline();
1268    if (baseline > 0)
1269        return topNonEmptySection->logicalTop() + baseline;
1270
1271    // FIXME: A table row always has a baseline per CSS 2.1. Will this return the right value?
1272    return -1;
1273}
1274
1275LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, OverlayScrollbarSizeRelevancy relevancy)
1276{
1277    LayoutRect rect = RenderBlock::overflowClipRect(location, relevancy);
1278
1279    // If we have a caption, expand the clip to include the caption.
1280    // FIXME: Technically this is wrong, but it's virtually impossible to fix this
1281    // for real until captions have been re-written.
1282    // FIXME: This code assumes (like all our other caption code) that only top/bottom are
1283    // supported.  When we actually support left/right and stop mapping them to top/bottom,
1284    // we might have to hack this code first (depending on what order we do these bug fixes in).
1285    if (!m_captions.isEmpty()) {
1286        if (style()->isHorizontalWritingMode()) {
1287            rect.setHeight(height());
1288            rect.setY(location.y());
1289        } else {
1290            rect.setWidth(width());
1291            rect.setX(location.x());
1292        }
1293    }
1294
1295    return rect;
1296}
1297
1298bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
1299{
1300    LayoutPoint adjustedLocation = accumulatedOffset + location();
1301
1302    // Check kids first.
1303    if (!hasOverflowClip() || locationInContainer.intersects(overflowClipRect(adjustedLocation))) {
1304        for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
1305            if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
1306                LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), adjustedLocation);
1307                if (child->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
1308                    updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
1309                    return true;
1310                }
1311            }
1312        }
1313    }
1314
1315    // Check our bounds next.
1316    LayoutRect boundsRect(adjustedLocation, size());
1317    if (visibleToHitTestRequest(request) && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && locationInContainer.intersects(boundsRect)) {
1318        updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(adjustedLocation)));
1319        if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect))
1320            return true;
1321    }
1322
1323    return false;
1324}
1325
1326RenderTable* RenderTable::createAnonymousWithParentRenderer(const RenderObject* parent)
1327{
1328    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE);
1329    RenderTable* newTable = new RenderTable(0);
1330    newTable->setDocumentForAnonymous(&parent->document());
1331    newTable->setStyle(newStyle.release());
1332    return newTable;
1333}
1334
1335const BorderValue& RenderTable::tableStartBorderAdjoiningCell(const RenderTableCell* cell) const
1336{
1337    ASSERT(cell->isFirstOrLastCellInRow());
1338    if (hasSameDirectionAs(cell->row()))
1339        return style()->borderStart();
1340
1341    return style()->borderEnd();
1342}
1343
1344const BorderValue& RenderTable::tableEndBorderAdjoiningCell(const RenderTableCell* cell) const
1345{
1346    ASSERT(cell->isFirstOrLastCellInRow());
1347    if (hasSameDirectionAs(cell->row()))
1348        return style()->borderEnd();
1349
1350    return style()->borderStart();
1351}
1352
1353}
1354