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