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