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