Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 1997 Martin Jones (mjones (at) kde.org)
      3  *           (C) 1997 Torben Weis (weis (at) kde.org)
      4  *           (C) 1998 Waldo Bastian (bastian (at) kde.org)
      5  *           (C) 1999 Lars Knoll (knoll (at) kde.org)
      6  *           (C) 1999 Antti Koivisto (koivisto (at) 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 (at) 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 
     50 namespace blink {
     51 
     52 using namespace HTMLNames;
     53 
     54 RenderTable::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 
     75 RenderTable::~RenderTable()
     76 {
     77 }
     78 
     79 void 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 
    108 static 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 
    119 static 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 
    127 void 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 
    211 void RenderTable::addCaption(const RenderTableCaption* caption)
    212 {
    213     ASSERT(m_captions.find(caption) == kNotFound);
    214     m_captions.append(const_cast<RenderTableCaption*>(caption));
    215 }
    216 
    217 void 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 
    227 void RenderTable::invalidateCachedColumns()
    228 {
    229     m_columnRenderersValid = false;
    230     m_columnRenderers.resize(0);
    231 }
    232 
    233 void RenderTable::addColumn(const RenderTableCol*)
    234 {
    235     invalidateCachedColumns();
    236 }
    237 
    238 void 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 
    247 void 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.
    316 LayoutUnit 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 
    330 LayoutUnit 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 
    353 void 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 
    376 void 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 
    390 void RenderTable::simplifiedNormalFlowLayout()
    391 {
    392     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
    393         section->layoutIfNeeded();
    394         section->computeOverflowFromCells();
    395     }
    396 }
    397 
    398 void 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.
    571 void 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 
    590 void 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 
    616 void RenderTable::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
    617 {
    618     TablePainter(*this).paint(paintInfo, paintOffset);
    619 }
    620 
    621 void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
    622 {
    623     TablePainter(*this).paintObject(paintInfo, paintOffset);
    624 }
    625 
    626 void 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 
    643 void RenderTable::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
    644 {
    645     TablePainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset);
    646 }
    647 
    648 void RenderTable::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
    649 {
    650     TablePainter(*this).paintMask(paintInfo, paintOffset);
    651 }
    652 
    653 void 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 
    666 void 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 
    700 RenderTableSection* RenderTable::topNonEmptySection() const
    701 {
    702     RenderTableSection* section = topSection();
    703     if (section && !section->numRows())
    704         section = sectionBelow(section, SkipEmptySections);
    705     return section;
    706 }
    707 
    708 void 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 
    731 void 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 
    756 RenderTableCol* 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 
    766 void 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 
    780 RenderTableCol* 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 
    806 void 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 
    877 int 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 
    931 int 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 
    986 void 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 
    993 int RenderTable::borderBefore() const
    994 {
    995     if (collapseBorders()) {
    996         recalcSectionsIfNeeded();
    997         return outerBorderBefore();
    998     }
    999     return RenderBlock::borderBefore();
   1000 }
   1001 
   1002 int RenderTable::borderAfter() const
   1003 {
   1004     if (collapseBorders()) {
   1005         recalcSectionsIfNeeded();
   1006         return outerBorderAfter();
   1007     }
   1008     return RenderBlock::borderAfter();
   1009 }
   1010 
   1011 int 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 
   1029 int 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 
   1048 int 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 
   1075 int 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 
   1102 RenderTableSection* 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 
   1120 RenderTableSection* 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 
   1138 RenderTableSection* 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 
   1153 RenderTableCell* 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 
   1182 RenderTableCell* 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 
   1209 RenderTableCell* 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 
   1223 RenderTableCell* 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 
   1233 int 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 
   1246 int RenderTable::inlineBlockBaseline(LineDirectionMode) const
   1247 {
   1248     // Tables are skipped when computing an inline-block's baseline.
   1249     return -1;
   1250 }
   1251 
   1252 int 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 
   1275 LayoutRect 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 
   1298 bool 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 
   1326 RenderTable* 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 
   1335 const 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 
   1344 const 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