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