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