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 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 "RenderTable.h"
     28 
     29 #include "AutoTableLayout.h"
     30 #include "CollapsedBorderValue.h"
     31 #include "DeleteButtonController.h"
     32 #include "Document.h"
     33 #include "FixedTableLayout.h"
     34 #include "FrameView.h"
     35 #include "HitTestResult.h"
     36 #include "HTMLNames.h"
     37 #include "RenderLayer.h"
     38 #include "RenderTableCell.h"
     39 #include "RenderTableCol.h"
     40 #include "RenderTableSection.h"
     41 #ifdef ANDROID_LAYOUT
     42 #include "Settings.h"
     43 #endif
     44 #include "RenderView.h"
     45 
     46 using namespace std;
     47 
     48 namespace WebCore {
     49 
     50 using namespace HTMLNames;
     51 
     52 RenderTable::RenderTable(Node* node)
     53     : RenderBlock(node)
     54     , m_caption(0)
     55     , m_head(0)
     56     , m_foot(0)
     57     , m_firstBody(0)
     58     , m_currentBorder(0)
     59     , m_hasColElements(false)
     60     , m_needsSectionRecalc(0)
     61     , m_hSpacing(0)
     62     , m_vSpacing(0)
     63     , m_borderStart(0)
     64     , m_borderEnd(0)
     65 {
     66     setChildrenInline(false);
     67     m_columnPos.fill(0, 2);
     68     m_columns.fill(ColumnStruct(), 1);
     69 
     70 #ifdef ANDROID_LAYOUT
     71     m_singleColumn = false;
     72 #endif
     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     ETableLayout oldTableLayout = oldStyle ? oldStyle->tableLayout() : TAUTO;
     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()->tableLayout() != oldTableLayout) {
     92         // According to the CSS2 spec, you only use fixed table layout if an
     93         // explicit width is specified on the table.  Auto width implies auto table layout.
     94         if (style()->tableLayout() == TFIXED && !style()->logicalWidth().isAuto())
     95             m_tableLayout.set(new FixedTableLayout(this));
     96         else
     97             m_tableLayout.set(new AutoTableLayout(this));
     98     }
     99 }
    100 
    101 static inline void resetSectionPointerIfNotBefore(RenderTableSection*& ptr, RenderObject* before)
    102 {
    103     if (!before || !ptr)
    104         return;
    105     RenderObject* o = before->previousSibling();
    106     while (o && o != ptr)
    107         o = o->previousSibling();
    108     if (!o)
    109         ptr = 0;
    110 }
    111 
    112 void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
    113 {
    114     // Make sure we don't append things after :after-generated content if we have it.
    115     if (!beforeChild && isAfterContent(lastChild()))
    116         beforeChild = lastChild();
    117 
    118     bool wrapInAnonymousSection = !child->isPositioned();
    119 
    120     if (child->isRenderBlock() && child->style()->display() == TABLE_CAPTION) {
    121         // First caption wins.
    122         if (beforeChild && m_caption) {
    123             RenderObject* o = beforeChild->previousSibling();
    124             while (o && o != m_caption)
    125                 o = o->previousSibling();
    126             if (!o) {
    127                 m_caption = 0;
    128                 setNeedsSectionRecalc();
    129             }
    130         }
    131         if (!m_caption)
    132             m_caption = toRenderBlock(child);
    133         else
    134             setNeedsSectionRecalc();
    135         wrapInAnonymousSection = false;
    136     } else if (child->isTableCol()) {
    137         m_hasColElements = true;
    138         wrapInAnonymousSection = false;
    139     } else if (child->isTableSection()) {
    140         switch (child->style()->display()) {
    141             case TABLE_HEADER_GROUP:
    142                 resetSectionPointerIfNotBefore(m_head, beforeChild);
    143                 if (!m_head) {
    144                     m_head = toRenderTableSection(child);
    145                 } else {
    146                     resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
    147                     if (!m_firstBody)
    148                         m_firstBody = toRenderTableSection(child);
    149                 }
    150                 wrapInAnonymousSection = false;
    151                 break;
    152             case TABLE_FOOTER_GROUP:
    153                 resetSectionPointerIfNotBefore(m_foot, beforeChild);
    154                 if (!m_foot) {
    155                     m_foot = toRenderTableSection(child);
    156                     wrapInAnonymousSection = false;
    157                     break;
    158                 }
    159                 // Fall through.
    160             case TABLE_ROW_GROUP:
    161                 resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
    162                 if (!m_firstBody)
    163                     m_firstBody = toRenderTableSection(child);
    164                 wrapInAnonymousSection = false;
    165                 break;
    166             default:
    167                 ASSERT_NOT_REACHED();
    168         }
    169     } else if (child->isTableCell() || child->isTableRow())
    170         wrapInAnonymousSection = true;
    171     else
    172         wrapInAnonymousSection = true;
    173 
    174     if (!wrapInAnonymousSection) {
    175         // If the next renderer is actually wrapped in an anonymous table section, we need to go up and find that.
    176         while (beforeChild && beforeChild->parent() != this)
    177             beforeChild = beforeChild->parent();
    178 
    179         RenderBox::addChild(child, beforeChild);
    180         return;
    181     }
    182 
    183     if (!beforeChild && lastChild() && lastChild()->isTableSection() && lastChild()->isAnonymous()) {
    184         lastChild()->addChild(child);
    185         return;
    186     }
    187 
    188     RenderObject* lastBox = beforeChild;
    189     while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION && lastBox->style()->display() != TABLE_COLUMN_GROUP)
    190         lastBox = lastBox->parent();
    191     if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox)) {
    192         if (beforeChild == lastBox)
    193             beforeChild = lastBox->firstChild();
    194         lastBox->addChild(child, beforeChild);
    195         return;
    196     }
    197 
    198     if (beforeChild && !beforeChild->isTableSection() && beforeChild->style()->display() != TABLE_CAPTION && beforeChild->style()->display() != TABLE_COLUMN_GROUP)
    199         beforeChild = 0;
    200     RenderTableSection* section = new (renderArena()) RenderTableSection(document() /* anonymous */);
    201     RefPtr<RenderStyle> newStyle = RenderStyle::create();
    202     newStyle->inheritFrom(style());
    203     newStyle->setDisplay(TABLE_ROW_GROUP);
    204     section->setStyle(newStyle.release());
    205     addChild(section, beforeChild);
    206     section->addChild(child);
    207 }
    208 
    209 void RenderTable::removeChild(RenderObject* oldChild)
    210 {
    211     RenderBox::removeChild(oldChild);
    212 
    213     if (m_caption && oldChild == m_caption && node())
    214         node()->setNeedsStyleRecalc();
    215     setNeedsSectionRecalc();
    216 }
    217 
    218 void RenderTable::computeLogicalWidth()
    219 {
    220 #ifdef ANDROID_LAYOUT
    221     if (view()->frameView())
    222         setVisibleWidth(view()->frameView()->textWrapWidth());
    223 #endif
    224 
    225     if (isPositioned())
    226         computePositionedLogicalWidth();
    227 
    228     RenderBlock* cb = containingBlock();
    229 
    230     int availableLogicalWidth = containingBlockLogicalWidthForContent();
    231     bool hasPerpendicularContainingBlock = cb->style()->isHorizontalWritingMode() != style()->isHorizontalWritingMode();
    232     int containerWidthInInlineDirection = hasPerpendicularContainingBlock ? perpendicularContainingBlockLogicalHeight() : availableLogicalWidth;
    233 
    234     LengthType logicalWidthType = style()->logicalWidth().type();
    235     if (logicalWidthType > Relative && style()->logicalWidth().isPositive()) {
    236         // Percent or fixed table
    237         setLogicalWidth(style()->logicalWidth().calcMinValue(containerWidthInInlineDirection));
    238         setLogicalWidth(max(minPreferredLogicalWidth(), logicalWidth()));
    239     } else {
    240         // Subtract out any fixed margins from our available width for auto width tables.
    241         int marginTotal = 0;
    242         if (!style()->marginStart().isAuto())
    243             marginTotal += style()->marginStart().calcValue(availableLogicalWidth);
    244         if (!style()->marginEnd().isAuto())
    245             marginTotal += style()->marginEnd().calcValue(availableLogicalWidth);
    246 
    247         // Subtract out our margins to get the available content width.
    248         int availableContentLogicalWidth = max(0, containerWidthInInlineDirection - marginTotal);
    249 
    250         // Ensure we aren't bigger than our max width or smaller than our min width.
    251         setLogicalWidth(min(availableContentLogicalWidth, maxPreferredLogicalWidth()));
    252     }
    253 
    254     setLogicalWidth(max(logicalWidth(), minPreferredLogicalWidth()));
    255 
    256     // Finally, with our true width determined, compute our margins for real.
    257     setMarginStart(0);
    258     setMarginEnd(0);
    259 #ifdef ANDROID_LAYOUT
    260     // in SSR mode, we ignore left/right margin for table
    261     if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR)
    262         return;
    263 #endif
    264     if (!hasPerpendicularContainingBlock)
    265         computeInlineDirectionMargins(cb, availableLogicalWidth, logicalWidth());
    266     else {
    267         setMarginStart(style()->marginStart().calcMinValue(availableLogicalWidth));
    268         setMarginEnd(style()->marginEnd().calcMinValue(availableLogicalWidth));
    269     }
    270 }
    271 
    272 void RenderTable::adjustLogicalHeightForCaption()
    273 {
    274     ASSERT(m_caption);
    275     IntRect captionRect(m_caption->x(), m_caption->y(), m_caption->width(), m_caption->height());
    276 
    277     m_caption->setLogicalLocation(m_caption->marginStart(), logicalHeight());
    278     if (!selfNeedsLayout() && m_caption->checkForRepaintDuringLayout())
    279         m_caption->repaintDuringLayoutIfMoved(captionRect);
    280 
    281     setLogicalHeight(logicalHeight() + m_caption->logicalHeight() + m_caption->marginBefore() + m_caption->marginAfter());
    282 }
    283 
    284 void RenderTable::layout()
    285 {
    286     ASSERT(needsLayout());
    287 
    288     if (simplifiedLayout())
    289         return;
    290 
    291     recalcSectionsIfNeeded();
    292 
    293     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
    294     LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), style()->isFlippedBlocksWritingMode());
    295 
    296     setLogicalHeight(0);
    297     m_overflow.clear();
    298 
    299     initMaxMarginValues();
    300 
    301 #ifdef ANDROID_LAYOUT
    302     bool relayoutChildren = false;
    303 #endif
    304 
    305     int oldLogicalWidth = logicalWidth();
    306     computeLogicalWidth();
    307 
    308 #ifdef ANDROID_LAYOUT
    309     if (!checkAndSetRelayoutChildren(&relayoutChildren)
    310         && document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) {
    311         // if the width of a table is wider than its container width, or it has a nested table,
    312         // we will render it with single column.
    313         int cw = containingBlockLogicalWidthForContent();
    314         bool shouldRenderAsSingleColumn = (width() > cw);
    315         if (!shouldRenderAsSingleColumn) {
    316             RenderObject* child = firstChild();
    317             while (child) {
    318                 if (child->isTable()) {
    319                     shouldRenderAsSingleColumn = true;
    320                     break;
    321                 }
    322                 child = child->nextInPreOrder();
    323             }
    324         }
    325 
    326         if (shouldRenderAsSingleColumn) {
    327             m_singleColumn = true;
    328             if (width() > cw)
    329                 setWidth(cw);
    330             if (m_minPreferredLogicalWidth > cw)
    331                 m_minPreferredLogicalWidth = cw;
    332             if (m_maxPreferredLogicalWidth > cw)
    333                 m_maxPreferredLogicalWidth = cw;
    334         }
    335     }
    336 #endif
    337     if (m_caption && logicalWidth() != oldLogicalWidth)
    338         m_caption->setNeedsLayout(true, false);
    339 
    340     // FIXME: The optimisation below doesn't work since the internal table
    341     // layout could have changed.  we need to add a flag to the table
    342     // layout that tells us if something has changed in the min max
    343     // calculations to do it correctly.
    344 //     if ( oldWidth != width() || columns.size() + 1 != columnPos.size() )
    345     m_tableLayout->layout();
    346 
    347     setCellLogicalWidths();
    348 
    349     int totalSectionLogicalHeight = 0;
    350     int oldTableLogicalTop = m_caption ? m_caption->logicalHeight() + m_caption->marginBefore() + m_caption->marginAfter() : 0;
    351 
    352     bool collapsing = collapseBorders();
    353 
    354     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
    355 #ifdef ANDROID_LAYOUT
    356         if (relayoutChildren) {
    357             child->setNeedsLayout(true, false);
    358             if (!child->isTableSection()) {
    359                 child->layoutIfNeeded();
    360                 continue;
    361             }
    362             // fall through
    363         }
    364 #endif
    365         if (child->isTableSection()) {
    366             child->layoutIfNeeded();
    367             RenderTableSection* section = toRenderTableSection(child);
    368             totalSectionLogicalHeight += section->calcRowLogicalHeight();
    369             if (collapsing)
    370                 section->recalcOuterBorder();
    371             ASSERT(!section->needsLayout());
    372         } else if (child->isTableCol()) {
    373             child->layoutIfNeeded();
    374             ASSERT(!child->needsLayout());
    375         }
    376     }
    377 
    378     // Only lay out one caption, since it's the only one we're going to end up painting.
    379     if (m_caption)
    380         m_caption->layoutIfNeeded();
    381 
    382     // If any table section moved vertically, we will just repaint everything from that
    383     // section down (it is quite unlikely that any of the following sections
    384     // did not shift).
    385     bool sectionMoved = false;
    386     int movedSectionLogicalTop = 0;
    387 
    388     // FIXME: Collapse caption margin.
    389     if (m_caption && m_caption->style()->captionSide() != CAPBOTTOM) {
    390         adjustLogicalHeightForCaption();
    391         if (logicalHeight() != oldTableLogicalTop) {
    392             sectionMoved = true;
    393             movedSectionLogicalTop = min(logicalHeight(), oldTableLogicalTop);
    394         }
    395     }
    396 
    397     int borderAndPaddingBefore = borderBefore() + (collapsing ? 0 : paddingBefore());
    398     int borderAndPaddingAfter = borderAfter() + (collapsing ? 0 : paddingAfter());
    399 
    400     setLogicalHeight(logicalHeight() + borderAndPaddingBefore);
    401 
    402     if (!isPositioned())
    403         computeLogicalHeight();
    404 
    405     Length logicalHeightLength = style()->logicalHeight();
    406     int computedLogicalHeight = 0;
    407     if (logicalHeightLength.isFixed()) {
    408         // Tables size as though CSS height includes border/padding.
    409         computedLogicalHeight = logicalHeightLength.value() - (borderAndPaddingBefore + borderAndPaddingAfter);
    410     } else if (logicalHeightLength.isPercent())
    411         computedLogicalHeight = computePercentageLogicalHeight(logicalHeightLength);
    412     computedLogicalHeight = max(0, computedLogicalHeight);
    413 
    414     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
    415         if (child->isTableSection())
    416             // FIXME: Distribute extra height between all table body sections instead of giving it all to the first one.
    417             toRenderTableSection(child)->layoutRows(child == m_firstBody ? max(0, computedLogicalHeight - totalSectionLogicalHeight) : 0);
    418     }
    419 
    420     if (!m_firstBody && computedLogicalHeight > totalSectionLogicalHeight && !document()->inQuirksMode()) {
    421         // Completely empty tables (with no sections or anything) should at least honor specified height
    422         // in strict mode.
    423         setLogicalHeight(logicalHeight() + computedLogicalHeight);
    424     }
    425 
    426     int sectionLogicalLeft = style()->isLeftToRightDirection() ? borderStart() : borderEnd();
    427     if (!collapsing)
    428         sectionLogicalLeft += style()->isLeftToRightDirection() ? paddingStart() : paddingEnd();
    429 
    430     // position the table sections
    431     RenderTableSection* section = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
    432     while (section) {
    433         if (!sectionMoved && section->logicalTop() != logicalHeight()) {
    434             sectionMoved = true;
    435             movedSectionLogicalTop = min(logicalHeight(), section->logicalTop()) + (style()->isHorizontalWritingMode() ? section->minYVisualOverflow() : section->minXVisualOverflow());
    436         }
    437         section->setLogicalLocation(sectionLogicalLeft, logicalHeight());
    438 
    439         setLogicalHeight(logicalHeight() + section->logicalHeight());
    440         section = sectionBelow(section);
    441     }
    442 
    443     setLogicalHeight(logicalHeight() + borderAndPaddingAfter);
    444 
    445     if (m_caption && m_caption->style()->captionSide() == CAPBOTTOM)
    446         adjustLogicalHeightForCaption();
    447 
    448     if (isPositioned())
    449         computeLogicalHeight();
    450 
    451     // table can be containing block of positioned elements.
    452     // FIXME: Only pass true if width or height changed.
    453     layoutPositionedObjects(true);
    454 
    455     updateLayerTransform();
    456 
    457     computeOverflow(clientLogicalBottom());
    458 
    459     statePusher.pop();
    460 
    461     if (view()->layoutState()->pageLogicalHeight())
    462         setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(logicalTop()));
    463 
    464     bool didFullRepaint = repainter.repaintAfterLayout();
    465     // Repaint with our new bounds if they are different from our old bounds.
    466     if (!didFullRepaint && sectionMoved) {
    467         if (style()->isHorizontalWritingMode())
    468             repaintRectangle(IntRect(minXVisualOverflow(), movedSectionLogicalTop, maxXVisualOverflow() - minXVisualOverflow(), maxYVisualOverflow() - movedSectionLogicalTop));
    469         else
    470             repaintRectangle(IntRect(movedSectionLogicalTop, minYVisualOverflow(), maxXVisualOverflow() - movedSectionLogicalTop, maxYVisualOverflow() - minYVisualOverflow()));
    471     }
    472 
    473     setNeedsLayout(false);
    474 }
    475 
    476 void RenderTable::addOverflowFromChildren()
    477 {
    478     // Add overflow from borders.
    479     // Technically it's odd that we are incorporating the borders into layout overflow, which is only supposed to be about overflow from our
    480     // descendant objects, but since tables don't support overflow:auto, this works out fine.
    481     if (collapseBorders()) {
    482         int rightBorderOverflow = width() + outerBorderRight() - borderRight();
    483         int leftBorderOverflow = borderLeft() - outerBorderLeft();
    484         int bottomBorderOverflow = height() + outerBorderBottom() - borderBottom();
    485         int topBorderOverflow = borderTop() - outerBorderTop();
    486         IntRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow);
    487         if (borderOverflowRect != borderBoxRect()) {
    488             addLayoutOverflow(borderOverflowRect);
    489             addVisualOverflow(borderOverflowRect);
    490         }
    491     }
    492 
    493     // Add overflow from our caption.
    494     if (m_caption)
    495         addOverflowFromChild(m_caption);
    496 
    497     // Add overflow from our sections.
    498     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
    499         if (child->isTableSection()) {
    500             RenderTableSection* section = toRenderTableSection(child);
    501             addOverflowFromChild(section);
    502         }
    503     }
    504 }
    505 
    506 void RenderTable::setCellLogicalWidths()
    507 {
    508     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
    509         if (child->isTableSection())
    510             toRenderTableSection(child)->setCellLogicalWidths();
    511     }
    512 }
    513 
    514 void RenderTable::paint(PaintInfo& paintInfo, int tx, int ty)
    515 {
    516     tx += x();
    517     ty += y();
    518 
    519     PaintPhase paintPhase = paintInfo.phase;
    520 
    521     if (!isRoot()) {
    522         IntRect overflowBox = visualOverflowRect();
    523         flipForWritingMode(overflowBox);
    524         overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
    525         overflowBox.move(tx, ty);
    526         if (!overflowBox.intersects(paintInfo.rect))
    527             return;
    528     }
    529 
    530     bool pushedClip = pushContentsClip(paintInfo, tx, ty);
    531     paintObject(paintInfo, tx, ty);
    532     if (pushedClip)
    533         popContentsClip(paintInfo, paintPhase, tx, ty);
    534 }
    535 
    536 void RenderTable::paintObject(PaintInfo& paintInfo, int tx, int ty)
    537 {
    538     PaintPhase paintPhase = paintInfo.phase;
    539     if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style()->visibility() == VISIBLE)
    540         paintBoxDecorations(paintInfo, tx, ty);
    541 
    542     if (paintPhase == PaintPhaseMask) {
    543         paintMask(paintInfo, tx, ty);
    544         return;
    545     }
    546 
    547     // We're done.  We don't bother painting any children.
    548     if (paintPhase == PaintPhaseBlockBackground)
    549         return;
    550 
    551     // We don't paint our own background, but we do let the kids paint their backgrounds.
    552     if (paintPhase == PaintPhaseChildBlockBackgrounds)
    553         paintPhase = PaintPhaseChildBlockBackground;
    554 
    555     PaintInfo info(paintInfo);
    556     info.phase = paintPhase;
    557     info.updatePaintingRootForChildren(this);
    558 
    559     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
    560         if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption)) {
    561             IntPoint childPoint = flipForWritingMode(toRenderBox(child), IntPoint(tx, ty), ParentToChildFlippingAdjustment);
    562             child->paint(info, childPoint.x(), childPoint.y());
    563         }
    564     }
    565 
    566     if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
    567         // Collect all the unique border styles that we want to paint in a sorted list.  Once we
    568         // have all the styles sorted, we then do individual passes, painting each style of border
    569         // from lowest precedence to highest precedence.
    570         info.phase = PaintPhaseCollapsedTableBorders;
    571         RenderTableCell::CollapsedBorderStyles borderStyles;
    572         RenderObject* stop = nextInPreOrderAfterChildren();
    573         for (RenderObject* o = firstChild(); o && o != stop; o = o->nextInPreOrder()) {
    574             if (o->isTableCell())
    575                 toRenderTableCell(o)->collectBorderStyles(borderStyles);
    576         }
    577         RenderTableCell::sortBorderStyles(borderStyles);
    578         size_t count = borderStyles.size();
    579         for (size_t i = 0; i < count; ++i) {
    580             m_currentBorder = &borderStyles[i];
    581             for (RenderObject* child = firstChild(); child; child = child->nextSibling())
    582                 if (child->isTableSection()) {
    583                     IntPoint childPoint = flipForWritingMode(toRenderTableSection(child), IntPoint(tx, ty), ParentToChildFlippingAdjustment);
    584                     child->paint(info, childPoint.x(), childPoint.y());
    585                 }
    586         }
    587         m_currentBorder = 0;
    588     }
    589 
    590     // Paint outline.
    591     if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
    592         paintOutline(paintInfo.context, tx, ty, width(), height());
    593 }
    594 
    595 void RenderTable::subtractCaptionRect(IntRect& rect) const
    596 {
    597     if (!m_caption)
    598         return;
    599 
    600     int captionLogicalHeight = m_caption->logicalHeight() + m_caption->marginBefore() + m_caption->marginAfter();
    601     bool captionIsBefore = (m_caption->style()->captionSide() != CAPBOTTOM) ^ style()->isFlippedBlocksWritingMode();
    602     if (style()->isHorizontalWritingMode()) {
    603         rect.setHeight(rect.height() - captionLogicalHeight);
    604         if (captionIsBefore)
    605             rect.move(0, captionLogicalHeight);
    606     } else {
    607         rect.setWidth(rect.width() - captionLogicalHeight);
    608         if (captionIsBefore)
    609             rect.move(captionLogicalHeight, 0);
    610     }
    611 }
    612 
    613 void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
    614 {
    615     if (!paintInfo.shouldPaintWithinRoot(this))
    616         return;
    617 
    618     IntRect rect(tx, ty, width(), height());
    619     subtractCaptionRect(rect);
    620 
    621     paintBoxShadow(paintInfo.context, rect.x(), rect.y(), rect.width(), rect.height(), style(), Normal);
    622 
    623     if (isRoot())
    624         paintRootBoxFillLayers(paintInfo);
    625     else if (!isBody() || document()->documentElement()->renderer()->hasBackground())
    626         // The <body> only paints its background if the root element has defined a background
    627         // independent of the body.
    628         paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), rect.x(), rect.y(), rect.width(), rect.height());
    629 
    630     paintBoxShadow(paintInfo.context, rect.x(), rect.y(), rect.width(), rect.height(), style(), Inset);
    631 
    632     if (style()->hasBorder() && !collapseBorders())
    633         paintBorder(paintInfo.context, rect.x(), rect.y(), rect.width(), rect.height(), style());
    634 }
    635 
    636 void RenderTable::paintMask(PaintInfo& paintInfo, int tx, int ty)
    637 {
    638     if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
    639         return;
    640 
    641     IntRect rect(tx, ty, width(), height());
    642     subtractCaptionRect(rect);
    643 
    644     paintMaskImages(paintInfo, rect.x(), rect.y(), rect.width(), rect.height());
    645 }
    646 
    647 void RenderTable::computePreferredLogicalWidths()
    648 {
    649     ASSERT(preferredLogicalWidthsDirty());
    650 
    651     recalcSectionsIfNeeded();
    652     recalcBordersInRowDirection();
    653 
    654     m_tableLayout->computePreferredLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
    655 
    656     if (m_caption)
    657         m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_caption->minPreferredLogicalWidth());
    658 
    659     setPreferredLogicalWidthsDirty(false);
    660 }
    661 
    662 void RenderTable::splitColumn(int pos, int firstSpan)
    663 {
    664     // we need to add a new columnStruct
    665     int oldSize = m_columns.size();
    666     m_columns.grow(oldSize + 1);
    667     int oldSpan = m_columns[pos].span;
    668     ASSERT(oldSpan > firstSpan);
    669     m_columns[pos].span = firstSpan;
    670     memmove(m_columns.data() + pos + 1, m_columns.data() + pos, (oldSize - pos) * sizeof(ColumnStruct));
    671     m_columns[pos + 1].span = oldSpan - firstSpan;
    672 
    673     // change width of all rows.
    674     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
    675         if (child->isTableSection())
    676             toRenderTableSection(child)->splitColumn(pos, firstSpan);
    677     }
    678 
    679     m_columnPos.grow(numEffCols() + 1);
    680     setNeedsLayoutAndPrefWidthsRecalc();
    681 }
    682 
    683 void RenderTable::appendColumn(int span)
    684 {
    685     // easy case.
    686     int pos = m_columns.size();
    687     int newSize = pos + 1;
    688     m_columns.grow(newSize);
    689     m_columns[pos].span = span;
    690 
    691     // change width of all rows.
    692     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
    693         if (child->isTableSection())
    694             toRenderTableSection(child)->appendColumn(pos);
    695     }
    696 
    697     m_columnPos.grow(numEffCols() + 1);
    698     setNeedsLayoutAndPrefWidthsRecalc();
    699 }
    700 
    701 RenderTableCol* RenderTable::nextColElement(RenderTableCol* current) const
    702 {
    703     RenderObject* next = current->firstChild();
    704     if (!next)
    705         next = current->nextSibling();
    706     if (!next && current->parent()->isTableCol())
    707         next = current->parent()->nextSibling();
    708 
    709     while (next) {
    710         if (next->isTableCol())
    711             return toRenderTableCol(next);
    712         if (next != m_caption)
    713             return 0;
    714         next = next->nextSibling();
    715     }
    716 
    717     return 0;
    718 }
    719 
    720 RenderTableCol* RenderTable::colElement(int col, bool* startEdge, bool* endEdge) const
    721 {
    722     if (!m_hasColElements)
    723         return 0;
    724     RenderObject* child = firstChild();
    725     int cCol = 0;
    726 
    727     while (child) {
    728         if (child->isTableCol())
    729             break;
    730         if (child != m_caption)
    731             return 0;
    732         child = child->nextSibling();
    733     }
    734     if (!child)
    735         return 0;
    736 
    737     RenderTableCol* colElem = toRenderTableCol(child);
    738     while (colElem) {
    739         int span = colElem->span();
    740         if (!colElem->firstChild()) {
    741             int startCol = cCol;
    742             int endCol = cCol + span - 1;
    743             cCol += span;
    744             if (cCol > col) {
    745                 if (startEdge)
    746                     *startEdge = startCol == col;
    747                 if (endEdge)
    748                     *endEdge = endCol == col;
    749                 return colElem;
    750             }
    751         }
    752         colElem = nextColElement(colElem);
    753     }
    754 
    755     return 0;
    756 }
    757 
    758 void RenderTable::recalcCaption(RenderBlock* caption) const
    759 {
    760     if (!m_caption) {
    761         m_caption = caption;
    762         m_caption->setNeedsLayout(true);
    763     } else {
    764         // Make sure to null out the child's renderer.
    765         if (Node* node = caption->node())
    766             node->setRenderer(0);
    767 
    768         // Destroy the child now.
    769         caption->destroy();
    770     }
    771 }
    772 
    773 void RenderTable::recalcSections() const
    774 {
    775     m_caption = 0;
    776     m_head = 0;
    777     m_foot = 0;
    778     m_firstBody = 0;
    779     m_hasColElements = false;
    780 
    781     // We need to get valid pointers to caption, head, foot and first body again
    782     RenderObject* nextSibling;
    783     for (RenderObject* child = firstChild(); child; child = nextSibling) {
    784         nextSibling = child->nextSibling();
    785         switch (child->style()->display()) {
    786             case TABLE_CAPTION:
    787                 if (child->isRenderBlock())
    788                     recalcCaption(toRenderBlock(child));
    789                 break;
    790             case TABLE_COLUMN:
    791             case TABLE_COLUMN_GROUP:
    792                 m_hasColElements = true;
    793                 break;
    794             case TABLE_HEADER_GROUP:
    795                 if (child->isTableSection()) {
    796                     RenderTableSection* section = toRenderTableSection(child);
    797                     if (!m_head)
    798                         m_head = section;
    799                     else if (!m_firstBody)
    800                         m_firstBody = section;
    801                     section->recalcCellsIfNeeded();
    802                 }
    803                 break;
    804             case TABLE_FOOTER_GROUP:
    805                 if (child->isTableSection()) {
    806                     RenderTableSection* section = toRenderTableSection(child);
    807                     if (!m_foot)
    808                         m_foot = section;
    809                     else if (!m_firstBody)
    810                         m_firstBody = section;
    811                     section->recalcCellsIfNeeded();
    812                 }
    813                 break;
    814             case TABLE_ROW_GROUP:
    815                 if (child->isTableSection()) {
    816                     RenderTableSection* section = toRenderTableSection(child);
    817                     if (!m_firstBody)
    818                         m_firstBody = section;
    819                     section->recalcCellsIfNeeded();
    820                 }
    821                 break;
    822             default:
    823                 break;
    824         }
    825     }
    826 
    827     // repair column count (addChild can grow it too much, because it always adds elements to the last row of a section)
    828     int maxCols = 0;
    829     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
    830         if (child->isTableSection()) {
    831             RenderTableSection* section = toRenderTableSection(child);
    832             int sectionCols = section->numColumns();
    833             if (sectionCols > maxCols)
    834                 maxCols = sectionCols;
    835         }
    836     }
    837 
    838     m_columns.resize(maxCols);
    839     m_columnPos.resize(maxCols + 1);
    840 
    841     ASSERT(selfNeedsLayout());
    842 
    843     m_needsSectionRecalc = false;
    844 }
    845 
    846 int RenderTable::calcBorderStart() const
    847 {
    848     if (collapseBorders()) {
    849         // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2.
    850         if (!numEffCols())
    851             return 0;
    852 
    853         unsigned borderWidth = 0;
    854 
    855         const BorderValue& tb = style()->borderStart();
    856         if (tb.style() == BHIDDEN)
    857             return 0;
    858         if (tb.style() > BHIDDEN)
    859             borderWidth = tb.width();
    860 
    861         if (RenderTableCol* colGroup = colElement(0)) {
    862             const BorderValue& gb = colGroup->style()->borderStart();
    863             if (gb.style() == BHIDDEN)
    864                 return 0;
    865             if (gb.style() > BHIDDEN)
    866                 borderWidth = max(borderWidth, static_cast<unsigned>(gb.width()));
    867         }
    868 
    869         RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
    870         if (firstNonEmptySection && !firstNonEmptySection->numRows())
    871             firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
    872 
    873         if (firstNonEmptySection) {
    874             const BorderValue& sb = firstNonEmptySection->style()->borderStart();
    875             if (sb.style() == BHIDDEN)
    876                 return 0;
    877 
    878             if (sb.style() > BHIDDEN)
    879                 borderWidth = max(borderWidth, static_cast<unsigned>(sb.width()));
    880 
    881             const RenderTableSection::CellStruct& cs = firstNonEmptySection->cellAt(0, 0);
    882 
    883             if (cs.hasCells()) {
    884                 const BorderValue& cb = cs.primaryCell()->style()->borderStart(); // FIXME: Make this work with perpendicualr and flipped cells.
    885                 if (cb.style() == BHIDDEN)
    886                     return 0;
    887 
    888                 const BorderValue& rb = cs.primaryCell()->parent()->style()->borderStart();
    889                 if (rb.style() == BHIDDEN)
    890                     return 0;
    891 
    892                 if (cb.style() > BHIDDEN)
    893                     borderWidth = max(borderWidth, static_cast<unsigned>(cb.width()));
    894                 if (rb.style() > BHIDDEN)
    895                     borderWidth = max(borderWidth, static_cast<unsigned>(rb.width()));
    896             }
    897         }
    898         return (borderWidth + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
    899     }
    900     return RenderBlock::borderStart();
    901 }
    902 
    903 int RenderTable::calcBorderEnd() const
    904 {
    905     if (collapseBorders()) {
    906         // Determined by the last cell of the first row. See the CSS 2.1 spec, section 17.6.2.
    907         if (!numEffCols())
    908             return 0;
    909 
    910         unsigned borderWidth = 0;
    911 
    912         const BorderValue& tb = style()->borderEnd();
    913         if (tb.style() == BHIDDEN)
    914             return 0;
    915         if (tb.style() > BHIDDEN)
    916             borderWidth = tb.width();
    917 
    918         int endColumn = numEffCols() - 1;
    919         if (RenderTableCol* colGroup = colElement(endColumn)) {
    920             const BorderValue& gb = colGroup->style()->borderEnd();
    921             if (gb.style() == BHIDDEN)
    922                 return 0;
    923             if (gb.style() > BHIDDEN)
    924                 borderWidth = max(borderWidth, static_cast<unsigned>(gb.width()));
    925         }
    926 
    927         RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
    928         if (firstNonEmptySection && !firstNonEmptySection->numRows())
    929             firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
    930 
    931         if (firstNonEmptySection) {
    932             const BorderValue& sb = firstNonEmptySection->style()->borderEnd();
    933             if (sb.style() == BHIDDEN)
    934                 return 0;
    935 
    936             if (sb.style() > BHIDDEN)
    937                 borderWidth = max(borderWidth, static_cast<unsigned>(sb.width()));
    938 
    939             const RenderTableSection::CellStruct& cs = firstNonEmptySection->cellAt(0, endColumn);
    940 
    941             if (cs.hasCells()) {
    942                 const BorderValue& cb = cs.primaryCell()->style()->borderEnd(); // FIXME: Make this work with perpendicular and flipped cells.
    943                 if (cb.style() == BHIDDEN)
    944                     return 0;
    945 
    946                 const BorderValue& rb = cs.primaryCell()->parent()->style()->borderEnd();
    947                 if (rb.style() == BHIDDEN)
    948                     return 0;
    949 
    950                 if (cb.style() > BHIDDEN)
    951                     borderWidth = max(borderWidth, static_cast<unsigned>(cb.width()));
    952                 if (rb.style() > BHIDDEN)
    953                     borderWidth = max(borderWidth, static_cast<unsigned>(rb.width()));
    954             }
    955         }
    956         return (borderWidth + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
    957     }
    958     return RenderBlock::borderEnd();
    959 }
    960 
    961 void RenderTable::recalcBordersInRowDirection()
    962 {
    963     m_borderStart = calcBorderStart();
    964     m_borderEnd = calcBorderEnd();
    965 }
    966 
    967 int RenderTable::borderBefore() const
    968 {
    969     if (collapseBorders())
    970         return outerBorderBefore();
    971     return RenderBlock::borderBefore();
    972 }
    973 
    974 int RenderTable::borderAfter() const
    975 {
    976     if (collapseBorders())
    977         return outerBorderAfter();
    978     return RenderBlock::borderAfter();
    979 }
    980 
    981 int RenderTable::outerBorderBefore() const
    982 {
    983     if (!collapseBorders())
    984         return 0;
    985     int borderWidth = 0;
    986     RenderTableSection* topSection;
    987     if (m_head)
    988         topSection = m_head;
    989     else if (m_firstBody)
    990         topSection = m_firstBody;
    991     else if (m_foot)
    992         topSection = m_foot;
    993     else
    994         topSection = 0;
    995     if (topSection) {
    996         borderWidth = topSection->outerBorderBefore();
    997         if (borderWidth == -1)
    998             return 0;   // Overridden by hidden
    999     }
   1000     const BorderValue& tb = style()->borderBefore();
   1001     if (tb.style() == BHIDDEN)
   1002         return 0;
   1003     if (tb.style() > BHIDDEN)
   1004         borderWidth = max(borderWidth, static_cast<int>(tb.width() / 2));
   1005     return borderWidth;
   1006 }
   1007 
   1008 int RenderTable::outerBorderAfter() const
   1009 {
   1010     if (!collapseBorders())
   1011         return 0;
   1012     int borderWidth = 0;
   1013     RenderTableSection* bottomSection;
   1014     if (m_foot)
   1015         bottomSection = m_foot;
   1016     else {
   1017         RenderObject* child;
   1018         for (child = lastChild(); child && !child->isTableSection(); child = child->previousSibling()) { }
   1019         bottomSection = child ? toRenderTableSection(child) : 0;
   1020     }
   1021     if (bottomSection) {
   1022         borderWidth = bottomSection->outerBorderAfter();
   1023         if (borderWidth == -1)
   1024             return 0;   // Overridden by hidden
   1025     }
   1026     const BorderValue& tb = style()->borderAfter();
   1027     if (tb.style() == BHIDDEN)
   1028         return 0;
   1029     if (tb.style() > BHIDDEN)
   1030         borderWidth = max(borderWidth, static_cast<int>((tb.width() + 1) / 2));
   1031     return borderWidth;
   1032 }
   1033 
   1034 int RenderTable::outerBorderStart() const
   1035 {
   1036     if (!collapseBorders())
   1037         return 0;
   1038 
   1039     int borderWidth = 0;
   1040 
   1041     const BorderValue& tb = style()->borderStart();
   1042     if (tb.style() == BHIDDEN)
   1043         return 0;
   1044     if (tb.style() > BHIDDEN)
   1045         borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
   1046 
   1047     bool allHidden = true;
   1048     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
   1049         if (!child->isTableSection())
   1050             continue;
   1051         int sw = toRenderTableSection(child)->outerBorderStart();
   1052         if (sw == -1)
   1053             continue;
   1054         else
   1055             allHidden = false;
   1056         borderWidth = max(borderWidth, sw);
   1057     }
   1058     if (allHidden)
   1059         return 0;
   1060 
   1061     return borderWidth;
   1062 }
   1063 
   1064 int RenderTable::outerBorderEnd() const
   1065 {
   1066     if (!collapseBorders())
   1067         return 0;
   1068 
   1069     int borderWidth = 0;
   1070 
   1071     const BorderValue& tb = style()->borderEnd();
   1072     if (tb.style() == BHIDDEN)
   1073         return 0;
   1074     if (tb.style() > BHIDDEN)
   1075         borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
   1076 
   1077     bool allHidden = true;
   1078     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
   1079         if (!child->isTableSection())
   1080             continue;
   1081         int sw = toRenderTableSection(child)->outerBorderEnd();
   1082         if (sw == -1)
   1083             continue;
   1084         else
   1085             allHidden = false;
   1086         borderWidth = max(borderWidth, sw);
   1087     }
   1088     if (allHidden)
   1089         return 0;
   1090 
   1091     return borderWidth;
   1092 }
   1093 
   1094 RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section, bool skipEmptySections) const
   1095 {
   1096     recalcSectionsIfNeeded();
   1097 
   1098     if (section == m_head)
   1099         return 0;
   1100 
   1101     RenderObject* prevSection = section == m_foot ? lastChild() : section->previousSibling();
   1102     while (prevSection) {
   1103         if (prevSection->isTableSection() && prevSection != m_head && prevSection != m_foot && (!skipEmptySections || toRenderTableSection(prevSection)->numRows()))
   1104             break;
   1105         prevSection = prevSection->previousSibling();
   1106     }
   1107     if (!prevSection && m_head && (!skipEmptySections || m_head->numRows()))
   1108         prevSection = m_head;
   1109     return toRenderTableSection(prevSection);
   1110 }
   1111 
   1112 RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, bool skipEmptySections) const
   1113 {
   1114     recalcSectionsIfNeeded();
   1115 
   1116     if (section == m_foot)
   1117         return 0;
   1118 
   1119     RenderObject* nextSection = section == m_head ? firstChild() : section->nextSibling();
   1120     while (nextSection) {
   1121         if (nextSection->isTableSection() && nextSection != m_head && nextSection != m_foot && (!skipEmptySections || toRenderTableSection(nextSection)->numRows()))
   1122             break;
   1123         nextSection = nextSection->nextSibling();
   1124     }
   1125     if (!nextSection && m_foot && (!skipEmptySections || m_foot->numRows()))
   1126         nextSection = m_foot;
   1127     return toRenderTableSection(nextSection);
   1128 }
   1129 
   1130 RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
   1131 {
   1132     recalcSectionsIfNeeded();
   1133 
   1134     // Find the section and row to look in
   1135     int r = cell->row();
   1136     RenderTableSection* section = 0;
   1137     int rAbove = 0;
   1138     if (r > 0) {
   1139         // cell is not in the first row, so use the above row in its own section
   1140         section = cell->section();
   1141         rAbove = r - 1;
   1142     } else {
   1143         section = sectionAbove(cell->section(), true);
   1144         if (section)
   1145             rAbove = section->numRows() - 1;
   1146     }
   1147 
   1148     // Look up the cell in the section's grid, which requires effective col index
   1149     if (section) {
   1150         int effCol = colToEffCol(cell->col());
   1151         RenderTableSection::CellStruct& aboveCell = section->cellAt(rAbove, effCol);
   1152         return aboveCell.primaryCell();
   1153     } else
   1154         return 0;
   1155 }
   1156 
   1157 RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
   1158 {
   1159     recalcSectionsIfNeeded();
   1160 
   1161     // Find the section and row to look in
   1162     int r = cell->row() + cell->rowSpan() - 1;
   1163     RenderTableSection* section = 0;
   1164     int rBelow = 0;
   1165     if (r < cell->section()->numRows() - 1) {
   1166         // The cell is not in the last row, so use the next row in the section.
   1167         section = cell->section();
   1168         rBelow = r + 1;
   1169     } else {
   1170         section = sectionBelow(cell->section(), true);
   1171         if (section)
   1172             rBelow = 0;
   1173     }
   1174 
   1175     // Look up the cell in the section's grid, which requires effective col index
   1176     if (section) {
   1177         int effCol = colToEffCol(cell->col());
   1178         RenderTableSection::CellStruct& belowCell = section->cellAt(rBelow, effCol);
   1179         return belowCell.primaryCell();
   1180     } else
   1181         return 0;
   1182 }
   1183 
   1184 RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
   1185 {
   1186     recalcSectionsIfNeeded();
   1187 
   1188     RenderTableSection* section = cell->section();
   1189     int effCol = colToEffCol(cell->col());
   1190     if (!effCol)
   1191         return 0;
   1192 
   1193     // If we hit a colspan back up to a real cell.
   1194     RenderTableSection::CellStruct& prevCell = section->cellAt(cell->row(), effCol - 1);
   1195     return prevCell.primaryCell();
   1196 }
   1197 
   1198 RenderTableCell* RenderTable::cellAfter(const RenderTableCell* cell) const
   1199 {
   1200     recalcSectionsIfNeeded();
   1201 
   1202     int effCol = colToEffCol(cell->col() + cell->colSpan());
   1203     if (effCol >= numEffCols())
   1204         return 0;
   1205     return cell->section()->primaryCellAt(cell->row(), effCol);
   1206 }
   1207 
   1208 RenderBlock* RenderTable::firstLineBlock() const
   1209 {
   1210     return 0;
   1211 }
   1212 
   1213 void RenderTable::updateFirstLetter()
   1214 {
   1215 }
   1216 
   1217 int RenderTable::firstLineBoxBaseline() const
   1218 {
   1219     if (isWritingModeRoot())
   1220         return -1;
   1221 
   1222     recalcSectionsIfNeeded();
   1223 
   1224     RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
   1225     if (firstNonEmptySection && !firstNonEmptySection->numRows())
   1226         firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
   1227 
   1228     if (!firstNonEmptySection)
   1229         return -1;
   1230 
   1231     return firstNonEmptySection->logicalTop() + firstNonEmptySection->firstLineBoxBaseline();
   1232 }
   1233 
   1234 IntRect RenderTable::overflowClipRect(int tx, int ty, OverlayScrollbarSizeRelevancy relevancy)
   1235 {
   1236     IntRect rect = RenderBlock::overflowClipRect(tx, ty, relevancy);
   1237 
   1238     // If we have a caption, expand the clip to include the caption.
   1239     // FIXME: Technically this is wrong, but it's virtually impossible to fix this
   1240     // for real until captions have been re-written.
   1241     // FIXME: This code assumes (like all our other caption code) that only top/bottom are
   1242     // supported.  When we actually support left/right and stop mapping them to top/bottom,
   1243     // we might have to hack this code first (depending on what order we do these bug fixes in).
   1244     if (m_caption) {
   1245         if (style()->isHorizontalWritingMode()) {
   1246             rect.setHeight(height());
   1247             rect.setY(ty);
   1248         } else {
   1249             rect.setWidth(width());
   1250             rect.setX(tx);
   1251         }
   1252     }
   1253 
   1254     return rect;
   1255 }
   1256 
   1257 bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction action)
   1258 {
   1259     tx += x();
   1260     ty += y();
   1261 
   1262     // Check kids first.
   1263     if (!hasOverflowClip() || overflowClipRect(tx, ty).intersects(result.rectForPoint(xPos, yPos))) {
   1264         for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
   1265             if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption)) {
   1266                 IntPoint childPoint = flipForWritingMode(toRenderBox(child), IntPoint(tx, ty), ParentToChildFlippingAdjustment);
   1267                 if (child->nodeAtPoint(request, result, xPos, yPos, childPoint.x(), childPoint.y(), action)) {
   1268                     updateHitTestResult(result, IntPoint(xPos - childPoint.x(), yPos - childPoint.y()));
   1269                     return true;
   1270                 }
   1271             }
   1272         }
   1273     }
   1274 
   1275     // Check our bounds next.
   1276     IntRect boundsRect = IntRect(tx, ty, width(), height());
   1277     if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && boundsRect.intersects(result.rectForPoint(xPos, yPos))) {
   1278         updateHitTestResult(result, flipForWritingMode(IntPoint(xPos - tx, yPos - ty)));
   1279         if (!result.addNodeToRectBasedTestResult(node(), xPos, yPos, boundsRect))
   1280             return true;
   1281     }
   1282 
   1283     return false;
   1284 }
   1285 
   1286 }
   1287