• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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 "RenderLayer.h"
46 
47 #include "CSSPropertyNames.h"
48 #include "Document.h"
49 #include "EventHandler.h"
50 #include "EventNames.h"
51 #include "FloatRect.h"
52 #include "FocusController.h"
53 #include "Frame.h"
54 #include "FrameTree.h"
55 #include "FrameView.h"
56 #include "Gradient.h"
57 #include "GraphicsContext.h"
58 #include "HTMLNames.h"
59 #include "HitTestRequest.h"
60 #include "HitTestResult.h"
61 #include "OverflowEvent.h"
62 #include "Page.h"
63 #include "PlatformMouseEvent.h"
64 #include "RenderArena.h"
65 #include "RenderInline.h"
66 #include "RenderMarquee.h"
67 #include "RenderReplica.h"
68 #include "RenderScrollbar.h"
69 #include "RenderScrollbarPart.h"
70 #include "RenderTheme.h"
71 #include "RenderView.h"
72 #include "ScaleTransformOperation.h"
73 #include "Scrollbar.h"
74 #include "ScrollbarTheme.h"
75 #include "SelectionController.h"
76 #include "TranslateTransformOperation.h"
77 #include <wtf/StdLibExtras.h>
78 
79 #if ENABLE(SVG)
80 #include "SVGNames.h"
81 #endif
82 
83 #define MIN_INTERSECT_FOR_REVEAL 32
84 
85 using namespace std;
86 
87 namespace WebCore {
88 
89 using namespace HTMLNames;
90 
91 const RenderLayer::ScrollAlignment RenderLayer::gAlignCenterIfNeeded = { RenderLayer::noScroll, RenderLayer::alignCenter, RenderLayer::alignToClosestEdge };
92 const RenderLayer::ScrollAlignment RenderLayer::gAlignToEdgeIfNeeded = { RenderLayer::noScroll, RenderLayer::alignToClosestEdge, RenderLayer::alignToClosestEdge };
93 const RenderLayer::ScrollAlignment RenderLayer::gAlignCenterAlways = { RenderLayer::alignCenter, RenderLayer::alignCenter, RenderLayer::alignCenter };
94 const RenderLayer::ScrollAlignment RenderLayer::gAlignTopAlways = { RenderLayer::alignTop, RenderLayer::alignTop, RenderLayer::alignTop };
95 const RenderLayer::ScrollAlignment RenderLayer::gAlignBottomAlways = { RenderLayer::alignBottom, RenderLayer::alignBottom, RenderLayer::alignBottom };
96 
97 const int MinimumWidthWhileResizing = 100;
98 const int MinimumHeightWhileResizing = 40;
99 
operator new(size_t sz,RenderArena * renderArena)100 void* ClipRects::operator new(size_t sz, RenderArena* renderArena) throw()
101 {
102     return renderArena->allocate(sz);
103 }
104 
operator delete(void * ptr,size_t sz)105 void ClipRects::operator delete(void* ptr, size_t sz)
106 {
107     // Stash size where destroy can find it.
108     *(size_t *)ptr = sz;
109 }
110 
destroy(RenderArena * renderArena)111 void ClipRects::destroy(RenderArena* renderArena)
112 {
113     delete this;
114 
115     // Recover the size left there for us by operator delete and free the memory.
116     renderArena->free(*(size_t *)this, this);
117 }
118 
RenderLayer(RenderBox * renderer)119 RenderLayer::RenderLayer(RenderBox* renderer)
120     : m_renderer(renderer)
121     , m_parent(0)
122     , m_previous(0)
123     , m_next(0)
124     , m_first(0)
125     , m_last(0)
126     , m_relX(0)
127     , m_relY(0)
128     , m_x(0)
129     , m_y(0)
130     , m_width(0)
131     , m_height(0)
132     , m_scrollX(0)
133     , m_scrollY(0)
134     , m_scrollOriginX(0)
135     , m_scrollLeftOverflow(0)
136     , m_scrollWidth(0)
137     , m_scrollHeight(0)
138     , m_inResizeMode(false)
139     , m_posZOrderList(0)
140     , m_negZOrderList(0)
141     , m_overflowList(0)
142     , m_clipRects(0)
143 #ifndef NDEBUG
144     , m_clipRectsRoot(0)
145 #endif
146     , m_scrollDimensionsDirty(true)
147     , m_zOrderListsDirty(true)
148     , m_overflowListDirty(true)
149     , m_isOverflowOnly(shouldBeOverflowOnly())
150     , m_usedTransparency(false)
151     , m_paintingInsideReflection(false)
152     , m_inOverflowRelayout(false)
153     , m_needsFullRepaint(false)
154     , m_overflowStatusDirty(true)
155     , m_visibleContentStatusDirty(true)
156     , m_hasVisibleContent(false)
157     , m_visibleDescendantStatusDirty(false)
158     , m_hasVisibleDescendant(false)
159     , m_marquee(0)
160     , m_staticX(0)
161     , m_staticY(0)
162     , m_transform(0)
163     , m_reflection(0)
164     , m_scrollCorner(0)
165     , m_resizer(0)
166 {
167     if (!renderer->firstChild() && renderer->style()) {
168         m_visibleContentStatusDirty = false;
169         m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
170     }
171 }
172 
~RenderLayer()173 RenderLayer::~RenderLayer()
174 {
175     if (inResizeMode() && !renderer()->documentBeingDestroyed()) {
176         if (Frame* frame = renderer()->document()->frame())
177             frame->eventHandler()->resizeLayerDestroyed();
178     }
179 
180     destroyScrollbar(HorizontalScrollbar);
181     destroyScrollbar(VerticalScrollbar);
182 
183     // Child layers will be deleted by their corresponding render objects, so
184     // we don't need to delete them ourselves.
185 
186     delete m_posZOrderList;
187     delete m_negZOrderList;
188     delete m_overflowList;
189     delete m_marquee;
190 
191     // Make sure we have no lingering clip rects.
192     ASSERT(!m_clipRects);
193 
194     if (m_reflection) {
195         if (!m_reflection->documentBeingDestroyed())
196             m_reflection->removeLayers(this);
197         m_reflection->setParent(0);
198         m_reflection->destroy();
199     }
200 
201     if (m_scrollCorner)
202         m_scrollCorner->destroy();
203     if (m_resizer)
204         m_resizer->destroy();
205 }
206 
updateLayerPositions(bool doFullRepaint,bool checkForRepaint)207 void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
208 {
209     if (doFullRepaint) {
210         renderer()->repaint();
211         checkForRepaint = doFullRepaint = false;
212     }
213 
214     updateLayerPosition(); // For relpositioned layers or non-positioned layers,
215                            // we need to keep in sync, since we may have shifted relative
216                            // to our parent layer.
217 
218     int x = 0;
219     int y = 0;
220     convertToLayerCoords(root(), x, y);
221     positionOverflowControls(x, y);
222 
223     updateVisibilityStatus();
224 
225     updateTransform();
226 
227     if (m_hasVisibleContent) {
228         RenderView* view = renderer()->view();
229         ASSERT(view);
230         // FIXME: Optimize using LayoutState and remove the disableLayoutState() call
231         // from updateScrollInfoAfterLayout().
232         ASSERT(!view->layoutStateEnabled());
233 
234         IntRect newRect = renderer()->absoluteClippedOverflowRect();
235         IntRect newOutlineBox = renderer()->absoluteOutlineBounds();
236         if (checkForRepaint) {
237             if (view && !view->printing()) {
238                 if (m_needsFullRepaint) {
239                     view->repaintViewRectangle(m_repaintRect);
240                     if (newRect != m_repaintRect)
241                         view->repaintViewRectangle(newRect);
242                 } else
243                     renderer()->repaintAfterLayoutIfNeeded(m_repaintRect, m_outlineBox);
244             }
245         }
246         m_repaintRect = newRect;
247         m_outlineBox = newOutlineBox;
248     } else {
249         m_repaintRect = IntRect();
250         m_outlineBox = IntRect();
251     }
252 
253     m_needsFullRepaint = false;
254 
255     // Go ahead and update the reflection's position and size.
256     if (m_reflection)
257         m_reflection->layout();
258 
259     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
260         child->updateLayerPositions(doFullRepaint, checkForRepaint);
261 
262     // With all our children positioned, now update our marquee if we need to.
263     if (m_marquee)
264         m_marquee->updateMarqueePosition();
265 }
266 
updateTransform()267 void RenderLayer::updateTransform()
268 {
269     bool hasTransform = renderer()->hasTransform();
270     bool hadTransform = m_transform;
271     if (hasTransform != hadTransform) {
272         if (hasTransform)
273             m_transform.set(new TransformationMatrix);
274         else
275             m_transform.clear();
276     }
277 
278     if (hasTransform) {
279         m_transform->reset();
280         renderer()->style()->applyTransform(*m_transform, renderer()->borderBoxRect().size());
281     }
282 }
283 
setHasVisibleContent(bool b)284 void RenderLayer::setHasVisibleContent(bool b)
285 {
286     if (m_hasVisibleContent == b && !m_visibleContentStatusDirty)
287         return;
288     m_visibleContentStatusDirty = false;
289     m_hasVisibleContent = b;
290     if (m_hasVisibleContent) {
291         m_repaintRect = renderer()->absoluteClippedOverflowRect();
292         m_outlineBox = renderer()->absoluteOutlineBounds();
293         if (!isOverflowOnly())
294             dirtyStackingContextZOrderLists();
295     }
296     if (parent())
297         parent()->childVisibilityChanged(m_hasVisibleContent);
298 }
299 
dirtyVisibleContentStatus()300 void RenderLayer::dirtyVisibleContentStatus()
301 {
302     m_visibleContentStatusDirty = true;
303     if (parent())
304         parent()->dirtyVisibleDescendantStatus();
305 }
306 
childVisibilityChanged(bool newVisibility)307 void RenderLayer::childVisibilityChanged(bool newVisibility)
308 {
309     if (m_hasVisibleDescendant == newVisibility || m_visibleDescendantStatusDirty)
310         return;
311     if (newVisibility) {
312         RenderLayer* l = this;
313         while (l && !l->m_visibleDescendantStatusDirty && !l->m_hasVisibleDescendant) {
314             l->m_hasVisibleDescendant = true;
315             l = l->parent();
316         }
317     } else
318         dirtyVisibleDescendantStatus();
319 }
320 
dirtyVisibleDescendantStatus()321 void RenderLayer::dirtyVisibleDescendantStatus()
322 {
323     RenderLayer* l = this;
324     while (l && !l->m_visibleDescendantStatusDirty) {
325         l->m_visibleDescendantStatusDirty = true;
326         l = l->parent();
327     }
328 }
329 
updateVisibilityStatus()330 void RenderLayer::updateVisibilityStatus()
331 {
332     if (m_visibleDescendantStatusDirty) {
333         m_hasVisibleDescendant = false;
334         for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
335             child->updateVisibilityStatus();
336             if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) {
337                 m_hasVisibleDescendant = true;
338                 break;
339             }
340         }
341         m_visibleDescendantStatusDirty = false;
342     }
343 
344     if (m_visibleContentStatusDirty) {
345         if (renderer()->style()->visibility() == VISIBLE)
346             m_hasVisibleContent = true;
347         else {
348             // layer may be hidden but still have some visible content, check for this
349             m_hasVisibleContent = false;
350             RenderObject* r = renderer()->firstChild();
351             while (r) {
352                 if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
353                     m_hasVisibleContent = true;
354                     break;
355                 }
356                 if (r->firstChild() && !r->hasLayer())
357                     r = r->firstChild();
358                 else if (r->nextSibling())
359                     r = r->nextSibling();
360                 else {
361                     do {
362                         r = r->parent();
363                         if (r==renderer())
364                             r = 0;
365                     } while (r && !r->nextSibling());
366                     if (r)
367                         r = r->nextSibling();
368                 }
369             }
370         }
371         m_visibleContentStatusDirty = false;
372     }
373 }
374 
updateLayerPosition()375 void RenderLayer::updateLayerPosition()
376 {
377     // Clear our cached clip rect information.
378     clearClipRects();
379 
380     int x = renderer()->x();
381     int y = renderer()->y();
382 
383     if (!renderer()->isPositioned() && renderer()->parent()) {
384         // We must adjust our position by walking up the render tree looking for the
385         // nearest enclosing object with a layer.
386         RenderBox* curr = renderer()->parentBox();
387         while (curr && !curr->hasLayer()) {
388             if (!curr->isTableRow()) {
389                 // Rows and cells share the same coordinate space (that of the section).
390                 // Omit them when computing our xpos/ypos.
391                 x += curr->x();
392                 y += curr->y();
393             }
394             curr = curr->parentBox();
395         }
396         if (curr->isTableRow()) {
397             // Put ourselves into the row coordinate space.
398             x -= curr->x();
399             y -= curr->y();
400         }
401     }
402 
403     m_relX = m_relY = 0;
404     if (renderer()->isRelPositioned()) {
405         m_relX = toRenderBox(renderer())->relativePositionOffsetX();
406         m_relY = toRenderBox(renderer())->relativePositionOffsetY();
407         x += m_relX; y += m_relY;
408     }
409 
410     // Subtract our parent's scroll offset.
411     if (renderer()->isPositioned() && enclosingPositionedAncestor()) {
412         RenderLayer* positionedParent = enclosingPositionedAncestor();
413 
414         // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
415         positionedParent->subtractScrolledContentOffset(x, y);
416 
417         if (renderer()->isPositioned()) {
418             IntSize offset = toRenderBox(renderer())->offsetForPositionedInContainer(positionedParent->renderer());
419             x += offset.width();
420             y += offset.height();
421         }
422     } else if (parent())
423         parent()->subtractScrolledContentOffset(x, y);
424 
425     // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
426 
427     setPos(x, y);
428 
429     if (renderer()->isRenderInline()) {
430         RenderInline* inlineFlow = static_cast<RenderInline*>(renderer());
431         IntRect lineBox = inlineFlow->linesBoundingBox();
432         setWidth(lineBox.width());
433         setHeight(lineBox.height());
434     } else {
435         setWidth(renderer()->width());
436         setHeight(renderer()->height());
437 
438         if (!renderer()->hasOverflowClip()) {
439             if (renderer()->overflowWidth() > renderer()->width())
440                 setWidth(renderer()->overflowWidth());
441             if (renderer()->overflowHeight() > renderer()->height())
442                 setHeight(renderer()->overflowHeight());
443         }
444     }
445 }
446 
stackingContext() const447 RenderLayer *RenderLayer::stackingContext() const
448 {
449     RenderLayer* curr = parent();
450     for ( ; curr && !curr->renderer()->isRenderView() && !curr->renderer()->isRoot() &&
451           curr->renderer()->style()->hasAutoZIndex();
452           curr = curr->parent()) { }
453     return curr;
454 }
455 
enclosingPositionedAncestor() const456 RenderLayer* RenderLayer::enclosingPositionedAncestor() const
457 {
458     RenderLayer* curr = parent();
459     for ( ; curr && !curr->renderer()->isRenderView() && !curr->renderer()->isPositioned() && !curr->renderer()->isRelPositioned() && !curr->hasTransform();
460          curr = curr->parent()) { }
461     return curr;
462 }
463 
enclosingTransformedAncestor() const464 RenderLayer* RenderLayer::enclosingTransformedAncestor() const
465 {
466     RenderLayer* curr = parent();
467     for ( ; curr && !curr->renderer()->isRenderView() && !curr->transform(); curr = curr->parent())
468         { }
469     return curr;
470 }
471 
absoluteToContents(const IntPoint & absolutePoint) const472 IntPoint RenderLayer::absoluteToContents(const IntPoint& absolutePoint) const
473 {
474     // We don't use convertToLayerCoords because it doesn't know about transforms
475     return roundedIntPoint(renderer()->absoluteToLocal(absolutePoint, false, true));
476 }
477 
requiresSlowRepaints() const478 bool RenderLayer::requiresSlowRepaints() const
479 {
480     if (isTransparent() || hasReflection() || hasTransform())
481         return true;
482     if (!parent())
483         return false;
484     return parent()->requiresSlowRepaints();
485 }
486 
isTransparent() const487 bool RenderLayer::isTransparent() const
488 {
489 #if ENABLE(SVG)
490     if (renderer()->node()->namespaceURI() == SVGNames::svgNamespaceURI)
491         return false;
492 #endif
493     return renderer()->isTransparent() || renderer()->hasMask();
494 }
495 
496 RenderLayer*
transparentAncestor()497 RenderLayer::transparentAncestor()
498 {
499     RenderLayer* curr = parent();
500     for ( ; curr && !curr->isTransparent(); curr = curr->parent()) { }
501     return curr;
502 }
503 
transparencyClipBox(const TransformationMatrix & enclosingTransform,const RenderLayer * l,const RenderLayer * rootLayer)504 static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransform, const RenderLayer* l, const RenderLayer* rootLayer)
505 {
506     // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
507     // paintDirtyRect, and that should cut down on the amount we have to paint.  Still it
508     // would be better to respect clips.
509 
510     TransformationMatrix* t = l->transform();
511     if (t && rootLayer != l) {
512         // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
513         // the transformed layer and all of its children.
514         int x = 0;
515         int y = 0;
516         l->convertToLayerCoords(rootLayer, x, y);
517         TransformationMatrix transform;
518         transform.translate(x, y);
519         transform = *t * transform;
520         transform = transform * enclosingTransform;
521 
522         // We now have a transform that will produce a rectangle in our view's space.
523         IntRect clipRect = transform.mapRect(l->boundingBox(l));
524 
525         // Now shift the root layer to be us and pass down the new enclosing transform.
526         for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) {
527             if (!l->reflection() || l->reflectionLayer() != curr)
528                 clipRect.unite(transparencyClipBox(transform, curr, l));
529         }
530 
531         return clipRect;
532     }
533 
534     // Note: we don't have to walk z-order lists since transparent elements always establish
535     // a stacking context.  This means we can just walk the layer tree directly.
536     IntRect clipRect = l->boundingBox(rootLayer);
537 
538     // If we have a mask, then the clip is limited to the border box area (and there is
539     // no need to examine child layers).
540     if (!l->renderer()->hasMask()) {
541         for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) {
542             if (!l->reflection() || l->reflectionLayer() != curr)
543                 clipRect.unite(transparencyClipBox(enclosingTransform, curr, rootLayer));
544         }
545     }
546 
547     // Now map the clipRect via the enclosing transform
548     return enclosingTransform.mapRect(clipRect);
549 }
550 
beginTransparencyLayers(GraphicsContext * p,const RenderLayer * rootLayer)551 void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer)
552 {
553     if (p->paintingDisabled() || (isTransparent() && m_usedTransparency))
554         return;
555 
556     RenderLayer* ancestor = transparentAncestor();
557     if (ancestor)
558         ancestor->beginTransparencyLayers(p, rootLayer);
559 
560     if (isTransparent()) {
561         m_usedTransparency = true;
562         p->save();
563         p->clip(transparencyClipBox(TransformationMatrix(), this, rootLayer));
564         p->beginTransparencyLayer(renderer()->opacity());
565     }
566 }
567 
operator new(size_t sz,RenderArena * renderArena)568 void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
569 {
570     return renderArena->allocate(sz);
571 }
572 
operator delete(void * ptr,size_t sz)573 void RenderLayer::operator delete(void* ptr, size_t sz)
574 {
575     // Stash size where destroy can find it.
576     *(size_t *)ptr = sz;
577 }
578 
destroy(RenderArena * renderArena)579 void RenderLayer::destroy(RenderArena* renderArena)
580 {
581     delete this;
582 
583     // Recover the size left there for us by operator delete and free the memory.
584     renderArena->free(*(size_t *)this, this);
585 }
586 
addChild(RenderLayer * child,RenderLayer * beforeChild)587 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
588 {
589     RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
590     if (prevSibling) {
591         child->setPreviousSibling(prevSibling);
592         prevSibling->setNextSibling(child);
593     } else
594         setFirstChild(child);
595 
596     if (beforeChild) {
597         beforeChild->setPreviousSibling(child);
598         child->setNextSibling(beforeChild);
599     } else
600         setLastChild(child);
601 
602     child->setParent(this);
603 
604     if (child->isOverflowOnly())
605         dirtyOverflowList();
606 
607     if (!child->isOverflowOnly() || child->firstChild()) {
608         // Dirty the z-order list in which we are contained.  The stackingContext() can be null in the
609         // case where we're building up generated content layers.  This is ok, since the lists will start
610         // off dirty in that case anyway.
611         child->dirtyStackingContextZOrderLists();
612     }
613 
614     child->updateVisibilityStatus();
615     if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
616         childVisibilityChanged(true);
617 }
618 
removeChild(RenderLayer * oldChild)619 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
620 {
621     // remove the child
622     if (oldChild->previousSibling())
623         oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
624     if (oldChild->nextSibling())
625         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
626 
627     if (m_first == oldChild)
628         m_first = oldChild->nextSibling();
629     if (m_last == oldChild)
630         m_last = oldChild->previousSibling();
631 
632     if (oldChild->isOverflowOnly())
633         dirtyOverflowList();
634     if (!oldChild->isOverflowOnly() || oldChild->firstChild()) {
635         // Dirty the z-order list in which we are contained.  When called via the
636         // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
637         // from the main layer tree, so we need to null-check the |stackingContext| value.
638         oldChild->dirtyStackingContextZOrderLists();
639     }
640 
641     oldChild->setPreviousSibling(0);
642     oldChild->setNextSibling(0);
643     oldChild->setParent(0);
644 
645     oldChild->updateVisibilityStatus();
646     if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
647         childVisibilityChanged(false);
648 
649     return oldChild;
650 }
651 
removeOnlyThisLayer()652 void RenderLayer::removeOnlyThisLayer()
653 {
654     if (!m_parent)
655         return;
656 
657     // Dirty the clip rects.
658     clearClipRectsIncludingDescendants();
659 
660     // Remove us from the parent.
661     RenderLayer* parent = m_parent;
662     RenderLayer* nextSib = nextSibling();
663     parent->removeChild(this);
664 
665     if (reflection())
666         removeChild(reflectionLayer());
667 
668     // Now walk our kids and reattach them to our parent.
669     RenderLayer* current = m_first;
670     while (current) {
671         RenderLayer* next = current->nextSibling();
672         removeChild(current);
673         parent->addChild(current, nextSib);
674         current->updateLayerPositions();
675         current = next;
676     }
677 
678     destroy(renderer()->renderArena());
679 }
680 
insertOnlyThisLayer()681 void RenderLayer::insertOnlyThisLayer()
682 {
683     if (!m_parent && renderer()->parent()) {
684         // We need to connect ourselves when our renderer() has a parent.
685         // Find our enclosingLayer and add ourselves.
686         RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
687         RenderLayer* beforeChild = parentLayer->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0;
688         if (parentLayer)
689             parentLayer->addChild(this, beforeChild);
690     }
691 
692     // Remove all descendant layers from the hierarchy and add them to the new position.
693     for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
694         curr->moveLayers(m_parent, this);
695 
696     // Clear out all the clip rects.
697     clearClipRectsIncludingDescendants();
698 }
699 
700 void
convertToLayerCoords(const RenderLayer * ancestorLayer,int & x,int & y) const701 RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const
702 {
703     if (ancestorLayer == this)
704         return;
705 
706     if (renderer()->style()->position() == FixedPosition) {
707         // Add in the offset of the view.  We can obtain this by calling
708         // localToAbsolute() on the RenderView.
709         FloatPoint absPos = renderer()->localToAbsolute(FloatPoint(), true);
710         x += absPos.x();
711         y += absPos.y();
712         return;
713     }
714 
715     RenderLayer* parentLayer;
716     if (renderer()->style()->position() == AbsolutePosition)
717         parentLayer = enclosingPositionedAncestor();
718     else
719         parentLayer = parent();
720 
721     if (!parentLayer) return;
722 
723     parentLayer->convertToLayerCoords(ancestorLayer, x, y);
724 
725     x += xPos();
726     y += yPos();
727 }
728 
panScrollFromPoint(const IntPoint & sourcePoint)729 void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
730 {
731     // We want to reduce the speed if we're close from the original point to improve the handleability of the scroll
732     const int shortDistanceLimit = 100;  // We delimit a 200 pixels long square enclosing the original point
733     const int speedReducer = 2;          // Within this square we divide the scrolling speed by 2
734 
735     const int iconRadius = 10;
736     Frame* frame = renderer()->document()->frame();
737     if (!frame)
738         return;
739 
740     IntPoint currentMousePosition = frame->eventHandler()->currentMousePosition();
741 
742     // We need to check if the current mouse position is out of the window. When the mouse is out of the window, the position is incoherent
743     static IntPoint previousMousePosition;
744     if (currentMousePosition.x() < 0 || currentMousePosition.y() < 0)
745         currentMousePosition = previousMousePosition;
746     else
747         previousMousePosition = currentMousePosition;
748 
749     int xDelta = currentMousePosition.x() - sourcePoint.x();
750     int yDelta = currentMousePosition.y() - sourcePoint.y();
751 
752     if (abs(xDelta) < iconRadius) // at the center we let the space for the icon
753         xDelta = 0;
754     if (abs(yDelta) < iconRadius)
755         yDelta = 0;
756 
757     // Let's attenuate the speed for the short distances
758     if (abs(xDelta) < shortDistanceLimit)
759         xDelta /= speedReducer;
760     if (abs(yDelta) < shortDistanceLimit)
761         yDelta /= speedReducer;
762 
763     scrollByRecursively(xDelta, yDelta);
764 }
765 
scrollByRecursively(int xDelta,int yDelta)766 void RenderLayer::scrollByRecursively(int xDelta, int yDelta)
767 {
768     bool restrictedByLineClamp = false;
769     if (renderer()->parent())
770         restrictedByLineClamp = renderer()->parent()->style()->lineClamp() >= 0;
771 
772     if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
773         int newOffsetX = scrollXOffset() + xDelta;
774         int newOffsetY = scrollYOffset() + yDelta;
775         scrollToOffset(newOffsetX, newOffsetY);
776 
777         // If this layer can't do the scroll we ask its parent
778         int leftToScrollX = newOffsetX - scrollXOffset();
779         int leftToScrollY = newOffsetY - scrollYOffset();
780         if ((leftToScrollX || leftToScrollY) && renderer()->parent()) {
781             renderer()->parent()->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY);
782             Frame* frame = renderer()->document()->frame();
783             if (frame)
784                 frame->eventHandler()->updateAutoscrollRenderer();
785         }
786     } else if (renderer()->view()->frameView())
787         renderer()->view()->frameView()->scrollBy(IntSize(xDelta, yDelta));
788 }
789 
790 
791 void
addScrolledContentOffset(int & x,int & y) const792 RenderLayer::addScrolledContentOffset(int& x, int& y) const
793 {
794     x += scrollXOffset() + m_scrollLeftOverflow;
795     y += scrollYOffset();
796 }
797 
798 void
subtractScrolledContentOffset(int & x,int & y) const799 RenderLayer::subtractScrolledContentOffset(int& x, int& y) const
800 {
801     x -= scrollXOffset() + m_scrollLeftOverflow;
802     y -= scrollYOffset();
803 }
804 
scrollToOffset(int x,int y,bool updateScrollbars,bool repaint)805 void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint)
806 {
807     if (renderer()->style()->overflowX() != OMARQUEE) {
808         if (x < 0) x = 0;
809         if (y < 0) y = 0;
810 
811         // Call the scrollWidth/Height functions so that the dimensions will be computed if they need
812         // to be (for overflow:hidden blocks).
813         int maxX = scrollWidth() - renderer()->clientWidth();
814         int maxY = scrollHeight() - renderer()->clientHeight();
815 
816         if (x > maxX) x = maxX;
817         if (y > maxY) y = maxY;
818     }
819 
820     // FIXME: Eventually, we will want to perform a blit.  For now never
821     // blit, since the check for blitting is going to be very
822     // complicated (since it will involve testing whether our layer
823     // is either occluded by another layer or clipped by an enclosing
824     // layer or contains fixed backgrounds, etc.).
825     int newScrollX = x - m_scrollOriginX;
826     if (m_scrollY == y && m_scrollX == newScrollX)
827         return;
828     m_scrollX = newScrollX;
829     m_scrollY = y;
830 
831     // Update the positions of our child layers.
832     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
833         child->updateLayerPositions(false, false);
834 
835     RenderView* view = renderer()->view();
836 
837     // We should have a RenderView if we're trying to scroll.
838     ASSERT(view);
839     if (view) {
840 #if ENABLE(DASHBOARD_SUPPORT)
841         // Update dashboard regions, scrolling may change the clip of a
842         // particular region.
843         view->frameView()->updateDashboardRegions();
844 #endif
845 
846         view->updateWidgetPositions();
847     }
848 
849     // The caret rect needs to be invalidated after scrolling
850     Frame* frame = renderer()->document()->frame();
851     if (frame)
852         frame->invalidateSelection();
853 
854     // Just schedule a full repaint of our object.
855     if (repaint)
856         renderer()->repaint();
857 
858     if (updateScrollbars) {
859         if (m_hBar)
860             m_hBar->setValue(scrollXOffset());
861         if (m_vBar)
862             m_vBar->setValue(m_scrollY);
863     }
864 
865     // Schedule the scroll DOM event.
866     if (view) {
867         if (FrameView* frameView = view->frameView())
868             frameView->scheduleEvent(Event::create(eventNames().scrollEvent, false, false), EventTargetNodeCast(renderer()->element()));
869     }
870 }
871 
scrollRectToVisible(const IntRect & rect,bool scrollToAnchor,const ScrollAlignment & alignX,const ScrollAlignment & alignY)872 void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
873 {
874     RenderLayer* parentLayer = 0;
875     IntRect newRect = rect;
876     int xOffset = 0, yOffset = 0;
877 
878     // We may end up propagating a scroll event. It is important that we suspend events until
879     // the end of the function since they could delete the layer or the layer's renderer().
880     FrameView* frameView = renderer()->document()->view();
881     if (frameView)
882         frameView->pauseScheduledEvents();
883 
884     bool restrictedByLineClamp = false;
885     if (renderer()->parent()) {
886         parentLayer = renderer()->parent()->enclosingLayer();
887         restrictedByLineClamp = renderer()->parent()->style()->lineClamp() >= 0;
888     }
889 
890     if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
891         // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property.
892         // This will prevent us from revealing text hidden by the slider in Safari RSS.
893         FloatPoint absPos = renderer()->localToAbsolute();
894         absPos.move(renderer()->borderLeft(), renderer()->borderTop());
895 
896         IntRect layerBounds = IntRect(absPos.x() + scrollXOffset(), absPos.y() + scrollYOffset(), renderer()->clientWidth(), renderer()->clientHeight());
897         IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());
898         IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);
899 
900         xOffset = r.x() - absPos.x();
901         yOffset = r.y() - absPos.y();
902         // Adjust offsets if they're outside of the allowable range.
903         xOffset = max(0, min(scrollWidth() - layerBounds.width(), xOffset));
904         yOffset = max(0, min(scrollHeight() - layerBounds.height(), yOffset));
905 
906         if (xOffset != scrollXOffset() || yOffset != scrollYOffset()) {
907             int diffX = scrollXOffset();
908             int diffY = scrollYOffset();
909             scrollToOffset(xOffset, yOffset);
910             diffX = scrollXOffset() - diffX;
911             diffY = scrollYOffset() - diffY;
912             newRect.setX(rect.x() - diffX);
913             newRect.setY(rect.y() - diffY);
914         }
915     } else if (!parentLayer && renderer()->canBeProgramaticallyScrolled(scrollToAnchor)) {
916         if (frameView) {
917             if (renderer()->document() && renderer()->document()->ownerElement() && renderer()->document()->ownerElement()->renderer()) {
918                 IntRect viewRect = frameView->visibleContentRect();
919                 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
920 
921                 xOffset = r.x();
922                 yOffset = r.y();
923                 // Adjust offsets if they're outside of the allowable range.
924                 xOffset = max(0, min(frameView->contentsWidth(), xOffset));
925                 yOffset = max(0, min(frameView->contentsHeight(), yOffset));
926 
927                 frameView->setScrollPosition(IntPoint(xOffset, yOffset));
928                 parentLayer = renderer()->document()->ownerElement()->renderer()->enclosingLayer();
929                 newRect.setX(rect.x() - frameView->scrollX() + frameView->x());
930                 newRect.setY(rect.y() - frameView->scrollY() + frameView->y());
931             } else {
932                 IntRect viewRect = frameView->visibleContentRect(true);
933                 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
934 
935                 // If this is the outermost view that RenderLayer needs to scroll, then we should scroll the view recursively
936                 // Other apps, like Mail, rely on this feature.
937                 frameView->scrollRectIntoViewRecursively(r);
938             }
939         }
940     }
941 
942     if (parentLayer)
943         parentLayer->scrollRectToVisible(newRect, scrollToAnchor, alignX, alignY);
944 
945     if (frameView)
946         frameView->resumeScheduledEvents();
947 }
948 
getRectToExpose(const IntRect & visibleRect,const IntRect & exposeRect,const ScrollAlignment & alignX,const ScrollAlignment & alignY)949 IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
950 {
951     // Determine the appropriate X behavior.
952     ScrollBehavior scrollX;
953     IntRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height());
954     int intersectWidth = intersection(visibleRect, exposeRectX).width();
955     if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL)
956         // If the rectangle is fully visible, use the specified visible behavior.
957         // If the rectangle is partially visible, but over a certain threshold,
958         // then treat it as fully visible to avoid unnecessary horizontal scrolling
959         scrollX = getVisibleBehavior(alignX);
960     else if (intersectWidth == visibleRect.width()) {
961         // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
962         scrollX = getVisibleBehavior(alignX);
963         if (scrollX == alignCenter)
964             scrollX = noScroll;
965     } else if (intersectWidth > 0)
966         // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior
967         scrollX = getPartialBehavior(alignX);
968     else
969         scrollX = getHiddenBehavior(alignX);
970     // If we're trying to align to the closest edge, and the exposeRect is further right
971     // than the visibleRect, and not bigger than the visible area, then align with the right.
972     if (scrollX == alignToClosestEdge && exposeRect.right() > visibleRect.right() && exposeRect.width() < visibleRect.width())
973         scrollX = alignRight;
974 
975     // Given the X behavior, compute the X coordinate.
976     int x;
977     if (scrollX == noScroll)
978         x = visibleRect.x();
979     else if (scrollX == alignRight)
980         x = exposeRect.right() - visibleRect.width();
981     else if (scrollX == alignCenter)
982         x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2;
983     else
984         x = exposeRect.x();
985 
986     // Determine the appropriate Y behavior.
987     ScrollBehavior scrollY;
988     IntRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height());
989     int intersectHeight = intersection(visibleRect, exposeRectY).height();
990     if (intersectHeight == exposeRect.height())
991         // If the rectangle is fully visible, use the specified visible behavior.
992         scrollY = getVisibleBehavior(alignY);
993     else if (intersectHeight == visibleRect.height()) {
994         // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
995         scrollY = getVisibleBehavior(alignY);
996         if (scrollY == alignCenter)
997             scrollY = noScroll;
998     } else if (intersectHeight > 0)
999         // If the rectangle is partially visible, use the specified partial behavior
1000         scrollY = getPartialBehavior(alignY);
1001     else
1002         scrollY = getHiddenBehavior(alignY);
1003     // If we're trying to align to the closest edge, and the exposeRect is further down
1004     // than the visibleRect, and not bigger than the visible area, then align with the bottom.
1005     if (scrollY == alignToClosestEdge && exposeRect.bottom() > visibleRect.bottom() && exposeRect.height() < visibleRect.height())
1006         scrollY = alignBottom;
1007 
1008     // Given the Y behavior, compute the Y coordinate.
1009     int y;
1010     if (scrollY == noScroll)
1011         y = visibleRect.y();
1012     else if (scrollY == alignBottom)
1013         y = exposeRect.bottom() - visibleRect.height();
1014     else if (scrollY == alignCenter)
1015         y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2;
1016     else
1017         y = exposeRect.y();
1018 
1019     return IntRect(IntPoint(x, y), visibleRect.size());
1020 }
1021 
autoscroll()1022 void RenderLayer::autoscroll()
1023 {
1024     Frame* frame = renderer()->document()->frame();
1025     if (!frame)
1026         return;
1027 
1028     FrameView* frameView = frame->view();
1029     if (!frameView)
1030         return;
1031 
1032     frame->eventHandler()->updateSelectionForMouseDrag();
1033 
1034     IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition());
1035     scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, gAlignToEdgeIfNeeded, gAlignToEdgeIfNeeded);
1036 }
1037 
resize(const PlatformMouseEvent & evt,const IntSize & oldOffset)1038 void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset)
1039 {
1040     if (!inResizeMode() || !renderer()->hasOverflowClip())
1041         return;
1042 
1043     // Set the width and height of the shadow ancestor node if there is one.
1044     // This is necessary for textarea elements since the resizable layer is in the shadow content.
1045     Element* element = static_cast<Element*>(renderer()->node()->shadowAncestorNode());
1046     RenderBox* renderer = toRenderBox(element->renderer());
1047 
1048     EResize resize = renderer->style()->resize();
1049     if (resize == RESIZE_NONE)
1050         return;
1051 
1052     Document* document = element->document();
1053     if (!document->frame()->eventHandler()->mousePressed())
1054         return;
1055 
1056     float zoomFactor = renderer->style()->effectiveZoom();
1057 
1058     IntSize newOffset = offsetFromResizeCorner(document->view()->windowToContents(evt.pos()));
1059     newOffset.setWidth(newOffset.width() / zoomFactor);
1060     newOffset.setHeight(newOffset.height() / zoomFactor);
1061 
1062     IntSize currentSize = IntSize(renderer->width() / zoomFactor, renderer->height() / zoomFactor);
1063     IntSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize);
1064     element->setMinimumSizeForResizing(minimumSize);
1065 
1066     IntSize adjustedOldOffset = IntSize(oldOffset.width() / zoomFactor, oldOffset.height() / zoomFactor);
1067 
1068     IntSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize;
1069 
1070     CSSStyleDeclaration* style = element->style();
1071     bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX;
1072 
1073     ExceptionCode ec;
1074 
1075     if (difference.width()) {
1076         if (element && element->isControl()) {
1077             // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
1078             style->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false, ec);
1079             style->setProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false, ec);
1080         }
1081         int baseWidth = renderer->width() - (isBoxSizingBorder ? 0
1082             : renderer->borderLeft() + renderer->paddingLeft() + renderer->borderRight() + renderer->paddingRight());
1083         baseWidth = baseWidth / zoomFactor;
1084         style->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false, ec);
1085     }
1086 
1087     if (difference.height()) {
1088         if (element && element->isControl()) {
1089             // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
1090             style->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false, ec);
1091             style->setProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false, ec);
1092         }
1093         int baseHeight = renderer->height() - (isBoxSizingBorder ? 0
1094             : renderer->borderTop() + renderer->paddingTop() + renderer->borderBottom() + renderer->paddingBottom());
1095         baseHeight = baseHeight / zoomFactor;
1096         style->setProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false, ec);
1097     }
1098 
1099     document->updateLayout();
1100 
1101     // FIXME (Radar 4118564): We should also autoscroll the window as necessary to keep the point under the cursor in view.
1102 }
1103 
valueChanged(Scrollbar *)1104 void RenderLayer::valueChanged(Scrollbar*)
1105 {
1106     // Update scroll position from scrollbars.
1107 
1108     bool needUpdate = false;
1109     int newX = scrollXOffset();
1110     int newY = m_scrollY;
1111 
1112     if (m_hBar) {
1113         newX = m_hBar->value();
1114         if (newX != scrollXOffset())
1115            needUpdate = true;
1116     }
1117 
1118     if (m_vBar) {
1119         newY = m_vBar->value();
1120         if (newY != m_scrollY)
1121            needUpdate = true;
1122     }
1123 
1124     if (needUpdate)
1125         scrollToOffset(newX, newY, false);
1126 }
1127 
isActive() const1128 bool RenderLayer::isActive() const
1129 {
1130     Page* page = renderer()->document()->frame()->page();
1131     return page && page->focusController()->isActive();
1132 }
1133 
1134 
cornerRect(const RenderLayer * layer,const IntRect & bounds)1135 static IntRect cornerRect(const RenderLayer* layer, const IntRect& bounds)
1136 {
1137     int horizontalThickness;
1138     int verticalThickness;
1139     if (!layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
1140         // FIXME: This isn't right.  We need to know the thickness of custom scrollbars
1141         // even when they don't exist in order to set the resizer square size properly.
1142         horizontalThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();
1143         verticalThickness = horizontalThickness;
1144     } else if (layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
1145         horizontalThickness = layer->verticalScrollbar()->width();
1146         verticalThickness = horizontalThickness;
1147     } else if (layer->horizontalScrollbar() && !layer->verticalScrollbar()) {
1148         verticalThickness = layer->horizontalScrollbar()->height();
1149         horizontalThickness = verticalThickness;
1150     } else {
1151         horizontalThickness = layer->verticalScrollbar()->width();
1152         verticalThickness = layer->horizontalScrollbar()->height();
1153     }
1154     return IntRect(bounds.right() - horizontalThickness - layer->renderer()->style()->borderRightWidth(),
1155                    bounds.bottom() - verticalThickness - layer->renderer()->style()->borderBottomWidth(),
1156                    horizontalThickness, verticalThickness);
1157 }
1158 
scrollCornerRect(const RenderLayer * layer,const IntRect & bounds)1159 static IntRect scrollCornerRect(const RenderLayer* layer, const IntRect& bounds)
1160 {
1161     // We have a scrollbar corner when a scrollbar is visible and not filling the entire length of the box.
1162     // This happens when:
1163     // (a) A resizer is present and at least one scrollbar is present
1164     // (b) Both scrollbars are present.
1165     bool hasHorizontalBar = layer->horizontalScrollbar();
1166     bool hasVerticalBar = layer->verticalScrollbar();
1167     bool hasResizer = layer->renderer()->style()->resize() != RESIZE_NONE;
1168     if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar)))
1169         return cornerRect(layer, bounds);
1170     return IntRect();
1171 }
1172 
resizerCornerRect(const RenderLayer * layer,const IntRect & bounds)1173 static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds)
1174 {
1175     if (layer->renderer()->style()->resize() == RESIZE_NONE)
1176         return IntRect();
1177     return cornerRect(layer, bounds);
1178 }
1179 
scrollbarCornerPresent() const1180 bool RenderLayer::scrollbarCornerPresent() const
1181 {
1182     return !scrollCornerRect(this, renderer()->borderBoxRect()).isEmpty();
1183 }
1184 
invalidateScrollbarRect(Scrollbar * scrollbar,const IntRect & rect)1185 void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
1186 {
1187     IntRect scrollRect = rect;
1188     if (scrollbar == m_vBar.get())
1189         scrollRect.move(renderer()->width() - renderer()->borderRight() - scrollbar->width(), renderer()->borderTop());
1190     else
1191         scrollRect.move(renderer()->borderLeft(), renderer()->height() - renderer()->borderBottom() - scrollbar->height());
1192     renderer()->repaintRectangle(scrollRect);
1193 }
1194 
createScrollbar(ScrollbarOrientation orientation)1195 PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation)
1196 {
1197     RefPtr<Scrollbar> widget;
1198     bool hasCustomScrollbarStyle = renderer()->node()->shadowAncestorNode()->renderer()->style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
1199     if (hasCustomScrollbarStyle)
1200         widget = RenderScrollbar::createCustomScrollbar(this, orientation, renderer()->node()->shadowAncestorNode()->renderBox());
1201     else
1202         widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
1203     renderer()->document()->view()->addChild(widget.get());
1204     return widget.release();
1205 }
1206 
destroyScrollbar(ScrollbarOrientation orientation)1207 void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation)
1208 {
1209     RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
1210     if (scrollbar) {
1211         scrollbar->removeFromParent();
1212         scrollbar->setClient(0);
1213         scrollbar = 0;
1214     }
1215 }
1216 
setHasHorizontalScrollbar(bool hasScrollbar)1217 void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
1218 {
1219     if (hasScrollbar == (m_hBar != 0))
1220         return;
1221 
1222     if (hasScrollbar)
1223         m_hBar = createScrollbar(HorizontalScrollbar);
1224     else
1225         destroyScrollbar(HorizontalScrollbar);
1226 
1227     // Destroying or creating one bar can cause our scrollbar corner to come and go.  We need to update the opposite scrollbar's style.
1228     if (m_hBar)
1229         m_hBar->styleChanged();
1230     if (m_vBar)
1231         m_vBar->styleChanged();
1232 
1233 #if ENABLE(DASHBOARD_SUPPORT)
1234     // Force an update since we know the scrollbars have changed things.
1235     if (renderer()->document()->hasDashboardRegions())
1236         renderer()->document()->setDashboardRegionsDirty(true);
1237 #endif
1238 }
1239 
setHasVerticalScrollbar(bool hasScrollbar)1240 void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
1241 {
1242     if (hasScrollbar == (m_vBar != 0))
1243         return;
1244 
1245     if (hasScrollbar)
1246         m_vBar = createScrollbar(VerticalScrollbar);
1247     else
1248         destroyScrollbar(VerticalScrollbar);
1249 
1250      // Destroying or creating one bar can cause our scrollbar corner to come and go.  We need to update the opposite scrollbar's style.
1251     if (m_hBar)
1252         m_hBar->styleChanged();
1253     if (m_vBar)
1254         m_vBar->styleChanged();
1255 
1256 #if ENABLE(DASHBOARD_SUPPORT)
1257     // Force an update since we know the scrollbars have changed things.
1258     if (renderer()->document()->hasDashboardRegions())
1259         renderer()->document()->setDashboardRegionsDirty(true);
1260 #endif
1261 }
1262 
verticalScrollbarWidth() const1263 int RenderLayer::verticalScrollbarWidth() const
1264 {
1265     if (!m_vBar)
1266         return 0;
1267     return m_vBar->width();
1268 }
1269 
horizontalScrollbarHeight() const1270 int RenderLayer::horizontalScrollbarHeight() const
1271 {
1272     if (!m_hBar)
1273         return 0;
1274     return m_hBar->height();
1275 }
1276 
offsetFromResizeCorner(const IntPoint & absolutePoint) const1277 IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const
1278 {
1279     // Currently the resize corner is always the bottom right corner
1280     IntPoint bottomRight(width(), height());
1281     IntPoint localPoint = absoluteToContents(absolutePoint);
1282     return localPoint - bottomRight;
1283 }
1284 
positionOverflowControls(int tx,int ty)1285 void RenderLayer::positionOverflowControls(int tx, int ty)
1286 {
1287     if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
1288         return;
1289 
1290     IntRect borderBox = renderer()->borderBoxRect();
1291     IntRect scrollCorner(scrollCornerRect(this, borderBox));
1292     IntRect absBounds(borderBox.x() + tx, borderBox.y() + ty, borderBox.width(), borderBox.height());
1293     if (m_vBar)
1294         m_vBar->setFrameRect(IntRect(absBounds.right() - renderer()->borderRight() - m_vBar->width(),
1295                                      absBounds.y() + renderer()->borderTop(),
1296                                      m_vBar->width(),
1297                                      absBounds.height() - (renderer()->borderTop() + renderer()->borderBottom()) - scrollCorner.height()));
1298 
1299     if (m_hBar)
1300         m_hBar->setFrameRect(IntRect(absBounds.x() + renderer()->borderLeft(),
1301                                      absBounds.bottom() - renderer()->borderBottom() - m_hBar->height(),
1302                                      absBounds.width() - (renderer()->borderLeft() + renderer()->borderRight()) - scrollCorner.width(),
1303                                      m_hBar->height()));
1304 
1305     if (m_scrollCorner)
1306         m_scrollCorner->setFrameRect(scrollCorner);
1307     if (m_resizer)
1308         m_resizer->setFrameRect(resizerCornerRect(this, borderBox));
1309 }
1310 
scrollWidth()1311 int RenderLayer::scrollWidth()
1312 {
1313     if (m_scrollDimensionsDirty)
1314         computeScrollDimensions();
1315     return m_scrollWidth;
1316 }
1317 
scrollHeight()1318 int RenderLayer::scrollHeight()
1319 {
1320     if (m_scrollDimensionsDirty)
1321         computeScrollDimensions();
1322     return m_scrollHeight;
1323 }
1324 
computeScrollDimensions(bool * needHBar,bool * needVBar)1325 void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
1326 {
1327     m_scrollDimensionsDirty = false;
1328 
1329     bool ltr = renderer()->style()->direction() == LTR;
1330 
1331     int clientWidth = renderer()->clientWidth();
1332     int clientHeight = renderer()->clientHeight();
1333 
1334     m_scrollLeftOverflow = ltr ? 0 : min(0, renderer()->leftmostPosition(true, false) - renderer()->borderLeft());
1335 
1336     int rightPos = ltr ?
1337                     renderer()->rightmostPosition(true, false) - renderer()->borderLeft() :
1338                     clientWidth - m_scrollLeftOverflow;
1339     int bottomPos = renderer()->lowestPosition(true, false) - renderer()->borderTop();
1340 
1341     m_scrollWidth = max(rightPos, clientWidth);
1342     m_scrollHeight = max(bottomPos, clientHeight);
1343 
1344     m_scrollOriginX = ltr ? 0 : m_scrollWidth - clientWidth;
1345 
1346     if (needHBar)
1347         *needHBar = rightPos > clientWidth;
1348     if (needVBar)
1349         *needVBar = bottomPos > clientHeight;
1350 }
1351 
updateOverflowStatus(bool horizontalOverflow,bool verticalOverflow)1352 void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
1353 {
1354     if (m_overflowStatusDirty) {
1355         m_horizontalOverflow = horizontalOverflow;
1356         m_verticalOverflow = verticalOverflow;
1357         m_overflowStatusDirty = false;
1358 
1359         return;
1360     }
1361 
1362     bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
1363     bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
1364 
1365     if (horizontalOverflowChanged || verticalOverflowChanged) {
1366         m_horizontalOverflow = horizontalOverflow;
1367         m_verticalOverflow = verticalOverflow;
1368 
1369         if (FrameView* frameView = renderer()->document()->view()) {
1370             frameView->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow),
1371                 EventTargetNodeCast(renderer()->element()));
1372         }
1373     }
1374 }
1375 
1376 void
updateScrollInfoAfterLayout()1377 RenderLayer::updateScrollInfoAfterLayout()
1378 {
1379     m_scrollDimensionsDirty = true;
1380 
1381     bool horizontalOverflow, verticalOverflow;
1382     computeScrollDimensions(&horizontalOverflow, &verticalOverflow);
1383 
1384     if (renderer()->style()->overflowX() != OMARQUEE) {
1385         // Layout may cause us to be in an invalid scroll position.  In this case we need
1386         // to pull our scroll offsets back to the max (or push them up to the min).
1387         int newX = max(0, min(scrollXOffset(), scrollWidth() - renderer()->clientWidth()));
1388         int newY = max(0, min(m_scrollY, scrollHeight() - renderer()->clientHeight()));
1389         if (newX != scrollXOffset() || newY != m_scrollY) {
1390             RenderView* view = renderer()->view();
1391             ASSERT(view);
1392             // scrollToOffset() may call updateLayerPositions(), which doesn't work
1393             // with LayoutState.
1394             // FIXME: Remove the disableLayoutState/enableLayoutState if the above changes.
1395             if (view)
1396                 view->disableLayoutState();
1397             scrollToOffset(newX, newY);
1398             if (view)
1399                 view->enableLayoutState();
1400         }
1401     }
1402 
1403     bool haveHorizontalBar = m_hBar;
1404     bool haveVerticalBar = m_vBar;
1405 
1406     // overflow:scroll should just enable/disable.
1407     if (renderer()->style()->overflowX() == OSCROLL)
1408         m_hBar->setEnabled(horizontalOverflow);
1409     if (renderer()->style()->overflowY() == OSCROLL)
1410         m_vBar->setEnabled(verticalOverflow);
1411 
1412     // A dynamic change from a scrolling overflow to overflow:hidden means we need to get rid of any
1413     // scrollbars that may be present.
1414     if (renderer()->style()->overflowX() == OHIDDEN && haveHorizontalBar)
1415         setHasHorizontalScrollbar(false);
1416     if (renderer()->style()->overflowY() == OHIDDEN && haveVerticalBar)
1417         setHasVerticalScrollbar(false);
1418 
1419     // overflow:auto may need to lay out again if scrollbars got added/removed.
1420     bool scrollbarsChanged = (renderer()->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) ||
1421                              (renderer()->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
1422     if (scrollbarsChanged) {
1423         if (renderer()->hasAutoHorizontalScrollbar())
1424             setHasHorizontalScrollbar(horizontalOverflow);
1425         if (renderer()->hasAutoVerticalScrollbar())
1426             setHasVerticalScrollbar(verticalOverflow);
1427 
1428 #if ENABLE(DASHBOARD_SUPPORT)
1429         // Force an update since we know the scrollbars have changed things.
1430         if (renderer()->document()->hasDashboardRegions())
1431             renderer()->document()->setDashboardRegionsDirty(true);
1432 #endif
1433 
1434         renderer()->repaint();
1435 
1436         if (renderer()->style()->overflowX() == OAUTO || renderer()->style()->overflowY() == OAUTO) {
1437             if (!m_inOverflowRelayout) {
1438                 // Our proprietary overflow: overlay value doesn't trigger a layout.
1439                 m_inOverflowRelayout = true;
1440                 renderer()->setNeedsLayout(true, false);
1441                 if (renderer()->isRenderBlock())
1442                     static_cast<RenderBlock*>(renderer())->layoutBlock(true);
1443                 else
1444                     renderer()->layout();
1445                 m_inOverflowRelayout = false;
1446             }
1447         }
1448     }
1449 
1450     // If overflow:scroll is turned into overflow:auto a bar might still be disabled (Bug 11985).
1451     if (m_hBar && renderer()->hasAutoHorizontalScrollbar())
1452         m_hBar->setEnabled(true);
1453     if (m_vBar && renderer()->hasAutoVerticalScrollbar())
1454         m_vBar->setEnabled(true);
1455 
1456     // Set up the range (and page step/line step).
1457     if (m_hBar) {
1458         int clientWidth = renderer()->clientWidth();
1459         int pageStep = (clientWidth - cAmountToKeepWhenPaging);
1460         if (pageStep < 0) pageStep = clientWidth;
1461         m_hBar->setSteps(cScrollbarPixelsPerLineStep, pageStep);
1462         m_hBar->setProportion(clientWidth, m_scrollWidth);
1463         m_hBar->setValue(scrollXOffset());
1464     }
1465     if (m_vBar) {
1466         int clientHeight = renderer()->clientHeight();
1467         int pageStep = (clientHeight - cAmountToKeepWhenPaging);
1468         if (pageStep < 0) pageStep = clientHeight;
1469         m_vBar->setSteps(cScrollbarPixelsPerLineStep, pageStep);
1470         m_vBar->setProportion(clientHeight, m_scrollHeight);
1471     }
1472 
1473     if (renderer()->element() && renderer()->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1474         updateOverflowStatus(horizontalOverflow, verticalOverflow);
1475 }
1476 
paintOverflowControls(GraphicsContext * context,int tx,int ty,const IntRect & damageRect)1477 void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
1478 {
1479     // Don't do anything if we have no overflow.
1480     if (!renderer()->hasOverflowClip())
1481         return;
1482 
1483     // Move the scrollbar widgets if necessary.  We normally move and resize widgets during layout, but sometimes
1484     // widgets can move without layout occurring (most notably when you scroll a document that
1485     // contains fixed positioned elements).
1486     positionOverflowControls(tx, ty);
1487 
1488     // Now that we're sure the scrollbars are in the right place, paint them.
1489     if (m_hBar)
1490         m_hBar->paint(context, damageRect);
1491     if (m_vBar)
1492         m_vBar->paint(context, damageRect);
1493 
1494     // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the
1495     // edge of the box.
1496     paintScrollCorner(context, tx, ty, damageRect);
1497 
1498     // Paint our resizer last, since it sits on top of the scroll corner.
1499     paintResizer(context, tx, ty, damageRect);
1500 }
1501 
paintScrollCorner(GraphicsContext * context,int tx,int ty,const IntRect & damageRect)1502 void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
1503 {
1504     IntRect cornerRect = scrollCornerRect(this, renderer()->borderBoxRect());
1505     IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
1506     if (!absRect.intersects(damageRect))
1507         return;
1508 
1509     if (context->updatingControlTints()) {
1510         updateScrollCornerStyle();
1511         return;
1512     }
1513 
1514     if (m_scrollCorner) {
1515         m_scrollCorner->paintIntoRect(context, tx, ty, absRect);
1516         return;
1517     }
1518 
1519     context->fillRect(absRect, Color::white);
1520 }
1521 
paintResizer(GraphicsContext * context,int tx,int ty,const IntRect & damageRect)1522 void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
1523 {
1524     if (renderer()->style()->resize() == RESIZE_NONE)
1525         return;
1526 
1527     IntRect cornerRect = resizerCornerRect(this, renderer()->borderBoxRect());
1528     IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
1529     if (!absRect.intersects(damageRect))
1530         return;
1531 
1532     if (context->updatingControlTints()) {
1533         updateResizerStyle();
1534         return;
1535     }
1536 
1537     if (m_resizer) {
1538         m_resizer->paintIntoRect(context, tx, ty, absRect);
1539         return;
1540     }
1541 
1542     // Paint the resizer control.
1543     DEFINE_STATIC_LOCAL(RefPtr<Image>, resizeCornerImage, (Image::loadPlatformResource("textAreaResizeCorner")));
1544     IntPoint imagePoint(absRect.right() - resizeCornerImage->width(), absRect.bottom() - resizeCornerImage->height());
1545     context->drawImage(resizeCornerImage.get(), imagePoint);
1546 
1547     // Draw a frame around the resizer (1px grey line) if there are any scrollbars present.
1548     // Clipping will exclude the right and bottom edges of this frame.
1549     if (m_hBar || m_vBar) {
1550         context->save();
1551         IntRect largerCorner = absRect;
1552         largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1));
1553         context->setStrokeColor(Color(makeRGB(217, 217, 217)));
1554         context->setStrokeThickness(1.0f);
1555         context->setFillColor(Color::transparent);
1556         context->drawRect(largerCorner);
1557         context->restore();
1558     }
1559 }
1560 
isPointInResizeControl(const IntPoint & absolutePoint) const1561 bool RenderLayer::isPointInResizeControl(const IntPoint& absolutePoint) const
1562 {
1563     if (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)
1564         return false;
1565 
1566     IntPoint localPoint = absoluteToContents(absolutePoint);
1567 
1568     IntRect localBounds(0, 0, renderer()->width(), renderer()->height());
1569     return resizerCornerRect(this, localBounds).contains(localPoint);
1570 }
1571 
hitTestOverflowControls(HitTestResult & result)1572 bool RenderLayer::hitTestOverflowControls(HitTestResult& result)
1573 {
1574     if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
1575         return false;
1576 
1577     int x = 0;
1578     int y = 0;
1579     convertToLayerCoords(root(), x, y);
1580     IntRect absBounds(x, y, renderer()->width(), renderer()->height());
1581 
1582     IntRect resizeControlRect;
1583     if (renderer()->style()->resize() != RESIZE_NONE) {
1584         resizeControlRect = resizerCornerRect(this, absBounds);
1585         if (resizeControlRect.contains(result.point()))
1586             return true;
1587     }
1588 
1589     int resizeControlSize = max(resizeControlRect.height(), 0);
1590 
1591     if (m_vBar) {
1592         IntRect vBarRect(absBounds.right() - renderer()->borderRight() - m_vBar->width(), absBounds.y() + renderer()->borderTop(), m_vBar->width(), absBounds.height() - (renderer()->borderTop() + renderer()->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
1593         if (vBarRect.contains(result.point())) {
1594             result.setScrollbar(m_vBar.get());
1595             return true;
1596         }
1597     }
1598 
1599     resizeControlSize = max(resizeControlRect.width(), 0);
1600     if (m_hBar) {
1601         IntRect hBarRect(absBounds.x() + renderer()->borderLeft(), absBounds.bottom() - renderer()->borderBottom() - m_hBar->height(), absBounds.width() - (renderer()->borderLeft() + renderer()->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize), m_hBar->height());
1602         if (hBarRect.contains(result.point())) {
1603             result.setScrollbar(m_hBar.get());
1604             return true;
1605         }
1606     }
1607 
1608     return false;
1609 }
1610 
scroll(ScrollDirection direction,ScrollGranularity granularity,float multiplier)1611 bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
1612 {
1613     bool didHorizontalScroll = false;
1614     bool didVerticalScroll = false;
1615 
1616     if (m_hBar) {
1617         if (granularity == ScrollByDocument) {
1618             // Special-case for the ScrollByDocument granularity. A document scroll can only be up
1619             // or down and in both cases the horizontal bar goes all the way to the left.
1620             didHorizontalScroll = m_hBar->scroll(ScrollLeft, ScrollByDocument, multiplier);
1621         } else
1622             didHorizontalScroll = m_hBar->scroll(direction, granularity, multiplier);
1623     }
1624 
1625     if (m_vBar)
1626         didVerticalScroll = m_vBar->scroll(direction, granularity, multiplier);
1627 
1628     return (didHorizontalScroll || didVerticalScroll);
1629 }
1630 
1631 void
paint(GraphicsContext * p,const IntRect & damageRect,PaintRestriction paintRestriction,RenderObject * paintingRoot)1632 RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintRestriction paintRestriction, RenderObject *paintingRoot)
1633 {
1634     paintLayer(this, p, damageRect, false, paintRestriction, paintingRoot);
1635 }
1636 
setClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)1637 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
1638 {
1639     if (paintDirtyRect == clipRect)
1640         return;
1641     p->save();
1642     p->clip(clipRect);
1643 }
1644 
restoreClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)1645 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
1646 {
1647     if (paintDirtyRect == clipRect)
1648         return;
1649     p->restore();
1650 }
1651 
1652 void
paintLayer(RenderLayer * rootLayer,GraphicsContext * p,const IntRect & paintDirtyRect,bool haveTransparency,PaintRestriction paintRestriction,RenderObject * paintingRoot,bool appliedTransform,bool temporaryClipRects)1653 RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
1654                         const IntRect& paintDirtyRect, bool haveTransparency, PaintRestriction paintRestriction,
1655                         RenderObject* paintingRoot, bool appliedTransform, bool temporaryClipRects)
1656 {
1657     // Avoid painting layers when stylesheets haven't loaded.  This eliminates FOUC.
1658     // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
1659     // will do a full repaint().
1660     if (renderer()->document()->didLayoutWithPendingStylesheets() && !renderer()->isRenderView() && !renderer()->isRoot())
1661         return;
1662 
1663     // If this layer is totally invisible then there is nothing to paint.
1664     if (!renderer()->opacity())
1665         return;
1666 
1667     if (isTransparent())
1668         haveTransparency = true;
1669 
1670     // Apply a transform if we have one.  A reflection is considered to be a transform, since it is a flip and a translate.
1671     if (m_transform && !appliedTransform) {
1672         // If the transform can't be inverted, then don't paint anything.
1673         if (!m_transform->isInvertible())
1674             return;
1675 
1676         // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
1677         // layer from the parent now.
1678         if (haveTransparency)
1679             parent()->beginTransparencyLayers(p, rootLayer);
1680 
1681         // Make sure the parent's clip rects have been calculated.
1682         IntRect clipRect = paintDirtyRect;
1683         if (parent()) {
1684             if (temporaryClipRects) {
1685                 ClipRects parentClipRects;
1686                 parent()->calculateClipRects(rootLayer, parentClipRects);
1687                 clipRect = parentClipRects.overflowClipRect();
1688             } else {
1689                 parent()->updateClipRects(rootLayer);
1690                 clipRect = parent()->clipRects()->overflowClipRect();
1691             }
1692             clipRect.intersect(paintDirtyRect);
1693         }
1694 
1695         // Push the parent coordinate space's clip.
1696         setClip(p, paintDirtyRect, clipRect);
1697 
1698         // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
1699         // This involves subtracting out the position of the layer in our current coordinate space.
1700         int x = 0;
1701         int y = 0;
1702         convertToLayerCoords(rootLayer, x, y);
1703         TransformationMatrix transform;
1704         transform.translate(x, y);
1705         transform = *m_transform * transform;
1706 
1707         // Apply the transform.
1708         p->save();
1709         p->concatCTM(transform);
1710 
1711         // Now do a paint with the root layer shifted to be us.
1712         paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), haveTransparency, paintRestriction, paintingRoot, true, temporaryClipRects);
1713 
1714         p->restore();
1715 
1716         // Restore the clip.
1717         restoreClip(p, paintDirtyRect, clipRect);
1718 
1719         return;
1720     }
1721 
1722     // Paint the reflection first if we have one.
1723     if (m_reflection && !m_paintingInsideReflection && (!m_transform || appliedTransform)) {
1724         // Mark that we are now inside replica painting.
1725         m_paintingInsideReflection = true;
1726         reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
1727         m_paintingInsideReflection = false;
1728     }
1729 
1730     // Calculate the clip rects we should use.
1731     IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
1732     calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, temporaryClipRects);
1733     int x = layerBounds.x();
1734     int y = layerBounds.y();
1735     int tx = x - renderer()->x();
1736     int ty = y - renderer()->y();
1737 
1738     // Ensure our lists are up-to-date.
1739     updateZOrderLists();
1740     updateOverflowList();
1741 
1742     bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText;
1743     bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
1744 
1745     // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
1746     // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
1747     // Else, our renderer tree may or may not contain the painting root, so we pass that root along
1748     // so it will be tested against as we decend through the renderers.
1749     RenderObject* paintingRootForRenderer = 0;
1750     if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
1751         paintingRootForRenderer = paintingRoot;
1752 
1753     // We want to paint our layer, but only if we intersect the damage rect.
1754     bool shouldPaint = intersectsDamageRect(layerBounds, damageRect, rootLayer) && m_hasVisibleContent;
1755     if (shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
1756         // Begin transparency layers lazily now that we know we have to paint something.
1757         if (haveTransparency)
1758             beginTransparencyLayers(p, rootLayer);
1759 
1760         // Paint our background first, before painting any child layers.
1761         // Establish the clip used to paint our background.
1762         setClip(p, paintDirtyRect, damageRect);
1763 
1764         // Paint the background.
1765         RenderObject::PaintInfo paintInfo(p, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
1766         renderer()->paint(paintInfo, tx, ty);
1767 
1768         // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
1769         // z-index.  We paint after we painted the background/border, so that the scrollbars will
1770         // sit above the background/border.
1771         paintOverflowControls(p, x, y, damageRect);
1772 
1773         // Restore the clip.
1774         restoreClip(p, paintDirtyRect, damageRect);
1775     }
1776 
1777     // Now walk the sorted list of children with negative z-indices.
1778     if (m_negZOrderList)
1779         for (Vector<RenderLayer*>::iterator it = m_negZOrderList->begin(); it != m_negZOrderList->end(); ++it)
1780             it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
1781 
1782     // Now establish the appropriate clip and paint our child RenderObjects.
1783     if (shouldPaint && !clipRectToApply.isEmpty()) {
1784         // Begin transparency layers lazily now that we know we have to paint something.
1785         if (haveTransparency)
1786             beginTransparencyLayers(p, rootLayer);
1787 
1788         // Set up the clip used when painting our children.
1789         setClip(p, paintDirtyRect, clipRectToApply);
1790         RenderObject::PaintInfo paintInfo(p, clipRectToApply,
1791                                           selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
1792                                           forceBlackText, paintingRootForRenderer, 0);
1793         renderer()->paint(paintInfo, tx, ty);
1794         if (!selectionOnly) {
1795             paintInfo.phase = PaintPhaseFloat;
1796             renderer()->paint(paintInfo, tx, ty);
1797             paintInfo.phase = PaintPhaseForeground;
1798             renderer()->paint(paintInfo, tx, ty);
1799             paintInfo.phase = PaintPhaseChildOutlines;
1800             renderer()->paint(paintInfo, tx, ty);
1801         }
1802 
1803         // Now restore our clip.
1804         restoreClip(p, paintDirtyRect, clipRectToApply);
1805     }
1806 
1807     if (!outlineRect.isEmpty()) {
1808         // Paint our own outline
1809         RenderObject::PaintInfo paintInfo(p, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
1810         setClip(p, paintDirtyRect, outlineRect);
1811         renderer()->paint(paintInfo, tx, ty);
1812         restoreClip(p, paintDirtyRect, outlineRect);
1813     }
1814 
1815     // Paint any child layers that have overflow.
1816     if (m_overflowList)
1817         for (Vector<RenderLayer*>::iterator it = m_overflowList->begin(); it != m_overflowList->end(); ++it)
1818             it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
1819 
1820     // Now walk the sorted list of children with positive z-indices.
1821     if (m_posZOrderList)
1822         for (Vector<RenderLayer*>::iterator it = m_posZOrderList->begin(); it != m_posZOrderList->end(); ++it)
1823             it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
1824 
1825     if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
1826         setClip(p, paintDirtyRect, damageRect);
1827 
1828         // Paint the mask.
1829         RenderObject::PaintInfo paintInfo(p, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0);
1830         renderer()->paint(paintInfo, tx, ty);
1831 
1832         // Restore the clip.
1833         restoreClip(p, paintDirtyRect, damageRect);
1834     }
1835 
1836     // End our transparency layer
1837     if (isTransparent() && m_usedTransparency) {
1838         p->endTransparencyLayer();
1839         p->restore();
1840         m_usedTransparency = false;
1841     }
1842 }
1843 
frameVisibleRect(RenderObject * renderer)1844 static inline IntRect frameVisibleRect(RenderObject* renderer)
1845 {
1846     FrameView* frameView = renderer->document()->view();
1847     if (!frameView)
1848         return IntRect();
1849 
1850     return frameView->visibleContentRect();
1851 }
1852 
hitTest(const HitTestRequest & request,HitTestResult & result)1853 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
1854 {
1855     renderer()->document()->updateLayout();
1856 
1857     IntRect boundsRect(m_x, m_y, width(), height());
1858     boundsRect.intersect(frameVisibleRect(renderer()));
1859 
1860     RenderLayer* insideLayer = hitTestLayer(this, request, result, boundsRect, result.point());
1861 
1862     // Now determine if the result is inside an anchor; make sure an image map wins if
1863     // it already set URLElement and only use the innermost.
1864     Node* node = result.innerNode();
1865     while (node) {
1866         // for imagemaps, URLElement is the associated area element not the image itself
1867         if (node->isLink() && !result.URLElement() && !node->hasTagName(imgTag))
1868             result.setURLElement(static_cast<Element*>(node));
1869         node = node->eventParentNode();
1870     }
1871 
1872     // Next set up the correct :hover/:active state along the new chain.
1873     updateHoverActiveState(request, result);
1874 
1875     // Now return whether we were inside this layer (this will always be true for the root
1876     // layer).
1877     return insideLayer;
1878 }
1879 
enclosingElement() const1880 Node* RenderLayer::enclosingElement() const
1881 {
1882     for (RenderObject* r = renderer(); r; r = r->parent()) {
1883         if (Node* e = r->element())
1884             return e;
1885     }
1886     ASSERT_NOT_REACHED();
1887     return 0;
1888 }
1889 
hitTestLayer(RenderLayer * rootLayer,const HitTestRequest & request,HitTestResult & result,const IntRect & hitTestRect,const IntPoint & hitTestPoint,bool appliedTransform)1890 RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
1891                                        const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform)
1892 {
1893     // Apply a transform if we have one.
1894     if (m_transform && !appliedTransform) {
1895         // If the transform can't be inverted, then don't hit test this layer at all.
1896         if (!m_transform->isInvertible())
1897             return 0;
1898 
1899         // Make sure the parent's clip rects have been calculated.
1900         if (parent()) {
1901             parent()->updateClipRects(rootLayer);
1902 
1903             // Go ahead and test the enclosing clip now.
1904             IntRect clipRect = parent()->clipRects()->overflowClipRect();
1905             if (!clipRect.contains(hitTestPoint))
1906                 return 0;
1907         }
1908 
1909         // Adjust the transform such that the renderer's upper left corner is at (0,0) in user space.
1910         // This involves subtracting out the position of the layer in our current coordinate space.
1911         int x = 0;
1912         int y = 0;
1913         convertToLayerCoords(rootLayer, x, y);
1914         TransformationMatrix transform;
1915         transform.translate(x, y);
1916         transform = *m_transform * transform;
1917 
1918         // Map the hit test point into the transformed space and then do a hit test with the root layer shifted to be us.
1919         return hitTestLayer(this, request, result, transform.inverse().mapRect(hitTestRect), transform.inverse().mapPoint(hitTestPoint), true);
1920     }
1921 
1922     // Calculate the clip rects we should use.
1923     IntRect layerBounds;
1924     IntRect bgRect;
1925     IntRect fgRect;
1926     IntRect outlineRect;
1927     calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect);
1928 
1929     // Ensure our lists are up-to-date.
1930     updateZOrderLists();
1931     updateOverflowList();
1932 
1933     // This variable tracks which layer the mouse ends up being inside.  The minute we find an insideLayer,
1934     // we are done and can return it.
1935     RenderLayer* insideLayer = 0;
1936 
1937     // Begin by walking our list of positive layers from highest z-index down to the lowest
1938     // z-index.
1939     if (m_posZOrderList) {
1940         for (int i = m_posZOrderList->size() - 1; i >= 0; --i) {
1941             insideLayer = m_posZOrderList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
1942             if (insideLayer)
1943                 return insideLayer;
1944         }
1945     }
1946 
1947     // Now check our overflow objects.
1948     if (m_overflowList) {
1949         for (int i = m_overflowList->size() - 1; i >= 0; --i) {
1950             insideLayer = m_overflowList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
1951             if (insideLayer)
1952                 return insideLayer;
1953         }
1954     }
1955 
1956     // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
1957     if (fgRect.contains(hitTestPoint) &&
1958         renderer()->hitTest(request, result, hitTestPoint,
1959                             layerBounds.x() - renderer()->x(),
1960                             layerBounds.y() - renderer()->y(),
1961                             HitTestDescendants)) {
1962         // For positioned generated content, we might still not have a
1963         // node by the time we get to the layer level, since none of
1964         // the content in the layer has an element. So just walk up
1965         // the tree.
1966         if (!result.innerNode() || !result.innerNonSharedNode()) {
1967             Node* e = enclosingElement();
1968             if (!result.innerNode())
1969                 result.setInnerNode(e);
1970             if (!result.innerNonSharedNode())
1971                 result.setInnerNonSharedNode(e);
1972         }
1973 
1974         return this;
1975     }
1976 
1977     // Now check our negative z-index children.
1978     if (m_negZOrderList) {
1979         for (int i = m_negZOrderList->size() - 1; i >= 0; --i) {
1980             insideLayer = m_negZOrderList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
1981             if (insideLayer)
1982                 return insideLayer;
1983         }
1984     }
1985 
1986     // Next we want to see if the mouse is inside this layer but not any of its children.
1987     if (bgRect.contains(hitTestPoint) &&
1988         renderer()->hitTest(request, result, hitTestPoint,
1989                             layerBounds.x() - renderer()->x(),
1990                             layerBounds.y() - renderer()->y(),
1991                             HitTestSelf)) {
1992         if (!result.innerNode() || !result.innerNonSharedNode()) {
1993             Node* e = enclosingElement();
1994             if (!result.innerNode())
1995                 result.setInnerNode(e);
1996             if (!result.innerNonSharedNode())
1997                 result.setInnerNonSharedNode(e);
1998         }
1999 
2000         return this;
2001     }
2002 
2003     // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down,
2004     // return ourselves. We do this so mouse events continue getting delivered after a drag has
2005     // exited the WebView, and so hit testing over a scrollbar hits the content document.
2006     if ((request.active || request.mouseUp) && renderer()->isRenderView()) {
2007         renderer()->updateHitTestResult(result, hitTestPoint);
2008         return this;
2009     }
2010 
2011     return 0;
2012 }
2013 
updateClipRects(const RenderLayer * rootLayer)2014 void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
2015 {
2016     if (m_clipRects) {
2017         ASSERT(rootLayer == m_clipRectsRoot);
2018         return; // We have the correct cached value.
2019     }
2020 
2021     // For transformed layers, the root layer was shifted to be us, so there is no need to
2022     // examine the parent.  We want to cache clip rects with us as the root.
2023     RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
2024     if (parentLayer)
2025         parentLayer->updateClipRects(rootLayer);
2026 
2027     ClipRects clipRects;
2028     calculateClipRects(rootLayer, clipRects, true);
2029 
2030     if (parentLayer && parentLayer->clipRects() && clipRects == *parentLayer->clipRects())
2031         m_clipRects = parentLayer->clipRects();
2032     else
2033         m_clipRects = new (renderer()->renderArena()) ClipRects(clipRects);
2034     m_clipRects->ref();
2035 #ifndef NDEBUG
2036     m_clipRectsRoot = rootLayer;
2037 #endif
2038 }
2039 
calculateClipRects(const RenderLayer * rootLayer,ClipRects & clipRects,bool useCached) const2040 void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached) const
2041 {
2042     IntRect infiniteRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX);
2043     if (!parent()) {
2044         // The root layer's clip rect is always infinite.
2045         clipRects.reset(infiniteRect);
2046         return;
2047     }
2048 
2049     // For transformed layers, the root layer was shifted to be us, so there is no need to
2050     // examine the parent.  We want to cache clip rects with us as the root.
2051     RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
2052 
2053     // Ensure that our parent's clip has been calculated so that we can examine the values.
2054     if (parentLayer) {
2055         if (useCached && parentLayer->clipRects())
2056             clipRects = *parentLayer->clipRects();
2057         else
2058             parentLayer->calculateClipRects(rootLayer, clipRects);
2059     }
2060     else
2061         clipRects.reset(infiniteRect);
2062 
2063     // A fixed object is essentially the root of its containing block hierarchy, so when
2064     // we encounter such an object, we reset our clip rects to the fixedClipRect.
2065     if (renderer()->style()->position() == FixedPosition) {
2066         clipRects.setPosClipRect(clipRects.fixedClipRect());
2067         clipRects.setOverflowClipRect(clipRects.fixedClipRect());
2068         clipRects.setFixed(true);
2069     }
2070     else if (renderer()->style()->position() == RelativePosition)
2071         clipRects.setPosClipRect(clipRects.overflowClipRect());
2072     else if (renderer()->style()->position() == AbsolutePosition)
2073         clipRects.setOverflowClipRect(clipRects.posClipRect());
2074 
2075     // Update the clip rects that will be passed to child layers.
2076     if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
2077         // This layer establishes a clip of some kind.
2078         int x = 0;
2079         int y = 0;
2080         convertToLayerCoords(rootLayer, x, y);
2081         RenderView* view = renderer()->view();
2082         ASSERT(view);
2083         if (view && clipRects.fixed() && rootLayer->renderer() == view) {
2084             x -= view->frameView()->scrollX();
2085             y -= view->frameView()->scrollY();
2086         }
2087 
2088         if (renderer()->hasOverflowClip()) {
2089             IntRect newOverflowClip = renderer()->getOverflowClipRect(x,y);
2090             clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
2091             if (renderer()->isPositioned() || renderer()->isRelPositioned())
2092                 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
2093         }
2094         if (renderer()->hasClip()) {
2095             IntRect newPosClip = renderer()->getClipRect(x,y);
2096             clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
2097             clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
2098             clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
2099         }
2100     }
2101 }
2102 
calculateRects(const RenderLayer * rootLayer,const IntRect & paintDirtyRect,IntRect & layerBounds,IntRect & backgroundRect,IntRect & foregroundRect,IntRect & outlineRect,bool temporaryClipRects) const2103 void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
2104                                  IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects) const
2105 {
2106     if (rootLayer != this && parent()) {
2107         ClipRects parentClipRects;
2108         if (temporaryClipRects)
2109             parent()->calculateClipRects(rootLayer, parentClipRects);
2110         else {
2111             parent()->updateClipRects(rootLayer);
2112             parentClipRects = *parent()->clipRects();
2113         }
2114 
2115         backgroundRect = renderer()->style()->position() == FixedPosition ? parentClipRects.fixedClipRect() :
2116                          (renderer()->isPositioned() ? parentClipRects.posClipRect() :
2117                                                      parentClipRects.overflowClipRect());
2118         RenderView* view = renderer()->view();
2119         ASSERT(view);
2120         if (view && parentClipRects.fixed() && rootLayer->renderer() == view)
2121             backgroundRect.move(view->frameView()->scrollX(), view->frameView()->scrollY());
2122 
2123         backgroundRect.intersect(paintDirtyRect);
2124     } else
2125         backgroundRect = paintDirtyRect;
2126 
2127     foregroundRect = backgroundRect;
2128     outlineRect = backgroundRect;
2129 
2130     int x = 0;
2131     int y = 0;
2132     convertToLayerCoords(rootLayer, x, y);
2133     layerBounds = IntRect(x, y, width(), height());
2134 
2135     // Update the clip rects that will be passed to child layers.
2136     if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
2137         // This layer establishes a clip of some kind.
2138         if (renderer()->hasOverflowClip())
2139             foregroundRect.intersect(renderer()->getOverflowClipRect(x,y));
2140         if (renderer()->hasClip()) {
2141             // Clip applies to *us* as well, so go ahead and update the damageRect.
2142             IntRect newPosClip = renderer()->getClipRect(x,y);
2143             backgroundRect.intersect(newPosClip);
2144             foregroundRect.intersect(newPosClip);
2145             outlineRect.intersect(newPosClip);
2146         }
2147 
2148         // If we establish a clip at all, then go ahead and make sure our background
2149         // rect is intersected with our layer's bounds.
2150         if (ShadowData* boxShadow = renderer()->style()->boxShadow()) {
2151             IntRect overflow = layerBounds;
2152             do {
2153                 IntRect shadowRect = layerBounds;
2154                 shadowRect.move(boxShadow->x, boxShadow->y);
2155                 shadowRect.inflate(boxShadow->blur);
2156                 overflow.unite(shadowRect);
2157                 boxShadow = boxShadow->next;
2158             } while (boxShadow);
2159             backgroundRect.intersect(overflow);
2160         } else
2161             backgroundRect.intersect(layerBounds);
2162     }
2163 }
2164 
childrenClipRect() const2165 IntRect RenderLayer::childrenClipRect() const
2166 {
2167     RenderLayer* rootLayer = renderer()->view()->layer();
2168     IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
2169     calculateRects(rootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect);
2170     return foregroundRect;
2171 }
2172 
selfClipRect() const2173 IntRect RenderLayer::selfClipRect() const
2174 {
2175     RenderLayer* rootLayer = renderer()->view()->layer();
2176     IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
2177     calculateRects(rootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect);
2178     return backgroundRect;
2179 }
2180 
intersectsDamageRect(const IntRect & layerBounds,const IntRect & damageRect,const RenderLayer * rootLayer) const2181 bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const
2182 {
2183     // Always examine the canvas and the root.
2184     // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
2185     // paints the root's background.
2186     if (renderer()->isRenderView() || renderer()->isRoot())
2187         return true;
2188 
2189     // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we
2190     // can go ahead and return true.
2191     RenderView* view = renderer()->view();
2192     ASSERT(view);
2193     if (view && !renderer()->isRenderInline()) {
2194         IntRect b = layerBounds;
2195         b.inflate(view->maximalOutlineSize());
2196         if (b.intersects(damageRect))
2197             return true;
2198     }
2199 
2200     // Otherwise we need to compute the bounding box of this single layer and see if it intersects
2201     // the damage rect.
2202     return boundingBox(rootLayer).intersects(damageRect);
2203 }
2204 
boundingBox(const RenderLayer * rootLayer) const2205 IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
2206 {
2207     // There are three special cases we need to consider.
2208     // (1) Inline Flows.  For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
2209     // inline.  In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the root
2210     // line boxes of all three lines (including overflow on those lines).
2211     // (2) Left/Top Overflow.  The width/height of layers already includes right/bottom overflow.  However, in the case of left/top
2212     // overflow, we have to create a bounding box that will extend to include this overflow.
2213     // (3) Floats.  When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats
2214     // as part of our bounding box.  We do this because we are the responsible layer for both hit testing and painting those
2215     // floats.
2216     IntRect result;
2217     if (renderer()->isRenderInline()) {
2218         // Go from our first line box to our last line box.
2219         RenderInline* inlineFlow = static_cast<RenderInline*>(renderer());
2220         InlineFlowBox* firstBox = inlineFlow->firstLineBox();
2221         if (!firstBox)
2222             return result;
2223         int top = firstBox->root()->topOverflow();
2224         int bottom = inlineFlow->lastLineBox()->root()->bottomOverflow();
2225         int left = firstBox->xPos();
2226         for (InlineRunBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox())
2227             left = min(left, curr->xPos());
2228         result = IntRect(m_x + left, m_y + (top - renderer()->y()), width(), bottom - top);
2229     } else if (renderer()->isTableRow()) {
2230         // Our bounding box is just the union of all of our cells' border/overflow rects.
2231         for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
2232             if (child->isTableCell()) {
2233                 IntRect bbox = toRenderBox(child)->borderBoxRect();
2234                 result.unite(bbox);
2235                 IntRect overflowRect = renderer()->overflowRect(false);
2236                 if (bbox != overflowRect)
2237                     result.unite(overflowRect);
2238             }
2239         }
2240         result.move(m_x, m_y);
2241     } else {
2242         if (renderer()->hasMask())
2243             result = renderer()->maskClipRect();
2244         else {
2245             IntRect bbox = renderer()->borderBoxRect();
2246             result = bbox;
2247             IntRect overflowRect = renderer()->overflowRect(false);
2248             if (bbox != overflowRect)
2249                 result.unite(overflowRect);
2250         }
2251 
2252         // We have to adjust the x/y of this result so that it is in the coordinate space of the layer.
2253         result.move(m_x, m_y);
2254     }
2255 
2256     // Convert the bounding box to an absolute position.  We can do this easily by looking at the delta
2257     // between the bounding box's xpos and our layer's xpos and then applying that to the absolute layerBounds
2258     // passed in.
2259     int absX = 0, absY = 0;
2260     convertToLayerCoords(rootLayer, absX, absY);
2261     result.move(absX - m_x, absY - m_y);
2262     RenderView* view = renderer()->view();
2263     ASSERT(view);
2264     if (view)
2265         result.inflate(view->maximalOutlineSize());
2266     return result;
2267 }
2268 
clearClipRectsIncludingDescendants()2269 void RenderLayer::clearClipRectsIncludingDescendants()
2270 {
2271     if (!m_clipRects)
2272         return;
2273 
2274     clearClipRects();
2275 
2276     for (RenderLayer* l = firstChild(); l; l = l->nextSibling())
2277         l->clearClipRectsIncludingDescendants();
2278 }
2279 
clearClipRects()2280 void RenderLayer::clearClipRects()
2281 {
2282     if (m_clipRects) {
2283         m_clipRects->deref(renderer()->renderArena());
2284         m_clipRects = 0;
2285 #ifndef NDEBUG
2286         m_clipRectsRoot = 0;
2287 #endif
2288     }
2289 }
2290 
commonAncestor(RenderObject * obj1,RenderObject * obj2)2291 static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
2292 {
2293     if (!obj1 || !obj2)
2294         return 0;
2295 
2296     for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor())
2297         for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor())
2298             if (currObj1 == currObj2)
2299                 return currObj1;
2300 
2301     return 0;
2302 }
2303 
updateHoverActiveState(const HitTestRequest & request,HitTestResult & result)2304 void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestResult& result)
2305 {
2306     // We don't update :hover/:active state when the result is marked as readonly.
2307     if (request.readonly)
2308         return;
2309 
2310     Document* doc = renderer()->document();
2311 
2312     Node* activeNode = doc->activeNode();
2313     if (activeNode && !request.active) {
2314         // We are clearing the :active chain because the mouse has been released.
2315         for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) {
2316             if (curr->element() && !curr->isText())
2317                 curr->element()->setInActiveChain(false);
2318         }
2319         doc->setActiveNode(0);
2320     } else {
2321         Node* newActiveNode = result.innerNode();
2322         if (!activeNode && newActiveNode && request.active) {
2323             // We are setting the :active chain and freezing it. If future moves happen, they
2324             // will need to reference this chain.
2325             for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) {
2326                 if (curr->element() && !curr->isText()) {
2327                     curr->element()->setInActiveChain(true);
2328                 }
2329             }
2330             doc->setActiveNode(newActiveNode);
2331         }
2332     }
2333 
2334     // If the mouse is down and if this is a mouse move event, we want to restrict changes in
2335     // :hover/:active to only apply to elements that are in the :active chain that we froze
2336     // at the time the mouse went down.
2337     bool mustBeInActiveChain = request.active && request.mouseMove;
2338 
2339     // Check to see if the hovered node has changed.  If not, then we don't need to
2340     // do anything.
2341     RefPtr<Node> oldHoverNode = doc->hoverNode();
2342     Node* newHoverNode = result.innerNode();
2343 
2344     // Update our current hover node.
2345     doc->setHoverNode(newHoverNode);
2346 
2347     // We have two different objects.  Fetch their renderers.
2348     RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
2349     RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;
2350 
2351     // Locate the common ancestor render object for the two renderers.
2352     RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
2353 
2354     if (oldHoverObj != newHoverObj) {
2355         // The old hover path only needs to be cleared up to (and not including) the common ancestor;
2356         for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) {
2357             if (curr->element() && !curr->isText() && (!mustBeInActiveChain || curr->element()->inActiveChain())) {
2358                 curr->element()->setActive(false);
2359                 curr->element()->setHovered(false);
2360             }
2361         }
2362     }
2363 
2364     // Now set the hover state for our new object up to the root.
2365     for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
2366         if (curr->element() && !curr->isText() && (!mustBeInActiveChain || curr->element()->inActiveChain())) {
2367             curr->element()->setActive(request.active);
2368             curr->element()->setHovered(true);
2369         }
2370     }
2371 }
2372 
2373 // Helper for the sorting of layers by z-index.
compareZIndex(RenderLayer * first,RenderLayer * second)2374 static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
2375 {
2376     return first->zIndex() < second->zIndex();
2377 }
2378 
dirtyZOrderLists()2379 void RenderLayer::dirtyZOrderLists()
2380 {
2381     if (m_posZOrderList)
2382         m_posZOrderList->clear();
2383     if (m_negZOrderList)
2384         m_negZOrderList->clear();
2385     m_zOrderListsDirty = true;
2386 }
2387 
dirtyStackingContextZOrderLists()2388 void RenderLayer::dirtyStackingContextZOrderLists()
2389 {
2390     RenderLayer* sc = stackingContext();
2391     if (sc)
2392         sc->dirtyZOrderLists();
2393 }
2394 
dirtyOverflowList()2395 void RenderLayer::dirtyOverflowList()
2396 {
2397     if (m_overflowList)
2398         m_overflowList->clear();
2399     m_overflowListDirty = true;
2400 }
2401 
updateZOrderLists()2402 void RenderLayer::updateZOrderLists()
2403 {
2404     if (!isStackingContext() || !m_zOrderListsDirty)
2405         return;
2406 
2407     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
2408         if (!m_reflection || reflectionLayer() != child)
2409             child->collectLayers(m_posZOrderList, m_negZOrderList);
2410 
2411     // Sort the two lists.
2412     if (m_posZOrderList)
2413         std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex);
2414     if (m_negZOrderList)
2415         std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
2416 
2417     m_zOrderListsDirty = false;
2418 }
2419 
updateOverflowList()2420 void RenderLayer::updateOverflowList()
2421 {
2422     if (!m_overflowListDirty)
2423         return;
2424 
2425     for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
2426         // Ignore non-overflow layers and reflections.
2427         if (child->isOverflowOnly() && (!m_reflection || reflectionLayer() != child)) {
2428             if (!m_overflowList)
2429                 m_overflowList = new Vector<RenderLayer*>;
2430             m_overflowList->append(child);
2431         }
2432     }
2433 
2434     m_overflowListDirty = false;
2435 }
2436 
collectLayers(Vector<RenderLayer * > * & posBuffer,Vector<RenderLayer * > * & negBuffer)2437 void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer)
2438 {
2439     updateVisibilityStatus();
2440 
2441     // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
2442     if ((m_hasVisibleContent || (m_hasVisibleDescendant && isStackingContext())) && !isOverflowOnly()) {
2443         // Determine which buffer the child should be in.
2444         Vector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
2445 
2446         // Create the buffer if it doesn't exist yet.
2447         if (!buffer)
2448             buffer = new Vector<RenderLayer*>;
2449 
2450         // Append ourselves at the end of the appropriate buffer.
2451         buffer->append(this);
2452     }
2453 
2454     // Recur into our children to collect more layers, but only if we don't establish
2455     // a stacking context.
2456     if (m_hasVisibleDescendant && !isStackingContext()) {
2457         for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
2458             // Ignore reflections.
2459             if (!m_reflection || reflectionLayer() != child)
2460                 child->collectLayers(posBuffer, negBuffer);
2461         }
2462     }
2463 }
2464 
repaintIncludingDescendants()2465 void RenderLayer::repaintIncludingDescendants()
2466 {
2467     renderer()->repaint();
2468     for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
2469         curr->repaintIncludingDescendants();
2470 }
2471 
shouldBeOverflowOnly() const2472 bool RenderLayer::shouldBeOverflowOnly() const
2473 {
2474     return (renderer()->hasOverflowClip() || renderer()->hasReflection()) &&
2475            !renderer()->isPositioned() &&
2476            !renderer()->isRelPositioned() &&
2477            !renderer()->hasTransform() &&
2478            !isTransparent();
2479 }
2480 
styleChanged(RenderStyle::Diff,const RenderStyle *)2481 void RenderLayer::styleChanged(RenderStyle::Diff, const RenderStyle*)
2482 {
2483     bool isOverflowOnly = shouldBeOverflowOnly();
2484     if (isOverflowOnly != m_isOverflowOnly) {
2485         m_isOverflowOnly = isOverflowOnly;
2486         RenderLayer* p = parent();
2487         if (p)
2488             p->dirtyOverflowList();
2489         dirtyStackingContextZOrderLists();
2490     }
2491 
2492     if (renderer()->style()->overflowX() == OMARQUEE && renderer()->style()->marqueeBehavior() != MNONE) {
2493         if (!m_marquee)
2494             m_marquee = new RenderMarquee(this);
2495         m_marquee->updateMarqueeStyle();
2496     }
2497     else if (m_marquee) {
2498         delete m_marquee;
2499         m_marquee = 0;
2500     }
2501 
2502     if (!hasReflection() && m_reflection) {
2503         m_reflection->destroy();
2504         m_reflection = 0;
2505     } else if (hasReflection()) {
2506         if (!m_reflection)
2507             createReflection();
2508         updateReflectionStyle();
2509     }
2510 
2511     // FIXME: Need to detect a swap from custom to native scrollbars (and vice versa).
2512     if (m_hBar)
2513         m_hBar->styleChanged();
2514     if (m_vBar)
2515         m_vBar->styleChanged();
2516 
2517     updateScrollCornerStyle();
2518     updateResizerStyle();
2519 }
2520 
updateScrollCornerStyle()2521 void RenderLayer::updateScrollCornerStyle()
2522 {
2523     RenderObject* actualRenderer = renderer()->node()->isElementNode() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
2524     RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RenderStyle::SCROLLBAR_CORNER, actualRenderer->style()) : 0;
2525     if (corner) {
2526         if (!m_scrollCorner) {
2527             m_scrollCorner = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
2528             m_scrollCorner->setParent(renderer());
2529         }
2530         m_scrollCorner->setStyle(corner.release());
2531     } else if (m_scrollCorner) {
2532         m_scrollCorner->destroy();
2533         m_scrollCorner = 0;
2534     }
2535 }
2536 
updateResizerStyle()2537 void RenderLayer::updateResizerStyle()
2538 {
2539     RenderObject* actualRenderer = renderer()->node()->isElementNode() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
2540     RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RenderStyle::RESIZER, actualRenderer->style()) : 0;
2541     if (resizer) {
2542         if (!m_resizer) {
2543             m_resizer = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
2544             m_resizer->setParent(renderer());
2545         }
2546         m_resizer->setStyle(resizer.release());
2547     } else if (m_resizer) {
2548         m_resizer->destroy();
2549         m_resizer = 0;
2550     }
2551 }
2552 
reflectionLayer() const2553 RenderLayer* RenderLayer::reflectionLayer() const
2554 {
2555     return m_reflection ? m_reflection->layer() : 0;
2556 }
2557 
createReflection()2558 void RenderLayer::createReflection()
2559 {
2560     ASSERT(!m_reflection);
2561     m_reflection = new (renderer()->renderArena()) RenderReplica(renderer()->document());
2562     m_reflection->setParent(renderer()); // We create a 1-way connection.
2563 }
2564 
updateReflectionStyle()2565 void RenderLayer::updateReflectionStyle()
2566 {
2567     RefPtr<RenderStyle> newStyle = RenderStyle::create();
2568     newStyle->inheritFrom(renderer()->style());
2569 
2570     // Map in our transform.
2571     TransformOperations transform;
2572     switch (renderer()->style()->boxReflect()->direction()) {
2573         case ReflectionBelow:
2574             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
2575             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
2576             transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
2577             break;
2578         case ReflectionAbove:
2579             transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
2580             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
2581             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
2582             break;
2583         case ReflectionRight:
2584             transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
2585             transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
2586             transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
2587             break;
2588         case ReflectionLeft:
2589             transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
2590             transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
2591             transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
2592             break;
2593     }
2594     newStyle->setTransform(transform);
2595 
2596     // Map in our mask.
2597     newStyle->setMaskBoxImage(renderer()->style()->boxReflect()->mask());
2598 
2599     m_reflection->setStyle(newStyle.release());
2600 }
2601 
suspendMarquees()2602 void RenderLayer::suspendMarquees()
2603 {
2604     if (m_marquee)
2605         m_marquee->suspend();
2606 
2607     for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
2608         curr->suspendMarquees();
2609 }
2610 
2611 } // namespace WebCore
2612