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