• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010 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 "ColumnInfo.h"
48 #include "CSSPropertyNames.h"
49 #include "CSSStyleDeclaration.h"
50 #include "CSSStyleSelector.h"
51 #include "Chrome.h"
52 #include "Document.h"
53 #include "EventHandler.h"
54 #include "EventQueue.h"
55 #include "FloatPoint3D.h"
56 #include "FloatRect.h"
57 #include "FocusController.h"
58 #include "Frame.h"
59 #include "FrameTree.h"
60 #include "FrameView.h"
61 #include "Gradient.h"
62 #include "GraphicsContext.h"
63 #include "HTMLFrameOwnerElement.h"
64 #include "HTMLNames.h"
65 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
66 #include "HTMLTextAreaElement.h"
67 #endif
68 #include "HitTestRequest.h"
69 #include "HitTestResult.h"
70 #include "OverflowEvent.h"
71 #include "OverlapTestRequestClient.h"
72 #include "Page.h"
73 #include "PlatformMouseEvent.h"
74 #include "RenderArena.h"
75 #include "RenderInline.h"
76 #include "RenderMarquee.h"
77 #include "RenderReplica.h"
78 #include "RenderScrollbar.h"
79 #include "RenderScrollbarPart.h"
80 #include "RenderTheme.h"
81 #include "RenderTreeAsText.h"
82 #include "RenderView.h"
83 #include "ScaleTransformOperation.h"
84 #include "Scrollbar.h"
85 #include "ScrollbarTheme.h"
86 #include "SelectionController.h"
87 #include "TextStream.h"
88 #include "TransformState.h"
89 #include "TransformationMatrix.h"
90 #include "TranslateTransformOperation.h"
91 #include <wtf/StdLibExtras.h>
92 #include <wtf/UnusedParam.h>
93 #include <wtf/text/CString.h>
94 
95 #if USE(ACCELERATED_COMPOSITING)
96 #include "RenderLayerBacking.h"
97 #include "RenderLayerCompositor.h"
98 #endif
99 
100 #if ENABLE(SVG)
101 #include "SVGNames.h"
102 #endif
103 
104 #define MIN_INTERSECT_FOR_REVEAL 32
105 
106 using namespace std;
107 
108 namespace WebCore {
109 
110 using namespace HTMLNames;
111 
112 const int MinimumWidthWhileResizing = 100;
113 const int MinimumHeightWhileResizing = 40;
114 
operator new(size_t sz,RenderArena * renderArena)115 void* ClipRects::operator new(size_t sz, RenderArena* renderArena) throw()
116 {
117     return renderArena->allocate(sz);
118 }
119 
operator delete(void * ptr,size_t sz)120 void ClipRects::operator delete(void* ptr, size_t sz)
121 {
122     // Stash size where destroy can find it.
123     *(size_t *)ptr = sz;
124 }
125 
destroy(RenderArena * renderArena)126 void ClipRects::destroy(RenderArena* renderArena)
127 {
128     delete this;
129 
130     // Recover the size left there for us by operator delete and free the memory.
131     renderArena->free(*(size_t *)this, this);
132 }
133 
RenderLayer(RenderBoxModelObject * renderer)134 RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
135     : m_renderer(renderer)
136     , m_parent(0)
137     , m_previous(0)
138     , m_next(0)
139     , m_first(0)
140     , m_last(0)
141     , m_relX(0)
142     , m_relY(0)
143     , m_x(0)
144     , m_y(0)
145     , m_width(0)
146     , m_height(0)
147     , m_scrollX(0)
148     , m_scrollY(0)
149     , m_scrollLeftOverflow(0)
150     , m_scrollTopOverflow(0)
151     , m_scrollWidth(0)
152     , m_scrollHeight(0)
153     , m_inResizeMode(false)
154     , m_posZOrderList(0)
155     , m_negZOrderList(0)
156     , m_normalFlowList(0)
157     , m_clipRects(0)
158 #ifndef NDEBUG
159     , m_clipRectsRoot(0)
160 #endif
161     , m_scrollDimensionsDirty(true)
162     , m_zOrderListsDirty(true)
163     , m_normalFlowListDirty(true)
164     , m_isNormalFlowOnly(shouldBeNormalFlowOnly())
165     , m_usedTransparency(false)
166     , m_paintingInsideReflection(false)
167     , m_inOverflowRelayout(false)
168     , m_needsFullRepaint(false)
169     , m_overflowStatusDirty(true)
170     , m_visibleContentStatusDirty(true)
171     , m_hasVisibleContent(false)
172     , m_visibleDescendantStatusDirty(false)
173     , m_hasVisibleDescendant(false)
174     , m_isPaginated(false)
175     , m_3DTransformedDescendantStatusDirty(true)
176     , m_has3DTransformedDescendant(false)
177 #if USE(ACCELERATED_COMPOSITING)
178     , m_hasCompositingDescendant(false)
179     , m_mustOverlapCompositedLayers(false)
180 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
181     , m_shouldComposite(false)
182 #endif
183 #endif
184     , m_containsDirtyOverlayScrollbars(false)
185 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
186     , m_hasOverflowScroll(false)
187 #endif
188     , m_marquee(0)
189     , m_staticInlinePosition(0)
190     , m_staticBlockPosition(0)
191     , m_reflection(0)
192     , m_scrollCorner(0)
193     , m_resizer(0)
194 {
195     ScrollableArea::setConstrainsScrollingToContentEdge(false);
196 
197     if (!renderer->firstChild() && renderer->style()) {
198         m_visibleContentStatusDirty = false;
199         m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
200     }
201 
202     if (Frame* frame = renderer->frame()) {
203         if (Page* page = frame->page()) {
204             m_page = page;
205             m_page->addScrollableArea(this);
206         }
207     }
208 }
209 
~RenderLayer()210 RenderLayer::~RenderLayer()
211 {
212     if (inResizeMode() && !renderer()->documentBeingDestroyed()) {
213         if (Frame* frame = renderer()->frame())
214             frame->eventHandler()->resizeLayerDestroyed();
215     }
216 
217     if (m_page)
218         m_page->removeScrollableArea(this);
219 
220     destroyScrollbar(HorizontalScrollbar);
221     destroyScrollbar(VerticalScrollbar);
222 
223     if (m_reflection)
224         removeReflection();
225 
226     // Child layers will be deleted by their corresponding render objects, so
227     // we don't need to delete them ourselves.
228 
229     delete m_posZOrderList;
230     delete m_negZOrderList;
231     delete m_normalFlowList;
232     delete m_marquee;
233 
234 #if USE(ACCELERATED_COMPOSITING)
235     clearBacking();
236 #endif
237 
238     // Make sure we have no lingering clip rects.
239     ASSERT(!m_clipRects);
240 
241     if (m_scrollCorner)
242         m_scrollCorner->destroy();
243     if (m_resizer)
244         m_resizer->destroy();
245 }
246 
247 #if USE(ACCELERATED_COMPOSITING)
compositor() const248 RenderLayerCompositor* RenderLayer::compositor() const
249 {
250     ASSERT(renderer()->view());
251     return renderer()->view()->compositor();
252 }
253 
contentChanged(ContentChangeType changeType)254 void RenderLayer::contentChanged(ContentChangeType changeType)
255 {
256     // This can get called when video becomes accelerated, so the layers may change.
257     if ((changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged) && compositor()->updateLayerCompositingState(this))
258         compositor()->setCompositingLayersNeedRebuild();
259 
260     if (m_backing)
261         m_backing->contentChanged(changeType);
262 }
263 #endif // USE(ACCELERATED_COMPOSITING)
264 
hasAcceleratedCompositing() const265 bool RenderLayer::hasAcceleratedCompositing() const
266 {
267 #if USE(ACCELERATED_COMPOSITING)
268     return compositor()->hasAcceleratedCompositing();
269 #else
270     return false;
271 #endif
272 }
273 
canRender3DTransforms() const274 bool RenderLayer::canRender3DTransforms() const
275 {
276 #if USE(ACCELERATED_COMPOSITING)
277     return compositor()->canRender3DTransforms();
278 #else
279     return false;
280 #endif
281 }
282 
updateLayerPositions(UpdateLayerPositionsFlags flags,IntPoint * cachedOffset)283 void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint* cachedOffset)
284 {
285     updateLayerPosition(); // For relpositioned layers or non-positioned layers,
286                            // we need to keep in sync, since we may have shifted relative
287                            // to our parent layer.
288     IntPoint oldCachedOffset;
289     if (cachedOffset) {
290         // We can't cache our offset to the repaint container if the mapping is anything more complex than a simple translation
291         bool disableOffsetCache = renderer()->hasColumns() || renderer()->hasTransform() || isComposited();
292 #if ENABLE(SVG)
293         disableOffsetCache = disableOffsetCache || renderer()->isSVGRoot();
294 #endif
295         if (disableOffsetCache)
296             cachedOffset = 0; // If our cached offset is invalid make sure it's not passed to any of our children
297         else {
298             oldCachedOffset = *cachedOffset;
299             // Frequently our parent layer's renderer will be the same as our renderer's containing block.  In that case,
300             // we just update the cache using our offset to our parent (which is m_x / m_y).  Otherwise, regenerated cached
301             // offsets to the root from the render tree.
302             if (!m_parent || m_parent->renderer() == renderer()->containingBlock())
303                 cachedOffset->move(m_x, m_y); // Fast case
304             else {
305                 int x = 0;
306                 int y = 0;
307                 convertToLayerCoords(root(), x, y);
308                 *cachedOffset = IntPoint(x, y);
309             }
310         }
311     }
312 
313     int x = 0;
314     int y = 0;
315     if (cachedOffset) {
316         x += cachedOffset->x();
317         y += cachedOffset->y();
318 #ifndef NDEBUG
319         int nonCachedX = 0;
320         int nonCachedY = 0;
321         convertToLayerCoords(root(), nonCachedX, nonCachedY);
322         ASSERT(x == nonCachedX);
323         ASSERT(y == nonCachedY);
324 #endif
325     } else
326         convertToLayerCoords(root(), x, y);
327     positionOverflowControls(x, y);
328 
329     updateVisibilityStatus();
330 
331     if (flags & UpdatePagination)
332         updatePagination();
333     else
334         m_isPaginated = false;
335 
336     if (m_hasVisibleContent) {
337         RenderView* view = renderer()->view();
338         ASSERT(view);
339         // FIXME: Optimize using LayoutState and remove the disableLayoutState() call
340         // from updateScrollInfoAfterLayout().
341         ASSERT(!view->layoutStateEnabled());
342 
343         RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
344         IntRect newRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
345         IntRect newOutlineBox = renderer()->outlineBoundsForRepaint(repaintContainer, cachedOffset);
346         // FIXME: Should ASSERT that value calculated for newOutlineBox using the cached offset is the same
347         // as the value not using the cached offset, but we can't due to https://bugs.webkit.org/show_bug.cgi?id=37048
348         if (flags & CheckForRepaint) {
349             if (view && !view->printing()) {
350                 if (m_needsFullRepaint) {
351                     renderer()->repaintUsingContainer(repaintContainer, m_repaintRect);
352                     if (newRect != m_repaintRect)
353                         renderer()->repaintUsingContainer(repaintContainer, newRect);
354                 } else
355                     renderer()->repaintAfterLayoutIfNeeded(repaintContainer, m_repaintRect, m_outlineBox, &newRect, &newOutlineBox);
356             }
357         }
358         m_repaintRect = newRect;
359         m_outlineBox = newOutlineBox;
360     } else {
361         m_repaintRect = IntRect();
362         m_outlineBox = IntRect();
363     }
364 
365     m_needsFullRepaint = false;
366 
367     // Go ahead and update the reflection's position and size.
368     if (m_reflection)
369         m_reflection->layout();
370 
371 #if USE(ACCELERATED_COMPOSITING)
372     // Clear the IsCompositingUpdateRoot flag once we've found the first compositing layer in this update.
373     bool isUpdateRoot = (flags & IsCompositingUpdateRoot);
374     if (isComposited())
375         flags &= ~IsCompositingUpdateRoot;
376 #endif
377 
378     if (renderer()->hasColumns())
379         flags |= UpdatePagination;
380 
381     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
382         child->updateLayerPositions(flags, cachedOffset);
383 
384 #if USE(ACCELERATED_COMPOSITING)
385     if ((flags & UpdateCompositingLayers) && isComposited())
386         backing()->updateAfterLayout(RenderLayerBacking::CompositingChildren, isUpdateRoot);
387 #endif
388 
389     // With all our children positioned, now update our marquee if we need to.
390     if (m_marquee)
391         m_marquee->updateMarqueePosition();
392 
393     if (cachedOffset)
394         *cachedOffset = oldCachedOffset;
395 }
396 
repaintRectIncludingDescendants() const397 IntRect RenderLayer::repaintRectIncludingDescendants() const
398 {
399     IntRect repaintRect = m_repaintRect;
400     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
401         repaintRect.unite(child->repaintRectIncludingDescendants());
402     return repaintRect;
403 }
404 
computeRepaintRects()405 void RenderLayer::computeRepaintRects()
406 {
407     RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
408     m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
409     m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
410 }
411 
updateRepaintRectsAfterScroll(bool fixed)412 void RenderLayer::updateRepaintRectsAfterScroll(bool fixed)
413 {
414     if (fixed || renderer()->style()->position() == FixedPosition) {
415         computeRepaintRects();
416         fixed = true;
417     } else if (renderer()->hasTransform() && !renderer()->isRenderView()) {
418         // Transforms act as fixed position containers, so nothing inside a
419         // transformed element can be fixed relative to the viewport if the
420         // transformed element is not fixed itself or child of a fixed element.
421         return;
422     }
423 
424     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
425         child->updateRepaintRectsAfterScroll(fixed);
426 }
427 
updateTransform()428 void RenderLayer::updateTransform()
429 {
430     // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
431     // so check style too.
432     bool hasTransform = renderer()->hasTransform() && renderer()->style()->hasTransform();
433     bool had3DTransform = has3DTransform();
434 
435     bool hadTransform = m_transform;
436     if (hasTransform != hadTransform) {
437         if (hasTransform)
438             m_transform.set(new TransformationMatrix);
439         else
440             m_transform.clear();
441     }
442 
443     if (hasTransform) {
444         RenderBox* box = renderBox();
445         ASSERT(box);
446         m_transform->makeIdentity();
447         box->style()->applyTransform(*m_transform, box->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
448         makeMatrixRenderable(*m_transform, canRender3DTransforms());
449     }
450 
451     if (had3DTransform != has3DTransform())
452         dirty3DTransformedDescendantStatus();
453 }
454 
currentTransform() const455 TransformationMatrix RenderLayer::currentTransform() const
456 {
457     if (!m_transform)
458         return TransformationMatrix();
459 
460 #if USE(ACCELERATED_COMPOSITING)
461     if (renderer()->style()->isRunningAcceleratedAnimation()) {
462         TransformationMatrix currTransform;
463         RefPtr<RenderStyle> style = renderer()->animation()->getAnimatedStyleForRenderer(renderer());
464         style->applyTransform(currTransform, renderBox()->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
465         makeMatrixRenderable(currTransform, canRender3DTransforms());
466         return currTransform;
467     }
468 #endif
469 
470     return *m_transform;
471 }
472 
renderableTransform(PaintBehavior paintBehavior) const473 TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const
474 {
475     if (!m_transform)
476         return TransformationMatrix();
477 
478     if (paintBehavior & PaintBehaviorFlattenCompositingLayers) {
479         TransformationMatrix matrix = *m_transform;
480         makeMatrixRenderable(matrix, false /* flatten 3d */);
481         return matrix;
482     }
483 
484     return *m_transform;
485 }
486 
checkContainingBlockChainForPagination(RenderBoxModelObject * renderer,RenderBox * ancestorColumnsRenderer)487 static bool checkContainingBlockChainForPagination(RenderBoxModelObject* renderer, RenderBox* ancestorColumnsRenderer)
488 {
489     RenderView* view = renderer->view();
490     RenderBoxModelObject* prevBlock = renderer;
491     RenderBlock* containingBlock;
492     for (containingBlock = renderer->containingBlock();
493          containingBlock && containingBlock != view && containingBlock != ancestorColumnsRenderer;
494          containingBlock = containingBlock->containingBlock())
495         prevBlock = containingBlock;
496 
497     // If the columns block wasn't in our containing block chain, then we aren't paginated by it.
498     if (containingBlock != ancestorColumnsRenderer)
499         return false;
500 
501     // If the previous block is absolutely positioned, then we can't be paginated by the columns block.
502     if (prevBlock->isPositioned())
503         return false;
504 
505     // Otherwise we are paginated by the columns block.
506     return true;
507 }
508 
updatePagination()509 void RenderLayer::updatePagination()
510 {
511     m_isPaginated = false;
512     if (isComposited() || !parent())
513         return; // FIXME: We will have to deal with paginated compositing layers someday.
514                 // FIXME: For now the RenderView can't be paginated.  Eventually printing will move to a model where it is though.
515 
516     if (isNormalFlowOnly()) {
517         m_isPaginated = parent()->renderer()->hasColumns();
518         return;
519     }
520 
521     // If we're not normal flow, then we need to look for a multi-column object between us and our stacking context.
522     RenderLayer* ancestorStackingContext = stackingContext();
523     for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
524         if (curr->renderer()->hasColumns()) {
525             m_isPaginated = checkContainingBlockChainForPagination(renderer(), curr->renderBox());
526             return;
527         }
528         if (curr == ancestorStackingContext)
529             return;
530     }
531 }
532 
setHasVisibleContent(bool b)533 void RenderLayer::setHasVisibleContent(bool b)
534 {
535     if (m_hasVisibleContent == b && !m_visibleContentStatusDirty)
536         return;
537     m_visibleContentStatusDirty = false;
538     m_hasVisibleContent = b;
539     if (m_hasVisibleContent) {
540         RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
541         m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
542         m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
543         if (!isNormalFlowOnly()) {
544             for (RenderLayer* sc = stackingContext(); sc; sc = sc->stackingContext()) {
545                 sc->dirtyZOrderLists();
546                 if (sc->hasVisibleContent())
547                     break;
548             }
549         }
550     }
551     if (parent())
552         parent()->childVisibilityChanged(m_hasVisibleContent);
553 }
554 
dirtyVisibleContentStatus()555 void RenderLayer::dirtyVisibleContentStatus()
556 {
557     m_visibleContentStatusDirty = true;
558     if (parent())
559         parent()->dirtyVisibleDescendantStatus();
560 }
561 
childVisibilityChanged(bool newVisibility)562 void RenderLayer::childVisibilityChanged(bool newVisibility)
563 {
564     if (m_hasVisibleDescendant == newVisibility || m_visibleDescendantStatusDirty)
565         return;
566     if (newVisibility) {
567         RenderLayer* l = this;
568         while (l && !l->m_visibleDescendantStatusDirty && !l->m_hasVisibleDescendant) {
569             l->m_hasVisibleDescendant = true;
570             l = l->parent();
571         }
572     } else
573         dirtyVisibleDescendantStatus();
574 }
575 
dirtyVisibleDescendantStatus()576 void RenderLayer::dirtyVisibleDescendantStatus()
577 {
578     RenderLayer* l = this;
579     while (l && !l->m_visibleDescendantStatusDirty) {
580         l->m_visibleDescendantStatusDirty = true;
581         l = l->parent();
582     }
583 }
584 
updateVisibilityStatus()585 void RenderLayer::updateVisibilityStatus()
586 {
587     if (m_visibleDescendantStatusDirty) {
588         m_hasVisibleDescendant = false;
589         for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
590             child->updateVisibilityStatus();
591             if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) {
592                 m_hasVisibleDescendant = true;
593                 break;
594             }
595         }
596         m_visibleDescendantStatusDirty = false;
597     }
598 
599     if (m_visibleContentStatusDirty) {
600         if (renderer()->style()->visibility() == VISIBLE)
601             m_hasVisibleContent = true;
602         else {
603             // layer may be hidden but still have some visible content, check for this
604             m_hasVisibleContent = false;
605             RenderObject* r = renderer()->firstChild();
606             while (r) {
607                 if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
608                     m_hasVisibleContent = true;
609                     break;
610                 }
611                 if (r->firstChild() && !r->hasLayer())
612                     r = r->firstChild();
613                 else if (r->nextSibling())
614                     r = r->nextSibling();
615                 else {
616                     do {
617                         r = r->parent();
618                         if (r == renderer())
619                             r = 0;
620                     } while (r && !r->nextSibling());
621                     if (r)
622                         r = r->nextSibling();
623                 }
624             }
625         }
626         m_visibleContentStatusDirty = false;
627     }
628 }
629 
dirty3DTransformedDescendantStatus()630 void RenderLayer::dirty3DTransformedDescendantStatus()
631 {
632     RenderLayer* curr = stackingContext();
633     if (curr)
634         curr->m_3DTransformedDescendantStatusDirty = true;
635 
636     // This propagates up through preserve-3d hierarchies to the enclosing flattening layer.
637     // Note that preserves3D() creates stacking context, so we can just run up the stacking contexts.
638     while (curr && curr->preserves3D()) {
639         curr->m_3DTransformedDescendantStatusDirty = true;
640         curr = curr->stackingContext();
641     }
642 }
643 
644 // Return true if this layer or any preserve-3d descendants have 3d.
update3DTransformedDescendantStatus()645 bool RenderLayer::update3DTransformedDescendantStatus()
646 {
647     if (m_3DTransformedDescendantStatusDirty) {
648         m_has3DTransformedDescendant = false;
649 
650         // Transformed or preserve-3d descendants can only be in the z-order lists, not
651         // in the normal flow list, so we only need to check those.
652         if (m_posZOrderList) {
653             for (unsigned i = 0; i < m_posZOrderList->size(); ++i)
654                 m_has3DTransformedDescendant |= m_posZOrderList->at(i)->update3DTransformedDescendantStatus();
655         }
656 
657         // Now check our negative z-index children.
658         if (m_negZOrderList) {
659             for (unsigned i = 0; i < m_negZOrderList->size(); ++i)
660                 m_has3DTransformedDescendant |= m_negZOrderList->at(i)->update3DTransformedDescendantStatus();
661         }
662 
663         m_3DTransformedDescendantStatusDirty = false;
664     }
665 
666     // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs
667     // the m_has3DTransformedDescendant set.
668     if (preserves3D())
669         return has3DTransform() || m_has3DTransformedDescendant;
670 
671     return has3DTransform();
672 }
673 
updateLayerPosition()674 void RenderLayer::updateLayerPosition()
675 {
676     IntPoint localPoint;
677     IntSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done.
678     if (renderer()->isRenderInline()) {
679         RenderInline* inlineFlow = toRenderInline(renderer());
680         IntRect lineBox = inlineFlow->linesBoundingBox();
681         setWidth(lineBox.width());
682         setHeight(lineBox.height());
683         inlineBoundingBoxOffset = IntSize(lineBox.x(), lineBox.y());
684         localPoint += inlineBoundingBoxOffset;
685     } else if (RenderBox* box = renderBox()) {
686         setWidth(box->width());
687         setHeight(box->height());
688         localPoint += box->locationOffsetIncludingFlipping();
689     }
690 
691     // Clear our cached clip rect information.
692     clearClipRects();
693 
694     if (!renderer()->isPositioned() && renderer()->parent()) {
695         // We must adjust our position by walking up the render tree looking for the
696         // nearest enclosing object with a layer.
697         RenderObject* curr = renderer()->parent();
698         while (curr && !curr->hasLayer()) {
699             if (curr->isBox() && !curr->isTableRow()) {
700                 // Rows and cells share the same coordinate space (that of the section).
701                 // Omit them when computing our xpos/ypos.
702                 localPoint += toRenderBox(curr)->locationOffsetIncludingFlipping();
703             }
704             curr = curr->parent();
705         }
706         if (curr->isBox() && curr->isTableRow()) {
707             // Put ourselves into the row coordinate space.
708             localPoint -= toRenderBox(curr)->locationOffsetIncludingFlipping();
709         }
710     }
711 
712     // Subtract our parent's scroll offset.
713     if (renderer()->isPositioned() && enclosingPositionedAncestor()) {
714         RenderLayer* positionedParent = enclosingPositionedAncestor();
715 
716         // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
717         IntSize offset = positionedParent->scrolledContentOffset();
718         localPoint -= offset;
719 
720         if (renderer()->isPositioned() && positionedParent->renderer()->isRelPositioned() && positionedParent->renderer()->isRenderInline()) {
721             IntSize offset = toRenderInline(positionedParent->renderer())->relativePositionedInlineOffset(toRenderBox(renderer()));
722             localPoint += offset;
723         }
724     } else if (parent()) {
725         if (isComposited()) {
726             // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column.
727             // They won't split across columns properly.
728             IntSize columnOffset;
729             parent()->renderer()->adjustForColumns(columnOffset, localPoint);
730             localPoint += columnOffset;
731         }
732 
733         IntSize scrollOffset = parent()->scrolledContentOffset();
734         localPoint -= scrollOffset;
735     }
736 
737     m_relX = m_relY = 0;
738     if (renderer()->isRelPositioned()) {
739         m_relX = renderer()->relativePositionOffsetX();
740         m_relY = renderer()->relativePositionOffsetY();
741         localPoint.move(m_relX, m_relY);
742     }
743 
744     // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
745     localPoint -= inlineBoundingBoxOffset;
746     setLocation(localPoint.x(), localPoint.y());
747 }
748 
perspectiveTransform() const749 TransformationMatrix RenderLayer::perspectiveTransform() const
750 {
751     if (!renderer()->hasTransform())
752         return TransformationMatrix();
753 
754     RenderStyle* style = renderer()->style();
755     if (!style->hasPerspective())
756         return TransformationMatrix();
757 
758     // Maybe fetch the perspective from the backing?
759     const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
760     const float boxWidth = borderBox.width();
761     const float boxHeight = borderBox.height();
762 
763     float perspectiveOriginX = style->perspectiveOriginX().calcFloatValue(boxWidth);
764     float perspectiveOriginY = style->perspectiveOriginY().calcFloatValue(boxHeight);
765 
766     // A perspective origin of 0,0 makes the vanishing point in the center of the element.
767     // We want it to be in the top-left, so subtract half the height and width.
768     perspectiveOriginX -= boxWidth / 2.0f;
769     perspectiveOriginY -= boxHeight / 2.0f;
770 
771     TransformationMatrix t;
772     t.translate(perspectiveOriginX, perspectiveOriginY);
773     t.applyPerspective(style->perspective());
774     t.translate(-perspectiveOriginX, -perspectiveOriginY);
775 
776     return t;
777 }
778 
perspectiveOrigin() const779 FloatPoint RenderLayer::perspectiveOrigin() const
780 {
781     if (!renderer()->hasTransform())
782         return FloatPoint();
783 
784     const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
785     RenderStyle* style = renderer()->style();
786 
787     return FloatPoint(style->perspectiveOriginX().calcFloatValue(borderBox.width()),
788                       style->perspectiveOriginY().calcFloatValue(borderBox.height()));
789 }
790 
stackingContext() const791 RenderLayer* RenderLayer::stackingContext() const
792 {
793     RenderLayer* layer = parent();
794 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) || ENABLE(ANDROID_OVERFLOW_SCROLL)
795     // When using composited fixed elements, they are turned into a stacking
796     // context and we thus need to return them.
797     // We can simplify the while loop by using isStackingContext(); with
798     // composited fixed elements turned on, this will return true for them,
799     // and is otherwise equivalent to the replaced statements.
800     while (layer && !layer->renderer()->isRoot() && !layer->isStackingContext())
801 #else
802     while (layer && !layer->renderer()->isRenderView() && !layer->renderer()->isRoot() && layer->renderer()->style()->hasAutoZIndex())
803 #endif
804         layer = layer->parent();
805     return layer;
806 }
807 
isPositionedContainer(RenderLayer * layer)808 static inline bool isPositionedContainer(RenderLayer* layer)
809 {
810     RenderObject* o = layer->renderer();
811     return o->isRenderView() || o->isPositioned() || o->isRelPositioned() || layer->hasTransform();
812 }
813 
isFixedPositionedContainer(RenderLayer * layer)814 static inline bool isFixedPositionedContainer(RenderLayer* layer)
815 {
816     RenderObject* o = layer->renderer();
817     return o->isRenderView() || layer->hasTransform();
818 }
819 
enclosingPositionedAncestor() const820 RenderLayer* RenderLayer::enclosingPositionedAncestor() const
821 {
822     RenderLayer* curr = parent();
823     while (curr && !isPositionedContainer(curr))
824         curr = curr->parent();
825 
826     return curr;
827 }
828 
enclosingTransformedAncestor() const829 RenderLayer* RenderLayer::enclosingTransformedAncestor() const
830 {
831     RenderLayer* curr = parent();
832     while (curr && !curr->renderer()->isRenderView() && !curr->transform())
833         curr = curr->parent();
834 
835     return curr;
836 }
837 
compositingContainer(const RenderLayer * layer)838 static inline const RenderLayer* compositingContainer(const RenderLayer* layer)
839 {
840     return layer->isNormalFlowOnly() ? layer->parent() : layer->stackingContext();
841 }
842 
843 #if USE(ACCELERATED_COMPOSITING)
enclosingCompositingLayer(bool includeSelf) const844 RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const
845 {
846     if (includeSelf && isComposited())
847         return const_cast<RenderLayer*>(this);
848 
849     for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
850         if (curr->isComposited())
851             return const_cast<RenderLayer*>(curr);
852     }
853 
854     return 0;
855 }
856 #endif
857 
clippingRoot() const858 RenderLayer* RenderLayer::clippingRoot() const
859 {
860 #if USE(ACCELERATED_COMPOSITING)
861     if (isComposited())
862         return const_cast<RenderLayer*>(this);
863 #endif
864 
865     const RenderLayer* current = this;
866     while (current) {
867         if (current->renderer()->isRenderView())
868             return const_cast<RenderLayer*>(current);
869 
870         current = compositingContainer(current);
871         ASSERT(current);
872         if (current->transform()
873 #if USE(ACCELERATED_COMPOSITING)
874             || current->isComposited()
875 #endif
876         )
877             return const_cast<RenderLayer*>(current);
878     }
879 
880     ASSERT_NOT_REACHED();
881     return 0;
882 }
883 
absoluteToContents(const IntPoint & absolutePoint) const884 IntPoint RenderLayer::absoluteToContents(const IntPoint& absolutePoint) const
885 {
886     // We don't use convertToLayerCoords because it doesn't know about transforms
887     return roundedIntPoint(renderer()->absoluteToLocal(absolutePoint, false, true));
888 }
889 
requiresSlowRepaints() const890 bool RenderLayer::requiresSlowRepaints() const
891 {
892     if (isTransparent() || hasReflection() || hasTransform())
893         return true;
894     if (!parent())
895         return false;
896     return parent()->requiresSlowRepaints();
897 }
898 
isTransparent() const899 bool RenderLayer::isTransparent() const
900 {
901 #if ENABLE(SVG)
902     if (renderer()->node() && renderer()->node()->namespaceURI() == SVGNames::svgNamespaceURI)
903         return false;
904 #endif
905     return renderer()->isTransparent() || renderer()->hasMask();
906 }
907 
transparentPaintingAncestor()908 RenderLayer* RenderLayer::transparentPaintingAncestor()
909 {
910     if (isComposited())
911         return 0;
912 
913     for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
914         if (curr->isComposited())
915             return 0;
916         if (curr->isTransparent())
917             return curr;
918     }
919     return 0;
920 }
921 
922 static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior);
923 
expandClipRectForDescendantsAndReflection(IntRect & clipRect,const RenderLayer * l,const RenderLayer * rootLayer,PaintBehavior paintBehavior)924 static void expandClipRectForDescendantsAndReflection(IntRect& clipRect, const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
925 {
926     // If we have a mask, then the clip is limited to the border box area (and there is
927     // no need to examine child layers).
928     if (!l->renderer()->hasMask()) {
929         // Note: we don't have to walk z-order lists since transparent elements always establish
930         // a stacking context.  This means we can just walk the layer tree directly.
931         for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) {
932             if (!l->reflection() || l->reflectionLayer() != curr)
933                 clipRect.unite(transparencyClipBox(curr, rootLayer, paintBehavior));
934         }
935     }
936 
937     // If we have a reflection, then we need to account for that when we push the clip.  Reflect our entire
938     // current transparencyClipBox to catch all child layers.
939     // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this
940     // size into the parent layer.
941     if (l->renderer()->hasReflection()) {
942         int deltaX = 0;
943         int deltaY = 0;
944         l->convertToLayerCoords(rootLayer, deltaX, deltaY);
945         clipRect.move(-deltaX, -deltaY);
946         clipRect.unite(l->renderBox()->reflectedRect(clipRect));
947         clipRect.move(deltaX, deltaY);
948     }
949 }
950 
transparencyClipBox(const RenderLayer * l,const RenderLayer * rootLayer,PaintBehavior paintBehavior)951 static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
952 {
953     // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
954     // paintDirtyRect, and that should cut down on the amount we have to paint.  Still it
955     // would be better to respect clips.
956 
957     if (rootLayer != l && l->paintsWithTransform(paintBehavior)) {
958         // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
959         // the transformed layer and all of its children.
960         int x = 0;
961         int y = 0;
962         l->convertToLayerCoords(rootLayer, x, y);
963 
964         TransformationMatrix transform;
965         transform.translate(x, y);
966         transform = transform * *l->transform();
967 
968         IntRect clipRect = l->boundingBox(l);
969         expandClipRectForDescendantsAndReflection(clipRect, l, l, paintBehavior);
970         return transform.mapRect(clipRect);
971     }
972 
973     IntRect clipRect = l->boundingBox(rootLayer);
974     expandClipRectForDescendantsAndReflection(clipRect, l, rootLayer, paintBehavior);
975     return clipRect;
976 }
977 
beginTransparencyLayers(GraphicsContext * p,const RenderLayer * rootLayer,PaintBehavior paintBehavior)978 void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
979 {
980     if (p->paintingDisabled() || (paintsWithTransparency(paintBehavior) && m_usedTransparency))
981         return;
982 
983     RenderLayer* ancestor = transparentPaintingAncestor();
984     if (ancestor)
985         ancestor->beginTransparencyLayers(p, rootLayer, paintBehavior);
986 
987     if (paintsWithTransparency(paintBehavior)) {
988         m_usedTransparency = true;
989         p->save();
990         IntRect clipRect = transparencyClipBox(this, rootLayer, paintBehavior);
991         p->clip(clipRect);
992         p->beginTransparencyLayer(renderer()->opacity());
993 #ifdef REVEAL_TRANSPARENCY_LAYERS
994         p->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f), ColorSpaceDeviceRGB);
995         p->fillRect(clipRect);
996 #endif
997     }
998 }
999 
operator new(size_t sz,RenderArena * renderArena)1000 void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
1001 {
1002     return renderArena->allocate(sz);
1003 }
1004 
operator delete(void * ptr,size_t sz)1005 void RenderLayer::operator delete(void* ptr, size_t sz)
1006 {
1007     // Stash size where destroy can find it.
1008     *(size_t *)ptr = sz;
1009 }
1010 
destroy(RenderArena * renderArena)1011 void RenderLayer::destroy(RenderArena* renderArena)
1012 {
1013     delete this;
1014 
1015     // Recover the size left there for us by operator delete and free the memory.
1016     renderArena->free(*(size_t *)this, this);
1017 }
1018 
addChild(RenderLayer * child,RenderLayer * beforeChild)1019 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
1020 {
1021     RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
1022     if (prevSibling) {
1023         child->setPreviousSibling(prevSibling);
1024         prevSibling->setNextSibling(child);
1025         ASSERT(prevSibling != child);
1026     } else
1027         setFirstChild(child);
1028 
1029     if (beforeChild) {
1030         beforeChild->setPreviousSibling(child);
1031         child->setNextSibling(beforeChild);
1032         ASSERT(beforeChild != child);
1033     } else
1034         setLastChild(child);
1035 
1036     child->setParent(this);
1037 
1038     if (child->isNormalFlowOnly())
1039         dirtyNormalFlowList();
1040 
1041     if (!child->isNormalFlowOnly() || child->firstChild()) {
1042         // Dirty the z-order list in which we are contained.  The stackingContext() can be null in the
1043         // case where we're building up generated content layers.  This is ok, since the lists will start
1044         // off dirty in that case anyway.
1045         child->dirtyStackingContextZOrderLists();
1046     }
1047 
1048     child->updateVisibilityStatus();
1049     if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
1050         childVisibilityChanged(true);
1051 
1052 #if USE(ACCELERATED_COMPOSITING)
1053     compositor()->layerWasAdded(this, child);
1054 #endif
1055 }
1056 
removeChild(RenderLayer * oldChild)1057 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
1058 {
1059 #if USE(ACCELERATED_COMPOSITING)
1060     if (!renderer()->documentBeingDestroyed())
1061         compositor()->layerWillBeRemoved(this, oldChild);
1062 #endif
1063 
1064     // remove the child
1065     if (oldChild->previousSibling())
1066         oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
1067     if (oldChild->nextSibling())
1068         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
1069 
1070     if (m_first == oldChild)
1071         m_first = oldChild->nextSibling();
1072     if (m_last == oldChild)
1073         m_last = oldChild->previousSibling();
1074 
1075     if (oldChild->isNormalFlowOnly())
1076         dirtyNormalFlowList();
1077     if (!oldChild->isNormalFlowOnly() || oldChild->firstChild()) {
1078         // Dirty the z-order list in which we are contained.  When called via the
1079         // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
1080         // from the main layer tree, so we need to null-check the |stackingContext| value.
1081         oldChild->dirtyStackingContextZOrderLists();
1082     }
1083 
1084     oldChild->setPreviousSibling(0);
1085     oldChild->setNextSibling(0);
1086     oldChild->setParent(0);
1087 
1088     oldChild->updateVisibilityStatus();
1089     if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
1090         childVisibilityChanged(false);
1091 
1092     return oldChild;
1093 }
1094 
removeOnlyThisLayer()1095 void RenderLayer::removeOnlyThisLayer()
1096 {
1097     if (!m_parent)
1098         return;
1099 
1100     // Mark that we are about to lose our layer. This makes render tree
1101     // walks ignore this layer while we're removing it.
1102     m_renderer->setHasLayer(false);
1103 
1104 #if USE(ACCELERATED_COMPOSITING)
1105     compositor()->layerWillBeRemoved(m_parent, this);
1106 #endif
1107 
1108     // Dirty the clip rects.
1109     clearClipRectsIncludingDescendants();
1110 
1111     // Remove us from the parent.
1112     RenderLayer* parent = m_parent;
1113     RenderLayer* nextSib = nextSibling();
1114     parent->removeChild(this);
1115 
1116     if (reflection())
1117         removeChild(reflectionLayer());
1118 
1119     // Now walk our kids and reattach them to our parent.
1120     RenderLayer* current = m_first;
1121     while (current) {
1122         RenderLayer* next = current->nextSibling();
1123         removeChild(current);
1124         parent->addChild(current, nextSib);
1125         current->setNeedsFullRepaint();
1126         current->updateLayerPositions(); // Depends on hasLayer() already being false for proper layout.
1127         current = next;
1128     }
1129 
1130     m_renderer->destroyLayer();
1131 }
1132 
insertOnlyThisLayer()1133 void RenderLayer::insertOnlyThisLayer()
1134 {
1135     if (!m_parent && renderer()->parent()) {
1136         // We need to connect ourselves when our renderer() has a parent.
1137         // Find our enclosingLayer and add ourselves.
1138         RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
1139         ASSERT(parentLayer);
1140         RenderLayer* beforeChild = parentLayer->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0;
1141         parentLayer->addChild(this, beforeChild);
1142     }
1143 
1144     // Remove all descendant layers from the hierarchy and add them to the new position.
1145     for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
1146         curr->moveLayers(m_parent, this);
1147 
1148     // Clear out all the clip rects.
1149     clearClipRectsIncludingDescendants();
1150 }
1151 
1152 void
convertToLayerCoords(const RenderLayer * ancestorLayer,int & xPos,int & yPos) const1153 RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, int& yPos) const
1154 {
1155     if (ancestorLayer == this)
1156         return;
1157 
1158     EPosition position = renderer()->style()->position();
1159     if (position == FixedPosition && (!ancestorLayer || ancestorLayer == renderer()->view()->layer())) {
1160         // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
1161         // localToAbsolute() on the RenderView.
1162         FloatPoint absPos = renderer()->localToAbsolute(FloatPoint(), true);
1163         xPos += absPos.x();
1164         yPos += absPos.y();
1165         return;
1166     }
1167 
1168     if (position == FixedPosition) {
1169         // For a fixed layers, we need to walk up to the root to see if there's a fixed position container
1170         // (e.g. a transformed layer). It's an error to call convertToLayerCoords() across a layer with a transform,
1171         // so we should always find the ancestor at or before we find the fixed position container.
1172         RenderLayer* fixedPositionContainerLayer = 0;
1173         bool foundAncestor = false;
1174         for (RenderLayer* currLayer = parent(); currLayer; currLayer = currLayer->parent()) {
1175             if (currLayer == ancestorLayer)
1176                 foundAncestor = true;
1177 
1178             if (isFixedPositionedContainer(currLayer)) {
1179                 fixedPositionContainerLayer = currLayer;
1180                 ASSERT(foundAncestor);
1181                 break;
1182             }
1183         }
1184 
1185         ASSERT(fixedPositionContainerLayer); // We should have hit the RenderView's layer at least.
1186 
1187         if (fixedPositionContainerLayer != ancestorLayer) {
1188             int fixedContainerX = 0;
1189             int fixedContainerY = 0;
1190             convertToLayerCoords(fixedPositionContainerLayer, fixedContainerX, fixedContainerY);
1191 
1192             int ancestorX = 0;
1193             int ancestorY = 0;
1194             ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorX, ancestorY);
1195 
1196             xPos += (fixedContainerX - ancestorX);
1197             yPos += (fixedContainerY - ancestorY);
1198             return;
1199         }
1200     }
1201 
1202 
1203     RenderLayer* parentLayer;
1204     if (position == AbsolutePosition || position == FixedPosition) {
1205         // Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way.
1206         parentLayer = parent();
1207         bool foundAncestorFirst = false;
1208         while (parentLayer) {
1209             if (isPositionedContainer(parentLayer))
1210                 break;
1211 
1212             if (parentLayer == ancestorLayer) {
1213                 foundAncestorFirst = true;
1214                 break;
1215             }
1216 
1217             parentLayer = parentLayer->parent();
1218         }
1219 
1220         if (foundAncestorFirst) {
1221             // Found ancestorLayer before the abs. positioned container, so compute offset of both relative
1222             // to enclosingPositionedAncestor and subtract.
1223             RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor();
1224 
1225             int thisX = 0;
1226             int thisY = 0;
1227             convertToLayerCoords(positionedAncestor, thisX, thisY);
1228 
1229             int ancestorX = 0;
1230             int ancestorY = 0;
1231             ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorX, ancestorY);
1232 
1233             xPos += (thisX - ancestorX);
1234             yPos += (thisY - ancestorY);
1235             return;
1236         }
1237     } else
1238         parentLayer = parent();
1239 
1240     if (!parentLayer)
1241         return;
1242 
1243     parentLayer->convertToLayerCoords(ancestorLayer, xPos, yPos);
1244 
1245     xPos += x();
1246     yPos += y();
1247 }
1248 
adjustedScrollDelta(int beginningDelta)1249 static inline int adjustedScrollDelta(int beginningDelta) {
1250     // This implemention matches Firefox's.
1251     // http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856.
1252     const int speedReducer = 12;
1253 
1254     int adjustedDelta = beginningDelta / speedReducer;
1255     if (adjustedDelta > 1)
1256         adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(adjustedDelta))) - 1;
1257     else if (adjustedDelta < -1)
1258         adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(-adjustedDelta))) + 1;
1259 
1260     return adjustedDelta;
1261 }
1262 
panScrollFromPoint(const IntPoint & sourcePoint)1263 void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
1264 {
1265     Frame* frame = renderer()->frame();
1266     if (!frame)
1267         return;
1268 
1269     IntPoint currentMousePosition = frame->eventHandler()->currentMousePosition();
1270 
1271     // 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
1272     static IntPoint previousMousePosition;
1273     if (currentMousePosition.x() < 0 || currentMousePosition.y() < 0)
1274         currentMousePosition = previousMousePosition;
1275     else
1276         previousMousePosition = currentMousePosition;
1277 
1278     int xDelta = currentMousePosition.x() - sourcePoint.x();
1279     int yDelta = currentMousePosition.y() - sourcePoint.y();
1280 
1281     if (abs(xDelta) <= ScrollView::noPanScrollRadius) // at the center we let the space for the icon
1282         xDelta = 0;
1283     if (abs(yDelta) <= ScrollView::noPanScrollRadius)
1284         yDelta = 0;
1285 
1286     scrollByRecursively(adjustedScrollDelta(xDelta), adjustedScrollDelta(yDelta));
1287 }
1288 
scrollByRecursively(int xDelta,int yDelta)1289 void RenderLayer::scrollByRecursively(int xDelta, int yDelta)
1290 {
1291     if (!xDelta && !yDelta)
1292         return;
1293 
1294     bool restrictedByLineClamp = false;
1295     if (renderer()->parent())
1296         restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone();
1297 
1298     if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
1299         int newOffsetX = scrollXOffset() + xDelta;
1300         int newOffsetY = scrollYOffset() + yDelta;
1301         scrollToOffset(newOffsetX, newOffsetY);
1302 
1303         // If this layer can't do the scroll we ask the next layer up that can scroll to try
1304         int leftToScrollX = newOffsetX - scrollXOffset();
1305         int leftToScrollY = newOffsetY - scrollYOffset();
1306         if ((leftToScrollX || leftToScrollY) && renderer()->parent()) {
1307             RenderObject* nextRenderer = renderer()->parent();
1308             while (nextRenderer) {
1309                 if (nextRenderer->isBox() && toRenderBox(nextRenderer)->canBeScrolledAndHasScrollableArea()) {
1310                     nextRenderer->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY);
1311                     break;
1312                 }
1313                 nextRenderer = nextRenderer->parent();
1314             }
1315 
1316             Frame* frame = renderer()->frame();
1317             if (frame)
1318                 frame->eventHandler()->updateAutoscrollRenderer();
1319         }
1320     } else if (renderer()->view()->frameView()) {
1321         // If we are here, we were called on a renderer that can be programmatically scrolled, but doesn't
1322         // have an overflow clip. Which means that it is a document node that can be scrolled.
1323         renderer()->view()->frameView()->scrollBy(IntSize(xDelta, yDelta));
1324         // FIXME: If we didn't scroll the whole way, do we want to try looking at the frames ownerElement?
1325         // https://bugs.webkit.org/show_bug.cgi?id=28237
1326     }
1327 }
1328 
scrollToOffset(int x,int y)1329 void RenderLayer::scrollToOffset(int x, int y)
1330 {
1331     ScrollableArea::scrollToOffsetWithoutAnimation(IntPoint(x, y));
1332 }
1333 
scrollTo(int x,int y)1334 void RenderLayer::scrollTo(int x, int y)
1335 {
1336     RenderBox* box = renderBox();
1337     if (!box)
1338         return;
1339 
1340     if (box->style()->overflowX() != OMARQUEE) {
1341         if (x < 0)
1342             x = 0;
1343         if (y < 0)
1344             y = 0;
1345 
1346         // Call the scrollWidth/Height functions so that the dimensions will be computed if they need
1347         // to be (for overflow:hidden blocks).
1348         int maxX = scrollWidth() - box->clientWidth();
1349         if (maxX < 0)
1350             maxX = 0;
1351         int maxY = scrollHeight() - box->clientHeight();
1352         if (maxY < 0)
1353             maxY = 0;
1354 
1355         if (x > maxX)
1356             x = maxX;
1357         if (y > maxY)
1358             y = maxY;
1359     }
1360 
1361     // FIXME: Eventually, we will want to perform a blit.  For now never
1362     // blit, since the check for blitting is going to be very
1363     // complicated (since it will involve testing whether our layer
1364     // is either occluded by another layer or clipped by an enclosing
1365     // layer or contains fixed backgrounds, etc.).
1366     int newScrollX = x - m_scrollOrigin.x();
1367     int newScrollY = y - m_scrollOrigin.y();
1368     if (m_scrollY == newScrollY && m_scrollX == newScrollX)
1369         return;
1370     m_scrollX = newScrollX;
1371     m_scrollY = newScrollY;
1372 
1373     // Update the positions of our child layers. Don't have updateLayerPositions() update
1374     // compositing layers, because we need to do a deep update from the compositing ancestor.
1375     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
1376         child->updateLayerPositions(0);
1377 
1378     RenderView* view = renderer()->view();
1379 
1380     // We should have a RenderView if we're trying to scroll.
1381     ASSERT(view);
1382     if (view) {
1383 #if ENABLE(DASHBOARD_SUPPORT)
1384         // Update dashboard regions, scrolling may change the clip of a
1385         // particular region.
1386         view->frameView()->updateDashboardRegions();
1387 #endif
1388 
1389         view->updateWidgetPositions();
1390     }
1391 
1392 #if USE(ACCELERATED_COMPOSITING)
1393     if (compositor()->inCompositingMode()) {
1394         // Our stacking context is guaranteed to contain all of our descendants that may need
1395         // repositioning, so update compositing layers from there.
1396         if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) {
1397             if (compositor()->compositingConsultsOverlap())
1398                 compositor()->updateCompositingLayers(CompositingUpdateOnScroll, compositingAncestor);
1399             else {
1400                 bool isUpdateRoot = true;
1401                 compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants, isUpdateRoot);
1402             }
1403         }
1404     }
1405 #endif
1406 
1407     RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
1408     IntRect rectForRepaint = renderer()->clippedOverflowRectForRepaint(repaintContainer);
1409 
1410     Frame* frame = renderer()->frame();
1411     if (frame) {
1412         // The caret rect needs to be invalidated after scrolling
1413         frame->selection()->setCaretRectNeedsUpdate();
1414 
1415         FloatQuad quadForFakeMouseMoveEvent = FloatQuad(rectForRepaint);
1416         if (repaintContainer)
1417             quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent);
1418         frame->eventHandler()->dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent);
1419     }
1420 
1421     // Just schedule a full repaint of our object.
1422     if (view)
1423         renderer()->repaintUsingContainer(repaintContainer, rectForRepaint);
1424 
1425     // Schedule the scroll DOM event.
1426     renderer()->node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), EventQueue::ScrollEventElementTarget);
1427 }
1428 
scrollRectToVisible(const IntRect & rect,bool scrollToAnchor,const ScrollAlignment & alignX,const ScrollAlignment & alignY)1429 void RenderLayer::scrollRectToVisible(const IntRect& rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
1430 {
1431     RenderLayer* parentLayer = 0;
1432     IntRect newRect = rect;
1433     int xOffset = 0, yOffset = 0;
1434 
1435     // We may end up propagating a scroll event. It is important that we suspend events until
1436     // the end of the function since they could delete the layer or the layer's renderer().
1437     FrameView* frameView = renderer()->document()->view();
1438     if (frameView)
1439         frameView->pauseScheduledEvents();
1440 
1441     bool restrictedByLineClamp = false;
1442     if (renderer()->parent()) {
1443         parentLayer = renderer()->parent()->enclosingLayer();
1444         restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone();
1445     }
1446 
1447     if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
1448         // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property.
1449         // This will prevent us from revealing text hidden by the slider in Safari RSS.
1450         RenderBox* box = renderBox();
1451         ASSERT(box);
1452         FloatPoint absPos = box->localToAbsolute();
1453         absPos.move(box->borderLeft(), box->borderTop());
1454 
1455         IntRect layerBounds = IntRect(absPos.x() + scrollXOffset(), absPos.y() + scrollYOffset(), box->clientWidth(), box->clientHeight());
1456         IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());
1457         IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);
1458 
1459         xOffset = r.x() - absPos.x();
1460         yOffset = r.y() - absPos.y();
1461         // Adjust offsets if they're outside of the allowable range.
1462         xOffset = max(0, min(scrollWidth() - layerBounds.width(), xOffset));
1463         yOffset = max(0, min(scrollHeight() - layerBounds.height(), yOffset));
1464 
1465         if (xOffset != scrollXOffset() || yOffset != scrollYOffset()) {
1466             int diffX = scrollXOffset();
1467             int diffY = scrollYOffset();
1468             scrollToOffset(xOffset, yOffset);
1469             diffX = scrollXOffset() - diffX;
1470             diffY = scrollYOffset() - diffY;
1471             newRect.setX(rect.x() - diffX);
1472             newRect.setY(rect.y() - diffY);
1473         }
1474     } else if (!parentLayer && renderer()->isBox() && renderBox()->canBeProgramaticallyScrolled(scrollToAnchor)) {
1475         if (frameView) {
1476             if (renderer()->document() && renderer()->document()->ownerElement() && renderer()->document()->ownerElement()->renderer()) {
1477                 IntRect viewRect = frameView->visibleContentRect();
1478                 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
1479 
1480                 xOffset = r.x();
1481                 yOffset = r.y();
1482                 // Adjust offsets if they're outside of the allowable range.
1483                 xOffset = max(0, min(frameView->contentsWidth(), xOffset));
1484                 yOffset = max(0, min(frameView->contentsHeight(), yOffset));
1485 
1486                 frameView->setScrollPosition(IntPoint(xOffset, yOffset));
1487                 parentLayer = renderer()->document()->ownerElement()->renderer()->enclosingLayer();
1488                 newRect.setX(rect.x() - frameView->scrollX() + frameView->x());
1489                 newRect.setY(rect.y() - frameView->scrollY() + frameView->y());
1490             } else {
1491                 IntRect viewRect = frameView->visibleContentRect();
1492                 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
1493 
1494                 frameView->setScrollPosition(r.location());
1495 
1496                 // This is the outermost view of a web page, so after scrolling this view we
1497                 // scroll its container by calling Page::scrollRectIntoView.
1498                 // This only has an effect on the Mac platform in applications
1499                 // that put web views into scrolling containers, such as Mac OS X Mail.
1500                 // The canAutoscroll function in EventHandler also knows about this.
1501                 if (Frame* frame = frameView->frame()) {
1502                     if (Page* page = frame->page())
1503                         page->chrome()->scrollRectIntoView(rect);
1504                 }
1505             }
1506         }
1507     }
1508 
1509     if (parentLayer)
1510         parentLayer->scrollRectToVisible(newRect, scrollToAnchor, alignX, alignY);
1511 
1512     if (frameView)
1513         frameView->resumeScheduledEvents();
1514 }
1515 
getRectToExpose(const IntRect & visibleRect,const IntRect & exposeRect,const ScrollAlignment & alignX,const ScrollAlignment & alignY)1516 IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
1517 {
1518     // Determine the appropriate X behavior.
1519     ScrollBehavior scrollX;
1520     IntRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height());
1521     int intersectWidth = intersection(visibleRect, exposeRectX).width();
1522     if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL)
1523         // If the rectangle is fully visible, use the specified visible behavior.
1524         // If the rectangle is partially visible, but over a certain threshold,
1525         // then treat it as fully visible to avoid unnecessary horizontal scrolling
1526         scrollX = ScrollAlignment::getVisibleBehavior(alignX);
1527     else if (intersectWidth == visibleRect.width()) {
1528         // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
1529         scrollX = ScrollAlignment::getVisibleBehavior(alignX);
1530         if (scrollX == alignCenter)
1531             scrollX = noScroll;
1532     } else if (intersectWidth > 0)
1533         // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior
1534         scrollX = ScrollAlignment::getPartialBehavior(alignX);
1535     else
1536         scrollX = ScrollAlignment::getHiddenBehavior(alignX);
1537     // If we're trying to align to the closest edge, and the exposeRect is further right
1538     // than the visibleRect, and not bigger than the visible area, then align with the right.
1539     if (scrollX == alignToClosestEdge && exposeRect.maxX() > visibleRect.maxX() && exposeRect.width() < visibleRect.width())
1540         scrollX = alignRight;
1541 
1542     // Given the X behavior, compute the X coordinate.
1543     int x;
1544     if (scrollX == noScroll)
1545         x = visibleRect.x();
1546     else if (scrollX == alignRight)
1547         x = exposeRect.maxX() - visibleRect.width();
1548     else if (scrollX == alignCenter)
1549         x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2;
1550     else
1551         x = exposeRect.x();
1552 
1553     // Determine the appropriate Y behavior.
1554     ScrollBehavior scrollY;
1555     IntRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height());
1556     int intersectHeight = intersection(visibleRect, exposeRectY).height();
1557     if (intersectHeight == exposeRect.height())
1558         // If the rectangle is fully visible, use the specified visible behavior.
1559         scrollY = ScrollAlignment::getVisibleBehavior(alignY);
1560     else if (intersectHeight == visibleRect.height()) {
1561         // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
1562         scrollY = ScrollAlignment::getVisibleBehavior(alignY);
1563         if (scrollY == alignCenter)
1564             scrollY = noScroll;
1565     } else if (intersectHeight > 0)
1566         // If the rectangle is partially visible, use the specified partial behavior
1567         scrollY = ScrollAlignment::getPartialBehavior(alignY);
1568     else
1569         scrollY = ScrollAlignment::getHiddenBehavior(alignY);
1570     // If we're trying to align to the closest edge, and the exposeRect is further down
1571     // than the visibleRect, and not bigger than the visible area, then align with the bottom.
1572     if (scrollY == alignToClosestEdge && exposeRect.maxY() > visibleRect.maxY() && exposeRect.height() < visibleRect.height())
1573         scrollY = alignBottom;
1574 
1575     // Given the Y behavior, compute the Y coordinate.
1576     int y;
1577     if (scrollY == noScroll)
1578         y = visibleRect.y();
1579     else if (scrollY == alignBottom)
1580         y = exposeRect.maxY() - visibleRect.height();
1581     else if (scrollY == alignCenter)
1582         y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2;
1583     else
1584         y = exposeRect.y();
1585 
1586     return IntRect(IntPoint(x, y), visibleRect.size());
1587 }
1588 
autoscroll()1589 void RenderLayer::autoscroll()
1590 {
1591     Frame* frame = renderer()->frame();
1592     if (!frame)
1593         return;
1594 
1595     FrameView* frameView = frame->view();
1596     if (!frameView)
1597         return;
1598 
1599 #if ENABLE(DRAG_SUPPORT)
1600     frame->eventHandler()->updateSelectionForMouseDrag();
1601 #endif
1602 
1603     IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition());
1604     scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
1605 }
1606 
resize(const PlatformMouseEvent & evt,const IntSize & oldOffset)1607 void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset)
1608 {
1609     // FIXME: This should be possible on generated content but is not right now.
1610     if (!inResizeMode() || !renderer()->hasOverflowClip() || !renderer()->node())
1611         return;
1612 
1613     // Set the width and height of the shadow ancestor node if there is one.
1614     // This is necessary for textarea elements since the resizable layer is in the shadow content.
1615     Element* element = static_cast<Element*>(renderer()->node()->shadowAncestorNode());
1616     RenderBox* renderer = toRenderBox(element->renderer());
1617 
1618     EResize resize = renderer->style()->resize();
1619     if (resize == RESIZE_NONE)
1620         return;
1621 
1622     Document* document = element->document();
1623     if (!document->frame()->eventHandler()->mousePressed())
1624         return;
1625 
1626     float zoomFactor = renderer->style()->effectiveZoom();
1627 
1628     IntSize newOffset = offsetFromResizeCorner(document->view()->windowToContents(evt.pos()));
1629     newOffset.setWidth(newOffset.width() / zoomFactor);
1630     newOffset.setHeight(newOffset.height() / zoomFactor);
1631 
1632     IntSize currentSize = IntSize(renderer->width() / zoomFactor, renderer->height() / zoomFactor);
1633     IntSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize);
1634     element->setMinimumSizeForResizing(minimumSize);
1635 
1636     IntSize adjustedOldOffset = IntSize(oldOffset.width() / zoomFactor, oldOffset.height() / zoomFactor);
1637 
1638     IntSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize;
1639 
1640     CSSStyleDeclaration* style = element->style();
1641     bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX;
1642 
1643     ExceptionCode ec;
1644 
1645     if (resize != RESIZE_VERTICAL && difference.width()) {
1646         if (element->isFormControlElement()) {
1647             // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
1648             style->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false, ec);
1649             style->setProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false, ec);
1650         }
1651         int baseWidth = renderer->width() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingWidth());
1652         baseWidth = baseWidth / zoomFactor;
1653         style->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false, ec);
1654     }
1655 
1656     if (resize != RESIZE_HORIZONTAL && difference.height()) {
1657         if (element->isFormControlElement()) {
1658             // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
1659             style->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false, ec);
1660             style->setProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false, ec);
1661         }
1662         int baseHeight = renderer->height() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingHeight());
1663         baseHeight = baseHeight / zoomFactor;
1664         style->setProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false, ec);
1665     }
1666 
1667     document->updateLayout();
1668 
1669     // FIXME (Radar 4118564): We should also autoscroll the window as necessary to keep the point under the cursor in view.
1670 }
1671 
scrollSize(ScrollbarOrientation orientation) const1672 int RenderLayer::scrollSize(ScrollbarOrientation orientation) const
1673 {
1674     Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_hBar : m_vBar).get();
1675     return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0;
1676 }
1677 
setScrollOffset(const IntPoint & offset)1678 void RenderLayer::setScrollOffset(const IntPoint& offset)
1679 {
1680     scrollTo(offset.x(), offset.y());
1681 }
1682 
scrollPosition(Scrollbar * scrollbar) const1683 int RenderLayer::scrollPosition(Scrollbar* scrollbar) const
1684 {
1685     if (scrollbar->orientation() == HorizontalScrollbar)
1686         return scrollXOffset();
1687     if (scrollbar->orientation() == VerticalScrollbar)
1688         return scrollYOffset();
1689     return 0;
1690 }
1691 
isActive() const1692 bool RenderLayer::isActive() const
1693 {
1694     Page* page = renderer()->frame()->page();
1695     return page && page->focusController()->isActive();
1696 }
1697 
cornerRect(const RenderLayer * layer,const IntRect & bounds)1698 static IntRect cornerRect(const RenderLayer* layer, const IntRect& bounds)
1699 {
1700     int horizontalThickness;
1701     int verticalThickness;
1702     if (!layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
1703         // FIXME: This isn't right.  We need to know the thickness of custom scrollbars
1704         // even when they don't exist in order to set the resizer square size properly.
1705         horizontalThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();
1706         verticalThickness = horizontalThickness;
1707     } else if (layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
1708         horizontalThickness = layer->verticalScrollbar()->width();
1709         verticalThickness = horizontalThickness;
1710     } else if (layer->horizontalScrollbar() && !layer->verticalScrollbar()) {
1711         verticalThickness = layer->horizontalScrollbar()->height();
1712         horizontalThickness = verticalThickness;
1713     } else {
1714         horizontalThickness = layer->verticalScrollbar()->width();
1715         verticalThickness = layer->horizontalScrollbar()->height();
1716     }
1717     return IntRect(bounds.maxX() - horizontalThickness - layer->renderer()->style()->borderRightWidth(),
1718                    bounds.maxY() - verticalThickness - layer->renderer()->style()->borderBottomWidth(),
1719                    horizontalThickness, verticalThickness);
1720 }
1721 
scrollCornerRect() const1722 IntRect RenderLayer::scrollCornerRect() const
1723 {
1724     // We have a scrollbar corner when a scrollbar is visible and not filling the entire length of the box.
1725     // This happens when:
1726     // (a) A resizer is present and at least one scrollbar is present
1727     // (b) Both scrollbars are present.
1728     bool hasHorizontalBar = horizontalScrollbar();
1729     bool hasVerticalBar = verticalScrollbar();
1730     bool hasResizer = renderer()->style()->resize() != RESIZE_NONE;
1731     if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar)))
1732         return cornerRect(this, renderBox()->borderBoxRect());
1733     return IntRect();
1734 }
1735 
resizerCornerRect(const RenderLayer * layer,const IntRect & bounds)1736 static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds)
1737 {
1738     ASSERT(layer->renderer()->isBox());
1739     if (layer->renderer()->style()->resize() == RESIZE_NONE)
1740         return IntRect();
1741     return cornerRect(layer, bounds);
1742 }
1743 
scrollCornerAndResizerRect() const1744 IntRect RenderLayer::scrollCornerAndResizerRect() const
1745 {
1746     RenderBox* box = renderBox();
1747     if (!box)
1748         return IntRect();
1749     IntRect scrollCornerAndResizer = scrollCornerRect();
1750     if (scrollCornerAndResizer.isEmpty())
1751         scrollCornerAndResizer = resizerCornerRect(this, box->borderBoxRect());
1752     return scrollCornerAndResizer;
1753 }
1754 
isScrollCornerVisible() const1755 bool RenderLayer::isScrollCornerVisible() const
1756 {
1757     ASSERT(renderer()->isBox());
1758     return !scrollCornerRect().isEmpty();
1759 }
1760 
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntRect & scrollbarRect) const1761 IntRect RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
1762 {
1763     RenderView* view = renderer()->view();
1764     if (!view)
1765         return scrollbarRect;
1766 
1767     IntRect rect = scrollbarRect;
1768     rect.move(scrollbarOffset(scrollbar));
1769 
1770     return view->frameView()->convertFromRenderer(renderer(), rect);
1771 }
1772 
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntRect & parentRect) const1773 IntRect RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
1774 {
1775     RenderView* view = renderer()->view();
1776     if (!view)
1777         return parentRect;
1778 
1779     IntRect rect = view->frameView()->convertToRenderer(renderer(), parentRect);
1780     rect.move(-scrollbarOffset(scrollbar));
1781     return rect;
1782 }
1783 
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntPoint & scrollbarPoint) const1784 IntPoint RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
1785 {
1786     RenderView* view = renderer()->view();
1787     if (!view)
1788         return scrollbarPoint;
1789 
1790     IntPoint point = scrollbarPoint;
1791     point.move(scrollbarOffset(scrollbar));
1792     return view->frameView()->convertFromRenderer(renderer(), point);
1793 }
1794 
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntPoint & parentPoint) const1795 IntPoint RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
1796 {
1797     RenderView* view = renderer()->view();
1798     if (!view)
1799         return parentPoint;
1800 
1801     IntPoint point = view->frameView()->convertToRenderer(renderer(), parentPoint);
1802 
1803     point.move(-scrollbarOffset(scrollbar));
1804     return point;
1805 }
1806 
contentsSize() const1807 IntSize RenderLayer::contentsSize() const
1808 {
1809     return IntSize(const_cast<RenderLayer*>(this)->scrollWidth(), const_cast<RenderLayer*>(this)->scrollHeight());
1810 }
1811 
visibleHeight() const1812 int RenderLayer::visibleHeight() const
1813 {
1814     return m_height;
1815 }
1816 
visibleWidth() const1817 int RenderLayer::visibleWidth() const
1818 {
1819     return m_width;
1820 }
1821 
shouldSuspendScrollAnimations() const1822 bool RenderLayer::shouldSuspendScrollAnimations() const
1823 {
1824     RenderView* view = renderer()->view();
1825     if (!view)
1826         return true;
1827     return view->frameView()->shouldSuspendScrollAnimations();
1828 }
1829 
currentMousePosition() const1830 IntPoint RenderLayer::currentMousePosition() const
1831 {
1832     return renderer()->frame() ? renderer()->frame()->eventHandler()->currentMousePosition() : IntPoint();
1833 }
1834 
scrollbarOffset(const Scrollbar * scrollbar) const1835 IntSize RenderLayer::scrollbarOffset(const Scrollbar* scrollbar) const
1836 {
1837     RenderBox* box = renderBox();
1838 
1839     if (scrollbar == m_vBar.get())
1840         return IntSize(box->width() - box->borderRight() - scrollbar->width(), box->borderTop());
1841 
1842     if (scrollbar == m_hBar.get())
1843         return IntSize(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height());
1844 
1845     ASSERT_NOT_REACHED();
1846     return IntSize();
1847 }
1848 
invalidateScrollbarRect(Scrollbar * scrollbar,const IntRect & rect)1849 void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
1850 {
1851 #if USE(ACCELERATED_COMPOSITING)
1852     if (scrollbar == m_vBar.get()) {
1853         if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
1854             layer->setNeedsDisplayInRect(rect);
1855             return;
1856         }
1857     } else {
1858         if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
1859             layer->setNeedsDisplayInRect(rect);
1860             return;
1861         }
1862     }
1863 #endif
1864     IntRect scrollRect = rect;
1865     RenderBox* box = renderBox();
1866     ASSERT(box);
1867     if (scrollbar == m_vBar.get())
1868         scrollRect.move(box->width() - box->borderRight() - scrollbar->width(), box->borderTop());
1869     else
1870         scrollRect.move(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height());
1871     renderer()->repaintRectangle(scrollRect);
1872 }
1873 
invalidateScrollCornerRect(const IntRect & rect)1874 void RenderLayer::invalidateScrollCornerRect(const IntRect& rect)
1875 {
1876 #if USE(ACCELERATED_COMPOSITING)
1877     if (GraphicsLayer* layer = layerForScrollCorner()) {
1878         layer->setNeedsDisplayInRect(rect);
1879         return;
1880     }
1881 #endif
1882     if (m_scrollCorner)
1883         m_scrollCorner->repaintRectangle(rect);
1884     if (m_resizer)
1885         m_resizer->repaintRectangle(rect);
1886 }
1887 
createScrollbar(ScrollbarOrientation orientation)1888 PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation)
1889 {
1890     RefPtr<Scrollbar> widget;
1891     RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
1892     bool hasCustomScrollbarStyle = actualRenderer->isBox() && actualRenderer->style()->hasPseudoStyle(SCROLLBAR);
1893     if (hasCustomScrollbarStyle)
1894         widget = RenderScrollbar::createCustomScrollbar(this, orientation, toRenderBox(actualRenderer));
1895     else {
1896         widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
1897         if (orientation == HorizontalScrollbar)
1898             didAddHorizontalScrollbar(widget.get());
1899         else
1900             didAddVerticalScrollbar(widget.get());
1901     }
1902     renderer()->document()->view()->addChild(widget.get());
1903     return widget.release();
1904 }
1905 
destroyScrollbar(ScrollbarOrientation orientation)1906 void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation)
1907 {
1908     RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
1909     if (scrollbar) {
1910         if (scrollbar->isCustomScrollbar())
1911             static_cast<RenderScrollbar*>(scrollbar.get())->clearOwningRenderer();
1912         else {
1913             if (orientation == HorizontalScrollbar)
1914                 willRemoveHorizontalScrollbar(scrollbar.get());
1915             else
1916                 willRemoveVerticalScrollbar(scrollbar.get());
1917         }
1918 
1919         scrollbar->removeFromParent();
1920         scrollbar->disconnectFromScrollableArea();
1921         scrollbar = 0;
1922     }
1923 }
1924 
setHasHorizontalScrollbar(bool hasScrollbar)1925 void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
1926 {
1927     if (hasScrollbar == (m_hBar != 0))
1928         return;
1929 
1930     if (hasScrollbar)
1931         m_hBar = createScrollbar(HorizontalScrollbar);
1932     else
1933         destroyScrollbar(HorizontalScrollbar);
1934 
1935     // Destroying or creating one bar can cause our scrollbar corner to come and go.  We need to update the opposite scrollbar's style.
1936     if (m_hBar)
1937         m_hBar->styleChanged();
1938     if (m_vBar)
1939         m_vBar->styleChanged();
1940 
1941 #if ENABLE(DASHBOARD_SUPPORT)
1942     // Force an update since we know the scrollbars have changed things.
1943     if (renderer()->document()->hasDashboardRegions())
1944         renderer()->document()->setDashboardRegionsDirty(true);
1945 #endif
1946 }
1947 
setHasVerticalScrollbar(bool hasScrollbar)1948 void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
1949 {
1950     if (hasScrollbar == (m_vBar != 0))
1951         return;
1952 
1953     if (hasScrollbar)
1954         m_vBar = createScrollbar(VerticalScrollbar);
1955     else
1956         destroyScrollbar(VerticalScrollbar);
1957 
1958      // Destroying or creating one bar can cause our scrollbar corner to come and go.  We need to update the opposite scrollbar's style.
1959     if (m_hBar)
1960         m_hBar->styleChanged();
1961     if (m_vBar)
1962         m_vBar->styleChanged();
1963 
1964 #if ENABLE(DASHBOARD_SUPPORT)
1965     // Force an update since we know the scrollbars have changed things.
1966     if (renderer()->document()->hasDashboardRegions())
1967         renderer()->document()->setDashboardRegionsDirty(true);
1968 #endif
1969 }
1970 
verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy) const1971 int RenderLayer::verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy) const
1972 {
1973     if (!m_vBar || (m_vBar->isOverlayScrollbar() && relevancy == IgnoreOverlayScrollbarSize))
1974         return 0;
1975     return m_vBar->width();
1976 }
1977 
horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy) const1978 int RenderLayer::horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy) const
1979 {
1980     if (!m_hBar || (m_hBar->isOverlayScrollbar() && relevancy == IgnoreOverlayScrollbarSize))
1981         return 0;
1982     return m_hBar->height();
1983 }
1984 
offsetFromResizeCorner(const IntPoint & absolutePoint) const1985 IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const
1986 {
1987     // Currently the resize corner is always the bottom right corner
1988     IntPoint bottomRight(width(), height());
1989     IntPoint localPoint = absoluteToContents(absolutePoint);
1990     return localPoint - bottomRight;
1991 }
1992 
hasOverflowControls() const1993 bool RenderLayer::hasOverflowControls() const
1994 {
1995     return m_hBar || m_vBar || m_scrollCorner || renderer()->style()->resize() != RESIZE_NONE;
1996 }
1997 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
hasOverflowParent() const1998 bool RenderLayer::hasOverflowParent() const
1999 {
2000     const RenderLayer* layer = this;
2001     while (layer && !layer->hasOverflowScroll())
2002         layer = layer->parent();
2003     return layer;
2004 }
2005 #endif
2006 
positionOverflowControls(int tx,int ty)2007 void RenderLayer::positionOverflowControls(int tx, int ty)
2008 {
2009     if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
2010         return;
2011 
2012     RenderBox* box = renderBox();
2013     if (!box)
2014         return;
2015 
2016     const IntRect& borderBox = box->borderBoxRect();
2017     const IntRect& scrollCorner = scrollCornerRect();
2018     IntRect absBounds(borderBox.x() + tx, borderBox.y() + ty, borderBox.width(), borderBox.height());
2019     if (m_vBar)
2020         m_vBar->setFrameRect(IntRect(absBounds.maxX() - box->borderRight() - m_vBar->width(),
2021                                      absBounds.y() + box->borderTop(),
2022                                      m_vBar->width(),
2023                                      absBounds.height() - (box->borderTop() + box->borderBottom()) - scrollCorner.height()));
2024 
2025     if (m_hBar)
2026         m_hBar->setFrameRect(IntRect(absBounds.x() + box->borderLeft(),
2027                                      absBounds.maxY() - box->borderBottom() - m_hBar->height(),
2028                                      absBounds.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(),
2029                                      m_hBar->height()));
2030 
2031 #if USE(ACCELERATED_COMPOSITING)
2032     if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
2033         if (m_hBar) {
2034             layer->setPosition(IntPoint(m_hBar->frameRect().x() - tx, m_hBar->frameRect().y() - ty));
2035             layer->setSize(m_hBar->frameRect().size());
2036         }
2037         layer->setDrawsContent(m_hBar);
2038     }
2039     if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
2040         if (m_vBar) {
2041             layer->setPosition(IntPoint(m_vBar->frameRect().x() - tx, m_vBar->frameRect().y() - ty));
2042             layer->setSize(m_vBar->frameRect().size());
2043         }
2044         layer->setDrawsContent(m_vBar);
2045     }
2046 
2047     if (GraphicsLayer* layer = layerForScrollCorner()) {
2048         const IntRect& scrollCornerAndResizer = scrollCornerAndResizerRect();
2049         layer->setPosition(scrollCornerAndResizer.location());
2050         layer->setSize(scrollCornerAndResizer.size());
2051         layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
2052     }
2053 #endif
2054 
2055     if (m_scrollCorner)
2056         m_scrollCorner->setFrameRect(scrollCorner);
2057     if (m_resizer)
2058         m_resizer->setFrameRect(resizerCornerRect(this, borderBox));
2059 }
2060 
2061 #if PLATFORM(ANDROID)
2062 // When width/height change, the scrollWidth/scrollHeight should be dirty.
2063 // And this should be upstreamed to webkit.
setWidth(int w)2064 void RenderLayer::setWidth(int w)
2065 {
2066     if (m_width != w) {
2067         m_scrollDimensionsDirty = true;
2068         m_width = w;
2069     }
2070 }
2071 
setHeight(int h)2072 void RenderLayer::setHeight(int h)
2073 {
2074     if (m_height != h) {
2075         m_scrollDimensionsDirty = true;
2076         m_height = h;
2077     }
2078 }
2079 #endif
2080 
scrollWidth()2081 int RenderLayer::scrollWidth()
2082 {
2083     if (m_scrollDimensionsDirty)
2084         computeScrollDimensions();
2085     return m_scrollWidth;
2086 }
2087 
scrollHeight()2088 int RenderLayer::scrollHeight()
2089 {
2090     if (m_scrollDimensionsDirty)
2091         computeScrollDimensions();
2092     return m_scrollHeight;
2093 }
2094 
overflowTop() const2095 int RenderLayer::overflowTop() const
2096 {
2097     RenderBox* box = renderBox();
2098     IntRect overflowRect(box->layoutOverflowRect());
2099     box->flipForWritingMode(overflowRect);
2100     return overflowRect.y();
2101 }
2102 
overflowBottom() const2103 int RenderLayer::overflowBottom() const
2104 {
2105     RenderBox* box = renderBox();
2106     IntRect overflowRect(box->layoutOverflowRect());
2107     box->flipForWritingMode(overflowRect);
2108     return overflowRect.maxY();
2109 }
2110 
overflowLeft() const2111 int RenderLayer::overflowLeft() const
2112 {
2113     RenderBox* box = renderBox();
2114     IntRect overflowRect(box->layoutOverflowRect());
2115     box->flipForWritingMode(overflowRect);
2116     return overflowRect.x();
2117 }
2118 
overflowRight() const2119 int RenderLayer::overflowRight() const
2120 {
2121     RenderBox* box = renderBox();
2122     IntRect overflowRect(box->layoutOverflowRect());
2123     box->flipForWritingMode(overflowRect);
2124     return overflowRect.maxX();
2125 }
2126 
computeScrollDimensions(bool * needHBar,bool * needVBar)2127 void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
2128 {
2129     RenderBox* box = renderBox();
2130     ASSERT(box);
2131 
2132     m_scrollDimensionsDirty = false;
2133 
2134     m_scrollLeftOverflow = overflowLeft() - box->borderLeft();
2135     m_scrollTopOverflow = overflowTop() - box->borderTop();
2136 
2137     m_scrollWidth = overflowRight() - overflowLeft();
2138     m_scrollHeight = overflowBottom() - overflowTop();
2139 
2140     m_scrollOrigin = IntPoint(-m_scrollLeftOverflow, -m_scrollTopOverflow);
2141 
2142     if (needHBar)
2143         *needHBar = m_scrollWidth > box->clientWidth();
2144     if (needVBar)
2145         *needVBar = m_scrollHeight > box->clientHeight();
2146 }
2147 
updateOverflowStatus(bool horizontalOverflow,bool verticalOverflow)2148 void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2149 {
2150     if (m_overflowStatusDirty) {
2151         m_horizontalOverflow = horizontalOverflow;
2152         m_verticalOverflow = verticalOverflow;
2153         m_overflowStatusDirty = false;
2154         return;
2155     }
2156 
2157     bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2158     bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2159 
2160     if (horizontalOverflowChanged || verticalOverflowChanged) {
2161         m_horizontalOverflow = horizontalOverflow;
2162         m_verticalOverflow = verticalOverflow;
2163 
2164         if (FrameView* frameView = renderer()->document()->view()) {
2165             frameView->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow),
2166                 renderer()->node());
2167         }
2168     }
2169 }
2170 
updateScrollInfoAfterLayout()2171 void RenderLayer::updateScrollInfoAfterLayout()
2172 {
2173     RenderBox* box = renderBox();
2174     if (!box)
2175         return;
2176 
2177     m_scrollDimensionsDirty = true;
2178 
2179     bool horizontalOverflow, verticalOverflow;
2180     computeScrollDimensions(&horizontalOverflow, &verticalOverflow);
2181 
2182     if (box->style()->overflowX() != OMARQUEE) {
2183         // Layout may cause us to be in an invalid scroll position.  In this case we need
2184         // to pull our scroll offsets back to the max (or push them up to the min).
2185         int newX = max(0, min(scrollXOffset(), scrollWidth() - box->clientWidth()));
2186         int newY = max(0, min(scrollYOffset(), scrollHeight() - box->clientHeight()));
2187         if (newX != scrollXOffset() || newY != scrollYOffset()) {
2188             RenderView* view = renderer()->view();
2189             ASSERT(view);
2190             // scrollToOffset() may call updateLayerPositions(), which doesn't work
2191             // with LayoutState.
2192             // FIXME: Remove the disableLayoutState/enableLayoutState if the above changes.
2193             if (view)
2194                 view->disableLayoutState();
2195             scrollToOffset(newX, newY);
2196             if (view)
2197                 view->enableLayoutState();
2198         }
2199     }
2200 
2201     bool haveHorizontalBar = m_hBar;
2202     bool haveVerticalBar = m_vBar;
2203 
2204     // overflow:scroll should just enable/disable.
2205     if (renderer()->style()->overflowX() == OSCROLL)
2206         m_hBar->setEnabled(horizontalOverflow);
2207     if (renderer()->style()->overflowY() == OSCROLL)
2208         m_vBar->setEnabled(verticalOverflow);
2209 
2210     // A dynamic change from a scrolling overflow to overflow:hidden means we need to get rid of any
2211     // scrollbars that may be present.
2212     if (renderer()->style()->overflowX() == OHIDDEN && haveHorizontalBar)
2213         setHasHorizontalScrollbar(false);
2214     if (renderer()->style()->overflowY() == OHIDDEN && haveVerticalBar)
2215         setHasVerticalScrollbar(false);
2216 
2217     // overflow:auto may need to lay out again if scrollbars got added/removed.
2218     bool scrollbarsChanged = (box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) ||
2219                              (box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
2220     if (scrollbarsChanged) {
2221         if (box->hasAutoHorizontalScrollbar())
2222             setHasHorizontalScrollbar(horizontalOverflow);
2223         if (box->hasAutoVerticalScrollbar())
2224             setHasVerticalScrollbar(verticalOverflow);
2225 
2226 #if ENABLE(DASHBOARD_SUPPORT)
2227         // Force an update since we know the scrollbars have changed things.
2228         if (renderer()->document()->hasDashboardRegions())
2229             renderer()->document()->setDashboardRegionsDirty(true);
2230 #endif
2231 
2232         renderer()->repaint();
2233 
2234         if (renderer()->style()->overflowX() == OAUTO || renderer()->style()->overflowY() == OAUTO) {
2235             if (!m_inOverflowRelayout) {
2236                 // Our proprietary overflow: overlay value doesn't trigger a layout.
2237                 m_inOverflowRelayout = true;
2238                 renderer()->setNeedsLayout(true, false);
2239                 if (renderer()->isRenderBlock()) {
2240                     RenderBlock* block = toRenderBlock(renderer());
2241                     block->scrollbarsChanged(box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow,
2242                                              box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
2243                     block->layoutBlock(true);
2244                 } else
2245                     renderer()->layout();
2246                 m_inOverflowRelayout = false;
2247             }
2248         }
2249     }
2250 
2251     // If overflow:scroll is turned into overflow:auto a bar might still be disabled (Bug 11985).
2252     if (m_hBar && box->hasAutoHorizontalScrollbar())
2253         m_hBar->setEnabled(true);
2254     if (m_vBar && box->hasAutoVerticalScrollbar())
2255         m_vBar->setEnabled(true);
2256 
2257     // Set up the range (and page step/line step).
2258     if (m_hBar) {
2259         int clientWidth = box->clientWidth();
2260         int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1);
2261         m_hBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
2262         m_hBar->setProportion(clientWidth, m_scrollWidth);
2263     }
2264     if (m_vBar) {
2265         int clientHeight = box->clientHeight();
2266         int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1);
2267         m_vBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
2268         m_vBar->setProportion(clientHeight, m_scrollHeight);
2269     }
2270 
2271     RenderView* view = renderer()->view();
2272     view->disableLayoutState();
2273     scrollToOffset(scrollXOffset(), scrollYOffset());
2274     view->enableLayoutState();
2275 
2276     if (renderer()->node() && renderer()->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
2277         updateOverflowStatus(horizontalOverflow, verticalOverflow);
2278 
2279 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
2280     bool hasOverflowScroll = ((horizontalOverflow && m_hBar) || (verticalOverflow && m_vBar));
2281     if (hasOverflowScroll) {
2282         // Disable UI side scrolling for non-readonly textareas.
2283         if (renderer()->isTextArea() && (!renderer()->node()
2284                 || !static_cast<HTMLTextAreaElement*>(renderer()->node())->readOnly()))
2285             hasOverflowScroll = false;
2286     }
2287     if (hasOverflowScroll != m_hasOverflowScroll) {
2288         m_hasOverflowScroll = hasOverflowScroll;
2289         dirtyZOrderLists();
2290         dirtyStackingContextZOrderLists();
2291         if (renderer()->node())
2292             renderer()->node()->setNeedsStyleRecalc(SyntheticStyleChange);
2293     }
2294 #endif
2295 }
2296 
paintOverflowControls(GraphicsContext * context,int tx,int ty,const IntRect & damageRect,bool paintingOverlayControls)2297 void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty, const IntRect& damageRect, bool paintingOverlayControls)
2298 {
2299     // Don't do anything if we have no overflow.
2300     if (!renderer()->hasOverflowClip())
2301         return;
2302 
2303     // Overlay scrollbars paint in a second pass through the layer tree so that they will paint
2304     // on top of everything else. If this is the normal painting pass, paintingOverlayControls
2305     // will be false, and we should just tell the root layer that there are overlay scrollbars
2306     // that need to be painted. That will cause the second pass through the layer tree to run,
2307     // and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the
2308     // second pass doesn't need to re-enter the RenderTree to get it right.
2309     if (hasOverlayScrollbars() && !paintingOverlayControls) {
2310         RenderView* renderView = renderer()->view();
2311         renderView->layer()->setContainsDirtyOverlayScrollbars(true);
2312         m_cachedOverlayScrollbarOffset = IntPoint(tx, ty);
2313         renderView->frameView()->setContainsScrollableAreaWithOverlayScrollbars(true);
2314         return;
2315     }
2316 
2317     int offsetX = tx;
2318     int offsetY = ty;
2319     if (paintingOverlayControls) {
2320         offsetX = m_cachedOverlayScrollbarOffset.x();
2321         offsetY = m_cachedOverlayScrollbarOffset.y();
2322     }
2323 
2324     // Move the scrollbar widgets if necessary.  We normally move and resize widgets during layout, but sometimes
2325     // widgets can move without layout occurring (most notably when you scroll a document that
2326     // contains fixed positioned elements).
2327     positionOverflowControls(offsetX, offsetY);
2328 
2329     // Now that we're sure the scrollbars are in the right place, paint them.
2330     if (m_hBar
2331 #if USE(ACCELERATED_COMPOSITING)
2332         && !layerForHorizontalScrollbar()
2333 #endif
2334               )
2335         m_hBar->paint(context, damageRect);
2336     if (m_vBar
2337 #if USE(ACCELERATED_COMPOSITING)
2338         && !layerForVerticalScrollbar()
2339 #endif
2340               )
2341         m_vBar->paint(context, damageRect);
2342 
2343 #if USE(ACCELERATED_COMPOSITING)
2344     if (layerForScrollCorner())
2345         return;
2346 #endif
2347 
2348     // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the
2349     // edge of the box.
2350     paintScrollCorner(context, offsetX, offsetY, damageRect);
2351 
2352     // Paint our resizer last, since it sits on top of the scroll corner.
2353     paintResizer(context, offsetX, offsetY, damageRect);
2354 }
2355 
paintScrollCorner(GraphicsContext * context,int tx,int ty,const IntRect & damageRect)2356 void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
2357 {
2358     RenderBox* box = renderBox();
2359     ASSERT(box);
2360 
2361     IntRect cornerRect = scrollCornerRect();
2362     IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
2363     if (!absRect.intersects(damageRect))
2364         return;
2365 
2366     if (context->updatingControlTints()) {
2367         updateScrollCornerStyle();
2368         return;
2369     }
2370 
2371     if (m_scrollCorner) {
2372         m_scrollCorner->paintIntoRect(context, tx, ty, absRect);
2373         return;
2374     }
2375 
2376     // We don't want to paint white if we have overlay scrollbars, since we need
2377     // to see what is behind it.
2378     if (!hasOverlayScrollbars())
2379         context->fillRect(absRect, Color::white, box->style()->colorSpace());
2380 }
2381 
paintResizer(GraphicsContext * context,int tx,int ty,const IntRect & damageRect)2382 void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
2383 {
2384     if (renderer()->style()->resize() == RESIZE_NONE)
2385         return;
2386 
2387     RenderBox* box = renderBox();
2388     ASSERT(box);
2389 
2390     IntRect cornerRect = resizerCornerRect(this, box->borderBoxRect());
2391     IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
2392     if (!absRect.intersects(damageRect))
2393         return;
2394 
2395     if (context->updatingControlTints()) {
2396         updateResizerStyle();
2397         return;
2398     }
2399 
2400     if (m_resizer) {
2401         m_resizer->paintIntoRect(context, tx, ty, absRect);
2402         return;
2403     }
2404 
2405     // Paint the resizer control.
2406     DEFINE_STATIC_LOCAL(RefPtr<Image>, resizeCornerImage, (Image::loadPlatformResource("textAreaResizeCorner")));
2407     IntPoint imagePoint(absRect.maxX() - resizeCornerImage->width(), absRect.maxY() - resizeCornerImage->height());
2408     context->drawImage(resizeCornerImage.get(), box->style()->colorSpace(), imagePoint);
2409 
2410     // Draw a frame around the resizer (1px grey line) if there are any scrollbars present.
2411     // Clipping will exclude the right and bottom edges of this frame.
2412     if (!hasOverlayScrollbars() && (m_vBar || m_hBar)) {
2413         context->save();
2414         context->clip(absRect);
2415         IntRect largerCorner = absRect;
2416         largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1));
2417         context->setStrokeColor(Color(makeRGB(217, 217, 217)), ColorSpaceDeviceRGB);
2418         context->setStrokeThickness(1.0f);
2419         context->setFillColor(Color::transparent, ColorSpaceDeviceRGB);
2420         context->drawRect(largerCorner);
2421         context->restore();
2422     }
2423 }
2424 
isPointInResizeControl(const IntPoint & absolutePoint) const2425 bool RenderLayer::isPointInResizeControl(const IntPoint& absolutePoint) const
2426 {
2427     if (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)
2428         return false;
2429 
2430     RenderBox* box = renderBox();
2431     ASSERT(box);
2432 
2433     IntPoint localPoint = absoluteToContents(absolutePoint);
2434 
2435     IntRect localBounds(0, 0, box->width(), box->height());
2436     return resizerCornerRect(this, localBounds).contains(localPoint);
2437 }
2438 
hitTestOverflowControls(HitTestResult & result,const IntPoint & localPoint)2439 bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint)
2440 {
2441     if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
2442         return false;
2443 
2444     RenderBox* box = renderBox();
2445     ASSERT(box);
2446 
2447     IntRect resizeControlRect;
2448     if (renderer()->style()->resize() != RESIZE_NONE) {
2449         resizeControlRect = resizerCornerRect(this, box->borderBoxRect());
2450         if (resizeControlRect.contains(localPoint))
2451             return true;
2452     }
2453 
2454     int resizeControlSize = max(resizeControlRect.height(), 0);
2455 
2456     if (m_vBar) {
2457         IntRect vBarRect(box->width() - box->borderRight() - m_vBar->width(),
2458                          box->borderTop(),
2459                          m_vBar->width(),
2460                          box->height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
2461         if (vBarRect.contains(localPoint)) {
2462             result.setScrollbar(m_vBar.get());
2463             return true;
2464         }
2465     }
2466 
2467     resizeControlSize = max(resizeControlRect.width(), 0);
2468     if (m_hBar) {
2469         IntRect hBarRect(box->borderLeft(),
2470                          box->height() - box->borderBottom() - m_hBar->height(),
2471                          box->width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
2472                          m_hBar->height());
2473         if (hBarRect.contains(localPoint)) {
2474             result.setScrollbar(m_hBar.get());
2475             return true;
2476         }
2477     }
2478 
2479     return false;
2480 }
2481 
scroll(ScrollDirection direction,ScrollGranularity granularity,float multiplier)2482 bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
2483 {
2484     return ScrollableArea::scroll(direction, granularity, multiplier);
2485 }
2486 
paint(GraphicsContext * p,const IntRect & damageRect,PaintBehavior paintBehavior,RenderObject * paintingRoot)2487 void RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintBehavior paintBehavior, RenderObject *paintingRoot)
2488 {
2489     OverlapTestRequestMap overlapTestRequests;
2490     paintLayer(this, p, damageRect, paintBehavior, paintingRoot, &overlapTestRequests);
2491     OverlapTestRequestMap::iterator end = overlapTestRequests.end();
2492     for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
2493         it->first->setOverlapTestResult(false);
2494 }
2495 
paintOverlayScrollbars(GraphicsContext * p,const IntRect & damageRect,PaintBehavior paintBehavior,RenderObject * paintingRoot)2496 void RenderLayer::paintOverlayScrollbars(GraphicsContext* p, const IntRect& damageRect, PaintBehavior paintBehavior, RenderObject *paintingRoot)
2497 {
2498     if (!m_containsDirtyOverlayScrollbars)
2499         return;
2500     paintLayer(this, p, damageRect, paintBehavior, paintingRoot, 0, PaintLayerHaveTransparency | PaintLayerTemporaryClipRects
2501                | PaintLayerPaintingOverlayScrollbars);
2502     m_containsDirtyOverlayScrollbars = false;
2503 }
2504 
setClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)2505 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
2506 {
2507     if (paintDirtyRect == clipRect)
2508         return;
2509     p->save();
2510     p->clip(clipRect);
2511 }
2512 
restoreClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)2513 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
2514 {
2515     if (paintDirtyRect == clipRect)
2516         return;
2517     p->restore();
2518 }
2519 
performOverlapTests(OverlapTestRequestMap & overlapTestRequests,const RenderLayer * rootLayer,const RenderLayer * layer)2520 static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer)
2521 {
2522     Vector<OverlapTestRequestClient*> overlappedRequestClients;
2523     OverlapTestRequestMap::iterator end = overlapTestRequests.end();
2524     IntRect boundingBox = layer->boundingBox(rootLayer);
2525     for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) {
2526         if (!boundingBox.intersects(it->second))
2527             continue;
2528 
2529         it->first->setOverlapTestResult(true);
2530         overlappedRequestClients.append(it->first);
2531     }
2532     for (size_t i = 0; i < overlappedRequestClients.size(); ++i)
2533         overlapTestRequests.remove(overlappedRequestClients[i]);
2534 }
2535 
2536 #if USE(ACCELERATED_COMPOSITING)
shouldDoSoftwarePaint(const RenderLayer * layer,bool paintingReflection)2537 static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection)
2538 {
2539     return paintingReflection && !layer->has3DTransform();
2540 }
2541 #endif
2542 
paintLayer(RenderLayer * rootLayer,GraphicsContext * p,const IntRect & paintDirtyRect,PaintBehavior paintBehavior,RenderObject * paintingRoot,OverlapTestRequestMap * overlapTestRequests,PaintLayerFlags paintFlags)2543 void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
2544                         const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
2545                         RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests,
2546                         PaintLayerFlags paintFlags)
2547 {
2548 #if USE(ACCELERATED_COMPOSITING)
2549     if (isComposited()) {
2550         // The updatingControlTints() painting pass goes through compositing layers,
2551         // but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
2552         if (p->updatingControlTints() || (paintBehavior & PaintBehaviorFlattenCompositingLayers))
2553             paintFlags |= PaintLayerTemporaryClipRects;
2554         else if (!backing()->paintingGoesToWindow() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) {
2555             // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer().
2556             return;
2557         }
2558     }
2559 #endif
2560 
2561     // Avoid painting layers when stylesheets haven't loaded.  This eliminates FOUC.
2562     // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
2563     // will do a full repaint().
2564     if (renderer()->document()->didLayoutWithPendingStylesheets() && !renderer()->isRenderView() && !renderer()->isRoot())
2565         return;
2566 
2567     // If this layer is totally invisible then there is nothing to paint.
2568     if (!renderer()->opacity())
2569         return;
2570 
2571     if (paintsWithTransparency(paintBehavior))
2572         paintFlags |= PaintLayerHaveTransparency;
2573 
2574     // Apply a transform if we have one.  A reflection is considered to be a transform, since it is a flip and a translate.
2575     if (paintsWithTransform(paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) {
2576         TransformationMatrix layerTransform = renderableTransform(paintBehavior);
2577         // If the transform can't be inverted, then don't paint anything.
2578         if (!layerTransform.isInvertible())
2579             return;
2580 
2581         // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
2582         // layer from the parent now.
2583         if (paintFlags & PaintLayerHaveTransparency)
2584             parent()->beginTransparencyLayers(p, rootLayer, paintBehavior);
2585 
2586         // Make sure the parent's clip rects have been calculated.
2587         IntRect clipRect = paintDirtyRect;
2588         if (parent()) {
2589             clipRect = backgroundClipRect(rootLayer, paintFlags & PaintLayerTemporaryClipRects);
2590             clipRect.intersect(paintDirtyRect);
2591         }
2592 
2593         // Push the parent coordinate space's clip.
2594         setClip(p, paintDirtyRect, clipRect);
2595 
2596         // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
2597         // This involves subtracting out the position of the layer in our current coordinate space.
2598         int x = 0;
2599         int y = 0;
2600         convertToLayerCoords(rootLayer, x, y);
2601         TransformationMatrix transform(layerTransform);
2602         transform.translateRight(x, y);
2603 
2604         // Apply the transform.
2605         p->save();
2606         p->concatCTM(transform.toAffineTransform());
2607 
2608         // Now do a paint with the root layer shifted to be us.
2609         paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, overlapTestRequests, paintFlags | PaintLayerAppliedTransform);
2610 
2611         p->restore();
2612 
2613         // Restore the clip.
2614         restoreClip(p, paintDirtyRect, clipRect);
2615 
2616         return;
2617     }
2618 
2619     PaintLayerFlags localPaintFlags = paintFlags & ~PaintLayerAppliedTransform;
2620     bool haveTransparency = localPaintFlags & PaintLayerHaveTransparency;
2621 
2622     // Paint the reflection first if we have one.
2623     if (m_reflection && !m_paintingInsideReflection) {
2624         // Mark that we are now inside replica painting.
2625         m_paintingInsideReflection = true;
2626         reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection);
2627         m_paintingInsideReflection = false;
2628     }
2629 
2630     // Calculate the clip rects we should use.
2631     IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
2632     calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, localPaintFlags & PaintLayerTemporaryClipRects);
2633     int x = layerBounds.x();
2634     int y = layerBounds.y();
2635     int tx = x - renderBoxX();
2636     int ty = y - renderBoxY();
2637 
2638     // Ensure our lists are up-to-date.
2639     updateCompositingAndLayerListsIfNeeded();
2640 
2641     bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText;
2642     bool selectionOnly  = paintBehavior & PaintBehaviorSelectionOnly;
2643 
2644     // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
2645     // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
2646     // Else, our renderer tree may or may not contain the painting root, so we pass that root along
2647     // so it will be tested against as we descend through the renderers.
2648     RenderObject* paintingRootForRenderer = 0;
2649     if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
2650         paintingRootForRenderer = paintingRoot;
2651 
2652     if (overlapTestRequests && isSelfPaintingLayer())
2653         performOverlapTests(*overlapTestRequests, rootLayer, this);
2654 
2655     bool paintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScrollbars;
2656 
2657     // We want to paint our layer, but only if we intersect the damage rect.
2658     bool shouldPaint = intersectsDamageRect(layerBounds, damageRect, rootLayer) && m_hasVisibleContent && isSelfPaintingLayer();
2659     if (shouldPaint && !selectionOnly && !damageRect.isEmpty() && !paintingOverlayScrollbars) {
2660         // Begin transparency layers lazily now that we know we have to paint something.
2661         if (haveTransparency)
2662             beginTransparencyLayers(p, rootLayer, paintBehavior);
2663 
2664         // Paint our background first, before painting any child layers.
2665         // Establish the clip used to paint our background.
2666         setClip(p, paintDirtyRect, damageRect);
2667 
2668         // Paint the background.
2669         PaintInfo paintInfo(p, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
2670         renderer()->paint(paintInfo, tx, ty);
2671 
2672         // Restore the clip.
2673         restoreClip(p, paintDirtyRect, damageRect);
2674     }
2675 
2676     // Now walk the sorted list of children with negative z-indices.
2677     paintList(m_negZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
2678 
2679     // Now establish the appropriate clip and paint our child RenderObjects.
2680     if (shouldPaint && !clipRectToApply.isEmpty() && !paintingOverlayScrollbars) {
2681         // Begin transparency layers lazily now that we know we have to paint something.
2682         if (haveTransparency)
2683             beginTransparencyLayers(p, rootLayer, paintBehavior);
2684 
2685         // Set up the clip used when painting our children.
2686         setClip(p, paintDirtyRect, clipRectToApply);
2687         PaintInfo paintInfo(p, clipRectToApply,
2688                                           selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
2689                                           forceBlackText, paintingRootForRenderer, 0);
2690         renderer()->paint(paintInfo, tx, ty);
2691         if (!selectionOnly) {
2692             paintInfo.phase = PaintPhaseFloat;
2693             renderer()->paint(paintInfo, tx, ty);
2694             paintInfo.phase = PaintPhaseForeground;
2695             paintInfo.overlapTestRequests = overlapTestRequests;
2696             renderer()->paint(paintInfo, tx, ty);
2697             paintInfo.phase = PaintPhaseChildOutlines;
2698             renderer()->paint(paintInfo, tx, ty);
2699         }
2700 
2701         // Now restore our clip.
2702         restoreClip(p, paintDirtyRect, clipRectToApply);
2703     }
2704 
2705     if (!outlineRect.isEmpty() && isSelfPaintingLayer() && !paintingOverlayScrollbars) {
2706         // Paint our own outline
2707         PaintInfo paintInfo(p, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
2708         setClip(p, paintDirtyRect, outlineRect);
2709         renderer()->paint(paintInfo, tx, ty);
2710         restoreClip(p, paintDirtyRect, outlineRect);
2711     }
2712 
2713     // Paint any child layers that have overflow.
2714     paintList(m_normalFlowList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
2715 
2716     // Now walk the sorted list of children with positive z-indices.
2717     paintList(m_posZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
2718 
2719     if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty() && !paintingOverlayScrollbars) {
2720         setClip(p, paintDirtyRect, damageRect);
2721 
2722         // Paint the mask.
2723         PaintInfo paintInfo(p, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0);
2724         renderer()->paint(paintInfo, tx, ty);
2725 
2726         // Restore the clip.
2727         restoreClip(p, paintDirtyRect, damageRect);
2728     }
2729 
2730     if (paintingOverlayScrollbars) {
2731         setClip(p, paintDirtyRect, damageRect);
2732         paintOverflowControls(p, tx, ty, damageRect, true);
2733         restoreClip(p, paintDirtyRect, damageRect);
2734     }
2735 
2736     // End our transparency layer
2737     if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) {
2738         p->endTransparencyLayer();
2739         p->restore();
2740         m_usedTransparency = false;
2741     }
2742 }
2743 
paintList(Vector<RenderLayer * > * list,RenderLayer * rootLayer,GraphicsContext * p,const IntRect & paintDirtyRect,PaintBehavior paintBehavior,RenderObject * paintingRoot,OverlapTestRequestMap * overlapTestRequests,PaintLayerFlags paintFlags)2744 void RenderLayer::paintList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, GraphicsContext* p,
2745                             const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
2746                             RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests,
2747                             PaintLayerFlags paintFlags)
2748 {
2749     if (!list)
2750         return;
2751 
2752     for (size_t i = 0; i < list->size(); ++i) {
2753         RenderLayer* childLayer = list->at(i);
2754         if (!childLayer->isPaginated())
2755             childLayer->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags);
2756         else
2757             paintPaginatedChildLayer(childLayer, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags);
2758     }
2759 }
2760 
paintPaginatedChildLayer(RenderLayer * childLayer,RenderLayer * rootLayer,GraphicsContext * context,const IntRect & paintDirtyRect,PaintBehavior paintBehavior,RenderObject * paintingRoot,OverlapTestRequestMap * overlapTestRequests,PaintLayerFlags paintFlags)2761 void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context,
2762                                            const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
2763                                            RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests,
2764                                            PaintLayerFlags paintFlags)
2765 {
2766     // We need to do multiple passes, breaking up our child layer into strips.
2767     Vector<RenderLayer*> columnLayers;
2768     RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext();
2769     for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
2770         if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
2771             columnLayers.append(curr);
2772         if (curr == ancestorLayer)
2773             break;
2774     }
2775 
2776     ASSERT(columnLayers.size());
2777 
2778     paintChildLayerIntoColumns(childLayer, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags, columnLayers, columnLayers.size() - 1);
2779 }
2780 
paintChildLayerIntoColumns(RenderLayer * childLayer,RenderLayer * rootLayer,GraphicsContext * context,const IntRect & paintDirtyRect,PaintBehavior paintBehavior,RenderObject * paintingRoot,OverlapTestRequestMap * overlapTestRequests,PaintLayerFlags paintFlags,const Vector<RenderLayer * > & columnLayers,size_t colIndex)2781 void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context,
2782                                              const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
2783                                              RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests,
2784                                              PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex)
2785 {
2786     RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer());
2787 
2788     ASSERT(columnBlock && columnBlock->hasColumns());
2789     if (!columnBlock || !columnBlock->hasColumns())
2790         return;
2791 
2792     int layerX = 0;
2793     int layerY = 0;
2794     columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY);
2795 
2796     bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
2797 
2798     ColumnInfo* colInfo = columnBlock->columnInfo();
2799     unsigned colCount = columnBlock->columnCount(colInfo);
2800     int currLogicalTopOffset = 0;
2801     for (unsigned i = 0; i < colCount; i++) {
2802         // For each rect, we clip to the rect, and then we adjust our coords.
2803         IntRect colRect = columnBlock->columnRectAt(colInfo, i);
2804         columnBlock->flipForWritingMode(colRect);
2805         int logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent();
2806         IntSize offset = isHorizontal ? IntSize(logicalLeftOffset, currLogicalTopOffset) : IntSize(currLogicalTopOffset, logicalLeftOffset);
2807 
2808         colRect.move(layerX, layerY);
2809 
2810         IntRect localDirtyRect(paintDirtyRect);
2811         localDirtyRect.intersect(colRect);
2812 
2813         if (!localDirtyRect.isEmpty()) {
2814             context->save();
2815 
2816             // Each strip pushes a clip, since column boxes are specified as being
2817             // like overflow:hidden.
2818             context->clip(colRect);
2819 
2820             if (!colIndex) {
2821                 // Apply a translation transform to change where the layer paints.
2822                 TransformationMatrix oldTransform;
2823                 bool oldHasTransform = childLayer->transform();
2824                 if (oldHasTransform)
2825                     oldTransform = *childLayer->transform();
2826                 TransformationMatrix newTransform(oldTransform);
2827                 newTransform.translateRight(offset.width(), offset.height());
2828 
2829                 childLayer->m_transform.set(new TransformationMatrix(newTransform));
2830                 childLayer->paintLayer(rootLayer, context, localDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags);
2831                 if (oldHasTransform)
2832                     childLayer->m_transform.set(new TransformationMatrix(oldTransform));
2833                 else
2834                     childLayer->m_transform.clear();
2835             } else {
2836                 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
2837                 // This involves subtracting out the position of the layer in our current coordinate space.
2838                 int childX = 0;
2839                 int childY = 0;
2840                 columnLayers[colIndex - 1]->convertToLayerCoords(rootLayer, childX, childY);
2841                 TransformationMatrix transform;
2842                 transform.translateRight(childX + offset.width(), childY + offset.height());
2843 
2844                 // Apply the transform.
2845                 context->concatCTM(transform.toAffineTransform());
2846 
2847                 // Now do a paint with the root layer shifted to be the next multicol block.
2848                 paintChildLayerIntoColumns(childLayer, columnLayers[colIndex - 1], context, transform.inverse().mapRect(localDirtyRect), paintBehavior,
2849                                            paintingRoot, overlapTestRequests, paintFlags,
2850                                            columnLayers, colIndex - 1);
2851             }
2852 
2853             context->restore();
2854         }
2855 
2856         // Move to the next position.
2857         int blockDelta = isHorizontal ? colRect.height() : colRect.width();
2858         if (columnBlock->style()->isFlippedBlocksWritingMode())
2859             currLogicalTopOffset += blockDelta;
2860         else
2861             currLogicalTopOffset -= blockDelta;
2862     }
2863 }
2864 
frameVisibleRect(RenderObject * renderer)2865 static inline IntRect frameVisibleRect(RenderObject* renderer)
2866 {
2867     FrameView* frameView = renderer->document()->view();
2868     if (!frameView)
2869         return IntRect();
2870 
2871     return frameView->visibleContentRect();
2872 }
2873 
hitTest(const HitTestRequest & request,HitTestResult & result)2874 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
2875 {
2876     renderer()->document()->updateLayout();
2877 
2878     IntRect hitTestArea = renderer()->view()->documentRect();
2879     if (!request.ignoreClipping())
2880         hitTestArea.intersect(frameVisibleRect(renderer()));
2881 
2882     RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, result.point(), false);
2883     if (!insideLayer) {
2884         // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down,
2885         // return ourselves. We do this so mouse events continue getting delivered after a drag has
2886         // exited the WebView, and so hit testing over a scrollbar hits the content document.
2887         if ((request.active() || request.mouseUp()) && renderer()->isRenderView()) {
2888             renderer()->updateHitTestResult(result, result.point());
2889             insideLayer = this;
2890         }
2891     }
2892 
2893     // Now determine if the result is inside an anchor - if the urlElement isn't already set.
2894     Node* node = result.innerNode();
2895     if (node && !result.URLElement())
2896         result.setURLElement(static_cast<Element*>(node->enclosingLinkEventParentOrSelf()));
2897 
2898     // Next set up the correct :hover/:active state along the new chain.
2899     updateHoverActiveState(request, result);
2900 
2901     // Now return whether we were inside this layer (this will always be true for the root
2902     // layer).
2903     return insideLayer;
2904 }
2905 
enclosingElement() const2906 Node* RenderLayer::enclosingElement() const
2907 {
2908     for (RenderObject* r = renderer(); r; r = r->parent()) {
2909         if (Node* e = r->node())
2910             return e;
2911     }
2912     ASSERT_NOT_REACHED();
2913     return 0;
2914 }
2915 
2916 // Compute the z-offset of the point in the transformState.
2917 // This is effectively projecting a ray normal to the plane of ancestor, finding where that
2918 // ray intersects target, and computing the z delta between those two points.
computeZOffset(const HitTestingTransformState & transformState)2919 static double computeZOffset(const HitTestingTransformState& transformState)
2920 {
2921     // We got an affine transform, so no z-offset
2922     if (transformState.m_accumulatedTransform.isAffine())
2923         return 0;
2924 
2925     // Flatten the point into the target plane
2926     FloatPoint targetPoint = transformState.mappedPoint();
2927 
2928     // Now map the point back through the transform, which computes Z.
2929     FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoint(FloatPoint3D(targetPoint));
2930     return backmappedPoint.z();
2931 }
2932 
createLocalTransformState(RenderLayer * rootLayer,RenderLayer * containerLayer,const IntRect & hitTestRect,const IntPoint & hitTestPoint,const HitTestingTransformState * containerTransformState) const2933 PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
2934                                         const IntRect& hitTestRect, const IntPoint& hitTestPoint,
2935                                         const HitTestingTransformState* containerTransformState) const
2936 {
2937     RefPtr<HitTestingTransformState> transformState;
2938     int offsetX = 0;
2939     int offsetY = 0;
2940     if (containerTransformState) {
2941         // If we're already computing transform state, then it's relative to the container (which we know is non-null).
2942         transformState = HitTestingTransformState::create(*containerTransformState);
2943         convertToLayerCoords(containerLayer, offsetX, offsetY);
2944     } else {
2945         // If this is the first time we need to make transform state, then base it off of hitTestPoint,
2946         // which is relative to rootLayer.
2947         transformState = HitTestingTransformState::create(hitTestPoint, FloatQuad(hitTestRect));
2948         convertToLayerCoords(rootLayer, offsetX, offsetY);
2949     }
2950 
2951     RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0;
2952     if (renderer()->shouldUseTransformFromContainer(containerRenderer)) {
2953         TransformationMatrix containerTransform;
2954         renderer()->getTransformFromContainer(containerRenderer, IntSize(offsetX, offsetY), containerTransform);
2955         transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform);
2956     } else {
2957         transformState->translate(offsetX, offsetY, HitTestingTransformState::AccumulateTransform);
2958     }
2959 
2960     return transformState;
2961 }
2962 
2963 
isHitCandidate(const RenderLayer * hitLayer,bool canDepthSort,double * zOffset,const HitTestingTransformState * transformState)2964 static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState)
2965 {
2966     if (!hitLayer)
2967         return false;
2968 
2969     // The hit layer is depth-sorting with other layers, so just say that it was hit.
2970     if (canDepthSort)
2971         return true;
2972 
2973     // We need to look at z-depth to decide if this layer was hit.
2974     if (zOffset) {
2975         ASSERT(transformState);
2976         // This is actually computing our z, but that's OK because the hitLayer is coplanar with us.
2977         double childZOffset = computeZOffset(*transformState);
2978         if (childZOffset > *zOffset) {
2979             *zOffset = childZOffset;
2980             return true;
2981         }
2982         return false;
2983     }
2984 
2985     return true;
2986 }
2987 
2988 // hitTestPoint and hitTestRect are relative to rootLayer.
2989 // A 'flattening' layer is one preserves3D() == false.
2990 // transformState.m_accumulatedTransform holds the transform from the containing flattening layer.
2991 // transformState.m_lastPlanarPoint is the hitTestPoint in the plane of the containing flattening layer.
2992 // transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer.
2993 //
2994 // If zOffset is non-null (which indicates that the caller wants z offset information),
2995 //  *zOffset on return is the z offset of the hit point relative to the containing flattening layer.
hitTestLayer(RenderLayer * rootLayer,RenderLayer * containerLayer,const HitTestRequest & request,HitTestResult & result,const IntRect & hitTestRect,const IntPoint & hitTestPoint,bool appliedTransform,const HitTestingTransformState * transformState,double * zOffset)2996 RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
2997                                        const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform,
2998                                        const HitTestingTransformState* transformState, double* zOffset)
2999 {
3000     // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
3001 
3002     bool useTemporaryClipRects = false;
3003 #if USE(ACCELERATED_COMPOSITING)
3004     useTemporaryClipRects = compositor()->inCompositingMode();
3005 #endif
3006     useTemporaryClipRects |= renderer()->view()->frameView()->containsScrollableAreaWithOverlayScrollbars();
3007 
3008     IntRect hitTestArea = result.rectForPoint(hitTestPoint);
3009 
3010     // Apply a transform if we have one.
3011     if (transform() && !appliedTransform) {
3012         // Make sure the parent's clip rects have been calculated.
3013         if (parent()) {
3014             IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects, IncludeOverlayScrollbarSize);
3015             // Go ahead and test the enclosing clip now.
3016             if (!clipRect.intersects(hitTestArea))
3017                 return 0;
3018         }
3019 
3020         // Create a transform state to accumulate this transform.
3021         RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
3022 
3023         // If the transform can't be inverted, then don't hit test this layer at all.
3024         if (!newTransformState->m_accumulatedTransform.isInvertible())
3025             return 0;
3026 
3027         // Compute the point and the hit test rect in the coords of this layer by using the values
3028         // from the transformState, which store the point and quad in the coords of the last flattened
3029         // layer, and the accumulated transform which lets up map through preserve-3d layers.
3030         //
3031         // We can't just map hitTestPoint and hitTestRect because they may have been flattened (losing z)
3032         // by our container.
3033         IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint());
3034         IntRect localHitTestRect;
3035 #if USE(ACCELERATED_COMPOSITING)
3036         if (isComposited()) {
3037             // It doesn't make sense to project hitTestRect into the plane of this layer, so use the same bounds we use for painting.
3038             localHitTestRect = backing()->compositedBounds();
3039         } else
3040 #endif
3041             localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox();
3042 
3043         // Now do a hit test with the root layer shifted to be us.
3044         return hitTestLayer(this, containerLayer, request, result, localHitTestRect, localPoint, true, newTransformState.get(), zOffset);
3045     }
3046 
3047     // Ensure our lists and 3d status are up-to-date.
3048     updateCompositingAndLayerListsIfNeeded();
3049     update3DTransformedDescendantStatus();
3050 
3051     RefPtr<HitTestingTransformState> localTransformState;
3052     if (appliedTransform) {
3053         // We computed the correct state in the caller (above code), so just reference it.
3054         ASSERT(transformState);
3055         localTransformState = const_cast<HitTestingTransformState*>(transformState);
3056     } else if (transformState || m_has3DTransformedDescendant || preserves3D()) {
3057         // We need transform state for the first time, or to offset the container state, so create it here.
3058         localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
3059     }
3060 
3061     // Check for hit test on backface if backface-visibility is 'hidden'
3062     if (localTransformState && renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) {
3063         TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse();
3064         // If the z-vector of the matrix is negative, the back is facing towards the viewer.
3065         if (invertedMatrix.m33() < 0)
3066             return 0;
3067     }
3068 
3069     RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState;
3070     if (localTransformState && !preserves3D()) {
3071         // Keep a copy of the pre-flattening state, for computing z-offsets for the container
3072         unflattenedTransformState = HitTestingTransformState::create(*localTransformState);
3073         // This layer is flattening, so flatten the state passed to descendants.
3074         localTransformState->flatten();
3075     }
3076 
3077     // Calculate the clip rects we should use.
3078     IntRect layerBounds;
3079     IntRect bgRect;
3080     IntRect fgRect;
3081     IntRect outlineRect;
3082     calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, useTemporaryClipRects, IncludeOverlayScrollbarSize);
3083 
3084     // The following are used for keeping track of the z-depth of the hit point of 3d-transformed
3085     // descendants.
3086     double localZOffset = -numeric_limits<double>::infinity();
3087     double* zOffsetForDescendantsPtr = 0;
3088     double* zOffsetForContentsPtr = 0;
3089 
3090     bool depthSortDescendants = false;
3091     if (preserves3D()) {
3092         depthSortDescendants = true;
3093         // Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down.
3094         zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
3095         zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
3096     } else if (m_has3DTransformedDescendant) {
3097         // Flattening layer with 3d children; use a local zOffset pointer to depth-test children and foreground.
3098         depthSortDescendants = true;
3099         zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
3100         zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
3101     } else if (zOffset) {
3102         zOffsetForDescendantsPtr = 0;
3103         // Container needs us to give back a z offset for the hit layer.
3104         zOffsetForContentsPtr = zOffset;
3105     }
3106 
3107     // This variable tracks which layer the mouse ends up being inside.
3108     RenderLayer* candidateLayer = 0;
3109 
3110     // Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
3111     RenderLayer* hitLayer = hitTestList(m_posZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint,
3112                                         localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
3113     if (hitLayer) {
3114         if (!depthSortDescendants)
3115             return hitLayer;
3116         candidateLayer = hitLayer;
3117     }
3118 
3119     // Now check our overflow objects.
3120     hitLayer = hitTestList(m_normalFlowList, rootLayer, request, result, hitTestRect, hitTestPoint,
3121                            localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
3122     if (hitLayer) {
3123         if (!depthSortDescendants)
3124             return hitLayer;
3125         candidateLayer = hitLayer;
3126     }
3127 
3128 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
3129     if (hasOverflowParent()) {
3130         ClipRects clipRects;
3131         calculateClipRects(rootLayer, clipRects, useTemporaryClipRects);
3132         fgRect.intersect(clipRects.hitTestClip());
3133         bgRect.intersect(clipRects.hitTestClip());
3134     }
3135 #endif
3136     // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
3137     if (fgRect.intersects(hitTestArea) && isSelfPaintingLayer()) {
3138         // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost.
3139         HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding());
3140         if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) &&
3141             isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
3142             if (result.isRectBasedTest())
3143                 result.append(tempResult);
3144             else
3145                 result = tempResult;
3146             if (!depthSortDescendants)
3147                 return this;
3148             // Foreground can depth-sort with descendant layers, so keep this as a candidate.
3149             candidateLayer = this;
3150         } else if (result.isRectBasedTest())
3151             result.append(tempResult);
3152     }
3153 
3154     // Now check our negative z-index children.
3155     hitLayer = hitTestList(m_negZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint,
3156                                         localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
3157     if (hitLayer) {
3158         if (!depthSortDescendants)
3159             return hitLayer;
3160         candidateLayer = hitLayer;
3161     }
3162 
3163     // If we found a layer, return. Child layers, and foreground always render in front of background.
3164     if (candidateLayer)
3165         return candidateLayer;
3166 
3167     if (bgRect.intersects(hitTestArea) && isSelfPaintingLayer()) {
3168         HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding());
3169         if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) &&
3170             isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
3171             if (result.isRectBasedTest())
3172                 result.append(tempResult);
3173             else
3174                 result = tempResult;
3175             return this;
3176         } else if (result.isRectBasedTest())
3177             result.append(tempResult);
3178     }
3179 
3180     return 0;
3181 }
3182 
hitTestContents(const HitTestRequest & request,HitTestResult & result,const IntRect & layerBounds,const IntPoint & hitTestPoint,HitTestFilter hitTestFilter) const3183 bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const IntRect& layerBounds, const IntPoint& hitTestPoint, HitTestFilter hitTestFilter) const
3184 {
3185     if (!renderer()->hitTest(request, result, hitTestPoint,
3186                             layerBounds.x() - renderBoxX(),
3187                             layerBounds.y() - renderBoxY(),
3188                             hitTestFilter)) {
3189         // It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is
3190         // a rect-based test.
3191         ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBasedTestResult().size()));
3192         return false;
3193     }
3194 
3195     // For positioned generated content, we might still not have a
3196     // node by the time we get to the layer level, since none of
3197     // the content in the layer has an element. So just walk up
3198     // the tree.
3199     if (!result.innerNode() || !result.innerNonSharedNode()) {
3200         Node* e = enclosingElement();
3201         if (!result.innerNode())
3202             result.setInnerNode(e);
3203         if (!result.innerNonSharedNode())
3204             result.setInnerNonSharedNode(e);
3205     }
3206 
3207     return true;
3208 }
3209 
hitTestList(Vector<RenderLayer * > * list,RenderLayer * rootLayer,const HitTestRequest & request,HitTestResult & result,const IntRect & hitTestRect,const IntPoint & hitTestPoint,const HitTestingTransformState * transformState,double * zOffsetForDescendants,double * zOffset,const HitTestingTransformState * unflattenedTransformState,bool depthSortDescendants)3210 RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* rootLayer,
3211                                       const HitTestRequest& request, HitTestResult& result,
3212                                       const IntRect& hitTestRect, const IntPoint& hitTestPoint,
3213                                       const HitTestingTransformState* transformState,
3214                                       double* zOffsetForDescendants, double* zOffset,
3215                                       const HitTestingTransformState* unflattenedTransformState,
3216                                       bool depthSortDescendants)
3217 {
3218     if (!list)
3219         return 0;
3220 
3221     RenderLayer* resultLayer = 0;
3222     for (int i = list->size() - 1; i >= 0; --i) {
3223         RenderLayer* childLayer = list->at(i);
3224         RenderLayer* hitLayer = 0;
3225         HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding());
3226         if (childLayer->isPaginated())
3227             hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants);
3228         else
3229             hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, transformState, zOffsetForDescendants);
3230 
3231         // If it a rect-based test, we can safely append the temporary result since it might had hit
3232         // nodes but not necesserily had hitLayer set.
3233         if (result.isRectBasedTest())
3234             result.append(tempResult);
3235 
3236         if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) {
3237             resultLayer = hitLayer;
3238             if (!result.isRectBasedTest())
3239                 result = tempResult;
3240             if (!depthSortDescendants)
3241                 break;
3242         }
3243     }
3244 
3245     return resultLayer;
3246 }
3247 
hitTestPaginatedChildLayer(RenderLayer * childLayer,RenderLayer * rootLayer,const HitTestRequest & request,HitTestResult & result,const IntRect & hitTestRect,const IntPoint & hitTestPoint,const HitTestingTransformState * transformState,double * zOffset)3248 RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
3249                                                      const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset)
3250 {
3251     Vector<RenderLayer*> columnLayers;
3252     RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext();
3253     for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
3254         if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
3255             columnLayers.append(curr);
3256         if (curr == ancestorLayer)
3257             break;
3258     }
3259 
3260     ASSERT(columnLayers.size());
3261     return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestPoint, transformState, zOffset,
3262                                     columnLayers, columnLayers.size() - 1);
3263 }
3264 
hitTestChildLayerColumns(RenderLayer * childLayer,RenderLayer * rootLayer,const HitTestRequest & request,HitTestResult & result,const IntRect & hitTestRect,const IntPoint & hitTestPoint,const HitTestingTransformState * transformState,double * zOffset,const Vector<RenderLayer * > & columnLayers,size_t columnIndex)3265 RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
3266                                                    const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset,
3267                                                    const Vector<RenderLayer*>& columnLayers, size_t columnIndex)
3268 {
3269     RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer());
3270 
3271     ASSERT(columnBlock && columnBlock->hasColumns());
3272     if (!columnBlock || !columnBlock->hasColumns())
3273         return 0;
3274 
3275     int layerX = 0;
3276     int layerY = 0;
3277     columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY);
3278 
3279     ColumnInfo* colInfo = columnBlock->columnInfo();
3280     int colCount = columnBlock->columnCount(colInfo);
3281 
3282     // We have to go backwards from the last column to the first.
3283     bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
3284     int logicalLeft = columnBlock->logicalLeftOffsetForContent();
3285     int currLogicalTopOffset = 0;
3286     int i;
3287     for (i = 0; i < colCount; i++) {
3288         IntRect colRect = columnBlock->columnRectAt(colInfo, i);
3289         int blockDelta =  (isHorizontal ? colRect.height() : colRect.width());
3290         if (columnBlock->style()->isFlippedBlocksWritingMode())
3291             currLogicalTopOffset += blockDelta;
3292         else
3293             currLogicalTopOffset -= blockDelta;
3294     }
3295     for (i = colCount - 1; i >= 0; i--) {
3296         // For each rect, we clip to the rect, and then we adjust our coords.
3297         IntRect colRect = columnBlock->columnRectAt(colInfo, i);
3298         columnBlock->flipForWritingMode(colRect);
3299         int currLogicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - logicalLeft;
3300         int blockDelta =  (isHorizontal ? colRect.height() : colRect.width());
3301         if (columnBlock->style()->isFlippedBlocksWritingMode())
3302             currLogicalTopOffset -= blockDelta;
3303         else
3304             currLogicalTopOffset += blockDelta;
3305         colRect.move(layerX, layerY);
3306 
3307         IntRect localClipRect(hitTestRect);
3308         localClipRect.intersect(colRect);
3309 
3310         IntSize offset = isHorizontal ? IntSize(currLogicalLeftOffset, currLogicalTopOffset) : IntSize(currLogicalTopOffset, currLogicalLeftOffset);
3311 
3312         if (!localClipRect.isEmpty() && localClipRect.intersects(result.rectForPoint(hitTestPoint))) {
3313             RenderLayer* hitLayer = 0;
3314             if (!columnIndex) {
3315                 // Apply a translation transform to change where the layer paints.
3316                 TransformationMatrix oldTransform;
3317                 bool oldHasTransform = childLayer->transform();
3318                 if (oldHasTransform)
3319                     oldTransform = *childLayer->transform();
3320                 TransformationMatrix newTransform(oldTransform);
3321                 newTransform.translateRight(offset.width(), offset.height());
3322 
3323                 childLayer->m_transform.set(new TransformationMatrix(newTransform));
3324                 hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestPoint, false, transformState, zOffset);
3325                 if (oldHasTransform)
3326                     childLayer->m_transform.set(new TransformationMatrix(oldTransform));
3327                 else
3328                     childLayer->m_transform.clear();
3329             } else {
3330                 // Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space.
3331                 // This involves subtracting out the position of the layer in our current coordinate space.
3332                 RenderLayer* nextLayer = columnLayers[columnIndex - 1];
3333                 RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestPoint, transformState);
3334                 newTransformState->translate(offset.width(), offset.height(), HitTestingTransformState::AccumulateTransform);
3335                 IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint());
3336                 IntRect localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox();
3337                 newTransformState->flatten();
3338 
3339                 hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, localPoint,
3340                                                     newTransformState.get(), zOffset, columnLayers, columnIndex - 1);
3341             }
3342 
3343             if (hitLayer)
3344                 return hitLayer;
3345         }
3346     }
3347 
3348     return 0;
3349 }
3350 
updateClipRects(const RenderLayer * rootLayer,OverlayScrollbarSizeRelevancy relevancy)3351 void RenderLayer::updateClipRects(const RenderLayer* rootLayer, OverlayScrollbarSizeRelevancy relevancy)
3352 {
3353     if (m_clipRects) {
3354         ASSERT(rootLayer == m_clipRectsRoot);
3355         return; // We have the correct cached value.
3356     }
3357 
3358     // For transformed layers, the root layer was shifted to be us, so there is no need to
3359     // examine the parent.  We want to cache clip rects with us as the root.
3360     RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
3361     if (parentLayer)
3362         parentLayer->updateClipRects(rootLayer, relevancy);
3363 
3364     ClipRects clipRects;
3365     calculateClipRects(rootLayer, clipRects, true, relevancy);
3366 
3367     if (parentLayer && parentLayer->clipRects() && clipRects == *parentLayer->clipRects())
3368         m_clipRects = parentLayer->clipRects();
3369     else
3370         m_clipRects = new (renderer()->renderArena()) ClipRects(clipRects);
3371     m_clipRects->ref();
3372 #ifndef NDEBUG
3373     m_clipRectsRoot = rootLayer;
3374 #endif
3375 }
3376 
calculateClipRects(const RenderLayer * rootLayer,ClipRects & clipRects,bool useCached,OverlayScrollbarSizeRelevancy relevancy) const3377 void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached, OverlayScrollbarSizeRelevancy relevancy) const
3378 {
3379     if (!parent()) {
3380         // The root layer's clip rect is always infinite.
3381         clipRects.reset(PaintInfo::infiniteRect());
3382         return;
3383     }
3384 
3385     // For transformed layers, the root layer was shifted to be us, so there is no need to
3386     // examine the parent.  We want to cache clip rects with us as the root.
3387     RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
3388 
3389     // Ensure that our parent's clip has been calculated so that we can examine the values.
3390     if (parentLayer) {
3391         if (useCached && parentLayer->clipRects())
3392             clipRects = *parentLayer->clipRects();
3393         else
3394             parentLayer->calculateClipRects(rootLayer, clipRects);
3395     }
3396     else
3397         clipRects.reset(PaintInfo::infiniteRect());
3398 
3399     // A fixed object is essentially the root of its containing block hierarchy, so when
3400     // we encounter such an object, we reset our clip rects to the fixedClipRect.
3401     if (renderer()->style()->position() == FixedPosition) {
3402         clipRects.setPosClipRect(clipRects.fixedClipRect());
3403         clipRects.setOverflowClipRect(clipRects.fixedClipRect());
3404         clipRects.setFixed(true);
3405     }
3406     else if (renderer()->style()->position() == RelativePosition)
3407         clipRects.setPosClipRect(clipRects.overflowClipRect());
3408     else if (renderer()->style()->position() == AbsolutePosition)
3409         clipRects.setOverflowClipRect(clipRects.posClipRect());
3410 
3411     // Update the clip rects that will be passed to child layers.
3412     if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
3413         // This layer establishes a clip of some kind.
3414         int x = 0;
3415         int y = 0;
3416         convertToLayerCoords(rootLayer, x, y);
3417         RenderView* view = renderer()->view();
3418         ASSERT(view);
3419         if (view && clipRects.fixed() && rootLayer->renderer() == view) {
3420             x -= view->frameView()->scrollXForFixedPosition();
3421             y -= view->frameView()->scrollYForFixedPosition();
3422         }
3423 
3424         if (renderer()->hasOverflowClip()) {
3425             IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y, relevancy);
3426 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
3427             clipRects.setHitTestClip(intersection(clipRects.fixed() ? clipRects.fixedClipRect()
3428                     : newOverflowClip, clipRects.hitTestClip()));
3429             if (hasOverflowScroll()) {
3430                 RenderBox* box = toRenderBox(renderer());
3431                 newOverflowClip =
3432                     IntRect(x + box->borderLeft(), y + box->borderTop(),
3433                             m_scrollWidth, m_scrollHeight);
3434             }
3435 #endif
3436             clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
3437             if (renderer()->isPositioned() || renderer()->isRelPositioned())
3438                 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
3439         }
3440         if (renderer()->hasClip()) {
3441             IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
3442             clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
3443             clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
3444             clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
3445         }
3446     }
3447 }
3448 
parentClipRects(const RenderLayer * rootLayer,ClipRects & clipRects,bool temporaryClipRects,OverlayScrollbarSizeRelevancy relevancy) const3449 void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const
3450 {
3451     ASSERT(parent());
3452     if (temporaryClipRects) {
3453         parent()->calculateClipRects(rootLayer, clipRects, false, relevancy);
3454         return;
3455     }
3456 
3457     parent()->updateClipRects(rootLayer, relevancy);
3458     clipRects = *parent()->clipRects();
3459 }
3460 
backgroundClipRect(const RenderLayer * rootLayer,bool temporaryClipRects,OverlayScrollbarSizeRelevancy relevancy) const3461 IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const
3462 {
3463     IntRect backgroundRect;
3464     if (parent()) {
3465         ClipRects parentRects;
3466         parentClipRects(rootLayer, parentRects, temporaryClipRects, relevancy);
3467         backgroundRect = renderer()->style()->position() == FixedPosition ? parentRects.fixedClipRect() :
3468                          (renderer()->isPositioned() ? parentRects.posClipRect() :
3469                                                        parentRects.overflowClipRect());
3470         RenderView* view = renderer()->view();
3471         ASSERT(view);
3472         if (view && parentRects.fixed() && rootLayer->renderer() == view)
3473             backgroundRect.move(view->frameView()->scrollXForFixedPosition(), view->frameView()->scrollYForFixedPosition());
3474     }
3475     return backgroundRect;
3476 }
3477 
calculateRects(const RenderLayer * rootLayer,const IntRect & paintDirtyRect,IntRect & layerBounds,IntRect & backgroundRect,IntRect & foregroundRect,IntRect & outlineRect,bool temporaryClipRects,OverlayScrollbarSizeRelevancy relevancy) const3478 void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
3479                                  IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects,
3480                                  OverlayScrollbarSizeRelevancy relevancy) const
3481 {
3482     if (rootLayer != this && parent()) {
3483         backgroundRect = backgroundClipRect(rootLayer, temporaryClipRects, relevancy);
3484         backgroundRect.intersect(paintDirtyRect);
3485     } else
3486         backgroundRect = paintDirtyRect;
3487 
3488     foregroundRect = backgroundRect;
3489     outlineRect = backgroundRect;
3490 
3491     int x = 0;
3492     int y = 0;
3493     convertToLayerCoords(rootLayer, x, y);
3494     layerBounds = IntRect(x, y, width(), height());
3495 
3496     // Update the clip rects that will be passed to child layers.
3497     if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
3498         // This layer establishes a clip of some kind.
3499 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
3500         if (hasOverflowScroll()) {
3501             // Use the entire foreground rectangle to record the contents.
3502             RenderBox* box = toRenderBox(renderer());
3503             foregroundRect =
3504                 IntRect(x + box->borderLeft(), y + box->borderTop(),
3505                         m_scrollWidth, m_scrollHeight);
3506         } else
3507 #endif
3508         if (renderer()->hasOverflowClip())
3509             foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y, relevancy));
3510         if (renderer()->hasClip()) {
3511             // Clip applies to *us* as well, so go ahead and update the damageRect.
3512             IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
3513             backgroundRect.intersect(newPosClip);
3514             foregroundRect.intersect(newPosClip);
3515             outlineRect.intersect(newPosClip);
3516         }
3517 
3518         // If we establish a clip at all, then go ahead and make sure our background
3519         // rect is intersected with our layer's bounds.
3520         // FIXME: This could be changed to just use generic visual overflow.
3521         // See https://bugs.webkit.org/show_bug.cgi?id=37467 for more information.
3522         if (const ShadowData* boxShadow = renderer()->style()->boxShadow()) {
3523             IntRect overflow = layerBounds;
3524             do {
3525                 if (boxShadow->style() == Normal) {
3526                     IntRect shadowRect = layerBounds;
3527                     shadowRect.move(boxShadow->x(), boxShadow->y());
3528                     shadowRect.inflate(boxShadow->blur() + boxShadow->spread());
3529                     overflow.unite(shadowRect);
3530                 }
3531 
3532                 boxShadow = boxShadow->next();
3533             } while (boxShadow);
3534             backgroundRect.intersect(overflow);
3535         } else
3536             backgroundRect.intersect(layerBounds);
3537     }
3538 }
3539 
childrenClipRect() const3540 IntRect RenderLayer::childrenClipRect() const
3541 {
3542     RenderView* renderView = renderer()->view();
3543     RenderLayer* clippingRootLayer = clippingRoot();
3544     IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
3545     calculateRects(clippingRootLayer, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
3546     return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect)).enclosingBoundingBox();
3547 }
3548 
selfClipRect() const3549 IntRect RenderLayer::selfClipRect() const
3550 {
3551     RenderView* renderView = renderer()->view();
3552     RenderLayer* clippingRootLayer = clippingRoot();
3553     IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
3554     calculateRects(clippingRootLayer, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
3555     return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect)).enclosingBoundingBox();
3556 }
3557 
addBlockSelectionGapsBounds(const IntRect & bounds)3558 void RenderLayer::addBlockSelectionGapsBounds(const IntRect& bounds)
3559 {
3560     m_blockSelectionGapsBounds.unite(bounds);
3561 }
3562 
clearBlockSelectionGapsBounds()3563 void RenderLayer::clearBlockSelectionGapsBounds()
3564 {
3565     m_blockSelectionGapsBounds = IntRect();
3566     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3567         child->clearBlockSelectionGapsBounds();
3568 }
3569 
repaintBlockSelectionGaps()3570 void RenderLayer::repaintBlockSelectionGaps()
3571 {
3572     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3573         child->repaintBlockSelectionGaps();
3574 
3575     if (m_blockSelectionGapsBounds.isEmpty())
3576         return;
3577 
3578     IntRect rect = m_blockSelectionGapsBounds;
3579     rect.move(-scrolledContentOffset());
3580     if (renderer()->hasOverflowClip())
3581         rect.intersect(toRenderBox(renderer())->overflowClipRect(0, 0));
3582     if (renderer()->hasClip())
3583         rect.intersect(toRenderBox(renderer())->clipRect(0, 0));
3584     if (!rect.isEmpty())
3585         renderer()->repaintRectangle(rect);
3586 }
3587 
intersectsDamageRect(const IntRect & layerBounds,const IntRect & damageRect,const RenderLayer * rootLayer) const3588 bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const
3589 {
3590     // Always examine the canvas and the root.
3591     // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
3592     // paints the root's background.
3593     if (renderer()->isRenderView() || renderer()->isRoot())
3594         return true;
3595 
3596     // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we
3597     // can go ahead and return true.
3598     RenderView* view = renderer()->view();
3599     ASSERT(view);
3600     if (view && !renderer()->isRenderInline()) {
3601         IntRect b = layerBounds;
3602         b.inflate(view->maximalOutlineSize());
3603         if (b.intersects(damageRect))
3604             return true;
3605     }
3606 
3607     // Otherwise we need to compute the bounding box of this single layer and see if it intersects
3608     // the damage rect.
3609     return boundingBox(rootLayer).intersects(damageRect);
3610 }
3611 
localBoundingBox() const3612 IntRect RenderLayer::localBoundingBox() const
3613 {
3614     // There are three special cases we need to consider.
3615     // (1) Inline Flows.  For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
3616     // inline.  In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the
3617     // line boxes of all three lines (including overflow on those lines).
3618     // (2) Left/Top Overflow.  The width/height of layers already includes right/bottom overflow.  However, in the case of left/top
3619     // overflow, we have to create a bounding box that will extend to include this overflow.
3620     // (3) Floats.  When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats
3621     // as part of our bounding box.  We do this because we are the responsible layer for both hit testing and painting those
3622     // floats.
3623     IntRect result;
3624     if (renderer()->isRenderInline())
3625         result = toRenderInline(renderer())->linesVisualOverflowBoundingBox();
3626     else if (renderer()->isTableRow()) {
3627         // Our bounding box is just the union of all of our cells' border/overflow rects.
3628         for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
3629             if (child->isTableCell()) {
3630                 IntRect bbox = toRenderBox(child)->borderBoxRect();
3631                 result.unite(bbox);
3632                 IntRect overflowRect = renderBox()->visualOverflowRect();
3633                 if (bbox != overflowRect)
3634                     result.unite(overflowRect);
3635             }
3636         }
3637     } else {
3638         RenderBox* box = renderBox();
3639         ASSERT(box);
3640         if (box->hasMask())
3641             result = box->maskClipRect();
3642         else {
3643             IntRect bbox = box->borderBoxRect();
3644             result = bbox;
3645             IntRect overflowRect = box->visualOverflowRect();
3646             if (bbox != overflowRect)
3647                 result.unite(overflowRect);
3648         }
3649     }
3650 
3651     RenderView* view = renderer()->view();
3652     ASSERT(view);
3653     if (view)
3654         result.inflate(view->maximalOutlineSize()); // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
3655 
3656     return result;
3657 }
3658 
boundingBox(const RenderLayer * ancestorLayer) const3659 IntRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer) const
3660 {
3661     IntRect result = localBoundingBox();
3662     if (renderer()->isBox())
3663         renderBox()->flipForWritingMode(result);
3664     else
3665         renderer()->containingBlock()->flipForWritingMode(result);
3666     int deltaX = 0, deltaY = 0;
3667     convertToLayerCoords(ancestorLayer, deltaX, deltaY);
3668     result.move(deltaX, deltaY);
3669     return result;
3670 }
3671 
absoluteBoundingBox() const3672 IntRect RenderLayer::absoluteBoundingBox() const
3673 {
3674     return boundingBox(root());
3675 }
3676 
clearClipRectsIncludingDescendants()3677 void RenderLayer::clearClipRectsIncludingDescendants()
3678 {
3679     if (!m_clipRects)
3680         return;
3681 
3682     clearClipRects();
3683 
3684     for (RenderLayer* l = firstChild(); l; l = l->nextSibling())
3685         l->clearClipRectsIncludingDescendants();
3686 }
3687 
clearClipRects()3688 void RenderLayer::clearClipRects()
3689 {
3690     if (m_clipRects) {
3691         m_clipRects->deref(renderer()->renderArena());
3692         m_clipRects = 0;
3693 #ifndef NDEBUG
3694         m_clipRectsRoot = 0;
3695 #endif
3696     }
3697 }
3698 
3699 #if USE(ACCELERATED_COMPOSITING)
ensureBacking()3700 RenderLayerBacking* RenderLayer::ensureBacking()
3701 {
3702     if (!m_backing)
3703         m_backing.set(new RenderLayerBacking(this));
3704     return m_backing.get();
3705 }
3706 
clearBacking()3707 void RenderLayer::clearBacking()
3708 {
3709     m_backing.clear();
3710 }
3711 
hasCompositedMask() const3712 bool RenderLayer::hasCompositedMask() const
3713 {
3714     return m_backing && m_backing->hasMaskLayer();
3715 }
3716 
layerForHorizontalScrollbar() const3717 GraphicsLayer* RenderLayer::layerForHorizontalScrollbar() const
3718 {
3719     return m_backing ? m_backing->layerForHorizontalScrollbar() : 0;
3720 }
3721 
layerForVerticalScrollbar() const3722 GraphicsLayer* RenderLayer::layerForVerticalScrollbar() const
3723 {
3724     return m_backing ? m_backing->layerForVerticalScrollbar() : 0;
3725 }
3726 
layerForScrollCorner() const3727 GraphicsLayer* RenderLayer::layerForScrollCorner() const
3728 {
3729     return m_backing ? m_backing->layerForScrollCorner() : 0;
3730 }
3731 #endif
3732 
paintsWithTransform(PaintBehavior paintBehavior) const3733 bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const
3734 {
3735 #if USE(ACCELERATED_COMPOSITING)
3736     bool paintsToWindow = !isComposited() || backing()->paintingGoesToWindow();
3737 #else
3738     bool paintsToWindow = true;
3739 #endif
3740     return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || paintsToWindow);
3741 }
3742 
setParent(RenderLayer * parent)3743 void RenderLayer::setParent(RenderLayer* parent)
3744 {
3745     if (parent == m_parent)
3746         return;
3747 
3748 #if USE(ACCELERATED_COMPOSITING)
3749     if (m_parent && !renderer()->documentBeingDestroyed())
3750         compositor()->layerWillBeRemoved(m_parent, this);
3751 #endif
3752 
3753     m_parent = parent;
3754 
3755 #if USE(ACCELERATED_COMPOSITING)
3756     if (m_parent && !renderer()->documentBeingDestroyed())
3757         compositor()->layerWasAdded(m_parent, this);
3758 #endif
3759 }
3760 
commonAncestor(RenderObject * obj1,RenderObject * obj2)3761 static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
3762 {
3763     if (!obj1 || !obj2)
3764         return 0;
3765 
3766     for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor())
3767         for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor())
3768             if (currObj1 == currObj2)
3769                 return currObj1;
3770 
3771     return 0;
3772 }
3773 
updateHoverActiveState(const HitTestRequest & request,HitTestResult & result)3774 void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestResult& result)
3775 {
3776     // We don't update :hover/:active state when the result is marked as readOnly.
3777     if (request.readOnly())
3778         return;
3779 
3780     Document* doc = renderer()->document();
3781 
3782     Node* activeNode = doc->activeNode();
3783     if (activeNode && !request.active()) {
3784         // We are clearing the :active chain because the mouse has been released.
3785         for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) {
3786             if (curr->node() && !curr->isText())
3787                 curr->node()->clearInActiveChain();
3788         }
3789         doc->setActiveNode(0);
3790     } else {
3791         Node* newActiveNode = result.innerNode();
3792         if (!activeNode && newActiveNode && request.active()) {
3793             // We are setting the :active chain and freezing it. If future moves happen, they
3794             // will need to reference this chain.
3795             for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) {
3796                 if (curr->node() && !curr->isText()) {
3797                     curr->node()->setInActiveChain();
3798                 }
3799             }
3800             doc->setActiveNode(newActiveNode);
3801         }
3802     }
3803 
3804     // If the mouse is down and if this is a mouse move event, we want to restrict changes in
3805     // :hover/:active to only apply to elements that are in the :active chain that we froze
3806     // at the time the mouse went down.
3807     bool mustBeInActiveChain = request.active() && request.mouseMove();
3808 
3809     // Check to see if the hovered node has changed.  If not, then we don't need to
3810     // do anything.
3811     RefPtr<Node> oldHoverNode = doc->hoverNode();
3812     Node* newHoverNode = result.innerNode();
3813 
3814     // Update our current hover node.
3815     doc->setHoverNode(newHoverNode);
3816 
3817     // We have two different objects.  Fetch their renderers.
3818     RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
3819     RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;
3820 
3821     // Locate the common ancestor render object for the two renderers.
3822     RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
3823 
3824     Vector<RefPtr<Node>, 32> nodesToRemoveFromChain;
3825     Vector<RefPtr<Node>, 32> nodesToAddToChain;
3826 
3827     if (oldHoverObj != newHoverObj) {
3828         // The old hover path only needs to be cleared up to (and not including) the common ancestor;
3829         for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) {
3830             if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain()))
3831                 nodesToRemoveFromChain.append(curr->node());
3832         }
3833     }
3834 
3835     // Now set the hover state for our new object up to the root.
3836     for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
3837         if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain()))
3838             nodesToAddToChain.append(curr->node());
3839     }
3840 
3841     size_t removeCount = nodesToRemoveFromChain.size();
3842     for (size_t i = 0; i < removeCount; ++i) {
3843         nodesToRemoveFromChain[i]->setActive(false);
3844         nodesToRemoveFromChain[i]->setHovered(false);
3845     }
3846 
3847     size_t addCount = nodesToAddToChain.size();
3848     for (size_t i = 0; i < addCount; ++i) {
3849         nodesToAddToChain[i]->setActive(request.active());
3850         nodesToAddToChain[i]->setHovered(true);
3851     }
3852 }
3853 
3854 // Helper for the sorting of layers by z-index.
compareZIndex(RenderLayer * first,RenderLayer * second)3855 static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
3856 {
3857     return first->zIndex() < second->zIndex();
3858 }
3859 
dirtyZOrderLists()3860 void RenderLayer::dirtyZOrderLists()
3861 {
3862     if (m_posZOrderList)
3863         m_posZOrderList->clear();
3864     if (m_negZOrderList)
3865         m_negZOrderList->clear();
3866     m_zOrderListsDirty = true;
3867 
3868 #if USE(ACCELERATED_COMPOSITING)
3869     if (!renderer()->documentBeingDestroyed())
3870         compositor()->setCompositingLayersNeedRebuild();
3871 #endif
3872 }
3873 
dirtyStackingContextZOrderLists()3874 void RenderLayer::dirtyStackingContextZOrderLists()
3875 {
3876     RenderLayer* sc = stackingContext();
3877     if (sc)
3878         sc->dirtyZOrderLists();
3879 }
3880 
dirtyNormalFlowList()3881 void RenderLayer::dirtyNormalFlowList()
3882 {
3883     if (m_normalFlowList)
3884         m_normalFlowList->clear();
3885     m_normalFlowListDirty = true;
3886 
3887 #if USE(ACCELERATED_COMPOSITING)
3888     if (!renderer()->documentBeingDestroyed())
3889         compositor()->setCompositingLayersNeedRebuild();
3890 #endif
3891 }
3892 
updateZOrderLists()3893 void RenderLayer::updateZOrderLists()
3894 {
3895     if (!isStackingContext() || !m_zOrderListsDirty)
3896         return;
3897 
3898     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3899         if (!m_reflection || reflectionLayer() != child)
3900             child->collectLayers(m_posZOrderList, m_negZOrderList);
3901 
3902     // Sort the two lists.
3903     if (m_posZOrderList)
3904         std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex);
3905 
3906     if (m_negZOrderList)
3907         std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
3908 
3909     m_zOrderListsDirty = false;
3910 }
3911 
updateNormalFlowList()3912 void RenderLayer::updateNormalFlowList()
3913 {
3914     if (!m_normalFlowListDirty)
3915         return;
3916 
3917     for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
3918         // Ignore non-overflow layers and reflections.
3919         if (child->isNormalFlowOnly() && (!m_reflection || reflectionLayer() != child)) {
3920             if (!m_normalFlowList)
3921                 m_normalFlowList = new Vector<RenderLayer*>;
3922             m_normalFlowList->append(child);
3923         }
3924     }
3925 
3926     m_normalFlowListDirty = false;
3927 }
3928 
collectLayers(Vector<RenderLayer * > * & posBuffer,Vector<RenderLayer * > * & negBuffer)3929 void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer)
3930 {
3931     updateVisibilityStatus();
3932 
3933     // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
3934     if ((m_hasVisibleContent || (m_hasVisibleDescendant && isStackingContext())) && !isNormalFlowOnly()) {
3935         // Determine which buffer the child should be in.
3936         Vector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
3937 
3938         // Create the buffer if it doesn't exist yet.
3939         if (!buffer)
3940             buffer = new Vector<RenderLayer*>;
3941 
3942         // Append ourselves at the end of the appropriate buffer.
3943         buffer->append(this);
3944     }
3945 
3946     // Recur into our children to collect more layers, but only if we don't establish
3947     // a stacking context.
3948     if (m_hasVisibleDescendant && !isStackingContext()) {
3949         for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
3950             // Ignore reflections.
3951             if (!m_reflection || reflectionLayer() != child)
3952                 child->collectLayers(posBuffer, negBuffer);
3953         }
3954     }
3955 }
3956 
updateLayerListsIfNeeded()3957 void RenderLayer::updateLayerListsIfNeeded()
3958 {
3959     updateZOrderLists();
3960     updateNormalFlowList();
3961 }
3962 
updateCompositingAndLayerListsIfNeeded()3963 void RenderLayer::updateCompositingAndLayerListsIfNeeded()
3964 {
3965 #if USE(ACCELERATED_COMPOSITING)
3966     if (compositor()->inCompositingMode()) {
3967         if ((isStackingContext() && m_zOrderListsDirty) || m_normalFlowListDirty)
3968             compositor()->updateCompositingLayers(CompositingUpdateOnPaitingOrHitTest, this);
3969         return;
3970     }
3971 #endif
3972     updateLayerListsIfNeeded();
3973 }
3974 
repaintIncludingDescendants()3975 void RenderLayer::repaintIncludingDescendants()
3976 {
3977     renderer()->repaint();
3978     for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
3979         curr->repaintIncludingDescendants();
3980 }
3981 
3982 #if USE(ACCELERATED_COMPOSITING)
setBackingNeedsRepaint()3983 void RenderLayer::setBackingNeedsRepaint()
3984 {
3985     ASSERT(isComposited());
3986     if (backing()->paintingGoesToWindow()) {
3987         // If we're trying to repaint the placeholder document layer, propagate the
3988         // repaint to the native view system.
3989         RenderView* view = renderer()->view();
3990         if (view)
3991             view->repaintViewRectangle(absoluteBoundingBox());
3992     } else
3993         backing()->setContentsNeedDisplay();
3994 }
3995 
setBackingNeedsRepaintInRect(const IntRect & r)3996 void RenderLayer::setBackingNeedsRepaintInRect(const IntRect& r)
3997 {
3998     ASSERT(isComposited());
3999     if (backing()->paintingGoesToWindow()) {
4000         // If we're trying to repaint the placeholder document layer, propagate the
4001         // repaint to the native view system.
4002         IntRect absRect(r);
4003         int x = 0;
4004         int y = 0;
4005         convertToLayerCoords(root(), x, y);
4006         absRect.move(x, y);
4007 
4008         RenderView* view = renderer()->view();
4009         if (view)
4010             view->repaintViewRectangle(absRect);
4011     } else
4012         backing()->setContentsNeedDisplayInRect(r);
4013 }
4014 
4015 // Since we're only painting non-composited layers, we know that they all share the same repaintContainer.
repaintIncludingNonCompositingDescendants(RenderBoxModelObject * repaintContainer)4016 void RenderLayer::repaintIncludingNonCompositingDescendants(RenderBoxModelObject* repaintContainer)
4017 {
4018     renderer()->repaintUsingContainer(repaintContainer, renderer()->clippedOverflowRectForRepaint(repaintContainer));
4019 
4020     for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling()) {
4021         if (!curr->isComposited())
4022             curr->repaintIncludingNonCompositingDescendants(repaintContainer);
4023     }
4024 }
4025 #endif
4026 
shouldBeNormalFlowOnly() const4027 bool RenderLayer::shouldBeNormalFlowOnly() const
4028 {
4029     return (renderer()->hasOverflowClip()
4030                 || renderer()->hasReflection()
4031                 || renderer()->hasMask()
4032                 || renderer()->isVideo()
4033                 || renderer()->isEmbeddedObject()
4034                 || renderer()->isApplet()
4035                 || renderer()->isRenderIFrame()
4036                 || renderer()->style()->specifiesColumns())
4037             && !renderer()->isPositioned()
4038             && !renderer()->isRelPositioned()
4039             && !renderer()->hasTransform()
4040             && !isTransparent();
4041 }
4042 
isSelfPaintingLayer() const4043 bool RenderLayer::isSelfPaintingLayer() const
4044 {
4045 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
4046     if (hasOverflowScroll())
4047         return true;
4048 #endif
4049     return !isNormalFlowOnly()
4050         || renderer()->hasReflection()
4051         || renderer()->hasMask()
4052         || renderer()->isTableRow()
4053         || renderer()->isVideo()
4054         || renderer()->isEmbeddedObject()
4055         || renderer()->isApplet()
4056         || renderer()->isRenderIFrame();
4057 }
4058 
styleChanged(StyleDifference diff,const RenderStyle * oldStyle)4059 void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle)
4060 {
4061     bool isNormalFlowOnly = shouldBeNormalFlowOnly();
4062     if (isNormalFlowOnly != m_isNormalFlowOnly) {
4063         m_isNormalFlowOnly = isNormalFlowOnly;
4064         RenderLayer* p = parent();
4065         if (p)
4066             p->dirtyNormalFlowList();
4067         dirtyStackingContextZOrderLists();
4068     }
4069 
4070     if (renderer()->style()->overflowX() == OMARQUEE && renderer()->style()->marqueeBehavior() != MNONE && renderer()->isBox()) {
4071         if (!m_marquee)
4072             m_marquee = new RenderMarquee(this);
4073         m_marquee->updateMarqueeStyle();
4074     }
4075     else if (m_marquee) {
4076         delete m_marquee;
4077         m_marquee = 0;
4078     }
4079 
4080     if (!hasReflection() && m_reflection)
4081         removeReflection();
4082     else if (hasReflection()) {
4083         if (!m_reflection)
4084             createReflection();
4085         updateReflectionStyle();
4086     }
4087 
4088     // FIXME: Need to detect a swap from custom to native scrollbars (and vice versa).
4089     if (m_hBar)
4090         m_hBar->styleChanged();
4091     if (m_vBar)
4092         m_vBar->styleChanged();
4093 
4094     updateScrollCornerStyle();
4095     updateResizerStyle();
4096 
4097 #if USE(ACCELERATED_COMPOSITING)
4098     updateTransform();
4099 
4100     if (compositor()->updateLayerCompositingState(this))
4101         compositor()->setCompositingLayersNeedRebuild();
4102     else if (m_backing)
4103         m_backing->updateGraphicsLayerGeometry();
4104     else if (oldStyle && oldStyle->overflowX() != renderer()->style()->overflowX()) {
4105         if (stackingContext()->hasCompositingDescendant())
4106             compositor()->setCompositingLayersNeedRebuild();
4107     }
4108 
4109     if (m_backing && diff >= StyleDifferenceRepaint)
4110         m_backing->setContentsNeedDisplay();
4111 #else
4112     UNUSED_PARAM(diff);
4113 #endif
4114 }
4115 
updateScrollCornerStyle()4116 void RenderLayer::updateScrollCornerStyle()
4117 {
4118     RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
4119     RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, actualRenderer->style()) : 0;
4120     if (corner) {
4121         if (!m_scrollCorner) {
4122             m_scrollCorner = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
4123             m_scrollCorner->setParent(renderer());
4124         }
4125         m_scrollCorner->setStyle(corner.release());
4126     } else if (m_scrollCorner) {
4127         m_scrollCorner->destroy();
4128         m_scrollCorner = 0;
4129     }
4130 }
4131 
updateResizerStyle()4132 void RenderLayer::updateResizerStyle()
4133 {
4134     RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
4135     RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RESIZER, actualRenderer->style()) : 0;
4136     if (resizer) {
4137         if (!m_resizer) {
4138             m_resizer = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
4139             m_resizer->setParent(renderer());
4140         }
4141         m_resizer->setStyle(resizer.release());
4142     } else if (m_resizer) {
4143         m_resizer->destroy();
4144         m_resizer = 0;
4145     }
4146 }
4147 
reflectionLayer() const4148 RenderLayer* RenderLayer::reflectionLayer() const
4149 {
4150     return m_reflection ? m_reflection->layer() : 0;
4151 }
4152 
createReflection()4153 void RenderLayer::createReflection()
4154 {
4155     ASSERT(!m_reflection);
4156     m_reflection = new (renderer()->renderArena()) RenderReplica(renderer()->document());
4157     m_reflection->setParent(renderer()); // We create a 1-way connection.
4158 }
4159 
removeReflection()4160 void RenderLayer::removeReflection()
4161 {
4162     if (!m_reflection->documentBeingDestroyed())
4163         m_reflection->removeLayers(this);
4164 
4165     m_reflection->setParent(0);
4166     m_reflection->destroy();
4167     m_reflection = 0;
4168 }
4169 
updateReflectionStyle()4170 void RenderLayer::updateReflectionStyle()
4171 {
4172     RefPtr<RenderStyle> newStyle = RenderStyle::create();
4173     newStyle->inheritFrom(renderer()->style());
4174 
4175     // Map in our transform.
4176     TransformOperations transform;
4177     switch (renderer()->style()->boxReflect()->direction()) {
4178         case ReflectionBelow:
4179             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
4180             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
4181             transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
4182             break;
4183         case ReflectionAbove:
4184             transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
4185             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
4186             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
4187             break;
4188         case ReflectionRight:
4189             transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
4190             transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
4191             transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
4192             break;
4193         case ReflectionLeft:
4194             transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
4195             transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
4196             transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
4197             break;
4198     }
4199     newStyle->setTransform(transform);
4200 
4201     // Map in our mask.
4202     newStyle->setMaskBoxImage(renderer()->style()->boxReflect()->mask());
4203 
4204     m_reflection->setStyle(newStyle.release());
4205 }
4206 
updateContentsScale(float scale)4207 void RenderLayer::updateContentsScale(float scale)
4208 {
4209 #if USE(ACCELERATED_COMPOSITING)
4210     if (m_backing)
4211         m_backing->updateContentsScale(scale);
4212 #endif
4213 }
4214 
4215 } // namespace WebCore
4216 
4217 #ifndef NDEBUG
showLayerTree(const WebCore::RenderLayer * layer)4218 void showLayerTree(const WebCore::RenderLayer* layer)
4219 {
4220     if (!layer)
4221         return;
4222 
4223     if (WebCore::Frame* frame = layer->renderer()->frame()) {
4224         WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass | WebCore::RenderAsTextDontUpdateLayout | WebCore::RenderAsTextShowLayoutState);
4225         fprintf(stderr, "%s\n", output.utf8().data());
4226     }
4227 }
4228 
showLayerTree(const WebCore::RenderObject * renderer)4229 void showLayerTree(const WebCore::RenderObject* renderer)
4230 {
4231     if (!renderer)
4232         return;
4233     showLayerTree(renderer->enclosingLayer());
4234 }
4235 #endif
4236