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