Fix for 7837, make opacity work with table rows. Make transparent backgrounds
[WebKit-https.git] / WebCore / rendering / render_layer.cpp
1 /*
2  * Copyright (C) 2003 Apple Computer, Inc.
3  *
4  * Portions are Copyright (C) 1998 Netscape Communications Corporation.
5  *
6  * Other contributors:
7  *   Robert O'Callahan <roc+@cs.cmu.edu>
8  *   David Baron <dbaron@fas.harvard.edu>
9  *   Christian Biesinger <cbiesinger@web.de>
10  *   Randall Jesup <rjesup@wgate.com>
11  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
12  *   Josh Soref <timeless@mac.com>
13  *   Boris Zbarsky <bzbarsky@mit.edu>
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation; either
18  * version 2.1 of the License, or (at your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  *
29  * Alternatively, the contents of this file may be used under the terms
30  * of either the Mozilla Public License Version 1.1, found at
31  * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
32  * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
33  * (the "GPL"), in which case the provisions of the MPL or the GPL are
34  * applicable instead of those above.  If you wish to allow use of your
35  * version of this file only under the terms of one of those two
36  * licenses (the MPL or the GPL) and not to allow others to use your
37  * version of this file under the LGPL, indicate your decision by
38  * deletingthe provisions above and replace them with the notice and
39  * other provisions required by the MPL or the GPL, as the case may be.
40  * If you do not delete the provisions above, a recipient may use your
41  * version of this file under any of the LGPL, the MPL or the GPL.
42  */
43
44 #include "config.h"
45 #include "render_layer.h"
46
47 #include "DocumentImpl.h"
48 #include "EventNames.h"
49 #include "FrameView.h"
50 #include "Frame.h"
51 #include "GraphicsContext.h"
52 #include "dom2_eventsimpl.h"
53 #include "html_blockimpl.h"
54 #include "htmlnames.h"
55 #include "render_arena.h"
56 #include "render_canvas.h"
57 #include "render_inline.h"
58 #include "render_theme.h"
59 #include "SelectionController.h"
60 #include <assert.h>
61 #include <kxmlcore/Vector.h>
62 #include <qscrollbar.h>
63
64 #if SVG_SUPPORT
65 #include "SVGNames.h"
66 #endif
67
68 // These match the numbers we use over in WebKit (WebFrameView.m).
69 #define LINE_STEP   40
70 #define PAGE_KEEP   40
71
72 #define MIN_INTERSECT_FOR_REVEAL 32
73
74 namespace WebCore {
75
76 using namespace EventNames;
77 using namespace HTMLNames;
78
79 QScrollBar* RenderLayer::gScrollBar = 0;
80
81 #ifndef NDEBUG
82 static bool inRenderLayerDestroy;
83 #endif
84
85 const RenderLayer::ScrollAlignment RenderLayer::gAlignCenterIfNeeded = { RenderLayer::noScroll, RenderLayer::alignCenter, RenderLayer::alignToClosestEdge };
86 const RenderLayer::ScrollAlignment RenderLayer::gAlignToEdgeIfNeeded = { RenderLayer::noScroll, RenderLayer::alignToClosestEdge, RenderLayer::alignToClosestEdge };
87 const RenderLayer::ScrollAlignment RenderLayer::gAlignCenterAlways = { RenderLayer::alignCenter, RenderLayer::alignCenter, RenderLayer::alignCenter };
88 const RenderLayer::ScrollAlignment RenderLayer::gAlignTopAlways = { RenderLayer::alignTop, RenderLayer::alignTop, RenderLayer::alignTop };
89 const RenderLayer::ScrollAlignment RenderLayer::gAlignBottomAlways = { RenderLayer::alignBottom, RenderLayer::alignBottom, RenderLayer::alignBottom };
90
91 void* ClipRects::operator new(size_t sz, RenderArena* renderArena) throw()
92 {
93     return renderArena->allocate(sz);
94 }
95
96 void ClipRects::operator delete(void* ptr, size_t sz)
97 {
98     // Stash size where destroy can find it.
99     *(size_t *)ptr = sz;
100 }
101
102 void ClipRects::destroy(RenderArena* renderArena)
103 {
104     delete this;
105     
106     // Recover the size left there for us by operator delete and free the memory.
107     renderArena->free(*(size_t *)this, this);
108 }
109
110 RenderLayer::RenderLayer(RenderObject* object)
111 : m_object(object),
112 m_parent(0),
113 m_previous(0),
114 m_next(0),
115 m_first(0),
116 m_last(0),
117 m_relX(0),
118 m_relY(0),
119 m_x(0),
120 m_y(0),
121 m_width(0),
122 m_height(0),
123 m_scrollX(0),
124 m_scrollY(0),
125 m_scrollOriginX(0),
126 m_scrollLeftOverflow(0),
127 m_scrollWidth(0),
128 m_scrollHeight(0),
129 m_hBar(0),
130 m_vBar(0),
131 m_posZOrderList(0),
132 m_negZOrderList(0),
133 m_clipRects(0) ,
134 m_scrollDimensionsDirty(true),
135 m_zOrderListsDirty(true),
136 m_usedTransparency(false),
137 m_inOverflowRelayout(false),
138 m_marquee(0)
139 {
140 }
141
142 RenderLayer::~RenderLayer()
143 {
144     // Child layers will be deleted by their corresponding render objects, so
145     // our destructor doesn't have to do anything.
146     delete m_hBar;
147     delete m_vBar;
148     delete m_posZOrderList;
149     delete m_negZOrderList;
150     delete m_marquee;
151     
152     // Make sure we have no lingering clip rects.
153     assert(!m_clipRects);
154 }
155
156 void RenderLayer::computeRepaintRects()
157 {
158     // FIXME: Child object could override visibility.
159     if (m_object->style()->visibility() == VISIBLE) {
160         m_object->getAbsoluteRepaintRectIncludingFloats(m_repaintRect, m_fullRepaintRect);
161         m_object->absolutePosition(m_repaintX, m_repaintY);
162     }
163     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
164         child->computeRepaintRects();
165 }
166
167 void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
168 {
169     if (doFullRepaint) {
170         m_object->repaint();
171         checkForRepaint = doFullRepaint = false;
172     }
173     
174     updateLayerPosition(); // For relpositioned layers or non-positioned layers,
175                            // we need to keep in sync, since we may have shifted relative
176                            // to our parent layer.
177
178     if (m_hBar || m_vBar) {
179         // Need to position the scrollbars.
180         int x = 0;
181         int y = 0;
182         convertToLayerCoords(root(), x, y);
183         IntRect layerBounds = IntRect(x,y,width(),height());
184         positionScrollbars(layerBounds);
185     }
186
187     // FIXME: Child object could override visibility.
188     if (checkForRepaint && (m_object->style()->visibility() == VISIBLE)) {
189         int x, y;
190         m_object->absolutePosition(x, y);
191         if (x == m_repaintX && y == m_repaintY)
192             m_object->repaintAfterLayoutIfNeeded(m_repaintRect, m_fullRepaintRect);
193         else {
194             RenderCanvas *c = m_object->canvas();
195             if (c && !c->printingMode()) {
196                 c->repaintViewRectangle(m_fullRepaintRect);
197                 IntRect newRect, newFullRect;
198                 m_object->getAbsoluteRepaintRectIncludingFloats(newRect, newFullRect);
199                 if (newRect != m_repaintRect)
200                     c->repaintViewRectangle(newFullRect);
201             }
202         }
203     }
204     
205     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
206         child->updateLayerPositions(doFullRepaint, checkForRepaint);
207         
208     // With all our children positioned, now update our marquee if we need to.
209     if (m_marquee)
210         m_marquee->updateMarqueePosition();
211 }
212
213 void RenderLayer::updateLayerPosition()
214 {
215     // Clear our cached clip rect information.
216     clearClipRect();
217
218     // The canvas is sized to the docWidth/Height over in RenderCanvas::layout, so we
219     // don't need to ever update our layer position here.
220     if (renderer()->isCanvas())
221         return;
222     
223     int x = m_object->xPos();
224     int y = m_object->yPos() - m_object->borderTopExtra();
225
226     if (!m_object->isPositioned()) {
227         // We must adjust our position by walking up the render tree looking for the
228         // nearest enclosing object with a layer.
229         RenderObject* curr = m_object->parent();
230         while (curr && !curr->layer()) {
231             if (!curr->isTableRow()) {
232                 // Rows and cells share the same coordinate space (that of the section).
233                 // Omit them when computing our xpos/ypos.
234                 x += curr->xPos();
235                 y += curr->yPos();
236             }
237             curr = curr->parent();
238         }
239         y += curr->borderTopExtra();
240         if (curr->isTableRow()) {
241             // Put ourselves into the row coordinate space.
242             x -= curr->xPos();
243             y -= curr->yPos();
244         }
245     }
246
247     m_relX = m_relY = 0;
248     if (m_object->isRelPositioned()) {
249         static_cast<RenderBox*>(m_object)->relativePositionOffset(m_relX, m_relY);
250         x += m_relX; y += m_relY;
251     }
252     
253     // Subtract our parent's scroll offset.
254     if (m_object->isPositioned() && enclosingPositionedAncestor()) {
255         RenderLayer* positionedParent = enclosingPositionedAncestor();
256
257         // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
258         positionedParent->subtractScrollOffset(x, y);
259         
260         if (m_object->isPositioned() && positionedParent->renderer()->isRelPositioned() &&
261             positionedParent->renderer()->isInlineFlow()) {
262             // When we have an enclosing relpositioned inline, we need to add in the offset of the first line
263             // box from the rest of the content, but only in the cases where we know we're positioned
264             // relative to the inline itself.
265             RenderFlow* flow = static_cast<RenderFlow*>(positionedParent->renderer());
266             int sx = 0, sy = 0;
267             if (flow->firstLineBox()) {
268                 sx = flow->firstLineBox()->xPos();
269                 sy = flow->firstLineBox()->yPos();
270             }
271             else {
272                 sx = flow->staticX();
273                 sy = flow->staticY();
274             }
275             bool isInlineType = m_object->style()->isOriginalDisplayInlineType();
276             
277             if (!m_object->hasStaticX())
278                 x += sx;
279             
280             // This is not terribly intuitive, but we have to match other browsers.  Despite being a block display type inside
281             // an inline, we still keep our x locked to the left of the relative positioned inline.  Arguably the correct
282             // behavior would be to go flush left to the block that contains the inline, but that isn't what other browsers
283             // do.
284             if (m_object->hasStaticX() && !isInlineType)
285                 // Avoid adding in the left border/padding of the containing block twice.  Subtract it out.
286                 x += sx - (m_object->containingBlock()->borderLeft() + m_object->containingBlock()->paddingLeft());
287             
288             if (!m_object->hasStaticY())
289                 y += sy;
290         }
291     }
292     else if (parent())
293         parent()->subtractScrollOffset(x, y);
294     
295     setPos(x,y);
296
297     setWidth(m_object->width());
298     setHeight(m_object->height() + m_object->borderTopExtra() + m_object->borderBottomExtra());
299
300     if (!m_object->hasOverflowClip()) {
301         if (m_object->overflowWidth() > m_object->width())
302             setWidth(m_object->overflowWidth());
303         if (m_object->overflowHeight() > m_object->height())
304             setHeight(m_object->overflowHeight());
305     }    
306 }
307
308 RenderLayer *RenderLayer::stackingContext() const
309 {
310     RenderLayer* curr = parent();
311     for ( ; curr && !curr->m_object->isCanvas() && !curr->m_object->isRoot() &&
312           curr->m_object->style()->hasAutoZIndex();
313           curr = curr->parent());
314     return curr;
315 }
316
317 RenderLayer*
318 RenderLayer::enclosingPositionedAncestor() const
319 {
320     RenderLayer* curr = parent();
321     for ( ; curr && !curr->m_object->isCanvas() && !curr->m_object->isRoot() &&
322          !curr->m_object->isPositioned() && !curr->m_object->isRelPositioned();
323          curr = curr->parent());
324          
325     return curr;
326 }
327
328 bool
329 RenderLayer::isTransparent() const
330 {
331 #if SVG_SUPPORT
332     if (m_object->node()->namespaceURI() == KSVG::SVGNames::svgNamespaceURI)
333         return false;
334 #endif
335     return m_object->isTransparent();
336 }
337
338 RenderLayer*
339 RenderLayer::transparentAncestor()
340 {
341     RenderLayer* curr = parent();
342     for ( ; curr && !curr->isTransparent(); curr = curr->parent());
343     return curr;
344 }
345
346 static IntRect transparencyClipBox(RenderLayer* l)
347 {
348     // FIXME: Although this completely ignores clipping, we ultimately intersect with the
349     // paintDirtyRect, and that should cut down on the amount we have to paint.  Still it
350     // would be better to respect clips.
351     IntRect clipRect = l->absoluteBoundingBox();
352     
353     // Note: we don't have to walk z-order lists since transparent elements always establish
354     // a stacking context.  This means we can just walk the layer tree directly. 
355     for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) {
356         // Transparent children paint in a different transparency layer, and so we exclude them.
357         if (!curr->isTransparent())
358             clipRect.unite(curr->absoluteBoundingBox());
359     }
360     
361     return clipRect;
362 }
363
364 void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const IntRect& paintDirtyRect)
365 {
366     if (p->paintingDisabled() || (isTransparent() && m_usedTransparency))
367         return;
368     
369     RenderLayer* ancestor = transparentAncestor();
370     if (ancestor)
371         ancestor->beginTransparencyLayers(p, paintDirtyRect);
372     
373     if (isTransparent()) {
374         m_usedTransparency = true;
375         IntRect clipRect = transparencyClipBox(this);
376         clipRect.intersect(paintDirtyRect);
377         p->save();
378         p->addClip(clipRect);
379         p->beginTransparencyLayer(renderer()->opacity());
380     }
381 }
382
383 void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
384 {
385     return renderArena->allocate(sz);
386 }
387
388 void RenderLayer::operator delete(void* ptr, size_t sz)
389 {
390     assert(inRenderLayerDestroy);
391     
392     // Stash size where destroy can find it.
393     *(size_t *)ptr = sz;
394 }
395
396 void RenderLayer::destroy(RenderArena* renderArena)
397 {
398 #ifndef NDEBUG
399     inRenderLayerDestroy = true;
400 #endif
401     delete this;
402 #ifndef NDEBUG
403     inRenderLayerDestroy = false;
404 #endif
405     
406     // Recover the size left there for us by operator delete and free the memory.
407     renderArena->free(*(size_t *)this, this);
408 }
409
410 void RenderLayer::addChild(RenderLayer *child, RenderLayer* beforeChild)
411 {
412     RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
413     if (prevSibling) {
414         child->setPreviousSibling(prevSibling);
415         prevSibling->setNextSibling(child);
416     }
417     else
418         setFirstChild(child);
419
420     if (beforeChild) {
421         beforeChild->setPreviousSibling(child);
422         child->setNextSibling(beforeChild);
423     }
424     else
425         setLastChild(child);
426    
427     child->setParent(this);
428
429     // Dirty the z-order list in which we are contained.  The stackingContext() can be null in the
430     // case where we're building up generated content layers.  This is ok, since the lists will start
431     // off dirty in that case anyway.
432     RenderLayer* stackingContext = child->stackingContext();
433     if (stackingContext)
434         stackingContext->dirtyZOrderLists();
435 }
436
437 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
438 {
439     // remove the child
440     if (oldChild->previousSibling())
441         oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
442     if (oldChild->nextSibling())
443         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
444
445     if (m_first == oldChild)
446         m_first = oldChild->nextSibling();
447     if (m_last == oldChild)
448         m_last = oldChild->previousSibling();
449
450     // Dirty the z-order list in which we are contained.  When called via the
451     // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
452     // from the main layer tree, so we need to null-check the |stackingContext| value.
453     RenderLayer* stackingContext = oldChild->stackingContext();
454     if (stackingContext)
455         oldChild->stackingContext()->dirtyZOrderLists();
456     
457     oldChild->setPreviousSibling(0);
458     oldChild->setNextSibling(0);
459     oldChild->setParent(0);
460     
461     return oldChild;
462 }
463
464 void RenderLayer::removeOnlyThisLayer()
465 {
466     if (!m_parent)
467         return;
468     
469     // Dirty the clip rects.
470     clearClipRects();
471
472     // Remove us from the parent.
473     RenderLayer* parent = m_parent;
474     RenderLayer* nextSib = nextSibling();
475     parent->removeChild(this);
476     
477     // Now walk our kids and reattach them to our parent.
478     RenderLayer* current = m_first;
479     while (current) {
480         RenderLayer* next = current->nextSibling();
481         removeChild(current);
482         parent->addChild(current, nextSib);
483         current->updateLayerPositions();
484         current = next;
485     }
486     
487     destroy(renderer()->renderArena());
488 }
489
490 void RenderLayer::insertOnlyThisLayer()
491 {
492     if (!m_parent && renderer()->parent()) {
493         // We need to connect ourselves when our renderer() has a parent.
494         // Find our enclosingLayer and add ourselves.
495         RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
496         if (parentLayer)
497             parentLayer->addChild(this, 
498                                   renderer()->parent()->findNextLayer(parentLayer, renderer()));
499     }
500     
501     // Remove all descendant layers from the hierarchy and add them to the new position.
502     for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
503         curr->moveLayers(m_parent, this);
504         
505     // Clear out all the clip rects.
506     clearClipRects();
507 }
508
509 void 
510 RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const
511 {
512     if (ancestorLayer == this)
513         return;
514         
515     if (m_object->style()->position() == FixedPosition) {
516         // Add in the offset of the view.  We can obtain this by calling
517         // absolutePosition() on the RenderCanvas.
518         int xOff, yOff;
519         m_object->absolutePosition(xOff, yOff, true);
520         x += xOff;
521         y += yOff;
522         return;
523     }
524  
525     RenderLayer* parentLayer;
526     if (m_object->style()->position() == AbsolutePosition)
527         parentLayer = enclosingPositionedAncestor();
528     else
529         parentLayer = parent();
530     
531     if (!parentLayer) return;
532     
533     parentLayer->convertToLayerCoords(ancestorLayer, x, y);
534
535     x += xPos();
536     y += yPos();
537 }
538
539 void
540 RenderLayer::scrollOffset(int& x, int& y)
541 {
542     x += scrollXOffset() + m_scrollLeftOverflow;
543     y += scrollYOffset();
544 }
545
546 void
547 RenderLayer::subtractScrollOffset(int& x, int& y)
548 {
549     x -= scrollXOffset() + m_scrollLeftOverflow;
550     y -= scrollYOffset();
551 }
552
553 void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint)
554 {
555     if (renderer()->style()->overflow() != OMARQUEE) {
556         if (x < 0) x = 0;
557         if (y < 0) y = 0;
558     
559         // Call the scrollWidth/Height functions so that the dimensions will be computed if they need
560         // to be (for overflow:hidden blocks).
561         int maxX = scrollWidth() - m_object->clientWidth();
562         int maxY = scrollHeight() - m_object->clientHeight();
563         
564         if (x > maxX) x = maxX;
565         if (y > maxY) y = maxY;
566     }
567     
568     // FIXME: Eventually, we will want to perform a blit.  For now never
569     // blit, since the check for blitting is going to be very
570     // complicated (since it will involve testing whether our layer
571     // is either occluded by another layer or clipped by an enclosing
572     // layer or contains fixed backgrounds, etc.).
573     m_scrollX = x - m_scrollOriginX;
574     m_scrollY = y;
575
576     // Update the positions of our child layers.
577     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
578         child->updateLayerPositions(false, false);
579     
580     RenderCanvas *canvas = renderer()->canvas();
581     if (canvas) {
582 #if __APPLE__
583         // Update dashboard regions, scrolling may change the clip of a
584         // particular region.
585         canvas->view()->updateDashboardRegions();
586 #endif
587
588         m_object->canvas()->updateWidgetPositions();
589     }
590
591     // Just schedule a full repaint of our object.
592     if (repaint)
593         m_object->repaint();
594     
595     if (updateScrollbars) {
596         if (m_hBar)
597             m_hBar->setValue(scrollXOffset());
598         if (m_vBar)
599             m_vBar->setValue(m_scrollY);
600     }
601
602     // Fire the scroll DOM event.
603     m_object->element()->dispatchHTMLEvent(scrollEvent, true, false);
604 }
605
606 void RenderLayer::scrollRectToVisible(const IntRect &rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
607 {
608     RenderLayer* parentLayer = 0;
609     IntRect newRect = rect;
610     int xOffset = 0, yOffset = 0;
611     
612     if (m_object->hasOverflowClip()) {
613         IntRect layerBounds = IntRect(xPos() + scrollXOffset(), yPos() + scrollYOffset(), 
614                                       width() - verticalScrollbarWidth(), height() - horizontalScrollbarHeight());
615         IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());
616         IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);
617         
618         xOffset = r.x() - xPos();
619         yOffset = r.y() - yPos();
620         // Adjust offsets if they're outside of the allowable range.
621         xOffset = kMax(0, kMin(scrollWidth() - width(), xOffset));
622         yOffset = kMax(0, kMin(scrollHeight() - height(), yOffset));
623         
624         if (xOffset != scrollXOffset() || yOffset != scrollYOffset()) {
625             int diffX = scrollXOffset();
626             int diffY = scrollYOffset();
627             scrollToOffset(xOffset, yOffset);
628             // FIXME: At this point a scroll event fired, which could have deleted this layer.
629             // Need to handle this case.
630             diffX = scrollXOffset() - diffX;
631             diffY = scrollYOffset() - diffY;
632             newRect.setX(rect.x() - diffX);
633             newRect.setY(rect.y() - diffY);
634         }
635     
636         if (m_object->parent())
637             parentLayer = m_object->parent()->enclosingLayer();
638     } else {
639         FrameView* view = m_object->document()->view();
640         if (view) {
641             IntRect viewRect = IntRect(view->scrollXOffset(), view->scrollYOffset(), view->visibleWidth(), view->visibleHeight());
642             IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
643             
644             xOffset = r.x();
645             yOffset = r.y();
646             // Adjust offsets if they're outside of the allowable range.
647             xOffset = kMax(0, kMin(view->contentsWidth(), xOffset));
648             yOffset = kMax(0, kMin(view->contentsHeight(), yOffset));
649
650             if (m_object->document() && m_object->document()->ownerElement() && m_object->document()->ownerElement()->renderer()) {
651                 view->setContentsPos(xOffset, yOffset);
652                 parentLayer = m_object->document()->ownerElement()->renderer()->enclosingLayer();
653                 newRect.setX(rect.x() - view->contentsX() + view->x());
654                 newRect.setY(rect.y() - view->contentsY() + view->y());
655             } else {
656                 // If this is the outermost view that RenderLayer needs to scroll, then we should scroll the view recursively
657                 // Other apps, like Mail, rely on this feature.
658                 view->scrollPointRecursively(xOffset, yOffset);
659             }
660         }
661     }
662     
663     if (parentLayer)
664         parentLayer->scrollRectToVisible(newRect, alignX, alignY);
665 }
666
667 IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
668 {
669     // Determine the appropriate X behavior.
670     ScrollBehavior scrollX;
671     IntRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height());
672     int intersectWidth = intersection(visibleRect, exposeRectX).width();
673     if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL)
674         // If the rectangle is fully visible, use the specified visible behavior.
675         // If the rectangle is partially visible, but over a certain threshold,
676         // then treat it as fully visible to avoid unnecessary horizontal scrolling
677         scrollX = getVisibleBehavior(alignX);
678     else if (intersectWidth == visibleRect.width()) {
679         // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
680         scrollX = getVisibleBehavior(alignX);
681         if (scrollX == alignCenter)
682             scrollX = noScroll;
683     } else if (intersectWidth > 0)
684         // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior
685         scrollX = getPartialBehavior(alignX);
686     else
687         scrollX = getHiddenBehavior(alignX);
688     // If we're trying to align to the closest edge, and the exposeRect is further right
689     // than the visibleRect, and not bigger than the visible area, then align with the right.
690     if (scrollX == alignToClosestEdge && exposeRect.right() > visibleRect.right() && exposeRect.width() < visibleRect.width())
691         scrollX = alignRight;
692
693     // Given the X behavior, compute the X coordinate.
694     int x;
695     if (scrollX == noScroll) 
696         x = visibleRect.x();
697     else if (scrollX == alignRight)
698         x = exposeRect.right() - visibleRect.width();
699     else if (scrollX == alignCenter)
700         x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2;
701     else
702         x = exposeRect.x();
703
704     // Determine the appropriate Y behavior.
705     ScrollBehavior scrollY;
706     IntRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height());
707     int intersectHeight = intersection(visibleRect, exposeRectY).height();
708     if (intersectHeight == exposeRect.height())
709         // If the rectangle is fully visible, use the specified visible behavior.
710         scrollY = getVisibleBehavior(alignY);
711     else if (intersectHeight == visibleRect.height()) {
712         // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
713         scrollY = getVisibleBehavior(alignY);
714         if (scrollY == alignCenter)
715             scrollY = noScroll;
716     } else if (intersectHeight > 0)
717         // If the rectangle is partially visible, use the specified partial behavior
718         scrollY = getPartialBehavior(alignY);
719     else
720         scrollY = getHiddenBehavior(alignY);
721     // If we're trying to align to the closest edge, and the exposeRect is further down
722     // than the visibleRect, and not bigger than the visible area, then align with the bottom.
723     if (scrollY == alignToClosestEdge && exposeRect.bottom() > visibleRect.bottom() && exposeRect.height() < visibleRect.height())
724         scrollY = alignBottom;
725
726     // Given the Y behavior, compute the Y coordinate.
727     int y;
728     if (scrollY == noScroll) 
729         y = visibleRect.y();
730     else if (scrollY == alignBottom)
731         y = exposeRect.bottom() - visibleRect.height();
732     else if (scrollY == alignCenter)
733         y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2;
734     else
735         y = exposeRect.y();
736
737     return IntRect(IntPoint(x, y), visibleRect.size());
738 }
739
740 void RenderLayer::autoscroll()
741 {    
742     int xOffset = scrollXOffset();
743     int yOffset = scrollYOffset();
744
745     // Get the rectangle for the extent of the selection
746     SelectionController sel = renderer()->document()->frame()->selection();
747     IntRect extentRect = SelectionController(sel.extent(), sel.affinity()).caretRect();
748     extentRect.move(xOffset, yOffset);
749
750     IntRect bounds = IntRect(xPos() + xOffset, yPos() + yOffset, width() - verticalScrollbarWidth(), height() - horizontalScrollbarHeight());
751     
752     // Calculate how much the layer should scroll horizontally.
753     int diffX = 0;
754     if (extentRect.right() > bounds.right())
755         diffX = extentRect.right() - bounds.right();
756     else if (extentRect.x() < bounds.x())
757         diffX = extentRect.x() - bounds.x();
758         
759     // Calculate how much the layer should scroll vertically.
760     int diffY = 0;
761     if (extentRect.bottom() > bounds.bottom())
762         diffY = extentRect.bottom() - bounds.bottom();
763     else if (extentRect.y() < bounds.y())
764         diffY = extentRect.y() - bounds.y();
765
766     scrollToOffset(xOffset + diffX, yOffset + diffY);
767 }
768
769 bool RenderLayer::shouldAutoscroll()
770 {
771     if (renderer()->hasOverflowClip() && (m_object->style()->overflow() != OHIDDEN || renderer()->node()->isContentEditable()))
772         return true;
773     return false;
774 }
775
776 void RenderLayer::valueChanged(Widget*)
777 {
778     // Update scroll position from scroll bars.
779
780     bool needUpdate = false;
781     int newX = scrollXOffset();
782     int newY = m_scrollY;
783     
784     if (m_hBar) {
785         newX = m_hBar->value();
786         if (newX != scrollXOffset())
787            needUpdate = true;
788     }
789
790     if (m_vBar) {
791         newY = m_vBar->value();
792         if (newY != m_scrollY)
793            needUpdate = true;
794     }
795
796     if (needUpdate)
797         scrollToOffset(newX, newY, false);
798 }
799
800 void
801 RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
802 {
803     if (hasScrollbar && !m_hBar) {
804         FrameView* scrollView = m_object->element()->getDocument()->view();
805         m_hBar = new QScrollBar(HorizontalScrollBar);
806         m_hBar->setClient(this);
807         scrollView->addChild(m_hBar, 0, -50000);
808     } else if (!hasScrollbar && m_hBar) {
809         FrameView* scrollView = m_object->element()->getDocument()->view();
810         scrollView->removeChild(m_hBar);
811         delete m_hBar;
812         m_hBar = 0;
813     }
814 }
815
816 void
817 RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
818 {
819     if (hasScrollbar && !m_vBar) {
820         FrameView* scrollView = m_object->element()->getDocument()->view();
821         m_vBar = new QScrollBar(VerticalScrollBar);
822         m_vBar->setClient(this);
823         scrollView->addChild(m_vBar, 0, -50000);
824     } else if (!hasScrollbar && m_vBar) {
825         FrameView* scrollView = m_object->element()->getDocument()->view();
826         scrollView->removeChild(m_vBar);
827         delete m_vBar;
828         m_vBar = 0;
829     }
830 }
831
832 int
833 RenderLayer::verticalScrollbarWidth()
834 {
835     if (!m_vBar)
836         return 0;
837
838     return m_vBar->width();
839 }
840
841 int
842 RenderLayer::horizontalScrollbarHeight()
843 {
844     if (!m_hBar)
845         return 0;
846
847     return m_hBar->height();
848 }
849
850 void
851 RenderLayer::moveScrollbarsAside()
852 {
853     if (m_hBar)
854         m_hBar->move(0, -50000);
855     if (m_vBar)
856         m_vBar->move(0, -50000);
857 }
858
859 void
860 RenderLayer::positionScrollbars(const IntRect& absBounds)
861 {
862     if (m_vBar) {
863         m_vBar->move(absBounds.right() - m_object->borderRight() - m_vBar->width(),
864             absBounds.y() + m_object->borderTop());
865         m_vBar->resize(m_vBar->width(),
866             absBounds.height() - (m_object->borderTop() + m_object->borderBottom()) - (m_hBar ? m_hBar->height() - 1 : 0));
867     }
868
869     if (m_hBar) {
870         m_hBar->move(absBounds.x() + m_object->borderLeft(),
871             absBounds.bottom() - m_object->borderBottom() - m_hBar->height());
872         m_hBar->resize(absBounds.width() - (m_object->borderLeft() + m_object->borderRight()) - (m_vBar ? m_vBar->width() - 1 : 0),
873             m_hBar->height());
874     }
875 }
876
877 int RenderLayer::scrollWidth()
878 {
879     if (m_scrollDimensionsDirty)
880         computeScrollDimensions();
881     return m_scrollWidth;
882 }
883
884 int RenderLayer::scrollHeight()
885 {
886     if (m_scrollDimensionsDirty)
887         computeScrollDimensions();
888     return m_scrollHeight;
889 }
890
891 void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
892 {
893     m_scrollDimensionsDirty = false;
894     
895     bool ltr = m_object->style()->direction() == LTR;
896
897     int clientWidth = m_object->clientWidth();
898     int clientHeight = m_object->clientHeight();
899
900     m_scrollLeftOverflow = ltr ? 0 : kMin(0, m_object->leftmostPosition(true, false) - m_object->borderLeft());
901
902     int rightPos = ltr ?
903                     m_object->rightmostPosition(true, false) - m_object->borderLeft() :
904                     clientWidth - m_scrollLeftOverflow;
905     int bottomPos = m_object->lowestPosition(true, false) - m_object->borderTop();
906
907     m_scrollWidth = kMax(rightPos, clientWidth);
908     m_scrollHeight = kMax(bottomPos, clientHeight);
909     
910     m_scrollOriginX = ltr ? 0 : m_scrollWidth - clientWidth;
911
912     if (needHBar)
913         *needHBar = rightPos > clientWidth;
914     if (needVBar)
915         *needVBar = bottomPos > clientHeight;
916 }
917
918 void
919 RenderLayer::updateScrollInfoAfterLayout()
920 {
921     m_scrollDimensionsDirty = true;
922     if (m_object->style()->overflow() == OHIDDEN)
923         return; // All we had to do was dirty.
924
925     bool needHorizontalBar, needVerticalBar;
926     computeScrollDimensions(&needHorizontalBar, &needVerticalBar);
927
928     if (m_object->style()->overflow() != OMARQUEE) {
929         // Layout may cause us to be in an invalid scroll position.  In this case we need
930         // to pull our scroll offsets back to the max (or push them up to the min).
931         int newX = kMax(0, kMin(scrollXOffset(), scrollWidth() - m_object->clientWidth()));
932         int newY = kMax(0, kMin(m_scrollY, scrollHeight() - m_object->clientHeight()));
933         if (newX != scrollXOffset() || newY != m_scrollY)
934             scrollToOffset(newX, newY);
935         // FIXME: At this point a scroll event fired, which could have deleted this layer.
936         // Need to handle this case.
937     }
938
939     bool haveHorizontalBar = m_hBar;
940     bool haveVerticalBar = m_vBar;
941
942     // overflow:scroll should just enable/disable.
943     if (m_object->style()->overflow() == OSCROLL) {
944         m_hBar->setEnabled(needHorizontalBar);
945         m_vBar->setEnabled(needVerticalBar);
946     }
947
948     // overflow:auto may need to lay out again if scrollbars got added/removed.
949     bool scrollbarsChanged = (m_object->hasAutoScrollbars()) &&
950         (haveHorizontalBar != needHorizontalBar || haveVerticalBar != needVerticalBar);    
951     if (scrollbarsChanged) {
952         setHasHorizontalScrollbar(needHorizontalBar);
953         setHasVerticalScrollbar(needVerticalBar);
954     
955 #if __APPLE__
956         // Force an update since we know the scrollbars have changed things.
957         if (m_object->document()->hasDashboardRegions())
958             m_object->document()->setDashboardRegionsDirty(true);
959 #endif
960
961         m_object->repaint();
962
963         if (m_object->style()->overflow() == OAUTO) {
964             if (!m_inOverflowRelayout) {
965                 // Our proprietary overflow: overlay value doesn't trigger a layout.
966                 m_inOverflowRelayout = true;
967                 m_object->setNeedsLayout(true);
968                 if (m_object->isRenderBlock())
969                     static_cast<RenderBlock*>(m_object)->layoutBlock(true);
970                 else
971                     m_object->layout();
972                 m_inOverflowRelayout = false;
973             }
974         }
975     }
976
977     // Set up the range (and page step/line step).
978     if (m_hBar) {
979         int clientWidth = m_object->clientWidth();
980         int pageStep = (clientWidth-PAGE_KEEP);
981         if (pageStep < 0) pageStep = clientWidth;
982         m_hBar->setSteps(LINE_STEP, pageStep);
983         m_hBar->setKnobProportion(clientWidth, m_scrollWidth);
984         m_hBar->setValue(scrollXOffset());
985     }
986     if (m_vBar) {
987         int clientHeight = m_object->clientHeight();
988         int pageStep = (clientHeight-PAGE_KEEP);
989         if (pageStep < 0) pageStep = clientHeight;
990         m_vBar->setSteps(LINE_STEP, pageStep);
991         m_vBar->setKnobProportion(clientHeight, m_scrollHeight);
992         m_object->repaintRectangle(IntRect(m_object->borderLeft() + m_object->clientWidth(),
993                                    m_object->borderTop(), verticalScrollbarWidth(), 
994                                    m_object->height() - m_object->borderTop() - m_object->borderBottom()));
995     }
996  
997 #if __APPLE__
998     // Force an update since we know the scrollbars have changed things.
999     if (m_object->document()->hasDashboardRegions())
1000         m_object->document()->setDashboardRegionsDirty(true);
1001 #endif
1002
1003     m_object->repaint();
1004 }
1005
1006 void
1007 RenderLayer::paintScrollbars(GraphicsContext* p, const IntRect& damageRect)
1008 {
1009     // Move the widgets if necessary.  We normally move and resize widgets during layout, but sometimes
1010     // widgets can move without layout occurring (most notably when you scroll a document that
1011     // contains fixed positioned elements).
1012     if (m_hBar || m_vBar) {
1013         int x = 0;
1014         int y = 0;
1015         convertToLayerCoords(root(), x, y);
1016         IntRect layerBounds = IntRect(x, y, width(), height());
1017         positionScrollbars(layerBounds);
1018     }
1019
1020     // Now that we're sure the scrollbars are in the right place, paint them.
1021     if (m_hBar)
1022         m_hBar->paint(p, damageRect);
1023     if (m_vBar)
1024         m_vBar->paint(p, damageRect);
1025 }
1026
1027 bool RenderLayer::scroll(KWQScrollDirection direction, KWQScrollGranularity granularity, float multiplier)
1028 {
1029     bool didHorizontalScroll = false;
1030     bool didVerticalScroll = false;
1031     
1032     if (m_hBar != 0) {
1033         if (granularity == KWQScrollDocument) {
1034             // Special-case for the KWQScrollDocument granularity. A document scroll can only be up 
1035             // or down and in both cases the horizontal bar goes all the way to the left.
1036             didHorizontalScroll = m_hBar->scroll(KWQScrollLeft, KWQScrollDocument, multiplier);
1037         } else {
1038             didHorizontalScroll = m_hBar->scroll(direction, granularity, multiplier);
1039         }
1040     }
1041     if (m_vBar != 0) {
1042         didVerticalScroll = m_vBar->scroll(direction, granularity, multiplier);
1043     }
1044
1045     return (didHorizontalScroll || didVerticalScroll);
1046 }
1047
1048 void
1049 RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, bool selectionOnly, RenderObject *paintingRoot)
1050 {
1051     paintLayer(this, p, damageRect, false, selectionOnly, paintingRoot);
1052 }
1053
1054 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
1055 {
1056     if (paintDirtyRect == clipRect)
1057         return;
1058     p->save();
1059     p->addClip(clipRect);
1060 }
1061
1062 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
1063 {
1064     if (paintDirtyRect == clipRect)
1065         return;
1066     p->restore();
1067 }
1068
1069 void
1070 RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
1071                         const IntRect& paintDirtyRect, bool haveTransparency, bool selectionOnly,
1072                         RenderObject *paintingRoot)
1073 {
1074     // Calculate the clip rects we should use.
1075     IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
1076     calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
1077     int x = layerBounds.x();
1078     int y = layerBounds.y();
1079                              
1080     // Ensure our z-order lists are up-to-date.
1081     updateZOrderLists();
1082
1083     if (isTransparent())
1084         haveTransparency = true;
1085
1086     // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
1087     // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
1088     // Else, our renderer tree may or may not contain the painting root, so we pass that root along
1089     // so it will be tested against as we decend through the renderers.
1090     RenderObject *paintingRootForRenderer = 0;
1091     if (paintingRoot && !m_object->hasAncestor(paintingRoot))
1092         paintingRootForRenderer = paintingRoot;
1093     
1094     // We want to paint our layer, but only if we intersect the damage rect.
1095     bool shouldPaint = intersectsDamageRect(layerBounds, damageRect);
1096     if (shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
1097         // Begin transparency layers lazily now that we know we have to paint something.
1098         if (haveTransparency)
1099             beginTransparencyLayers(p, paintDirtyRect);
1100         
1101         // Paint our background first, before painting any child layers.
1102         // Establish the clip used to paint our background.
1103         setClip(p, paintDirtyRect, damageRect);
1104
1105         // Paint the background.
1106         RenderObject::PaintInfo info(p, damageRect, PaintActionBlockBackground, paintingRootForRenderer);
1107         renderer()->paint(info, x - renderer()->xPos(), y - renderer()->yPos() + renderer()->borderTopExtra());        
1108         // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
1109         // z-index.  We paint after we painted the background/border, so that the scrollbars will
1110         // sit above the background/border.
1111         paintScrollbars(p, damageRect);
1112         // Restore the clip.
1113         restoreClip(p, paintDirtyRect, damageRect);
1114     }
1115
1116     // Now walk the sorted list of children with negative z-indices.
1117     if (m_negZOrderList)
1118         for (Vector<RenderLayer*>::iterator it = m_negZOrderList->begin(); it != m_negZOrderList->end(); ++it)
1119             it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, selectionOnly, paintingRoot);
1120     
1121     // Now establish the appropriate clip and paint our child RenderObjects.
1122     if (shouldPaint && !clipRectToApply.isEmpty()) {
1123         // Begin transparency layers lazily now that we know we have to paint something.
1124         if (haveTransparency)
1125             beginTransparencyLayers(p, paintDirtyRect);
1126
1127         // Set up the clip used when painting our children.
1128         setClip(p, paintDirtyRect, clipRectToApply);
1129
1130         int tx = x - renderer()->xPos();
1131         int ty = y - renderer()->yPos() + renderer()->borderTopExtra();
1132         RenderObject::PaintInfo info(p, clipRectToApply, 
1133                                      selectionOnly ? PaintActionSelection : PaintActionChildBlockBackgrounds,
1134                                      paintingRootForRenderer);
1135         renderer()->paint(info, tx, ty);
1136         if (!selectionOnly) {
1137             info.phase = PaintActionFloat;
1138             renderer()->paint(info, tx, ty);
1139             info.phase = PaintActionForeground;
1140             renderer()->paint(info, tx, ty);
1141         }
1142
1143         // Now restore our clip.
1144         restoreClip(p, paintDirtyRect, clipRectToApply);
1145         
1146         setClip(p, paintDirtyRect, outlineRect);
1147         info.phase = PaintActionOutline;
1148         renderer()->paint(info, tx, ty);
1149         restoreClip(p, paintDirtyRect, outlineRect);
1150     }
1151     
1152     // Now walk the sorted list of children with positive z-indices.
1153     if (m_posZOrderList)
1154         for (Vector<RenderLayer*>::iterator it = m_posZOrderList->begin(); it != m_posZOrderList->end(); ++it)
1155             it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, selectionOnly, paintingRoot);
1156     
1157     // End our transparency layer
1158     if (isTransparent() && m_usedTransparency) {
1159         p->endTransparencyLayer();
1160         p->restore();
1161         m_usedTransparency = false;
1162     }
1163 }
1164
1165 bool
1166 RenderLayer::hitTest(RenderObject::NodeInfo& info, int x, int y)
1167 {
1168     gScrollBar = 0;
1169
1170     renderer()->document()->updateLayout();
1171     
1172     IntRect damageRect(m_x, m_y, width(), height());
1173     RenderLayer* insideLayer = hitTestLayer(this, info, x, y, damageRect);
1174
1175     // Now determine if the result is inside an anchor; make sure an image map wins if
1176     // it already set URLElement and only use the innermost.
1177     NodeImpl* node = info.innerNode();
1178     while (node) {
1179         if (node->isLink() && !info.URLElement())
1180             info.setURLElement(static_cast<ElementImpl*>(node));
1181         node = node->parentNode();
1182     }
1183
1184     // Next set up the correct :hover/:active state along the new chain.
1185     updateHoverActiveState(info);
1186     
1187     // Now return whether we were inside this layer (this will always be true for the root
1188     // layer).
1189     return insideLayer;
1190 }
1191
1192 RenderLayer*
1193 RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
1194                           int xMousePos, int yMousePos, const IntRect& hitTestRect)
1195 {
1196     // Calculate the clip rects we should use.
1197     IntRect layerBounds, bgRect, fgRect, outlineRect;
1198     calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect);
1199     
1200     // Ensure our z-order lists are up-to-date.
1201     updateZOrderLists();
1202
1203     // This variable tracks which layer the mouse ends up being inside.  The minute we find an insideLayer,
1204     // we are done and can return it.
1205     RenderLayer* insideLayer = 0;
1206     
1207     // Begin by walking our list of positive layers from highest z-index down to the lowest
1208     // z-index.
1209     if (m_posZOrderList) {
1210         for (int i = m_posZOrderList->size() - 1; i >= 0; --i) {
1211             insideLayer = m_posZOrderList->at(i)->hitTestLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
1212             if (insideLayer)
1213                 return insideLayer;
1214         }
1215     }
1216
1217     // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
1218     if (containsPoint(xMousePos, yMousePos, fgRect) && 
1219         renderer()->hitTest(info, xMousePos, yMousePos,
1220                             layerBounds.x() - renderer()->xPos(),
1221                             layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(), HitTestDescendants)) {
1222         // for positioned generated content, we might still not have a
1223         // node by the time we get to the layer level, since none of
1224         // the content in the layer has an element. So just walk up
1225         // the tree.
1226         if (!info.innerNode()) {
1227             for (RenderObject *r = renderer(); r != NULL; r = r->parent()) { 
1228                 if (r->element()) {
1229                     info.setInnerNode(r->element());
1230                     break;
1231                 }
1232             }
1233         }
1234
1235         if (!info.innerNonSharedNode()) {
1236              for (RenderObject *r = renderer(); r != NULL; r = r->parent()) { 
1237                  if (r->element()) {
1238                      info.setInnerNonSharedNode(r->element());
1239                      break;
1240                  }
1241              }
1242         }
1243         return this;
1244     }
1245         
1246     // Now check our negative z-index children.
1247     if (m_negZOrderList) {
1248         for (int i = m_negZOrderList->size() - 1; i >= 0; --i) {
1249             insideLayer = m_negZOrderList->at(i)->hitTestLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
1250             if (insideLayer)
1251                 return insideLayer;
1252         }
1253     }
1254
1255     // Next we want to see if the mouse pos is inside this layer but not any of its children.
1256     if (containsPoint(xMousePos, yMousePos, bgRect) &&
1257         renderer()->hitTest(info, xMousePos, yMousePos,
1258                             layerBounds.x() - renderer()->xPos(),
1259                             layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(),
1260                             HitTestSelf))
1261         return this;
1262
1263     // No luck.
1264     return 0;
1265 }
1266
1267 void RenderLayer::calculateClipRects(const RenderLayer* rootLayer)
1268 {
1269     if (m_clipRects)
1270         return; // We have the correct cached value.
1271
1272     if (!parent()) {
1273         // The root layer's clip rect is always just its dimensions.
1274         m_clipRects = new (m_object->renderArena()) ClipRects(IntRect(0,0,width(),height()));
1275         m_clipRects->ref();
1276         return;
1277     }
1278
1279     // Ensure that our parent's clip has been calculated so that we can examine the values.
1280     parent()->calculateClipRects(rootLayer);
1281
1282     // Set up our three rects to initially match the parent rects.
1283     IntRect posClipRect(parent()->clipRects()->posClipRect());
1284     IntRect overflowClipRect(parent()->clipRects()->overflowClipRect());
1285     IntRect fixedClipRect(parent()->clipRects()->fixedClipRect());
1286
1287     // A fixed object is essentially the root of its containing block hierarchy, so when
1288     // we encounter such an object, we reset our clip rects to the fixedClipRect.
1289     if (m_object->style()->position() == FixedPosition) {
1290         posClipRect = fixedClipRect;
1291         overflowClipRect = fixedClipRect;
1292     }
1293     else if (m_object->style()->position() == RelativePosition)
1294         posClipRect = overflowClipRect;
1295     else if (m_object->style()->position() == AbsolutePosition)
1296         overflowClipRect = posClipRect;
1297     
1298     // Update the clip rects that will be passed to child layers.
1299     if (m_object->hasOverflowClip() || m_object->hasClip()) {
1300         // This layer establishes a clip of some kind.
1301         int x = 0;
1302         int y = 0;
1303         convertToLayerCoords(rootLayer, x, y);
1304         
1305         if (m_object->hasOverflowClip()) {
1306             IntRect newOverflowClip = m_object->getOverflowClipRect(x,y);
1307             overflowClipRect.intersect(newOverflowClip);
1308             if (m_object->isPositioned() || m_object->isRelPositioned())
1309                 posClipRect.intersect(newOverflowClip);
1310         }
1311         if (m_object->hasClip()) {
1312             IntRect newPosClip = m_object->getClipRect(x,y);
1313             posClipRect.intersect(newPosClip);
1314             overflowClipRect.intersect(newPosClip);
1315             fixedClipRect.intersect(newPosClip);
1316         }
1317     }
1318     
1319     // If our clip rects match our parent's clip, then we can just share its data structure and
1320     // ref count.
1321     if (posClipRect == parent()->clipRects()->posClipRect() &&
1322         overflowClipRect == parent()->clipRects()->overflowClipRect() &&
1323         fixedClipRect == parent()->clipRects()->fixedClipRect())
1324         m_clipRects = parent()->clipRects();
1325     else
1326         m_clipRects = new (m_object->renderArena()) ClipRects(overflowClipRect, fixedClipRect, posClipRect);
1327     m_clipRects->ref();
1328 }
1329
1330 void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
1331                                  IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect)
1332 {
1333     if (parent()) {
1334         parent()->calculateClipRects(rootLayer);
1335         backgroundRect = m_object->style()->position() == FixedPosition ? parent()->clipRects()->fixedClipRect() :
1336                          (m_object->isPositioned() ? parent()->clipRects()->posClipRect() : 
1337                                                      parent()->clipRects()->overflowClipRect());
1338         backgroundRect.intersect(paintDirtyRect);
1339     } else
1340         backgroundRect = paintDirtyRect;
1341     foregroundRect = backgroundRect;
1342     outlineRect = backgroundRect;
1343     
1344     int x = 0;
1345     int y = 0;
1346     convertToLayerCoords(rootLayer, x, y);
1347     layerBounds = IntRect(x,y,width(),height());
1348     
1349     // Update the clip rects that will be passed to child layers.
1350     if (m_object->hasOverflowClip() || m_object->hasClip()) {
1351         // This layer establishes a clip of some kind.
1352         if (m_object->hasOverflowClip())
1353             foregroundRect.intersect(m_object->getOverflowClipRect(x,y));
1354         if (m_object->hasClip()) {
1355             // Clip applies to *us* as well, so go ahead and update the damageRect.
1356             IntRect newPosClip = m_object->getClipRect(x,y);
1357             backgroundRect.intersect(newPosClip);
1358             foregroundRect.intersect(newPosClip);
1359             outlineRect.intersect(newPosClip);
1360         }
1361
1362         // If we establish a clip at all, then go ahead and make sure our background
1363         // rect is intersected with our layer's bounds.
1364         backgroundRect.intersect(layerBounds);
1365     }
1366 }
1367
1368 bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect) const
1369 {
1370     // Always examine the canvas and the root.
1371     if (renderer()->isCanvas() || renderer()->isRoot())
1372         return true;
1373
1374     // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we 
1375     // can go ahead and return true.
1376     if (!renderer()->isInlineFlow() && layerBounds.intersects(damageRect))
1377         return true;
1378         
1379     // Otherwise we need to compute the bounding box of this single layer and see if it intersects
1380     // the damage rect.
1381     return absoluteBoundingBox().intersects(damageRect);
1382 }
1383
1384 IntRect RenderLayer::absoluteBoundingBox() const
1385 {
1386     // There are three special cases we need to consider.
1387     // (1) Inline Flows.  For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
1388     // inline.  In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the root
1389     // line boxes of all three lines (including overflow on those lines).
1390     // (2) Left/Top Overflow.  The width/height of layers already includes right/bottom overflow.  However, in the case of left/top
1391     // overflow, we have to create a bounding box that will extend to include this overflow.
1392     // (3) Floats.  When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats
1393     // as part of our bounding box.  We do this because we are the responsible layer for both hit testing and painting those
1394     // floats.
1395     IntRect result;
1396     if (renderer()->isInlineFlow()) {
1397         // Go from our first line box to our last line box.
1398         RenderInline* inlineFlow = static_cast<RenderInline*>(renderer());
1399         InlineFlowBox* firstBox = inlineFlow->firstLineBox();
1400         if (!firstBox)
1401             return result;
1402         int top = firstBox->root()->topOverflow();
1403         int bottom = inlineFlow->lastLineBox()->root()->bottomOverflow();
1404         int left = firstBox->xPos();
1405         for (InlineRunBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox())
1406             left = kMin(left, curr->xPos());
1407         result = IntRect(m_x + left, m_y + (top - renderer()->yPos()), width(), bottom - top);
1408     } else if (renderer()->isTableRow()) {
1409         // Our bounding box is just the union of all of our cells' border/overflow rects.
1410         for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
1411             if (child->isTableCell()) {
1412                 IntRect bbox = child->borderBox();
1413                 bbox.move(0, child->borderTopExtra());
1414                 result.unite(bbox);
1415                 IntRect overflowRect = renderer()->overflowRect(false);
1416                 overflowRect.move(0, child->borderTopExtra());
1417                 if (bbox != overflowRect)
1418                     result.unite(overflowRect);
1419             }
1420         }
1421         result.move(m_x, m_y);
1422     } else {
1423         IntRect bbox = renderer()->borderBox();
1424         result = bbox;
1425         IntRect overflowRect = renderer()->overflowRect(false);
1426         if (bbox != overflowRect)
1427             result.unite(overflowRect);
1428         IntRect floatRect = renderer()->floatRect();
1429         if (bbox != floatRect)
1430             result.unite(floatRect);
1431         
1432         // We have to adjust the x/y of this result so that it is in the coordinate space of the layer.
1433         // We also have to add in borderTopExtra here, since borderBox(), in order to play well with methods like
1434         // floatRect that deal with child content, uses an origin of (0,0) that is at the child content box (so
1435         // border box returns a y coord of -borderTopExtra().  The layer, however, uses the outer box.  This is all
1436         // really confusing.
1437         result.move(m_x, m_y + renderer()->borderTopExtra());
1438     }
1439     
1440     // Convert the bounding box to an absolute position.  We can do this easily by looking at the delta
1441     // between the bounding box's xpos and our layer's xpos and then applying that to the absolute layerBounds
1442     // passed in.
1443     int absX = 0, absY = 0;
1444     convertToLayerCoords(root(), absX, absY);
1445     result.move(absX - m_x, absY - m_y);
1446     return result;
1447 }
1448
1449 bool RenderLayer::containsPoint(int x, int y, const IntRect& damageRect) const
1450 {
1451     // Always returning true for the root object to ensure that mouse events occurring
1452     // outside the window (when dragging) always target some node.
1453     return renderer()->isRoot() || damageRect.contains(x, y);
1454 }
1455
1456 void RenderLayer::clearClipRects()
1457 {
1458     if (!m_clipRects)
1459         return;
1460
1461     clearClipRect();
1462     
1463     for (RenderLayer* l = firstChild(); l; l = l->nextSibling())
1464         l->clearClipRects();
1465 }
1466
1467 void RenderLayer::clearClipRect()
1468 {
1469     if (m_clipRects) {
1470         m_clipRects->deref(m_object->renderArena());
1471         m_clipRects = 0;
1472     }
1473 }
1474
1475 static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
1476 {
1477     if (!obj1 || !obj2)
1478         return 0;
1479
1480     for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor())
1481         for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor())
1482             if (currObj1 == currObj2)
1483                 return currObj1;
1484
1485     return 0;
1486 }
1487
1488 void RenderLayer::updateHoverActiveState(RenderObject::NodeInfo& info)
1489 {
1490     // We don't update :hover/:active state when the info is marked as readonly.
1491     if (info.readonly())
1492         return;
1493
1494     DocumentImpl* doc = renderer()->document();
1495     if (!doc) return;
1496
1497     NodeImpl* activeNode = doc->activeNode();
1498     if (activeNode && !info.active()) {
1499         // We are clearing the :active chain because the mouse has been released.
1500         for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) {
1501             if (curr->element() && !curr->isText())
1502                 curr->element()->setInActiveChain(false);
1503         }
1504         doc->setActiveNode(0);
1505     } else {
1506         NodeImpl* newActiveNode = info.innerNode();
1507         if (!activeNode && newActiveNode && info.active()) {
1508             // We are setting the :active chain and freezing it. If future moves happen, they
1509             // will need to reference this chain.
1510             for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) {
1511                 if (curr->element() && !curr->isText()) {
1512                     curr->element()->setInActiveChain(true);
1513                 }
1514             }
1515             doc->setActiveNode(newActiveNode);
1516         }
1517     }
1518
1519     // If the mouse is down and if this is a mouse move event, we want to restrict changes in 
1520     // :hover/:active to only apply to elements that are in the :active chain that we froze
1521     // at the time the mouse went down.
1522     bool mustBeInActiveChain = info.active() && info.mouseMove();
1523
1524     // Check to see if the hovered node has changed.  If not, then we don't need to
1525     // do anything.  
1526     DOM::NodeImpl* oldHoverNode = doc->hoverNode();
1527     DOM::NodeImpl* newHoverNode = info.innerNode();
1528
1529     // Update our current hover node.
1530     doc->setHoverNode(newHoverNode);
1531
1532     // We have two different objects.  Fetch their renderers.
1533     RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
1534     RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;
1535     
1536     // Locate the common ancestor render object for the two renderers.
1537     RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
1538
1539     if (oldHoverObj != newHoverObj) {
1540         // The old hover path only needs to be cleared up to (and not including) the common ancestor;
1541         for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) {
1542             if (curr->element() && !curr->isText() && (!mustBeInActiveChain || curr->element()->inActiveChain())) {
1543                 curr->element()->setActive(false);
1544                 curr->element()->setHovered(false);
1545             }
1546         }
1547     }
1548
1549     // Now set the hover state for our new object up to the root.
1550     for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
1551         if (curr->element() && !curr->isText() && (!mustBeInActiveChain || curr->element()->inActiveChain())) {
1552             curr->element()->setActive(info.active());
1553             curr->element()->setHovered(true);
1554         }
1555     }
1556 }
1557
1558 // Helpers for the sorting of layers by z-index.
1559 static inline bool isOverflowOnly(const RenderLayer* layer)
1560 {
1561     return layer->renderer()->hasOverflowClip() && 
1562            !layer->renderer()->isPositioned() &&
1563            !layer->renderer()->isRelPositioned() &&
1564            !layer->isTransparent();
1565 }
1566
1567 static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
1568 {
1569     return first->zIndex() < second->zIndex();
1570 }
1571
1572
1573 void RenderLayer::dirtyZOrderLists()
1574 {
1575     if (m_posZOrderList)
1576         m_posZOrderList->clear();
1577     if (m_negZOrderList)
1578         m_negZOrderList->clear();
1579     m_zOrderListsDirty = true;
1580 }
1581     
1582 void RenderLayer::updateZOrderLists()
1583 {
1584     if (!isStackingContext() || !m_zOrderListsDirty)
1585         return;
1586     
1587     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
1588         child->collectLayers(m_posZOrderList, m_negZOrderList);
1589
1590     // Sort the two lists.
1591     if (m_posZOrderList)
1592         std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex);
1593     if (m_negZOrderList)
1594         std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
1595
1596     m_zOrderListsDirty = false;
1597 }
1598
1599 void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer)
1600 {
1601     // FIXME: A child render object or layer could override visibility.  Don't remove this
1602     // optimization though until RenderObject's nodeAtPoint is patched to understand what to do
1603     // when visibility is overridden by a child.
1604     if (renderer()->style()->visibility() != VISIBLE)
1605         return;
1606     
1607     // Determine which buffer the child should be in.
1608     Vector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
1609
1610     // Create the buffer if it doesn't exist yet.
1611     if (!buffer)
1612         buffer = new Vector<RenderLayer*>;
1613     
1614     // Append ourselves at the end of the appropriate buffer.
1615     buffer->append(this);
1616
1617     // Recur into our children to collect more layers, but only if we don't establish
1618     // a stacking context.
1619     if (!isStackingContext())
1620         for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
1621             child->collectLayers(posBuffer, negBuffer);
1622 }
1623
1624 void RenderLayer::repaintIncludingDescendants()
1625 {
1626     m_object->repaint();
1627     for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
1628         curr->repaintIncludingDescendants();
1629 }
1630
1631 void RenderLayer::styleChanged()
1632 {
1633     if (m_object->style()->overflow() == OMARQUEE && m_object->style()->marqueeBehavior() != MNONE) {
1634         if (!m_marquee)
1635             m_marquee = new Marquee(this);
1636         m_marquee->updateMarqueeStyle();
1637     }
1638     else if (m_marquee) {
1639         delete m_marquee;
1640         m_marquee = 0;
1641     }
1642 }
1643
1644 void RenderLayer::suspendMarquees()
1645 {
1646     if (m_marquee)
1647         m_marquee->suspend();
1648     
1649     for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
1650         curr->suspendMarquees();
1651 }
1652
1653 // --------------------------------------------------------------------------
1654 // Marquee implementation
1655
1656 Marquee::Marquee(RenderLayer* l)
1657     : m_layer(l), m_currentLoop(0)
1658     , m_timer(this, &Marquee::timerFired)
1659     , m_start(0), m_end(0), m_speed(0), m_unfurlPos(0), m_reset(false)
1660     , m_suspended(false), m_stopped(false), m_whiteSpace(NORMAL), m_direction(MAUTO)
1661 {
1662 }
1663
1664 int Marquee::marqueeSpeed() const
1665 {
1666     int result = m_layer->renderer()->style()->marqueeSpeed();
1667     DOM::NodeImpl* elt = m_layer->renderer()->element();
1668     if (elt && elt->hasTagName(marqueeTag)) {
1669         HTMLMarqueeElementImpl* marqueeElt = static_cast<HTMLMarqueeElementImpl*>(elt);
1670         result = kMax(result, marqueeElt->minimumDelay());
1671     }
1672     return result;
1673 }
1674
1675 EMarqueeDirection Marquee::direction() const
1676 {
1677     // FIXME: Support the CSS3 "auto" value for determining the direction of the marquee.
1678     // For now just map MAUTO to MBACKWARD
1679     EMarqueeDirection result = m_layer->renderer()->style()->marqueeDirection();
1680     TextDirection dir = m_layer->renderer()->style()->direction();
1681     if (result == MAUTO)
1682         result = MBACKWARD;
1683     if (result == MFORWARD)
1684         result = (dir == LTR) ? MRIGHT : MLEFT;
1685     if (result == MBACKWARD)
1686         result = (dir == LTR) ? MLEFT : MRIGHT;
1687     
1688     // Now we have the real direction.  Next we check to see if the increment is negative.
1689     // If so, then we reverse the direction.
1690     Length increment = m_layer->renderer()->style()->marqueeIncrement();
1691     if (increment.value() < 0)
1692         result = static_cast<EMarqueeDirection>(-result);
1693     
1694     return result;
1695 }
1696
1697 bool Marquee::isHorizontal() const
1698 {
1699     return direction() == MLEFT || direction() == MRIGHT;
1700 }
1701
1702 bool Marquee::isUnfurlMarquee() const
1703 {
1704     EMarqueeBehavior behavior = m_layer->renderer()->style()->marqueeBehavior();
1705     return (behavior == MUNFURL);
1706 }
1707
1708 int Marquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge)
1709 {
1710     RenderObject* o = m_layer->renderer();
1711     RenderStyle* s = o->style();
1712     if (isHorizontal()) {
1713         bool ltr = s->direction() == LTR;
1714         int clientWidth = o->clientWidth();
1715         int contentWidth = ltr ? o->rightmostPosition(true, false) : o->leftmostPosition(true, false);
1716         if (ltr)
1717             contentWidth += (o->paddingRight() - o->borderLeft());
1718         else {
1719             contentWidth = o->width() - contentWidth;
1720             contentWidth += (o->paddingLeft() - o->borderRight());
1721         }
1722         if (dir == MRIGHT) {
1723             if (stopAtContentEdge)
1724                 return kMax(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
1725             else
1726                 return ltr ? contentWidth : clientWidth;
1727         }
1728         else {
1729             if (stopAtContentEdge)
1730                 return kMin(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
1731             else
1732                 return ltr ? -clientWidth : -contentWidth;
1733         }
1734     }
1735     else {
1736         int contentHeight = m_layer->renderer()->lowestPosition(true, false) - 
1737                             m_layer->renderer()->borderTop() + m_layer->renderer()->paddingBottom();
1738         int clientHeight = m_layer->renderer()->clientHeight();
1739         if (dir == MUP) {
1740             if (stopAtContentEdge)
1741                  return kMin(contentHeight - clientHeight, 0);
1742             else
1743                 return -clientHeight;
1744         }
1745         else {
1746             if (stopAtContentEdge)
1747                 return kMax(contentHeight - clientHeight, 0);
1748             else 
1749                 return contentHeight;
1750         }
1751     }    
1752 }
1753
1754 void Marquee::start()
1755 {
1756     if (m_timer.isActive() || m_layer->renderer()->style()->marqueeIncrement().value() == 0)
1757         return;
1758     
1759     if (!m_suspended && !m_stopped) {
1760         if (isUnfurlMarquee()) {
1761             bool forward = direction() == MDOWN || direction() == MRIGHT;
1762             bool isReversed = (forward && m_currentLoop % 2) || (!forward && !(m_currentLoop % 2));
1763             m_unfurlPos = isReversed ? m_end : m_start;
1764             m_layer->renderer()->setChildNeedsLayout(true);
1765         }
1766         else {
1767             if (isHorizontal())
1768                 m_layer->scrollToOffset(m_start, 0, false, false);
1769             else
1770                 m_layer->scrollToOffset(0, m_start, false, false);
1771         }
1772         // FIXME: At this point a scroll event fired, which could have deleted this layer,
1773         // including the marquee. Need to handle this case.
1774     }
1775     else {
1776         m_suspended = false;
1777         m_stopped = false;
1778     }
1779
1780     m_timer.startRepeating(speed() * 0.001);
1781 }
1782
1783 void Marquee::suspend()
1784 {
1785     m_timer.stop();
1786     m_suspended = true;
1787 }
1788
1789 void Marquee::stop()
1790 {
1791     m_timer.stop();
1792     m_stopped = true;
1793 }
1794
1795 void Marquee::updateMarqueePosition()
1796 {
1797     bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
1798     if (activate) {
1799         if (isUnfurlMarquee()) {
1800             if (m_unfurlPos < m_start) {
1801                 m_unfurlPos = m_start;
1802                 m_layer->renderer()->setChildNeedsLayout(true);
1803             }
1804             else if (m_unfurlPos > m_end) {
1805                 m_unfurlPos = m_end;
1806                 m_layer->renderer()->setChildNeedsLayout(true);
1807             }
1808         }
1809         else {
1810             EMarqueeBehavior behavior = m_layer->renderer()->style()->marqueeBehavior();
1811             m_start = computePosition(direction(), behavior == MALTERNATE);
1812             m_end = computePosition(reverseDirection(), behavior == MALTERNATE || behavior == MSLIDE);
1813         }
1814         if (!m_stopped)
1815             start();
1816     }
1817 }
1818
1819 void Marquee::updateMarqueeStyle()
1820 {
1821     RenderStyle* s = m_layer->renderer()->style();
1822     
1823     if (m_direction != s->marqueeDirection() || (m_totalLoops != s->marqueeLoopCount() && m_currentLoop >= m_totalLoops))
1824         m_currentLoop = 0; // When direction changes or our loopCount is a smaller number than our current loop, reset our loop.
1825     
1826     m_totalLoops = s->marqueeLoopCount();
1827     m_direction = s->marqueeDirection();
1828     m_whiteSpace = s->whiteSpace();
1829     
1830     if (m_layer->renderer()->isHTMLMarquee()) {
1831         // Hack for WinIE.  In WinIE, a value of 0 or lower for the loop count for SLIDE means to only do
1832         // one loop.
1833         if (m_totalLoops <= 0 && (s->marqueeBehavior() == MSLIDE || s->marqueeBehavior() == MUNFURL))
1834             m_totalLoops = 1;
1835         
1836         // Hack alert: Set the white-space value to nowrap for horizontal marquees with inline children, thus ensuring
1837         // all the text ends up on one line by default.  Limit this hack to the <marquee> element to emulate
1838         // WinIE's behavior.  Someone using CSS3 can use white-space: nowrap on their own to get this effect.
1839         // Second hack alert: Set the text-align back to auto.  WinIE completely ignores text-align on the
1840         // marquee element.
1841         // FIXME: Bring these up with the CSS WG.
1842         if (isHorizontal() && m_layer->renderer()->childrenInline()) {
1843             s->setWhiteSpace(NOWRAP);
1844             s->setTextAlign(TAAUTO);
1845         }
1846     }
1847     
1848     // Marquee height hack!! Make sure that, if it is a horizontal marquee, the height attribute is overridden 
1849     // if it is smaller than the font size. If it is a vertical marquee and height is not specified, we default
1850     // to a marquee of 200px.
1851     if (isHorizontal()) {
1852         if (s->height().isFixed() && s->height().value() < s->fontSize())
1853             s->setHeight(Length(s->fontSize(),Fixed));
1854     } else if (s->height().isAuto())  //vertical marquee with no specified height
1855         s->setHeight(Length(200, Fixed)); 
1856    
1857     if (speed() != marqueeSpeed()) {
1858         m_speed = marqueeSpeed();
1859         if (m_timer.isActive())
1860             m_timer.startRepeating(speed() * 0.001);
1861     }
1862     
1863     // Check the loop count to see if we should now stop.
1864     bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
1865     if (activate && !m_timer.isActive())
1866         m_layer->renderer()->setNeedsLayout(true);
1867     else if (!activate && m_timer.isActive())
1868         m_timer.stop();
1869 }
1870
1871 void Marquee::timerFired(Timer<Marquee>*)
1872 {
1873     if (m_layer->renderer()->needsLayout())
1874         return;
1875     
1876     if (m_reset) {
1877         m_reset = false;
1878         if (isHorizontal())
1879             m_layer->scrollToXOffset(m_start);
1880         else
1881             m_layer->scrollToYOffset(m_start);
1882         return;
1883     }
1884     
1885     RenderStyle* s = m_layer->renderer()->style();
1886     
1887     int endPoint = m_end;
1888     int range = m_end - m_start;
1889     int newPos;
1890     if (range == 0)
1891         newPos = m_end;
1892     else {  
1893         bool addIncrement = direction() == MUP || direction() == MLEFT;
1894         bool isReversed = s->marqueeBehavior() == MALTERNATE && m_currentLoop % 2;
1895         if (isUnfurlMarquee()) {
1896             isReversed = (!addIncrement && m_currentLoop % 2) || (addIncrement && !(m_currentLoop % 2));
1897             addIncrement = !isReversed;
1898         }
1899         if (isReversed) {
1900             // We're going in the reverse direction.
1901             endPoint = m_start;
1902             range = -range;
1903             if (!isUnfurlMarquee())
1904                 addIncrement = !addIncrement;
1905         }
1906         bool positive = range > 0;
1907         int clientSize = isUnfurlMarquee() ? abs(range) :
1908             (isHorizontal() ? m_layer->renderer()->clientWidth() : m_layer->renderer()->clientHeight());
1909         int increment = kMax(1, abs(m_layer->renderer()->style()->marqueeIncrement().calcValue(clientSize)));
1910         int currentPos = isUnfurlMarquee() ? m_unfurlPos : 
1911             (isHorizontal() ? m_layer->scrollXOffset() : m_layer->scrollYOffset());
1912         newPos =  currentPos + (addIncrement ? increment : -increment);
1913         if (positive)
1914             newPos = kMin(newPos, endPoint);
1915         else
1916             newPos = kMax(newPos, endPoint);
1917     }
1918
1919     if (newPos == endPoint) {
1920         m_currentLoop++;
1921         if (m_totalLoops > 0 && m_currentLoop >= m_totalLoops)
1922             m_timer.stop();
1923         else if (s->marqueeBehavior() != MALTERNATE && s->marqueeBehavior() != MUNFURL)
1924             m_reset = true;
1925     }
1926     
1927     if (isUnfurlMarquee()) {
1928         m_unfurlPos = newPos;
1929         m_layer->renderer()->setChildNeedsLayout(true);
1930     }
1931     else {
1932         if (isHorizontal())
1933             m_layer->scrollToXOffset(newPos);
1934         else
1935             m_layer->scrollToYOffset(newPos);
1936     }
1937 }
1938
1939 }