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