WebCore/rendering/RenderTable.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 1997 Martin Jones (mjones@kde.org)
       
     3  *           (C) 1997 Torben Weis (weis@kde.org)
       
     4  *           (C) 1998 Waldo Bastian (bastian@kde.org)
       
     5  *           (C) 1999 Lars Knoll (knoll@kde.org)
       
     6  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
       
     7  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
       
     8  * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
       
     9  *
       
    10  * This library is free software; you can redistribute it and/or
       
    11  * modify it under the terms of the GNU Library General Public
       
    12  * License as published by the Free Software Foundation; either
       
    13  * version 2 of the License, or (at your option) any later version.
       
    14  *
       
    15  * This library is distributed in the hope that it will be useful,
       
    16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    18  * Library General Public License for more details.
       
    19  *
       
    20  * You should have received a copy of the GNU Library General Public License
       
    21  * along with this library; see the file COPYING.LIB.  If not, write to
       
    22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    23  * Boston, MA 02110-1301, USA.
       
    24  */
       
    25 
       
    26 #include "config.h"
       
    27 #include "RenderTable.h"
       
    28 
       
    29 #include "AutoTableLayout.h"
       
    30 #include "DeleteButtonController.h"
       
    31 #include "Document.h"
       
    32 #include "FixedTableLayout.h"
       
    33 #include "FrameView.h"
       
    34 #include "HitTestResult.h"
       
    35 #include "HTMLNames.h"
       
    36 #include "RenderLayer.h"
       
    37 #include "RenderTableCell.h"
       
    38 #include "RenderTableCol.h"
       
    39 #include "RenderTableSection.h"
       
    40 #include "RenderView.h"
       
    41 
       
    42 using namespace std;
       
    43 
       
    44 namespace WebCore {
       
    45 
       
    46 using namespace HTMLNames;
       
    47 
       
    48 RenderTable::RenderTable(Node* node)
       
    49     : RenderBlock(node)
       
    50     , m_caption(0)
       
    51     , m_head(0)
       
    52     , m_foot(0)
       
    53     , m_firstBody(0)
       
    54     , m_currentBorder(0)
       
    55     , m_hasColElements(false)
       
    56     , m_needsSectionRecalc(0)
       
    57     , m_hSpacing(0)
       
    58     , m_vSpacing(0)
       
    59     , m_borderLeft(0)
       
    60     , m_borderRight(0)
       
    61 {
       
    62     m_columnPos.fill(0, 2);
       
    63     m_columns.fill(ColumnStruct(), 1);
       
    64 }
       
    65 
       
    66 void RenderTable::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
       
    67 {
       
    68     RenderBlock::styleDidChange(diff, oldStyle);
       
    69 
       
    70     ETableLayout oldTableLayout = oldStyle ? oldStyle->tableLayout() : TAUTO;
       
    71 
       
    72     // In the collapsed border model, there is no cell spacing.
       
    73     m_hSpacing = collapseBorders() ? 0 : style()->horizontalBorderSpacing();
       
    74     m_vSpacing = collapseBorders() ? 0 : style()->verticalBorderSpacing();
       
    75     m_columnPos[0] = m_hSpacing;
       
    76 
       
    77     if (!m_tableLayout || style()->tableLayout() != oldTableLayout) {
       
    78         // According to the CSS2 spec, you only use fixed table layout if an
       
    79         // explicit width is specified on the table.  Auto width implies auto table layout.
       
    80         if (style()->tableLayout() == TFIXED && !style()->width().isAuto())
       
    81             m_tableLayout.set(new FixedTableLayout(this));
       
    82         else
       
    83             m_tableLayout.set(new AutoTableLayout(this));
       
    84     }
       
    85 }
       
    86 
       
    87 static inline void resetSectionPointerIfNotBefore(RenderTableSection*& ptr, RenderObject* before)
       
    88 {
       
    89     if (!before || !ptr)
       
    90         return;
       
    91     RenderObject* o = before->previousSibling();
       
    92     while (o && o != ptr)
       
    93         o = o->previousSibling();
       
    94     if (!o)
       
    95         ptr = 0;
       
    96 }
       
    97 
       
    98 void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
       
    99 {
       
   100     // Make sure we don't append things after :after-generated content if we have it.
       
   101     if (!beforeChild && isAfterContent(lastChild()))
       
   102         beforeChild = lastChild();
       
   103 
       
   104     bool wrapInAnonymousSection = !child->isPositioned();
       
   105 
       
   106     if (child->isRenderBlock() && child->style()->display() == TABLE_CAPTION) {
       
   107         // First caption wins.
       
   108         if (beforeChild && m_caption) {
       
   109             RenderObject* o = beforeChild->previousSibling();
       
   110             while (o && o != m_caption)
       
   111                 o = o->previousSibling();
       
   112             if (!o)
       
   113                 m_caption = 0;
       
   114         }
       
   115         if (!m_caption)
       
   116             m_caption = toRenderBlock(child);
       
   117         wrapInAnonymousSection = false;
       
   118     } else if (child->isTableCol()) {
       
   119         m_hasColElements = true;
       
   120         wrapInAnonymousSection = false;
       
   121     } else if (child->isTableSection()) {
       
   122         switch (child->style()->display()) {
       
   123             case TABLE_HEADER_GROUP:
       
   124                 resetSectionPointerIfNotBefore(m_head, beforeChild);
       
   125                 if (!m_head) {
       
   126                     m_head = toRenderTableSection(child);
       
   127                 } else {
       
   128                     resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
       
   129                     if (!m_firstBody) 
       
   130                         m_firstBody = toRenderTableSection(child);
       
   131                 }
       
   132                 wrapInAnonymousSection = false;
       
   133                 break;
       
   134             case TABLE_FOOTER_GROUP:
       
   135                 resetSectionPointerIfNotBefore(m_foot, beforeChild);
       
   136                 if (!m_foot) {
       
   137                     m_foot = toRenderTableSection(child);
       
   138                     wrapInAnonymousSection = false;
       
   139                     break;
       
   140                 }
       
   141                 // Fall through.
       
   142             case TABLE_ROW_GROUP:
       
   143                 resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
       
   144                 if (!m_firstBody)
       
   145                     m_firstBody = toRenderTableSection(child);
       
   146                 wrapInAnonymousSection = false;
       
   147                 break;
       
   148             default:
       
   149                 ASSERT_NOT_REACHED();
       
   150         }
       
   151     } else if (child->isTableCell() || child->isTableRow())
       
   152         wrapInAnonymousSection = true;
       
   153     else
       
   154         wrapInAnonymousSection = true;
       
   155 
       
   156     if (!wrapInAnonymousSection) {
       
   157         // If the next renderer is actually wrapped in an anonymous table section, we need to go up and find that.
       
   158         while (beforeChild && !beforeChild->isTableSection() && !beforeChild->isTableCol() && beforeChild->style()->display() != TABLE_CAPTION)
       
   159             beforeChild = beforeChild->parent();
       
   160 
       
   161         RenderBox::addChild(child, beforeChild);
       
   162         return;
       
   163     }
       
   164 
       
   165     if (!beforeChild && lastChild() && lastChild()->isTableSection() && lastChild()->isAnonymous()) {
       
   166         lastChild()->addChild(child);
       
   167         return;
       
   168     }
       
   169 
       
   170     RenderObject* lastBox = beforeChild;
       
   171     while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION && lastBox->style()->display() != TABLE_COLUMN_GROUP)
       
   172         lastBox = lastBox->parent();
       
   173     if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox)) {
       
   174         lastBox->addChild(child, beforeChild);
       
   175         return;
       
   176     }
       
   177 
       
   178     if (beforeChild && !beforeChild->isTableSection() && beforeChild->style()->display() != TABLE_CAPTION && beforeChild->style()->display() != TABLE_COLUMN_GROUP)
       
   179         beforeChild = 0;
       
   180     RenderTableSection* section = new (renderArena()) RenderTableSection(document() /* anonymous */);
       
   181     RefPtr<RenderStyle> newStyle = RenderStyle::create();
       
   182     newStyle->inheritFrom(style());
       
   183     newStyle->setDisplay(TABLE_ROW_GROUP);
       
   184     section->setStyle(newStyle.release());
       
   185     addChild(section, beforeChild);
       
   186     section->addChild(child);
       
   187 }
       
   188 
       
   189 void RenderTable::removeChild(RenderObject* oldChild)
       
   190 {
       
   191     RenderBox::removeChild(oldChild);
       
   192     setNeedsSectionRecalc();
       
   193 }
       
   194 
       
   195 void RenderTable::calcWidth()
       
   196 {
       
   197     if (isPositioned())
       
   198         calcAbsoluteHorizontal();
       
   199 
       
   200     RenderBlock* cb = containingBlock();
       
   201     int availableWidth = cb->availableWidth();
       
   202 
       
   203     LengthType widthType = style()->width().type();
       
   204     if (widthType > Relative && style()->width().isPositive()) {
       
   205         // Percent or fixed table
       
   206         setWidth(style()->width().calcMinValue(availableWidth));
       
   207         setWidth(max(minPrefWidth(), width()));
       
   208     } else {
       
   209         // An auto width table should shrink to fit within the line width if necessary in order to 
       
   210         // avoid overlapping floats.
       
   211         availableWidth = cb->lineWidth(y(), false);
       
   212         
       
   213         // Subtract out any fixed margins from our available width for auto width tables.
       
   214         int marginTotal = 0;
       
   215         if (!style()->marginLeft().isAuto())
       
   216             marginTotal += style()->marginLeft().calcValue(availableWidth);
       
   217         if (!style()->marginRight().isAuto())
       
   218             marginTotal += style()->marginRight().calcValue(availableWidth);
       
   219             
       
   220         // Subtract out our margins to get the available content width.
       
   221         int availContentWidth = max(0, availableWidth - marginTotal);
       
   222         
       
   223         // Ensure we aren't bigger than our max width or smaller than our min width.
       
   224         setWidth(min(availContentWidth, maxPrefWidth()));
       
   225     }
       
   226     
       
   227     setWidth(max(width(), minPrefWidth()));
       
   228 
       
   229     // Finally, with our true width determined, compute our margins for real.
       
   230     m_marginRight = 0;
       
   231     m_marginLeft = 0;
       
   232     calcHorizontalMargins(style()->marginLeft(), style()->marginRight(), availableWidth);
       
   233 }
       
   234 
       
   235 void RenderTable::layout()
       
   236 {
       
   237     ASSERT(needsLayout());
       
   238 
       
   239     if (layoutOnlyPositionedObjects())
       
   240         return;
       
   241 
       
   242     recalcSectionsIfNeeded();
       
   243         
       
   244     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
       
   245     LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
       
   246 
       
   247     setHeight(0);
       
   248     m_overflow.clear();
       
   249 
       
   250     initMaxMarginValues();
       
   251     
       
   252     int oldWidth = width();
       
   253     calcWidth();
       
   254 
       
   255     if (m_caption && width() != oldWidth)
       
   256         m_caption->setNeedsLayout(true, false);
       
   257 
       
   258     // FIXME: The optimisation below doesn't work since the internal table
       
   259     // layout could have changed.  we need to add a flag to the table
       
   260     // layout that tells us if something has changed in the min max
       
   261     // calculations to do it correctly.
       
   262 //     if ( oldWidth != width() || columns.size() + 1 != columnPos.size() )
       
   263     m_tableLayout->layout();
       
   264 
       
   265     setCellWidths();
       
   266 
       
   267     // layout child objects
       
   268     int calculatedHeight = 0;
       
   269     int oldTableTop = m_caption ? m_caption->height() + m_caption->marginTop() + m_caption->marginBottom() : 0;
       
   270 
       
   271     bool collapsing = collapseBorders();
       
   272 
       
   273     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
       
   274         if (child->isTableSection()) {
       
   275             child->layoutIfNeeded();
       
   276             RenderTableSection* section = toRenderTableSection(child);
       
   277             calculatedHeight += section->calcRowHeight();
       
   278             if (collapsing)
       
   279                 section->recalcOuterBorder();
       
   280             ASSERT(!section->needsLayout());
       
   281         } else if (child->isTableCol()) {
       
   282             child->layoutIfNeeded();
       
   283             ASSERT(!child->needsLayout());
       
   284         }
       
   285     }
       
   286 
       
   287     // Only lay out one caption, since it's the only one we're going to end up painting.
       
   288     if (m_caption)
       
   289         m_caption->layoutIfNeeded();
       
   290 
       
   291     // If any table section moved vertically, we will just repaint everything from that
       
   292     // section down (it is quite unlikely that any of the following sections
       
   293     // did not shift).
       
   294     bool sectionMoved = false;
       
   295     int movedSectionTop = 0;
       
   296 
       
   297     // FIXME: Collapse caption margin.
       
   298     if (m_caption && m_caption->style()->captionSide() != CAPBOTTOM) {
       
   299         IntRect captionRect(m_caption->x(), m_caption->y(), m_caption->width(), m_caption->height());
       
   300 
       
   301         m_caption->setLocation(m_caption->marginLeft(), height());
       
   302         if (!selfNeedsLayout() && m_caption->checkForRepaintDuringLayout())
       
   303             m_caption->repaintDuringLayoutIfMoved(captionRect);
       
   304 
       
   305         setHeight(height() + m_caption->height() + m_caption->marginTop() + m_caption->marginBottom());
       
   306 
       
   307         if (height() != oldTableTop) {
       
   308             sectionMoved = true;
       
   309             movedSectionTop = min(height(), oldTableTop);
       
   310         }
       
   311     }
       
   312 
       
   313     int bpTop = borderTop() + (collapsing ? 0 : paddingTop());
       
   314     int bpBottom = borderBottom() + (collapsing ? 0 : paddingBottom());
       
   315     
       
   316     setHeight(height() + bpTop);
       
   317 
       
   318     if (!isPositioned())
       
   319         calcHeight();
       
   320 
       
   321     Length h = style()->height();
       
   322     int th = 0;
       
   323     if (h.isFixed())
       
   324         // Tables size as though CSS height includes border/padding.
       
   325         th = h.value() - (bpTop + bpBottom);
       
   326     else if (h.isPercent())
       
   327         th = calcPercentageHeight(h);
       
   328     th = max(0, th);
       
   329 
       
   330     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
       
   331         if (child->isTableSection())
       
   332             // FIXME: Distribute extra height between all table body sections instead of giving it all to the first one.
       
   333             toRenderTableSection(child)->layoutRows(child == m_firstBody ? max(0, th - calculatedHeight) : 0);
       
   334     }
       
   335 
       
   336     if (!m_firstBody && th > calculatedHeight && !style()->htmlHacks()) {
       
   337         // Completely empty tables (with no sections or anything) should at least honor specified height
       
   338         // in strict mode.
       
   339         setHeight(height() + th);
       
   340     }
       
   341     
       
   342     int bl = borderLeft();
       
   343     if (!collapsing)
       
   344         bl += paddingLeft();
       
   345 
       
   346     // position the table sections
       
   347     RenderTableSection* section = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
       
   348     while (section) {
       
   349         if (!sectionMoved && section->y() != height()) {
       
   350             sectionMoved = true;
       
   351             movedSectionTop = min(height(), section->y()) + section->topVisibleOverflow();
       
   352         }
       
   353         section->setLocation(bl, height());
       
   354 
       
   355         setHeight(height() + section->height());
       
   356         section = sectionBelow(section);
       
   357     }
       
   358 
       
   359     setHeight(height() + bpBottom);
       
   360 
       
   361     if (m_caption && m_caption->style()->captionSide() == CAPBOTTOM) {
       
   362         IntRect captionRect(m_caption->x(), m_caption->y(), m_caption->width(), m_caption->height());
       
   363 
       
   364         m_caption->setLocation(m_caption->marginLeft(), height());
       
   365         if (!selfNeedsLayout() && m_caption->checkForRepaintDuringLayout())
       
   366             m_caption->repaintDuringLayoutIfMoved(captionRect);
       
   367 
       
   368         setHeight(height() + m_caption->height() + m_caption->marginTop() + m_caption->marginBottom());
       
   369     }
       
   370 
       
   371     if (isPositioned())
       
   372         calcHeight();
       
   373 
       
   374     // table can be containing block of positioned elements.
       
   375     // FIXME: Only pass true if width or height changed.
       
   376     layoutPositionedObjects(true);
       
   377 
       
   378     // Add overflow from borders.
       
   379     int rightBorderOverflow = width() + (collapsing ? outerBorderRight() - borderRight() : 0);
       
   380     int leftBorderOverflow = collapsing ? borderLeft() - outerBorderLeft() : 0;
       
   381     int bottomBorderOverflow = height() + (collapsing ? outerBorderBottom() - borderBottom() : 0);
       
   382     int topBorderOverflow = collapsing ? borderTop() - outerBorderTop() : 0;
       
   383     addLayoutOverflow(IntRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow));
       
   384     
       
   385     // Add visual overflow from box-shadow and reflections.
       
   386     addShadowOverflow();
       
   387     
       
   388     // Add overflow from our caption.
       
   389     if (m_caption)
       
   390         addOverflowFromChild(m_caption);
       
   391 
       
   392     // Add overflow from our sections.
       
   393     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
       
   394         if (child->isTableSection()) {
       
   395             RenderTableSection* section = toRenderTableSection(child);
       
   396             addOverflowFromChild(section);
       
   397         }
       
   398     }
       
   399 
       
   400     statePusher.pop();
       
   401 
       
   402     bool didFullRepaint = repainter.repaintAfterLayout();
       
   403     // Repaint with our new bounds if they are different from our old bounds.
       
   404     if (!didFullRepaint && sectionMoved)
       
   405         repaintRectangle(IntRect(leftVisibleOverflow(), movedSectionTop, rightVisibleOverflow() - leftVisibleOverflow(), bottomVisibleOverflow() - movedSectionTop));
       
   406     
       
   407     setNeedsLayout(false);
       
   408 }
       
   409 
       
   410 void RenderTable::setCellWidths()
       
   411 {
       
   412     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
       
   413         if (child->isTableSection())
       
   414             toRenderTableSection(child)->setCellWidths();
       
   415     }
       
   416 }
       
   417 
       
   418 void RenderTable::paint(PaintInfo& paintInfo, int tx, int ty)
       
   419 {
       
   420     tx += x();
       
   421     ty += y();
       
   422 
       
   423     PaintPhase paintPhase = paintInfo.phase;
       
   424 
       
   425     int os = 2 * maximalOutlineSize(paintPhase);
       
   426     if (ty + topVisibleOverflow() >= paintInfo.rect.bottom() + os || ty + bottomVisibleOverflow() <= paintInfo.rect.y() - os)
       
   427         return;
       
   428     if (tx + leftVisibleOverflow() >= paintInfo.rect.right() + os || tx + rightVisibleOverflow() <= paintInfo.rect.x() - os)
       
   429         return;
       
   430 
       
   431     bool pushedClip = pushContentsClip(paintInfo, tx, ty);    
       
   432     paintObject(paintInfo, tx, ty);
       
   433     if (pushedClip)
       
   434         popContentsClip(paintInfo, paintPhase, tx, ty);
       
   435 }
       
   436 
       
   437 void RenderTable::paintObject(PaintInfo& paintInfo, int tx, int ty)
       
   438 {
       
   439     PaintPhase paintPhase = paintInfo.phase;
       
   440     if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style()->visibility() == VISIBLE)
       
   441         paintBoxDecorations(paintInfo, tx, ty);
       
   442 
       
   443     if (paintPhase == PaintPhaseMask) {
       
   444         paintMask(paintInfo, tx, ty);
       
   445         return;
       
   446     }
       
   447 
       
   448     // We're done.  We don't bother painting any children.
       
   449     if (paintPhase == PaintPhaseBlockBackground)
       
   450         return;
       
   451     
       
   452     // We don't paint our own background, but we do let the kids paint their backgrounds.
       
   453     if (paintPhase == PaintPhaseChildBlockBackgrounds)
       
   454         paintPhase = PaintPhaseChildBlockBackground;
       
   455 
       
   456     PaintInfo info(paintInfo);
       
   457     info.phase = paintPhase;
       
   458     info.updatePaintingRootForChildren(this);
       
   459 
       
   460     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
       
   461         if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption))
       
   462             child->paint(info, tx, ty);
       
   463     }
       
   464     
       
   465     if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
       
   466         // Collect all the unique border styles that we want to paint in a sorted list.  Once we
       
   467         // have all the styles sorted, we then do individual passes, painting each style of border
       
   468         // from lowest precedence to highest precedence.
       
   469         info.phase = PaintPhaseCollapsedTableBorders;
       
   470         RenderTableCell::CollapsedBorderStyles borderStyles;
       
   471         RenderObject* stop = nextInPreOrderAfterChildren();
       
   472         for (RenderObject* o = firstChild(); o && o != stop; o = o->nextInPreOrder())
       
   473             if (o->isTableCell())
       
   474                 toRenderTableCell(o)->collectBorderStyles(borderStyles);
       
   475         RenderTableCell::sortBorderStyles(borderStyles);
       
   476         size_t count = borderStyles.size();
       
   477         for (size_t i = 0; i < count; ++i) {
       
   478             m_currentBorder = &borderStyles[i];
       
   479             for (RenderObject* child = firstChild(); child; child = child->nextSibling())
       
   480                 if (child->isTableSection())
       
   481                     child->paint(info, tx, ty);
       
   482         }
       
   483         m_currentBorder = 0;
       
   484     }
       
   485 }
       
   486 
       
   487 void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
       
   488 {
       
   489     if (!paintInfo.shouldPaintWithinRoot(this))
       
   490         return;
       
   491 
       
   492     int w = width();
       
   493     int h = height();
       
   494 
       
   495     // Account for the caption.
       
   496     if (m_caption) {
       
   497         int captionHeight = (m_caption->height() + m_caption->marginBottom() +  m_caption->marginTop());
       
   498         h -= captionHeight;
       
   499         if (m_caption->style()->captionSide() != CAPBOTTOM)
       
   500             ty += captionHeight;
       
   501     }
       
   502 
       
   503     paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal);
       
   504     
       
   505     paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, w, h);
       
   506     paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset);
       
   507 
       
   508     if (style()->hasBorder() && !collapseBorders())
       
   509         paintBorder(paintInfo.context, tx, ty, w, h, style());
       
   510 }
       
   511 
       
   512 void RenderTable::paintMask(PaintInfo& paintInfo, int tx, int ty)
       
   513 {
       
   514     if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
       
   515         return;
       
   516 
       
   517     int w = width();
       
   518     int h = height();
       
   519 
       
   520     // Account for the caption.
       
   521     if (m_caption) {
       
   522         int captionHeight = (m_caption->height() + m_caption->marginBottom() +  m_caption->marginTop());
       
   523         h -= captionHeight;
       
   524         if (m_caption->style()->captionSide() != CAPBOTTOM)
       
   525             ty += captionHeight;
       
   526     }
       
   527 
       
   528     paintMaskImages(paintInfo, tx, ty, w, h);
       
   529 }
       
   530 
       
   531 void RenderTable::calcPrefWidths()
       
   532 {
       
   533     ASSERT(prefWidthsDirty());
       
   534 
       
   535     recalcSectionsIfNeeded();
       
   536     recalcHorizontalBorders();
       
   537 
       
   538     m_tableLayout->calcPrefWidths(m_minPrefWidth, m_maxPrefWidth);
       
   539 
       
   540     if (m_caption)
       
   541         m_minPrefWidth = max(m_minPrefWidth, m_caption->minPrefWidth());
       
   542 
       
   543     setPrefWidthsDirty(false);
       
   544 }
       
   545 
       
   546 void RenderTable::splitColumn(int pos, int firstSpan)
       
   547 {
       
   548     // we need to add a new columnStruct
       
   549     int oldSize = m_columns.size();
       
   550     m_columns.grow(oldSize + 1);
       
   551     int oldSpan = m_columns[pos].span;
       
   552     ASSERT(oldSpan > firstSpan);
       
   553     m_columns[pos].span = firstSpan;
       
   554     memmove(m_columns.data() + pos + 1, m_columns.data() + pos, (oldSize - pos) * sizeof(ColumnStruct));
       
   555     m_columns[pos + 1].span = oldSpan - firstSpan;
       
   556 
       
   557     // change width of all rows.
       
   558     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
       
   559         if (child->isTableSection())
       
   560             toRenderTableSection(child)->splitColumn(pos, oldSize + 1);
       
   561     }
       
   562 
       
   563     m_columnPos.grow(numEffCols() + 1);
       
   564     setNeedsLayoutAndPrefWidthsRecalc();
       
   565 }
       
   566 
       
   567 void RenderTable::appendColumn(int span)
       
   568 {
       
   569     // easy case.
       
   570     int pos = m_columns.size();
       
   571     int newSize = pos + 1;
       
   572     m_columns.grow(newSize);
       
   573     m_columns[pos].span = span;
       
   574 
       
   575     // change width of all rows.
       
   576     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
       
   577         if (child->isTableSection())
       
   578             toRenderTableSection(child)->appendColumn(pos);
       
   579     }
       
   580 
       
   581     m_columnPos.grow(numEffCols() + 1);
       
   582     setNeedsLayoutAndPrefWidthsRecalc();
       
   583 }
       
   584 
       
   585 RenderTableCol* RenderTable::nextColElement(RenderTableCol* current) const
       
   586 {
       
   587     RenderObject* next = current->firstChild();
       
   588     if (!next)
       
   589         next = current->nextSibling();
       
   590     if (!next && current->parent()->isTableCol())
       
   591         next = current->parent()->nextSibling();
       
   592 
       
   593     while (next) {
       
   594         if (next->isTableCol())
       
   595             return toRenderTableCol(next);
       
   596         if (next != m_caption)
       
   597             return 0;
       
   598         next = next->nextSibling();
       
   599     }
       
   600     
       
   601     return 0;
       
   602 }
       
   603 
       
   604 RenderTableCol* RenderTable::colElement(int col, bool* startEdge, bool* endEdge) const
       
   605 {
       
   606     if (!m_hasColElements)
       
   607         return 0;
       
   608     RenderObject* child = firstChild();
       
   609     int cCol = 0;
       
   610 
       
   611     while (child) {
       
   612         if (child->isTableCol())
       
   613             break;
       
   614         if (child != m_caption)
       
   615             return 0;
       
   616         child = child->nextSibling();
       
   617     }
       
   618     if (!child)
       
   619         return 0;
       
   620 
       
   621     RenderTableCol* colElem = toRenderTableCol(child);
       
   622     while (colElem) {
       
   623         int span = colElem->span();
       
   624         if (!colElem->firstChild()) {
       
   625             int startCol = cCol;
       
   626             int endCol = cCol + span - 1;
       
   627             cCol += span;
       
   628             if (cCol > col) {
       
   629                 if (startEdge)
       
   630                     *startEdge = startCol == col;
       
   631                 if (endEdge)
       
   632                     *endEdge = endCol == col;
       
   633                 return colElem;
       
   634             }
       
   635         }
       
   636         colElem = nextColElement(colElem);
       
   637     }
       
   638 
       
   639     return 0;
       
   640 }
       
   641 
       
   642 void RenderTable::recalcSections() const
       
   643 {
       
   644     m_caption = 0;
       
   645     m_head = 0;
       
   646     m_foot = 0;
       
   647     m_firstBody = 0;
       
   648     m_hasColElements = false;
       
   649 
       
   650     // We need to get valid pointers to caption, head, foot and first body again
       
   651     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
       
   652         switch (child->style()->display()) {
       
   653             case TABLE_CAPTION:
       
   654                 if (!m_caption && child->isRenderBlock()) {
       
   655                     m_caption = toRenderBlock(child);
       
   656                     m_caption->setNeedsLayout(true);
       
   657                 }
       
   658                 break;
       
   659             case TABLE_COLUMN:
       
   660             case TABLE_COLUMN_GROUP:
       
   661                 m_hasColElements = true;
       
   662                 break;
       
   663             case TABLE_HEADER_GROUP:
       
   664                 if (child->isTableSection()) {
       
   665                     RenderTableSection* section = toRenderTableSection(child);
       
   666                     if (!m_head)
       
   667                         m_head = section;
       
   668                     else if (!m_firstBody)
       
   669                         m_firstBody = section;
       
   670                     section->recalcCellsIfNeeded();
       
   671                 }
       
   672                 break;
       
   673             case TABLE_FOOTER_GROUP:
       
   674                 if (child->isTableSection()) {
       
   675                     RenderTableSection* section = toRenderTableSection(child);
       
   676                     if (!m_foot)
       
   677                         m_foot = section;
       
   678                     else if (!m_firstBody)
       
   679                         m_firstBody = section;
       
   680                     section->recalcCellsIfNeeded();
       
   681                 }
       
   682                 break;
       
   683             case TABLE_ROW_GROUP:
       
   684                 if (child->isTableSection()) {
       
   685                     RenderTableSection* section = toRenderTableSection(child);
       
   686                     if (!m_firstBody)
       
   687                         m_firstBody = section;
       
   688                     section->recalcCellsIfNeeded();
       
   689                 }
       
   690                 break;
       
   691             default:
       
   692                 break;
       
   693         }
       
   694     }
       
   695 
       
   696     // repair column count (addChild can grow it too much, because it always adds elements to the last row of a section)
       
   697     int maxCols = 0;
       
   698     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
       
   699         if (child->isTableSection()) {
       
   700             RenderTableSection* section = toRenderTableSection(child);
       
   701             int sectionCols = section->numColumns();
       
   702             if (sectionCols > maxCols)
       
   703                 maxCols = sectionCols;
       
   704         }
       
   705     }
       
   706     
       
   707     m_columns.resize(maxCols);
       
   708     m_columnPos.resize(maxCols + 1);
       
   709 
       
   710     ASSERT(selfNeedsLayout());
       
   711 
       
   712     m_needsSectionRecalc = false;
       
   713 }
       
   714 
       
   715 int RenderTable::calcBorderLeft() const
       
   716 {
       
   717     if (collapseBorders()) {
       
   718         // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2.
       
   719         if (!numEffCols())
       
   720             return 0;
       
   721 
       
   722         unsigned borderWidth = 0;
       
   723 
       
   724         const BorderValue& tb = style()->borderLeft();
       
   725         if (tb.style() == BHIDDEN)
       
   726             return 0;
       
   727         if (tb.style() > BHIDDEN)
       
   728             borderWidth = tb.width();
       
   729 
       
   730         int leftmostColumn = style()->direction() == RTL ? numEffCols() - 1 : 0;
       
   731         RenderTableCol* colGroup = colElement(leftmostColumn);
       
   732         if (colGroup) {
       
   733             const BorderValue& gb = style()->borderLeft();
       
   734             if (gb.style() == BHIDDEN)
       
   735                 return 0;
       
   736             if (gb.style() > BHIDDEN)
       
   737                 borderWidth = max(borderWidth, static_cast<unsigned>(gb.width()));
       
   738         }
       
   739         
       
   740         RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
       
   741         if (firstNonEmptySection && !firstNonEmptySection->numRows())
       
   742             firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
       
   743         
       
   744         if (firstNonEmptySection) {
       
   745             const BorderValue& sb = firstNonEmptySection->style()->borderLeft();
       
   746             if (sb.style() == BHIDDEN)
       
   747                 return 0;
       
   748 
       
   749             if (sb.style() > BHIDDEN)
       
   750                 borderWidth = max(borderWidth, static_cast<unsigned>(sb.width()));
       
   751 
       
   752             const RenderTableSection::CellStruct& cs = firstNonEmptySection->cellAt(0, leftmostColumn);
       
   753             
       
   754             if (cs.cell) {
       
   755                 const BorderValue& cb = cs.cell->style()->borderLeft();
       
   756                 if (cb.style() == BHIDDEN)
       
   757                     return 0;
       
   758 
       
   759                 const BorderValue& rb = cs.cell->parent()->style()->borderLeft();
       
   760                 if (rb.style() == BHIDDEN)
       
   761                     return 0;
       
   762 
       
   763                 if (cb.style() > BHIDDEN)
       
   764                     borderWidth = max(borderWidth, static_cast<unsigned>(cb.width()));
       
   765                 if (rb.style() > BHIDDEN)
       
   766                     borderWidth = max(borderWidth, static_cast<unsigned>(rb.width()));
       
   767             }
       
   768         }
       
   769         return borderWidth / 2;
       
   770     }
       
   771     return RenderBlock::borderLeft();
       
   772 }
       
   773     
       
   774 int RenderTable::calcBorderRight() const
       
   775 {
       
   776     if (collapseBorders()) {
       
   777         // Determined by the last cell of the first row. See the CSS 2.1 spec, section 17.6.2.
       
   778         if (!numEffCols())
       
   779             return 0;
       
   780 
       
   781         unsigned borderWidth = 0;
       
   782 
       
   783         const BorderValue& tb = style()->borderRight();
       
   784         if (tb.style() == BHIDDEN)
       
   785             return 0;
       
   786         if (tb.style() > BHIDDEN)
       
   787             borderWidth = tb.width();
       
   788 
       
   789         int rightmostColumn = style()->direction() == RTL ? 0 : numEffCols() - 1;
       
   790         RenderTableCol* colGroup = colElement(rightmostColumn);
       
   791         if (colGroup) {
       
   792             const BorderValue& gb = style()->borderRight();
       
   793             if (gb.style() == BHIDDEN)
       
   794                 return 0;
       
   795             if (gb.style() > BHIDDEN)
       
   796                 borderWidth = max(borderWidth, static_cast<unsigned>(gb.width()));
       
   797         }
       
   798         
       
   799         RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
       
   800         if (firstNonEmptySection && !firstNonEmptySection->numRows())
       
   801             firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
       
   802         
       
   803         if (firstNonEmptySection) {
       
   804             const BorderValue& sb = firstNonEmptySection->style()->borderRight();
       
   805             if (sb.style() == BHIDDEN)
       
   806                 return 0;
       
   807 
       
   808             if (sb.style() > BHIDDEN)
       
   809                 borderWidth = max(borderWidth, static_cast<unsigned>(sb.width()));
       
   810 
       
   811             const RenderTableSection::CellStruct& cs = firstNonEmptySection->cellAt(0, rightmostColumn);
       
   812             
       
   813             if (cs.cell) {
       
   814                 const BorderValue& cb = cs.cell->style()->borderRight();
       
   815                 if (cb.style() == BHIDDEN)
       
   816                     return 0;
       
   817 
       
   818                 const BorderValue& rb = cs.cell->parent()->style()->borderRight();
       
   819                 if (rb.style() == BHIDDEN)
       
   820                     return 0;
       
   821 
       
   822                 if (cb.style() > BHIDDEN)
       
   823                     borderWidth = max(borderWidth, static_cast<unsigned>(cb.width()));
       
   824                 if (rb.style() > BHIDDEN)
       
   825                     borderWidth = max(borderWidth, static_cast<unsigned>(rb.width()));
       
   826             }
       
   827         }
       
   828         return (borderWidth + 1) / 2;
       
   829     }
       
   830     return RenderBlock::borderRight();
       
   831 }
       
   832 
       
   833 void RenderTable::recalcHorizontalBorders()
       
   834 {
       
   835     m_borderLeft = calcBorderLeft();
       
   836     m_borderRight = calcBorderRight();
       
   837 }
       
   838 
       
   839 int RenderTable::borderTop() const
       
   840 {
       
   841     if (collapseBorders())
       
   842         return outerBorderTop();
       
   843     return RenderBlock::borderTop();
       
   844 }
       
   845 
       
   846 int RenderTable::borderBottom() const
       
   847 {
       
   848     if (collapseBorders())
       
   849         return outerBorderBottom();
       
   850     return RenderBlock::borderBottom();
       
   851 }
       
   852 
       
   853 int RenderTable::outerBorderTop() const
       
   854 {
       
   855     if (!collapseBorders())
       
   856         return 0;
       
   857     int borderWidth = 0;
       
   858     RenderTableSection* topSection;
       
   859     if (m_head)
       
   860         topSection = m_head;
       
   861     else if (m_firstBody)
       
   862         topSection = m_firstBody;
       
   863     else if (m_foot)
       
   864         topSection = m_foot;
       
   865     else
       
   866         topSection = 0;
       
   867     if (topSection) {
       
   868         borderWidth = topSection->outerBorderTop();
       
   869         if (borderWidth == -1)
       
   870             return 0;   // Overridden by hidden
       
   871     }
       
   872     const BorderValue& tb = style()->borderTop();
       
   873     if (tb.style() == BHIDDEN)
       
   874         return 0;
       
   875     if (tb.style() > BHIDDEN)
       
   876         borderWidth = max(borderWidth, static_cast<int>(tb.width() / 2));
       
   877     return borderWidth;
       
   878 }
       
   879 
       
   880 int RenderTable::outerBorderBottom() const
       
   881 {
       
   882     if (!collapseBorders())
       
   883         return 0;
       
   884     int borderWidth = 0;
       
   885     RenderTableSection* bottomSection;
       
   886     if (m_foot)
       
   887         bottomSection = m_foot;
       
   888     else {
       
   889         RenderObject* child;
       
   890         for (child = lastChild(); child && !child->isTableSection(); child = child->previousSibling()) { }
       
   891         bottomSection = child ? toRenderTableSection(child) : 0;
       
   892     }
       
   893     if (bottomSection) {
       
   894         borderWidth = bottomSection->outerBorderBottom();
       
   895         if (borderWidth == -1)
       
   896             return 0;   // Overridden by hidden
       
   897     }
       
   898     const BorderValue& tb = style()->borderBottom();
       
   899     if (tb.style() == BHIDDEN)
       
   900         return 0;
       
   901     if (tb.style() > BHIDDEN)
       
   902         borderWidth = max(borderWidth, static_cast<int>((tb.width() + 1) / 2));
       
   903     return borderWidth;
       
   904 }
       
   905 
       
   906 int RenderTable::outerBorderLeft() const
       
   907 {
       
   908     if (!collapseBorders())
       
   909         return 0;
       
   910 
       
   911     int borderWidth = 0;
       
   912 
       
   913     const BorderValue& tb = style()->borderLeft();
       
   914     if (tb.style() == BHIDDEN)
       
   915         return 0;
       
   916     if (tb.style() > BHIDDEN)
       
   917         borderWidth = tb.width() / 2;
       
   918 
       
   919     bool allHidden = true;
       
   920     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
       
   921         if (!child->isTableSection())
       
   922             continue;
       
   923         int sw = toRenderTableSection(child)->outerBorderLeft();
       
   924         if (sw == -1)
       
   925             continue;
       
   926         else
       
   927             allHidden = false;
       
   928         borderWidth = max(borderWidth, sw);
       
   929     }
       
   930     if (allHidden)
       
   931         return 0;
       
   932 
       
   933     return borderWidth;
       
   934 }
       
   935 
       
   936 int RenderTable::outerBorderRight() const
       
   937 {
       
   938     if (!collapseBorders())
       
   939         return 0;
       
   940 
       
   941     int borderWidth = 0;
       
   942 
       
   943     const BorderValue& tb = style()->borderRight();
       
   944     if (tb.style() == BHIDDEN)
       
   945         return 0;
       
   946     if (tb.style() > BHIDDEN)
       
   947         borderWidth = (tb.width() + 1) / 2;
       
   948 
       
   949     bool allHidden = true;
       
   950     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
       
   951         if (!child->isTableSection())
       
   952             continue;
       
   953         int sw = toRenderTableSection(child)->outerBorderRight();
       
   954         if (sw == -1)
       
   955             continue;
       
   956         else
       
   957             allHidden = false;
       
   958         borderWidth = max(borderWidth, sw);
       
   959     }
       
   960     if (allHidden)
       
   961         return 0;
       
   962 
       
   963     return borderWidth;
       
   964 }
       
   965 
       
   966 RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section, bool skipEmptySections) const
       
   967 {
       
   968     recalcSectionsIfNeeded();
       
   969 
       
   970     if (section == m_head)
       
   971         return 0;
       
   972 
       
   973     RenderObject* prevSection = section == m_foot ? lastChild() : section->previousSibling();
       
   974     while (prevSection) {
       
   975         if (prevSection->isTableSection() && prevSection != m_head && prevSection != m_foot && (!skipEmptySections || toRenderTableSection(prevSection)->numRows()))
       
   976             break;
       
   977         prevSection = prevSection->previousSibling();
       
   978     }
       
   979     if (!prevSection && m_head && (!skipEmptySections || m_head->numRows()))
       
   980         prevSection = m_head;
       
   981     return toRenderTableSection(prevSection);
       
   982 }
       
   983 
       
   984 RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, bool skipEmptySections) const
       
   985 {
       
   986     recalcSectionsIfNeeded();
       
   987 
       
   988     if (section == m_foot)
       
   989         return 0;
       
   990 
       
   991     RenderObject* nextSection = section == m_head ? firstChild() : section->nextSibling();
       
   992     while (nextSection) {
       
   993         if (nextSection->isTableSection() && nextSection != m_head && nextSection != m_foot && (!skipEmptySections || toRenderTableSection(nextSection)->numRows()))
       
   994             break;
       
   995         nextSection = nextSection->nextSibling();
       
   996     }
       
   997     if (!nextSection && m_foot && (!skipEmptySections || m_foot->numRows()))
       
   998         nextSection = m_foot;
       
   999     return toRenderTableSection(nextSection);
       
  1000 }
       
  1001 
       
  1002 RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
       
  1003 {
       
  1004     recalcSectionsIfNeeded();
       
  1005 
       
  1006     // Find the section and row to look in
       
  1007     int r = cell->row();
       
  1008     RenderTableSection* section = 0;
       
  1009     int rAbove = 0;
       
  1010     if (r > 0) {
       
  1011         // cell is not in the first row, so use the above row in its own section
       
  1012         section = cell->section();
       
  1013         rAbove = r - 1;
       
  1014     } else {
       
  1015         section = sectionAbove(cell->section(), true);
       
  1016         if (section)
       
  1017             rAbove = section->numRows() - 1;
       
  1018     }
       
  1019 
       
  1020     // Look up the cell in the section's grid, which requires effective col index
       
  1021     if (section) {
       
  1022         int effCol = colToEffCol(cell->col());
       
  1023         RenderTableSection::CellStruct aboveCell;
       
  1024         // If we hit a span back up to a real cell.
       
  1025         do {
       
  1026             aboveCell = section->cellAt(rAbove, effCol);
       
  1027             effCol--;
       
  1028         } while (!aboveCell.cell && aboveCell.inColSpan && effCol >= 0);
       
  1029         return aboveCell.cell;
       
  1030     } else
       
  1031         return 0;
       
  1032 }
       
  1033 
       
  1034 RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
       
  1035 {
       
  1036     recalcSectionsIfNeeded();
       
  1037 
       
  1038     // Find the section and row to look in
       
  1039     int r = cell->row() + cell->rowSpan() - 1;
       
  1040     RenderTableSection* section = 0;
       
  1041     int rBelow = 0;
       
  1042     if (r < cell->section()->numRows() - 1) {
       
  1043         // The cell is not in the last row, so use the next row in the section.
       
  1044         section = cell->section();
       
  1045         rBelow = r + 1;
       
  1046     } else {
       
  1047         section = sectionBelow(cell->section(), true);
       
  1048         if (section)
       
  1049             rBelow = 0;
       
  1050     }
       
  1051 
       
  1052     // Look up the cell in the section's grid, which requires effective col index
       
  1053     if (section) {
       
  1054         int effCol = colToEffCol(cell->col());
       
  1055         RenderTableSection::CellStruct belowCell;
       
  1056         // If we hit a colspan back up to a real cell.
       
  1057         do {
       
  1058             belowCell = section->cellAt(rBelow, effCol);
       
  1059             effCol--;
       
  1060         } while (!belowCell.cell && belowCell.inColSpan && effCol >= 0);
       
  1061         return belowCell.cell;
       
  1062     } else
       
  1063         return 0;
       
  1064 }
       
  1065 
       
  1066 RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
       
  1067 {
       
  1068     recalcSectionsIfNeeded();
       
  1069 
       
  1070     RenderTableSection* section = cell->section();
       
  1071     int effCol = colToEffCol(cell->col());
       
  1072     if (!effCol)
       
  1073         return 0;
       
  1074     
       
  1075     // If we hit a colspan back up to a real cell.
       
  1076     RenderTableSection::CellStruct prevCell;
       
  1077     do {
       
  1078         prevCell = section->cellAt(cell->row(), effCol - 1);
       
  1079         effCol--;
       
  1080     } while (!prevCell.cell && prevCell.inColSpan && effCol >= 0);
       
  1081     return prevCell.cell;
       
  1082 }
       
  1083 
       
  1084 RenderTableCell* RenderTable::cellAfter(const RenderTableCell* cell) const
       
  1085 {
       
  1086     recalcSectionsIfNeeded();
       
  1087 
       
  1088     int effCol = colToEffCol(cell->col() + cell->colSpan());
       
  1089     if (effCol >= numEffCols())
       
  1090         return 0;
       
  1091     return cell->section()->cellAt(cell->row(), effCol).cell;
       
  1092 }
       
  1093 
       
  1094 RenderBlock* RenderTable::firstLineBlock() const
       
  1095 {
       
  1096     return 0;
       
  1097 }
       
  1098 
       
  1099 void RenderTable::updateFirstLetter()
       
  1100 {
       
  1101 }
       
  1102 
       
  1103 int RenderTable::firstLineBoxBaseline() const
       
  1104 {
       
  1105     RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
       
  1106     if (firstNonEmptySection && !firstNonEmptySection->numRows())
       
  1107         firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
       
  1108 
       
  1109     if (!firstNonEmptySection)
       
  1110         return -1;
       
  1111 
       
  1112     return firstNonEmptySection->y() + firstNonEmptySection->firstLineBoxBaseline();
       
  1113 }
       
  1114 
       
  1115 IntRect RenderTable::overflowClipRect(int tx, int ty)
       
  1116 {
       
  1117     IntRect rect = RenderBlock::overflowClipRect(tx, ty);
       
  1118     
       
  1119     // If we have a caption, expand the clip to include the caption.
       
  1120     // FIXME: Technically this is wrong, but it's virtually impossible to fix this
       
  1121     // for real until captions have been re-written.
       
  1122     // FIXME: This code assumes (like all our other caption code) that only top/bottom are
       
  1123     // supported.  When we actually support left/right and stop mapping them to top/bottom,
       
  1124     // we might have to hack this code first (depending on what order we do these bug fixes in).
       
  1125     if (m_caption) {
       
  1126         rect.setHeight(height());
       
  1127         rect.setY(ty);
       
  1128     }
       
  1129 
       
  1130     return rect;
       
  1131 }
       
  1132 
       
  1133 bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction action)
       
  1134 {
       
  1135     tx += x();
       
  1136     ty += y();
       
  1137 
       
  1138     // Check kids first.
       
  1139     if (!hasOverflowClip() || overflowClipRect(tx, ty).intersects(result.rectFromPoint(xPos, yPos))) {
       
  1140         for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
       
  1141             if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption) &&
       
  1142                 child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
       
  1143                 updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
       
  1144                 return true;
       
  1145             }
       
  1146         }
       
  1147     }
       
  1148 
       
  1149     // Check our bounds next.
       
  1150     IntRect boundsRect = IntRect(tx, ty, width(), height());
       
  1151     if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && boundsRect.intersects(result.rectFromPoint(xPos, yPos))) {
       
  1152         updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
       
  1153         if (!result.addNodeToRectBasedTestResult(node(), xPos, yPos, boundsRect))
       
  1154             return true;
       
  1155     }
       
  1156 
       
  1157     return false;
       
  1158 }
       
  1159 
       
  1160 }