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