2011-06-06 Emil A Eklund <eae@chromium.org>
[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     int availableLogicalWidth = containingBlockLogicalWidthForContent();
219     bool hasPerpendicularContainingBlock = cb->style()->isHorizontalWritingMode() != style()->isHorizontalWritingMode();
220     int 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         int 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         int availableContentLogicalWidth = max(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, IntSize(x(), y()), style()->isFlippedBlocksWritingMode());
278
279     setLogicalHeight(0);
280     m_overflow.clear();
281
282     initMaxMarginValues();
283     
284     int 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     int totalSectionLogicalHeight = 0;
300     int 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     int 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     int borderAndPaddingBefore = borderBefore() + (collapsing ? 0 : paddingBefore());
338     int borderAndPaddingAfter = borderAfter() + (collapsing ? 0 : paddingAfter());
339
340     setLogicalHeight(logicalHeight() + borderAndPaddingBefore);
341
342     if (!isPositioned())
343         computeLogicalHeight();
344
345     Length logicalHeightLength = style()->logicalHeight();
346     int 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(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(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     int 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(IntPoint(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(IntRect(minXVisualOverflow(), movedSectionLogicalTop, maxXVisualOverflow() - minXVisualOverflow(), maxYVisualOverflow() - movedSectionLogicalTop));
409         else
410             repaintRectangle(IntRect(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, int tx, int ty)
455 {
456     tx += x();
457     ty += y();
458
459     PaintPhase paintPhase = paintInfo.phase;
460
461     if (!isRoot()) {
462         IntRect overflowBox = visualOverflowRect();
463         flipForWritingMode(overflowBox);
464         overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
465         overflowBox.move(tx, ty);
466         if (!overflowBox.intersects(paintInfo.rect))
467             return;
468     }
469
470     bool pushedClip = pushContentsClip(paintInfo, tx, ty);    
471     paintObject(paintInfo, IntPoint(tx, ty));
472     if (pushedClip)
473         popContentsClip(paintInfo, paintPhase, IntPoint(tx, ty));
474 }
475
476 void RenderTable::paintObject(PaintInfo& paintInfo, const IntPoint& paintOffset)
477 {
478     PaintPhase paintPhase = paintInfo.phase;
479     if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style()->visibility() == VISIBLE)
480         paintBoxDecorations(paintInfo, paintOffset);
481
482     if (paintPhase == PaintPhaseMask) {
483         paintMask(paintInfo, paintOffset);
484         return;
485     }
486
487     // We're done.  We don't bother painting any children.
488     if (paintPhase == PaintPhaseBlockBackground)
489         return;
490     
491     // We don't paint our own background, but we do let the kids paint their backgrounds.
492     if (paintPhase == PaintPhaseChildBlockBackgrounds)
493         paintPhase = PaintPhaseChildBlockBackground;
494
495     PaintInfo info(paintInfo);
496     info.phase = paintPhase;
497     info.updatePaintingRootForChildren(this);
498
499     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
500         if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption)) {
501             IntPoint childPoint = flipForWritingMode(toRenderBox(child), paintOffset, ParentToChildFlippingAdjustment);
502             child->paint(info, childPoint.x(), childPoint.y());
503         }
504     }
505     
506     if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
507         // Collect all the unique border styles that we want to paint in a sorted list.  Once we
508         // have all the styles sorted, we then do individual passes, painting each style of border
509         // from lowest precedence to highest precedence.
510         info.phase = PaintPhaseCollapsedTableBorders;
511         RenderTableCell::CollapsedBorderStyles borderStyles;
512         RenderObject* stop = nextInPreOrderAfterChildren();
513         for (RenderObject* o = firstChild(); o && o != stop; o = o->nextInPreOrder()) {
514             if (o->isTableCell())
515                 toRenderTableCell(o)->collectBorderStyles(borderStyles);
516         }
517         RenderTableCell::sortBorderStyles(borderStyles);
518         size_t count = borderStyles.size();
519         for (size_t i = 0; i < count; ++i) {
520             m_currentBorder = &borderStyles[i];
521             for (RenderObject* child = firstChild(); child; child = child->nextSibling())
522                 if (child->isTableSection()) {
523                     IntPoint childPoint = flipForWritingMode(toRenderTableSection(child), paintOffset, ParentToChildFlippingAdjustment);
524                     child->paint(info, childPoint.x(), childPoint.y());
525                 }
526         }
527         m_currentBorder = 0;
528     }
529
530     // Paint outline.
531     if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
532         paintOutline(paintInfo.context, IntRect(paintOffset, size()));
533 }
534
535 void RenderTable::subtractCaptionRect(IntRect& rect) const
536 {
537     if (!m_caption)
538         return;
539
540     int captionLogicalHeight = m_caption->logicalHeight() + m_caption->marginBefore() + m_caption->marginAfter();
541     bool captionIsBefore = (m_caption->style()->captionSide() != CAPBOTTOM) ^ style()->isFlippedBlocksWritingMode();
542     if (style()->isHorizontalWritingMode()) {
543         rect.setHeight(rect.height() - captionLogicalHeight);
544         if (captionIsBefore)
545             rect.move(0, captionLogicalHeight);
546     } else {
547         rect.setWidth(rect.width() - captionLogicalHeight);
548         if (captionIsBefore)
549             rect.move(captionLogicalHeight, 0);
550     }
551 }
552
553 void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, const IntPoint& paintOffset)
554 {
555     if (!paintInfo.shouldPaintWithinRoot(this))
556         return;
557
558     IntRect rect(paintOffset, size());
559     subtractCaptionRect(rect);
560
561     paintBoxShadow(paintInfo.context, rect, style(), Normal);
562     
563     if (isRoot())
564         paintRootBoxFillLayers(paintInfo);
565     else if (!isBody() || document()->documentElement()->renderer()->hasBackground())
566         // The <body> only paints its background if the root element has defined a background
567         // independent of the body.
568         paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), rect);
569
570     paintBoxShadow(paintInfo.context, rect, style(), Inset);
571
572     if (style()->hasBorder() && !collapseBorders())
573         paintBorder(paintInfo.context, rect, style());
574 }
575
576 void RenderTable::paintMask(PaintInfo& paintInfo, const IntPoint& paintOffset)
577 {
578     if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
579         return;
580
581     IntRect rect(paintOffset, size());
582     subtractCaptionRect(rect);
583
584     paintMaskImages(paintInfo, rect);
585 }
586
587 void RenderTable::computePreferredLogicalWidths()
588 {
589     ASSERT(preferredLogicalWidthsDirty());
590
591     recalcSectionsIfNeeded();
592     recalcBordersInRowDirection();
593
594     m_tableLayout->computePreferredLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
595
596     if (m_caption)
597         m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_caption->minPreferredLogicalWidth());
598
599     setPreferredLogicalWidthsDirty(false);
600 }
601
602 void RenderTable::splitColumn(int pos, int firstSpan)
603 {
604     // we need to add a new columnStruct
605     int oldSize = m_columns.size();
606     m_columns.grow(oldSize + 1);
607     int oldSpan = m_columns[pos].span;
608     ASSERT(oldSpan > firstSpan);
609     m_columns[pos].span = firstSpan;
610     memmove(m_columns.data() + pos + 1, m_columns.data() + pos, (oldSize - pos) * sizeof(ColumnStruct));
611     m_columns[pos + 1].span = oldSpan - firstSpan;
612
613     // change width of all rows.
614     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
615         if (child->isTableSection())
616             toRenderTableSection(child)->splitColumn(pos, firstSpan);
617     }
618
619     m_columnPos.grow(numEffCols() + 1);
620     setNeedsLayoutAndPrefWidthsRecalc();
621 }
622
623 void RenderTable::appendColumn(int span)
624 {
625     // easy case.
626     int pos = m_columns.size();
627     int newSize = pos + 1;
628     m_columns.grow(newSize);
629     m_columns[pos].span = span;
630
631     // change width of all rows.
632     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
633         if (child->isTableSection())
634             toRenderTableSection(child)->appendColumn(pos);
635     }
636
637     m_columnPos.grow(numEffCols() + 1);
638     setNeedsLayoutAndPrefWidthsRecalc();
639 }
640
641 RenderTableCol* RenderTable::nextColElement(RenderTableCol* current) const
642 {
643     RenderObject* next = current->firstChild();
644     if (!next)
645         next = current->nextSibling();
646     if (!next && current->parent()->isTableCol())
647         next = current->parent()->nextSibling();
648
649     while (next) {
650         if (next->isTableCol())
651             return toRenderTableCol(next);
652         if (next != m_caption)
653             return 0;
654         next = next->nextSibling();
655     }
656     
657     return 0;
658 }
659
660 RenderTableCol* RenderTable::colElement(int col, bool* startEdge, bool* endEdge) const
661 {
662     if (!m_hasColElements)
663         return 0;
664     RenderObject* child = firstChild();
665     int cCol = 0;
666
667     while (child) {
668         if (child->isTableCol())
669             break;
670         if (child != m_caption)
671             return 0;
672         child = child->nextSibling();
673     }
674     if (!child)
675         return 0;
676
677     RenderTableCol* colElem = toRenderTableCol(child);
678     while (colElem) {
679         int span = colElem->span();
680         if (!colElem->firstChild()) {
681             int startCol = cCol;
682             int endCol = cCol + span - 1;
683             cCol += span;
684             if (cCol > col) {
685                 if (startEdge)
686                     *startEdge = startCol == col;
687                 if (endEdge)
688                     *endEdge = endCol == col;
689                 return colElem;
690             }
691         }
692         colElem = nextColElement(colElem);
693     }
694
695     return 0;
696 }
697
698 void RenderTable::recalcCaption(RenderBlock* caption) const
699 {
700     if (!m_caption) {
701         m_caption = caption;
702         m_caption->setNeedsLayout(true);
703     } else {
704         // Make sure to null out the child's renderer.
705         if (Node* node = caption->node())
706             node->setRenderer(0);
707
708         // Destroy the child now.
709         caption->destroy();
710     }
711 }
712
713 void RenderTable::recalcSections() const
714 {
715     m_caption = 0;
716     m_head = 0;
717     m_foot = 0;
718     m_firstBody = 0;
719     m_hasColElements = false;
720
721     // We need to get valid pointers to caption, head, foot and first body again
722     RenderObject* nextSibling;
723     for (RenderObject* child = firstChild(); child; child = nextSibling) {
724         nextSibling = child->nextSibling();
725         switch (child->style()->display()) {
726             case TABLE_CAPTION:
727                 if (child->isRenderBlock())
728                     recalcCaption(toRenderBlock(child));
729                 break;
730             case TABLE_COLUMN:
731             case TABLE_COLUMN_GROUP:
732                 m_hasColElements = true;
733                 break;
734             case TABLE_HEADER_GROUP:
735                 if (child->isTableSection()) {
736                     RenderTableSection* section = toRenderTableSection(child);
737                     if (!m_head)
738                         m_head = section;
739                     else if (!m_firstBody)
740                         m_firstBody = section;
741                     section->recalcCellsIfNeeded();
742                 }
743                 break;
744             case TABLE_FOOTER_GROUP:
745                 if (child->isTableSection()) {
746                     RenderTableSection* section = toRenderTableSection(child);
747                     if (!m_foot)
748                         m_foot = section;
749                     else if (!m_firstBody)
750                         m_firstBody = section;
751                     section->recalcCellsIfNeeded();
752                 }
753                 break;
754             case TABLE_ROW_GROUP:
755                 if (child->isTableSection()) {
756                     RenderTableSection* section = toRenderTableSection(child);
757                     if (!m_firstBody)
758                         m_firstBody = section;
759                     section->recalcCellsIfNeeded();
760                 }
761                 break;
762             default:
763                 break;
764         }
765     }
766
767     // repair column count (addChild can grow it too much, because it always adds elements to the last row of a section)
768     int maxCols = 0;
769     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
770         if (child->isTableSection()) {
771             RenderTableSection* section = toRenderTableSection(child);
772             int sectionCols = section->numColumns();
773             if (sectionCols > maxCols)
774                 maxCols = sectionCols;
775         }
776     }
777     
778     m_columns.resize(maxCols);
779     m_columnPos.resize(maxCols + 1);
780
781     ASSERT(selfNeedsLayout());
782
783     m_needsSectionRecalc = false;
784 }
785
786 int RenderTable::calcBorderStart() const
787 {
788     if (collapseBorders()) {
789         // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2.
790         if (!numEffCols())
791             return 0;
792
793         unsigned borderWidth = 0;
794
795         const BorderValue& tb = style()->borderStart();
796         if (tb.style() == BHIDDEN)
797             return 0;
798         if (tb.style() > BHIDDEN)
799             borderWidth = tb.width();
800
801         if (RenderTableCol* colGroup = colElement(0)) {
802             const BorderValue& gb = colGroup->style()->borderStart();
803             if (gb.style() == BHIDDEN)
804                 return 0;
805             if (gb.style() > BHIDDEN)
806                 borderWidth = max(borderWidth, static_cast<unsigned>(gb.width()));
807         }
808         
809         RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
810         if (firstNonEmptySection && !firstNonEmptySection->numRows())
811             firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
812         
813         if (firstNonEmptySection) {
814             const BorderValue& sb = firstNonEmptySection->style()->borderStart();
815             if (sb.style() == BHIDDEN)
816                 return 0;
817
818             if (sb.style() > BHIDDEN)
819                 borderWidth = max(borderWidth, static_cast<unsigned>(sb.width()));
820
821             const RenderTableSection::CellStruct& cs = firstNonEmptySection->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(borderWidth, static_cast<unsigned>(cb.width()));
834                 if (rb.style() > BHIDDEN)
835                     borderWidth = max(borderWidth, static_cast<unsigned>(rb.width()));
836             }
837         }
838         return (borderWidth + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
839     }
840     return RenderBlock::borderStart();
841 }
842
843 int 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         unsigned 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(borderWidth, static_cast<unsigned>(gb.width()));
865         }
866         
867         RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
868         if (firstNonEmptySection && !firstNonEmptySection->numRows())
869             firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
870         
871         if (firstNonEmptySection) {
872             const BorderValue& sb = firstNonEmptySection->style()->borderEnd();
873             if (sb.style() == BHIDDEN)
874                 return 0;
875
876             if (sb.style() > BHIDDEN)
877                 borderWidth = max(borderWidth, static_cast<unsigned>(sb.width()));
878
879             const RenderTableSection::CellStruct& cs = firstNonEmptySection->cellAt(0, endColumn);
880             
881             if (cs.hasCells()) {
882                 const BorderValue& cb = cs.primaryCell()->style()->borderEnd(); // FIXME: Make this work with perpendicular and flipped cells.
883                 if (cb.style() == BHIDDEN)
884                     return 0;
885
886                 const BorderValue& rb = cs.primaryCell()->parent()->style()->borderEnd();
887                 if (rb.style() == BHIDDEN)
888                     return 0;
889
890                 if (cb.style() > BHIDDEN)
891                     borderWidth = max(borderWidth, static_cast<unsigned>(cb.width()));
892                 if (rb.style() > BHIDDEN)
893                     borderWidth = max(borderWidth, static_cast<unsigned>(rb.width()));
894             }
895         }
896         return (borderWidth + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
897     }
898     return RenderBlock::borderEnd();
899 }
900
901 void RenderTable::recalcBordersInRowDirection()
902 {
903     m_borderStart = calcBorderStart();
904     m_borderEnd = calcBorderEnd();
905 }
906
907 int RenderTable::borderBefore() const
908 {
909     if (collapseBorders())
910         return outerBorderBefore();
911     return RenderBlock::borderBefore();
912 }
913
914 int RenderTable::borderAfter() const
915 {
916     if (collapseBorders())
917         return outerBorderAfter();
918     return RenderBlock::borderAfter();
919 }
920
921 int RenderTable::outerBorderBefore() const
922 {
923     if (!collapseBorders())
924         return 0;
925     int borderWidth = 0;
926     RenderTableSection* topSection;
927     if (m_head)
928         topSection = m_head;
929     else if (m_firstBody)
930         topSection = m_firstBody;
931     else if (m_foot)
932         topSection = m_foot;
933     else
934         topSection = 0;
935     if (topSection) {
936         borderWidth = topSection->outerBorderBefore();
937         if (borderWidth == -1)
938             return 0;   // Overridden by hidden
939     }
940     const BorderValue& tb = style()->borderBefore();
941     if (tb.style() == BHIDDEN)
942         return 0;
943     if (tb.style() > BHIDDEN)
944         borderWidth = max(borderWidth, static_cast<int>(tb.width() / 2));
945     return borderWidth;
946 }
947
948 int RenderTable::outerBorderAfter() const
949 {
950     if (!collapseBorders())
951         return 0;
952     int borderWidth = 0;
953     RenderTableSection* bottomSection;
954     if (m_foot)
955         bottomSection = m_foot;
956     else {
957         RenderObject* child;
958         for (child = lastChild(); child && !child->isTableSection(); child = child->previousSibling()) { }
959         bottomSection = child ? toRenderTableSection(child) : 0;
960     }
961     if (bottomSection) {
962         borderWidth = bottomSection->outerBorderAfter();
963         if (borderWidth == -1)
964             return 0;   // Overridden by hidden
965     }
966     const BorderValue& tb = style()->borderAfter();
967     if (tb.style() == BHIDDEN)
968         return 0;
969     if (tb.style() > BHIDDEN)
970         borderWidth = max(borderWidth, static_cast<int>((tb.width() + 1) / 2));
971     return borderWidth;
972 }
973
974 int RenderTable::outerBorderStart() const
975 {
976     if (!collapseBorders())
977         return 0;
978
979     int borderWidth = 0;
980
981     const BorderValue& tb = style()->borderStart();
982     if (tb.style() == BHIDDEN)
983         return 0;
984     if (tb.style() > BHIDDEN)
985         borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
986
987     bool allHidden = true;
988     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
989         if (!child->isTableSection())
990             continue;
991         int sw = toRenderTableSection(child)->outerBorderStart();
992         if (sw == -1)
993             continue;
994         else
995             allHidden = false;
996         borderWidth = max(borderWidth, sw);
997     }
998     if (allHidden)
999         return 0;
1000
1001     return borderWidth;
1002 }
1003
1004 int RenderTable::outerBorderEnd() const
1005 {
1006     if (!collapseBorders())
1007         return 0;
1008
1009     int borderWidth = 0;
1010
1011     const BorderValue& tb = style()->borderEnd();
1012     if (tb.style() == BHIDDEN)
1013         return 0;
1014     if (tb.style() > BHIDDEN)
1015         borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
1016
1017     bool allHidden = true;
1018     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
1019         if (!child->isTableSection())
1020             continue;
1021         int sw = toRenderTableSection(child)->outerBorderEnd();
1022         if (sw == -1)
1023             continue;
1024         else
1025             allHidden = false;
1026         borderWidth = max(borderWidth, sw);
1027     }
1028     if (allHidden)
1029         return 0;
1030
1031     return borderWidth;
1032 }
1033
1034 RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section, bool skipEmptySections) const
1035 {
1036     recalcSectionsIfNeeded();
1037
1038     if (section == m_head)
1039         return 0;
1040
1041     RenderObject* prevSection = section == m_foot ? lastChild() : section->previousSibling();
1042     while (prevSection) {
1043         if (prevSection->isTableSection() && prevSection != m_head && prevSection != m_foot && (!skipEmptySections || toRenderTableSection(prevSection)->numRows()))
1044             break;
1045         prevSection = prevSection->previousSibling();
1046     }
1047     if (!prevSection && m_head && (!skipEmptySections || m_head->numRows()))
1048         prevSection = m_head;
1049     return toRenderTableSection(prevSection);
1050 }
1051
1052 RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, bool skipEmptySections) const
1053 {
1054     recalcSectionsIfNeeded();
1055
1056     if (section == m_foot)
1057         return 0;
1058
1059     RenderObject* nextSection = section == m_head ? firstChild() : section->nextSibling();
1060     while (nextSection) {
1061         if (nextSection->isTableSection() && nextSection != m_head && nextSection != m_foot && (!skipEmptySections || toRenderTableSection(nextSection)->numRows()))
1062             break;
1063         nextSection = nextSection->nextSibling();
1064     }
1065     if (!nextSection && m_foot && (!skipEmptySections || m_foot->numRows()))
1066         nextSection = m_foot;
1067     return toRenderTableSection(nextSection);
1068 }
1069
1070 RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
1071 {
1072     recalcSectionsIfNeeded();
1073
1074     // Find the section and row to look in
1075     int r = cell->row();
1076     RenderTableSection* section = 0;
1077     int rAbove = 0;
1078     if (r > 0) {
1079         // cell is not in the first row, so use the above row in its own section
1080         section = cell->section();
1081         rAbove = r - 1;
1082     } else {
1083         section = sectionAbove(cell->section(), true);
1084         if (section)
1085             rAbove = section->numRows() - 1;
1086     }
1087
1088     // Look up the cell in the section's grid, which requires effective col index
1089     if (section) {
1090         int effCol = colToEffCol(cell->col());
1091         RenderTableSection::CellStruct& aboveCell = section->cellAt(rAbove, effCol);
1092         return aboveCell.primaryCell();
1093     } else
1094         return 0;
1095 }
1096
1097 RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
1098 {
1099     recalcSectionsIfNeeded();
1100
1101     // Find the section and row to look in
1102     int r = cell->row() + cell->rowSpan() - 1;
1103     RenderTableSection* section = 0;
1104     int rBelow = 0;
1105     if (r < cell->section()->numRows() - 1) {
1106         // The cell is not in the last row, so use the next row in the section.
1107         section = cell->section();
1108         rBelow = r + 1;
1109     } else {
1110         section = sectionBelow(cell->section(), true);
1111         if (section)
1112             rBelow = 0;
1113     }
1114
1115     // Look up the cell in the section's grid, which requires effective col index
1116     if (section) {
1117         int effCol = colToEffCol(cell->col());
1118         RenderTableSection::CellStruct& belowCell = section->cellAt(rBelow, effCol);
1119         return belowCell.primaryCell();
1120     } else
1121         return 0;
1122 }
1123
1124 RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
1125 {
1126     recalcSectionsIfNeeded();
1127
1128     RenderTableSection* section = cell->section();
1129     int effCol = colToEffCol(cell->col());
1130     if (!effCol)
1131         return 0;
1132     
1133     // If we hit a colspan back up to a real cell.
1134     RenderTableSection::CellStruct& prevCell = section->cellAt(cell->row(), effCol - 1);
1135     return prevCell.primaryCell();
1136 }
1137
1138 RenderTableCell* RenderTable::cellAfter(const RenderTableCell* cell) const
1139 {
1140     recalcSectionsIfNeeded();
1141
1142     int effCol = colToEffCol(cell->col() + cell->colSpan());
1143     if (effCol >= numEffCols())
1144         return 0;
1145     return cell->section()->primaryCellAt(cell->row(), effCol);
1146 }
1147
1148 RenderBlock* RenderTable::firstLineBlock() const
1149 {
1150     return 0;
1151 }
1152
1153 void RenderTable::updateFirstLetter()
1154 {
1155 }
1156
1157 int RenderTable::firstLineBoxBaseline() const
1158 {
1159     if (isWritingModeRoot())
1160         return -1;
1161
1162     recalcSectionsIfNeeded();
1163
1164     RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
1165     if (firstNonEmptySection && !firstNonEmptySection->numRows())
1166         firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
1167
1168     if (!firstNonEmptySection)
1169         return -1;
1170
1171     return firstNonEmptySection->logicalTop() + firstNonEmptySection->firstLineBoxBaseline();
1172 }
1173
1174 IntRect RenderTable::overflowClipRect(const IntPoint& location, OverlayScrollbarSizeRelevancy relevancy)
1175 {
1176     IntRect rect = RenderBlock::overflowClipRect(location, relevancy);
1177     
1178     // If we have a caption, expand the clip to include the caption.
1179     // FIXME: Technically this is wrong, but it's virtually impossible to fix this
1180     // for real until captions have been re-written.
1181     // FIXME: This code assumes (like all our other caption code) that only top/bottom are
1182     // supported.  When we actually support left/right and stop mapping them to top/bottom,
1183     // we might have to hack this code first (depending on what order we do these bug fixes in).
1184     if (m_caption) {
1185         if (style()->isHorizontalWritingMode()) {
1186             rect.setHeight(height());
1187             rect.setY(location.y());
1188         } else {
1189             rect.setWidth(width());
1190             rect.setX(location.x());
1191         }
1192     }
1193
1194     return rect;
1195 }
1196
1197 bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const IntPoint& pointInContainer, int tx, int ty, HitTestAction action)
1198 {
1199     tx += x();
1200     ty += y();
1201
1202     // Check kids first.
1203     if (!hasOverflowClip() || overflowClipRect(IntPoint(tx, ty)).intersects(result.rectForPoint(pointInContainer))) {
1204         for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
1205             if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption)) {
1206                 IntPoint childPoint = flipForWritingMode(toRenderBox(child), IntPoint(tx, ty), ParentToChildFlippingAdjustment);
1207                 if (child->nodeAtPoint(request, result, pointInContainer, childPoint.x(), childPoint.y(), action)) {
1208                     updateHitTestResult(result, toPoint(pointInContainer - childPoint));
1209                     return true;
1210                 }
1211             }
1212         }
1213     }
1214
1215     // Check our bounds next.
1216     IntRect boundsRect = IntRect(tx, ty, width(), height());
1217     if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && boundsRect.intersects(result.rectForPoint(pointInContainer))) {
1218         updateHitTestResult(result, flipForWritingMode(pointInContainer - IntSize(tx, ty)));
1219         if (!result.addNodeToRectBasedTestResult(node(), pointInContainer, boundsRect))
1220             return true;
1221     }
1222
1223     return false;
1224 }
1225
1226 }