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