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