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