2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
4 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
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>
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.
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.
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
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.
45 #include "RenderLayer.h"
47 #include "ColumnInfo.h"
48 #include "CSSPropertyNames.h"
51 #include "DocumentEventQueue.h"
52 #include "EventHandler.h"
53 #if ENABLE(CSS_FILTERS)
54 #include "FEColorMatrix.h"
56 #include "FilterEffectRenderer.h"
58 #include "FloatConversion.h"
59 #include "FloatPoint3D.h"
60 #include "FloatRect.h"
61 #include "FocusController.h"
63 #include "FrameSelection.h"
64 #include "FrameTree.h"
65 #include "FrameView.h"
67 #include "GraphicsContext.h"
68 #include "HTMLFrameElement.h"
69 #include "HTMLFrameOwnerElement.h"
70 #include "HTMLNames.h"
71 #include "HitTestingTransformState.h"
72 #include "HitTestRequest.h"
73 #include "HitTestResult.h"
74 #include "OverflowEvent.h"
75 #include "OverlapTestRequestClient.h"
77 #include "PlatformMouseEvent.h"
78 #include "RenderArena.h"
79 #include "RenderFlowThread.h"
80 #include "RenderInline.h"
81 #include "RenderMarquee.h"
82 #include "RenderReplica.h"
83 #include "RenderScrollbar.h"
84 #include "RenderScrollbarPart.h"
85 #include "RenderTheme.h"
86 #include "RenderTreeAsText.h"
87 #include "RenderView.h"
88 #include "ScaleTransformOperation.h"
89 #include "ScrollAnimator.h"
90 #include "Scrollbar.h"
91 #include "ScrollbarTheme.h"
93 #include "SourceGraphic.h"
94 #include "StylePropertySet.h"
95 #include "StyleResolver.h"
96 #include "TextStream.h"
97 #include "TransformationMatrix.h"
98 #include "TranslateTransformOperation.h"
99 #include <wtf/StdLibExtras.h>
100 #include <wtf/UnusedParam.h>
101 #include <wtf/text/CString.h>
103 #if USE(ACCELERATED_COMPOSITING)
104 #include "RenderLayerBacking.h"
105 #include "RenderLayerCompositor.h"
109 #include "SVGNames.h"
112 #if PLATFORM(CHROMIUM) || PLATFORM(BLACKBERRY)
113 // FIXME: border radius clipping triggers too-slow path on Chromium
114 // https://bugs.webkit.org/show_bug.cgi?id=69866
115 #define DISABLE_ROUNDED_CORNER_CLIPPING
118 #define MIN_INTERSECT_FOR_REVEAL 32
124 using namespace HTMLNames;
126 const int MinimumWidthWhileResizing = 100;
127 const int MinimumHeightWhileResizing = 40;
129 bool ClipRect::intersects(const HitTestPoint& hitTestPoint)
131 return hitTestPoint.intersects(m_rect);
134 RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
135 : m_inResizeMode(false)
136 , m_scrollDimensionsDirty(true)
137 , m_normalFlowListDirty(true)
138 , m_hasSelfPaintingLayerDescendant(false)
139 , m_hasSelfPaintingLayerDescendantDirty(false)
140 , m_isRootLayer(renderer->isRenderView())
141 , m_usedTransparency(false)
142 , m_paintingInsideReflection(false)
143 , m_inOverflowRelayout(false)
144 , m_repaintStatus(NeedsNormalRepaint)
145 , m_visibleContentStatusDirty(true)
146 , m_hasVisibleContent(false)
147 , m_visibleDescendantStatusDirty(false)
148 , m_hasVisibleDescendant(false)
149 , m_isPaginated(false)
150 , m_3DTransformedDescendantStatusDirty(true)
151 , m_has3DTransformedDescendant(false)
152 #if USE(ACCELERATED_COMPOSITING)
153 , m_hasCompositingDescendant(false)
154 , m_indirectCompositingReason(NoIndirectCompositingReason)
156 , m_containsDirtyOverlayScrollbars(false)
158 , m_layerListMutationAllowed(true)
160 , m_canSkipRepaintRectsUpdateOnScroll(renderer->isTableCell())
161 #if ENABLE(CSS_FILTERS)
162 , m_hasFilterInfo(false)
164 , m_renderer(renderer)
172 , m_normalFlowList(0)
174 , m_staticInlinePosition(0)
175 , m_staticBlockPosition(0)
180 m_isNormalFlowOnly = shouldBeNormalFlowOnly();
181 m_isSelfPaintingLayer = shouldBeSelfPaintingLayer();
183 // Non-stacking contexts should have empty z-order lists. As this is already the case,
184 // there is no need to dirty / recompute these lists.
185 m_zOrderListsDirty = isStackingContext();
187 ScrollableArea::setConstrainsScrollingToContentEdge(false);
189 if (!renderer->firstChild() && renderer->style()) {
190 m_visibleContentStatusDirty = false;
191 m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
194 Node* node = renderer->node();
195 if (node && node->isElementNode()) {
196 // We save and restore only the scrollOffset as the other scroll values are recalculated.
197 Element* element = toElement(node);
198 m_scrollOffset = element->savedLayerScrollOffset();
199 if (!m_scrollOffset.isZero())
200 scrollAnimator()->setCurrentPosition(FloatPoint(m_scrollOffset.width(), m_scrollOffset.height()));
201 element->setSavedLayerScrollOffset(IntSize());
205 RenderLayer::~RenderLayer()
207 if (inResizeMode() && !renderer()->documentBeingDestroyed()) {
208 if (Frame* frame = renderer()->frame())
209 frame->eventHandler()->resizeLayerDestroyed();
212 if (Frame* frame = renderer()->frame()) {
213 if (FrameView* frameView = frame->view())
214 frameView->removeScrollableArea(this);
217 if (!m_renderer->documentBeingDestroyed()) {
218 Node* node = m_renderer->node();
219 if (node && node->isElementNode())
220 toElement(node)->setSavedLayerScrollOffset(m_scrollOffset);
223 destroyScrollbar(HorizontalScrollbar);
224 destroyScrollbar(VerticalScrollbar);
229 #if ENABLE(CSS_FILTERS)
230 removeFilterInfoIfNeeded();
233 // Child layers will be deleted by their corresponding render objects, so
234 // we don't need to delete them ourselves.
236 delete m_posZOrderList;
237 delete m_negZOrderList;
238 delete m_normalFlowList;
241 #if USE(ACCELERATED_COMPOSITING)
246 m_scrollCorner->destroy();
248 m_resizer->destroy();
251 #if USE(ACCELERATED_COMPOSITING)
252 RenderLayerCompositor* RenderLayer::compositor() const
254 ASSERT(renderer()->view());
255 return renderer()->view()->compositor();
258 void RenderLayer::contentChanged(ContentChangeType changeType)
260 // This can get called when video becomes accelerated, so the layers may change.
261 if ((changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged) && compositor()->updateLayerCompositingState(this))
262 compositor()->setCompositingLayersNeedRebuild();
265 m_backing->contentChanged(changeType);
267 #endif // USE(ACCELERATED_COMPOSITING)
269 bool RenderLayer::canRender3DTransforms() const
271 #if USE(ACCELERATED_COMPOSITING)
272 return compositor()->canRender3DTransforms();
278 #if ENABLE(CSS_FILTERS)
279 bool RenderLayer::paintsWithFilters() const
281 // FIXME: Eventually there will be more factors than isComposited() to decide whether or not to render the filter
282 if (!renderer()->hasFilter())
285 #if USE(ACCELERATED_COMPOSITING)
289 #if ENABLE(TIZEN_ACCELERATED_COMPOSITING)
290 if (!m_backing || !m_backing->canCompositeFilters())
299 bool RenderLayer::requiresFullLayerImageForFilters() const
301 if (!paintsWithFilters())
303 FilterEffectRenderer* filter = filterRenderer();
304 return filter ? filter->hasFilterThatMovesPixels() : false;
308 LayoutPoint RenderLayer::computeOffsetFromRoot(bool& hasLayerOffset) const
310 hasLayerOffset = true;
313 return LayoutPoint();
315 // This is similar to root() but we check if an ancestor layer would
316 // prevent the optimization from working.
317 const RenderLayer* rootLayer = 0;
318 for (const RenderLayer* parentLayer = parent(); parentLayer; rootLayer = parentLayer, parentLayer = parentLayer->parent()) {
319 hasLayerOffset = parentLayer->canUseConvertToLayerCoords();
321 return LayoutPoint();
323 ASSERT(rootLayer == root());
326 parent()->convertToLayerCoords(rootLayer, offset);
330 void RenderLayer::updateLayerPositions(LayoutPoint* offsetFromRoot, UpdateLayerPositionsFlags flags)
333 if (offsetFromRoot) {
335 LayoutPoint computedOffsetFromRoot = computeOffsetFromRoot(hasLayerOffset);
336 ASSERT(hasLayerOffset);
337 ASSERT(*offsetFromRoot == computedOffsetFromRoot);
341 updateLayerPosition(); // For relpositioned layers or non-positioned layers,
342 // we need to keep in sync, since we may have shifted relative
343 // to our parent layer.
344 LayoutPoint oldOffsetFromRoot;
345 if (offsetFromRoot) {
346 // We can't cache our offset to the repaint container if the mapping is anything more complex than a simple translation
347 if (!canUseConvertToLayerCoords())
348 offsetFromRoot = 0; // If our cached offset is invalid make sure it's not passed to any of our children
350 oldOffsetFromRoot = *offsetFromRoot;
351 // Frequently our parent layer's renderer will be the same as our renderer's containing block. In that case,
352 // we just update the cache using our offset to our parent (which is m_topLeft). Otherwise, regenerated cached
353 // offsets to the root from the render tree.
354 if (!m_parent || m_parent->renderer() == renderer()->containingBlock())
355 offsetFromRoot->move(m_topLeft.x(), m_topLeft.y()); // Fast case
358 convertToLayerCoords(root(), offset);
359 *offsetFromRoot = offset;
365 if (offsetFromRoot) {
366 offset = *offsetFromRoot;
368 LayoutPoint computedOffsetFromRoot;
369 convertToLayerCoords(root(), computedOffsetFromRoot);
370 ASSERT(offset == computedOffsetFromRoot);
373 // FIXME: It looks suspicious to call convertToLayerCoords here
374 // as canUseConvertToLayerCoords may be true for an ancestor layer.
375 convertToLayerCoords(root(), offset);
377 positionOverflowControls(toSize(roundedIntPoint(offset)));
379 updateDescendantDependentFlags();
381 if (flags & UpdatePagination)
384 m_isPaginated = false;
386 if (m_hasVisibleContent) {
387 RenderView* view = renderer()->view();
389 // FIXME: LayoutState does not work with RenderLayers as there is not a 1-to-1
390 // mapping between them and the RenderObjects. It would be neat to enable
391 // LayoutState outside the layout() phase and use it here.
392 ASSERT(!view->layoutStateEnabled());
394 RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
395 LayoutRect oldRepaintRect = m_repaintRect;
396 LayoutRect oldOutlineBox = m_outlineBox;
397 computeRepaintRects(offsetFromRoot);
398 // FIXME: Should ASSERT that value calculated for m_outlineBox using the cached offset is the same
399 // as the value not using the cached offset, but we can't due to https://bugs.webkit.org/show_bug.cgi?id=37048
400 if (flags & CheckForRepaint) {
401 if (view && !view->printing()) {
402 if (m_repaintStatus & NeedsFullRepaint) {
403 renderer()->repaintUsingContainer(repaintContainer, oldRepaintRect);
404 if (m_repaintRect != oldRepaintRect)
405 renderer()->repaintUsingContainer(repaintContainer, m_repaintRect);
406 } else if (shouldRepaintAfterLayout())
407 renderer()->repaintAfterLayoutIfNeeded(repaintContainer, oldRepaintRect, oldOutlineBox, &m_repaintRect, &m_outlineBox);
413 m_repaintStatus = NeedsNormalRepaint;
415 // Go ahead and update the reflection's position and size.
417 m_reflection->layout();
419 #if USE(ACCELERATED_COMPOSITING)
420 // Clear the IsCompositingUpdateRoot flag once we've found the first compositing layer in this update.
421 bool isUpdateRoot = (flags & IsCompositingUpdateRoot);
423 flags &= ~IsCompositingUpdateRoot;
426 if (renderer()->hasColumns())
427 flags |= UpdatePagination;
429 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
430 child->updateLayerPositions(offsetFromRoot, flags);
432 #if USE(ACCELERATED_COMPOSITING)
433 if ((flags & UpdateCompositingLayers) && isComposited())
434 backing()->updateAfterLayout(RenderLayerBacking::CompositingChildren, isUpdateRoot);
437 // With all our children positioned, now update our marquee if we need to.
439 m_marquee->updateMarqueePosition();
442 *offsetFromRoot = oldOffsetFromRoot;
445 LayoutRect RenderLayer::repaintRectIncludingNonCompositingDescendants() const
447 LayoutRect repaintRect = m_repaintRect;
448 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
449 // Don't include repaint rects for composited child layers; they will paint themselves and have a different origin.
450 if (child->isComposited())
453 repaintRect.unite(child->repaintRectIncludingNonCompositingDescendants());
458 void RenderLayer::setAncestorChainHasSelfPaintingLayerDescendant()
460 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
461 if (!layer->m_hasSelfPaintingLayerDescendantDirty && layer->hasSelfPaintingLayerDescendant())
464 layer->m_hasSelfPaintingLayerDescendantDirty = false;
465 layer->m_hasSelfPaintingLayerDescendant = true;
469 void RenderLayer::dirtyAncestorChainHasSelfPaintingLayerDescendantStatus()
471 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
472 layer->m_hasSelfPaintingLayerDescendantDirty = true;
473 // If we have reached a self-painting layer, we know our parent should have a self-painting descendant
474 // in this case, there is no need to dirty our ancestors further.
475 if (layer->isSelfPaintingLayer()) {
476 ASSERT(!parent() || parent()->m_hasSelfPaintingLayerDescendantDirty || parent()->hasSelfPaintingLayerDescendant());
482 void RenderLayer::computeRepaintRects(LayoutPoint* offsetFromRoot)
484 ASSERT(!m_visibleContentStatusDirty);
486 RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
487 m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
488 m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer, offsetFromRoot);
491 void RenderLayer::clearRepaintRects()
493 ASSERT(!m_hasVisibleContent);
494 ASSERT(!m_visibleContentStatusDirty);
496 m_repaintRect = IntRect();
497 m_outlineBox = IntRect();
500 void RenderLayer::updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrollFlags flags)
502 // FIXME: This shouldn't be needed, but there are some corner cases where
503 // these flags are still dirty. Update so that the check below is valid.
504 updateDescendantDependentFlags();
506 // If we have no visible content and no visible descendants, there is no point recomputing
507 // our rectangles as they will be empty. If our visibility changes, we are expected to
508 // recompute all our positions anyway.
509 if (!m_hasVisibleDescendant && !m_hasVisibleContent)
512 updateLayerPosition();
514 if ((flags & HasSeenFixedPositionedAncestor) || renderer()->style()->position() == FixedPosition) {
515 // FIXME: Is it worth passing the offsetFromRoot around like in updateLayerPositions?
516 computeRepaintRects();
517 flags |= HasSeenFixedPositionedAncestor;
518 } else if ((flags & HasSeenAncestorWithOverflowClip) && !m_canSkipRepaintRectsUpdateOnScroll) {
519 // If we have seen an overflow clip, we should update our repaint rects as clippedOverflowRectForRepaint
520 // intersects it with our ancestor overflow clip that may have moved.
521 computeRepaintRects();
524 if (renderer()->hasOverflowClip())
525 flags |= HasSeenAncestorWithOverflowClip;
527 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
528 child->updateLayerPositionsAfterScroll(flags);
530 // We don't update our reflection as scrolling is a translation which does not change the size()
531 // of an object, thus RenderReplica will still repaint itself properly as the layer position was
535 m_marquee->updateMarqueePosition();
538 void RenderLayer::updateTransform()
540 // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
541 // so check style too.
542 bool hasTransform = renderer()->hasTransform() && renderer()->style()->hasTransform();
543 bool had3DTransform = has3DTransform();
545 bool hadTransform = m_transform;
546 if (hasTransform != hadTransform) {
548 m_transform = adoptPtr(new TransformationMatrix);
552 // Layers with transforms act as clip rects roots, so clear the cached clip rects here.
553 clearClipRectsIncludingDescendants();
557 RenderBox* box = renderBox();
559 m_transform->makeIdentity();
560 box->style()->applyTransform(*m_transform, box->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
561 makeMatrixRenderable(*m_transform, canRender3DTransforms());
564 if (had3DTransform != has3DTransform())
565 dirty3DTransformedDescendantStatus();
568 TransformationMatrix RenderLayer::currentTransform(RenderStyle::ApplyTransformOrigin applyOrigin) const
571 return TransformationMatrix();
573 #if USE(ACCELERATED_COMPOSITING)
574 if (renderer()->style()->isRunningAcceleratedAnimation()) {
575 TransformationMatrix currTransform;
576 RefPtr<RenderStyle> style = renderer()->animation()->getAnimatedStyleForRenderer(renderer());
577 style->applyTransform(currTransform, renderBox()->pixelSnappedBorderBoxRect().size(), applyOrigin);
578 makeMatrixRenderable(currTransform, canRender3DTransforms());
579 return currTransform;
582 // m_transform includes transform-origin, so we need to recompute the transform here.
583 if (applyOrigin == RenderStyle::ExcludeTransformOrigin) {
584 RenderBox* box = renderBox();
585 TransformationMatrix currTransform;
586 box->style()->applyTransform(currTransform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
587 makeMatrixRenderable(currTransform, canRender3DTransforms());
588 return currTransform;
595 TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const
598 return TransformationMatrix();
600 if (paintBehavior & PaintBehaviorFlattenCompositingLayers) {
601 TransformationMatrix matrix = *m_transform;
602 makeMatrixRenderable(matrix, false /* flatten 3d */);
609 static bool checkContainingBlockChainForPagination(RenderBoxModelObject* renderer, RenderBox* ancestorColumnsRenderer)
611 RenderView* view = renderer->view();
612 RenderBoxModelObject* prevBlock = renderer;
613 RenderBlock* containingBlock;
614 for (containingBlock = renderer->containingBlock();
615 containingBlock && containingBlock != view && containingBlock != ancestorColumnsRenderer;
616 containingBlock = containingBlock->containingBlock())
617 prevBlock = containingBlock;
619 // If the columns block wasn't in our containing block chain, then we aren't paginated by it.
620 if (containingBlock != ancestorColumnsRenderer)
623 // If the previous block is absolutely positioned, then we can't be paginated by the columns block.
624 if (prevBlock->isOutOfFlowPositioned())
627 // Otherwise we are paginated by the columns block.
631 void RenderLayer::updatePagination()
633 m_isPaginated = false;
634 if (isComposited() || !parent())
635 return; // FIXME: We will have to deal with paginated compositing layers someday.
636 // FIXME: For now the RenderView can't be paginated. Eventually printing will move to a model where it is though.
638 if (isNormalFlowOnly()) {
639 m_isPaginated = parent()->renderer()->hasColumns();
643 // If we're not normal flow, then we need to look for a multi-column object between us and our stacking context.
644 RenderLayer* ancestorStackingContext = stackingContext();
645 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
646 if (curr->renderer()->hasColumns()) {
647 m_isPaginated = checkContainingBlockChainForPagination(renderer(), curr->renderBox());
650 if (curr == ancestorStackingContext)
655 void RenderLayer::setHasVisibleContent()
657 if (m_hasVisibleContent && !m_visibleContentStatusDirty) {
658 ASSERT(!parent() || parent()->hasVisibleDescendant());
662 m_visibleContentStatusDirty = false;
663 m_hasVisibleContent = true;
664 computeRepaintRects();
665 if (!isNormalFlowOnly()) {
666 // We don't collect invisible layers in z-order lists if we are not in compositing mode.
667 // As we became visible, we need to dirty our stacking contexts ancestors to be properly
668 // collected. FIXME: When compositing, we could skip this dirtying phase.
669 for (RenderLayer* sc = stackingContext(); sc; sc = sc->stackingContext()) {
670 sc->dirtyZOrderLists();
671 if (sc->hasVisibleContent())
677 parent()->setAncestorChainHasVisibleDescendant();
680 void RenderLayer::dirtyVisibleContentStatus()
682 m_visibleContentStatusDirty = true;
684 parent()->dirtyAncestorChainVisibleDescendantStatus();
687 void RenderLayer::dirtyAncestorChainVisibleDescendantStatus()
689 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
690 if (layer->m_visibleDescendantStatusDirty)
693 layer->m_visibleDescendantStatusDirty = true;
697 void RenderLayer::setAncestorChainHasVisibleDescendant()
699 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
700 if (!layer->m_visibleDescendantStatusDirty && layer->hasVisibleDescendant())
703 layer->m_hasVisibleDescendant = true;
704 layer->m_visibleDescendantStatusDirty = false;
708 void RenderLayer::updateDescendantDependentFlags()
710 if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty) {
711 m_hasVisibleDescendant = false;
712 m_hasSelfPaintingLayerDescendant = false;
713 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
714 child->updateDescendantDependentFlags();
716 bool hasVisibleDescendant = child->m_hasVisibleContent || child->m_hasVisibleDescendant;
717 bool hasSelfPaintingLayerDescendant = child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant();
719 m_hasVisibleDescendant |= hasVisibleDescendant;
720 m_hasSelfPaintingLayerDescendant |= hasSelfPaintingLayerDescendant;
722 if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant)
725 m_visibleDescendantStatusDirty = false;
726 m_hasSelfPaintingLayerDescendantDirty = false;
729 if (m_visibleContentStatusDirty) {
730 if (renderer()->style()->visibility() == VISIBLE)
731 m_hasVisibleContent = true;
733 // layer may be hidden but still have some visible content, check for this
734 m_hasVisibleContent = false;
735 RenderObject* r = renderer()->firstChild();
737 if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
738 m_hasVisibleContent = true;
741 if (r->firstChild() && !r->hasLayer())
743 else if (r->nextSibling())
744 r = r->nextSibling();
750 } while (r && !r->nextSibling());
752 r = r->nextSibling();
756 m_visibleContentStatusDirty = false;
760 void RenderLayer::dirty3DTransformedDescendantStatus()
762 RenderLayer* curr = stackingContext();
764 curr->m_3DTransformedDescendantStatusDirty = true;
766 // This propagates up through preserve-3d hierarchies to the enclosing flattening layer.
767 // Note that preserves3D() creates stacking context, so we can just run up the stacking contexts.
768 while (curr && curr->preserves3D()) {
769 curr->m_3DTransformedDescendantStatusDirty = true;
770 curr = curr->stackingContext();
774 // Return true if this layer or any preserve-3d descendants have 3d.
775 bool RenderLayer::update3DTransformedDescendantStatus()
777 if (m_3DTransformedDescendantStatusDirty) {
778 m_has3DTransformedDescendant = false;
782 // Transformed or preserve-3d descendants can only be in the z-order lists, not
783 // in the normal flow list, so we only need to check those.
784 if (Vector<RenderLayer*>* positiveZOrderList = posZOrderList()) {
785 for (unsigned i = 0; i < positiveZOrderList->size(); ++i)
786 m_has3DTransformedDescendant |= positiveZOrderList->at(i)->update3DTransformedDescendantStatus();
789 // Now check our negative z-index children.
790 if (Vector<RenderLayer*>* negativeZOrderList = negZOrderList()) {
791 for (unsigned i = 0; i < negativeZOrderList->size(); ++i)
792 m_has3DTransformedDescendant |= negativeZOrderList->at(i)->update3DTransformedDescendantStatus();
795 m_3DTransformedDescendantStatusDirty = false;
798 // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs
799 // the m_has3DTransformedDescendant set.
801 return has3DTransform() || m_has3DTransformedDescendant;
803 return has3DTransform();
806 void RenderLayer::updateLayerPosition()
808 LayoutPoint localPoint;
809 LayoutSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done.
810 if (renderer()->isRenderInline()) {
811 RenderInline* inlineFlow = toRenderInline(renderer());
812 IntRect lineBox = inlineFlow->linesBoundingBox();
813 setSize(lineBox.size());
814 inlineBoundingBoxOffset = toSize(lineBox.location());
815 localPoint += inlineBoundingBoxOffset;
816 } else if (RenderBox* box = renderBox()) {
817 // FIXME: Is snapping the size really needed here for the RenderBox case?
818 setSize(pixelSnappedIntSize(box->size(), box->location()));
819 localPoint += box->topLeftLocationOffset();
822 // Clear our cached clip rect information.
825 if (!renderer()->isOutOfFlowPositioned() && renderer()->parent()) {
826 // We must adjust our position by walking up the render tree looking for the
827 // nearest enclosing object with a layer.
828 RenderObject* curr = renderer()->parent();
829 while (curr && !curr->hasLayer()) {
830 if (curr->isBox() && !curr->isTableRow()) {
831 // Rows and cells share the same coordinate space (that of the section).
832 // Omit them when computing our xpos/ypos.
833 localPoint += toRenderBox(curr)->topLeftLocationOffset();
835 curr = curr->parent();
837 if (curr->isBox() && curr->isTableRow()) {
838 // Put ourselves into the row coordinate space.
839 localPoint -= toRenderBox(curr)->topLeftLocationOffset();
843 // Subtract our parent's scroll offset.
844 if (renderer()->isOutOfFlowPositioned() && enclosingPositionedAncestor()) {
845 RenderLayer* positionedParent = enclosingPositionedAncestor();
847 // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
848 if (positionedParent->renderer()->hasOverflowClip()) {
849 LayoutSize offset = positionedParent->scrolledContentOffset();
850 localPoint -= offset;
853 if (renderer()->isOutOfFlowPositioned() && positionedParent->renderer()->isRelPositioned() && positionedParent->renderer()->isRenderInline()) {
854 LayoutSize offset = toRenderInline(positionedParent->renderer())->relativePositionedInlineOffset(toRenderBox(renderer()));
855 localPoint += offset;
857 } else if (parent()) {
858 if (isComposited()) {
859 // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column.
860 // They won't split across columns properly.
861 LayoutSize columnOffset;
862 if (!parent()->renderer()->hasColumns() && parent()->renderer()->isRoot() && renderer()->view()->hasColumns())
863 renderer()->view()->adjustForColumns(columnOffset, localPoint);
865 parent()->renderer()->adjustForColumns(columnOffset, localPoint);
867 localPoint += columnOffset;
870 if (parent()->renderer()->hasOverflowClip()) {
871 IntSize scrollOffset = parent()->scrolledContentOffset();
872 localPoint -= scrollOffset;
876 if (renderer()->isRelPositioned()) {
877 m_relativeOffset = renderer()->relativePositionOffset();
878 localPoint.move(m_relativeOffset);
880 m_relativeOffset = LayoutSize();
883 // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
884 localPoint -= inlineBoundingBoxOffset;
885 setLocation(localPoint.x(), localPoint.y());
888 TransformationMatrix RenderLayer::perspectiveTransform() const
890 if (!renderer()->hasTransform())
891 return TransformationMatrix();
893 RenderStyle* style = renderer()->style();
894 if (!style->hasPerspective())
895 return TransformationMatrix();
897 // Maybe fetch the perspective from the backing?
898 const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
899 const float boxWidth = borderBox.width();
900 const float boxHeight = borderBox.height();
902 float perspectiveOriginX = floatValueForLength(style->perspectiveOriginX(), boxWidth);
903 float perspectiveOriginY = floatValueForLength(style->perspectiveOriginY(), boxHeight);
905 // A perspective origin of 0,0 makes the vanishing point in the center of the element.
906 // We want it to be in the top-left, so subtract half the height and width.
907 perspectiveOriginX -= boxWidth / 2.0f;
908 perspectiveOriginY -= boxHeight / 2.0f;
910 TransformationMatrix t;
911 t.translate(perspectiveOriginX, perspectiveOriginY);
912 t.applyPerspective(style->perspective());
913 t.translate(-perspectiveOriginX, -perspectiveOriginY);
918 FloatPoint RenderLayer::perspectiveOrigin() const
920 if (!renderer()->hasTransform())
923 const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
924 RenderStyle* style = renderer()->style();
926 return FloatPoint(floatValueForLength(style->perspectiveOriginX(), borderBox.width()),
927 floatValueForLength(style->perspectiveOriginY(), borderBox.height()));
930 RenderLayer* RenderLayer::stackingContext() const
932 RenderLayer* layer = parent();
933 while (layer && !layer->isRootLayer() && !layer->renderer()->isRoot() && layer->renderer()->style()->hasAutoZIndex())
934 layer = layer->parent();
938 static inline bool isPositionedContainer(RenderLayer* layer)
940 RenderBoxModelObject* layerRenderer = layer->renderer();
941 return layer->isRootLayer() || layerRenderer->isOutOfFlowPositioned() || layerRenderer->isRelPositioned() || layer->hasTransform();
944 static inline bool isFixedPositionedContainer(RenderLayer* layer)
946 return layer->isRootLayer() || layer->hasTransform();
949 RenderLayer* RenderLayer::enclosingPositionedAncestor() const
951 RenderLayer* curr = parent();
952 while (curr && !isPositionedContainer(curr))
953 curr = curr->parent();
958 RenderLayer* RenderLayer::enclosingScrollableLayer() const
960 for (RenderObject* nextRenderer = renderer()->parent(); nextRenderer; nextRenderer = nextRenderer->parent()) {
961 if (nextRenderer->isBox() && toRenderBox(nextRenderer)->canBeScrolledAndHasScrollableArea())
962 return nextRenderer->enclosingLayer();
968 IntRect RenderLayer::scrollableAreaBoundingBox() const
970 return renderer()->absoluteBoundingBoxRect();
973 RenderLayer* RenderLayer::enclosingTransformedAncestor() const
975 RenderLayer* curr = parent();
976 while (curr && !curr->isRootLayer() && !curr->transform())
977 curr = curr->parent();
982 static inline const RenderLayer* compositingContainer(const RenderLayer* layer)
984 return layer->isNormalFlowOnly() ? layer->parent() : layer->stackingContext();
987 inline bool RenderLayer::shouldRepaintAfterLayout() const
989 #if USE(ACCELERATED_COMPOSITING)
990 if (m_repaintStatus == NeedsNormalRepaint)
993 // Composited layers that were moved during a positioned movement only
994 // layout, don't need to be repainted. They just need to be recomposited.
995 ASSERT(m_repaintStatus == NeedsFullRepaintForPositionedMovementLayout);
996 #if ENABLE(TIZEN_FIX_REPAINTING_BUG_OF_COMPOSITED_LAYER)
997 return !isComposited() || backing()->paintsIntoCompositedAncestor();
999 return !isComposited();
1006 #if USE(ACCELERATED_COMPOSITING)
1007 RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const
1009 if (includeSelf && isComposited())
1010 return const_cast<RenderLayer*>(this);
1012 for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
1013 if (curr->isComposited())
1014 return const_cast<RenderLayer*>(curr);
1020 RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(bool includeSelf) const
1022 if (includeSelf && isComposited() && !backing()->paintsIntoCompositedAncestor())
1023 return const_cast<RenderLayer*>(this);
1025 for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
1026 if (curr->isComposited() && !curr->backing()->paintsIntoCompositedAncestor())
1027 return const_cast<RenderLayer*>(curr);
1034 #if ENABLE(CSS_FILTERS)
1035 RenderLayer* RenderLayer::enclosingFilterLayer(bool includeSelf) const
1037 const RenderLayer* curr = includeSelf ? this : parent();
1038 for (; curr; curr = curr->parent()) {
1039 if (curr->requiresFullLayerImageForFilters())
1040 return const_cast<RenderLayer*>(curr);
1046 RenderLayer* RenderLayer::enclosingFilterRepaintLayer() const
1048 for (const RenderLayer* curr = this; curr; curr = curr->parent()) {
1049 if ((curr != this && curr->requiresFullLayerImageForFilters()) || curr->isComposited() || curr->isRootLayer())
1050 return const_cast<RenderLayer*>(curr);
1055 void RenderLayer::setFilterBackendNeedsRepaintingInRect(const LayoutRect& rect, bool immediate)
1060 LayoutRect rectForRepaint = rect;
1062 #if ENABLE(CSS_FILTERS)
1063 if (renderer()->style()->hasFilterOutsets()) {
1068 renderer()->style()->getFilterOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
1069 rectForRepaint.move(-leftOutset, -topOutset);
1070 rectForRepaint.expand(leftOutset + rightOutset, topOutset + bottomOutset);
1074 RenderLayerFilterInfo* filterInfo = this->filterInfo();
1076 filterInfo->expandDirtySourceRect(rectForRepaint);
1078 #if ENABLE(CSS_SHADERS)
1079 ASSERT(filterInfo->renderer());
1080 if (filterInfo->renderer()->hasCustomShaderFilter()) {
1081 // If we have at least one custom shader, we need to update the whole bounding box of the layer, because the
1082 // shader can address any ouput pixel.
1083 // Note: This is only for output rect, so there's no need to expand the dirty source rect.
1084 rectForRepaint.unite(calculateLayerBounds(this, this));
1088 RenderLayer* parentLayer = enclosingFilterRepaintLayer();
1089 ASSERT(parentLayer);
1090 FloatQuad repaintQuad(rectForRepaint);
1091 LayoutRect parentLayerRect = renderer()->localToContainerQuad(repaintQuad, parentLayer->renderer()).enclosingBoundingBox();
1093 #if USE(ACCELERATED_COMPOSITING)
1094 if (parentLayer->isComposited()) {
1095 if (!parentLayer->backing()->paintsIntoWindow()) {
1096 parentLayer->setBackingNeedsRepaintInRect(parentLayerRect);
1099 // If the painting goes to window, redirect the painting to the parent RenderView.
1100 parentLayer = renderer()->view()->layer();
1101 parentLayerRect = renderer()->localToContainerQuad(repaintQuad, parentLayer->renderer()).enclosingBoundingBox();
1105 if (parentLayer->paintsWithFilters()) {
1106 parentLayer->setFilterBackendNeedsRepaintingInRect(parentLayerRect, immediate);
1110 if (parentLayer->isRootLayer()) {
1111 RenderView* view = toRenderView(parentLayer->renderer());
1112 view->repaintViewRectangle(parentLayerRect, immediate);
1116 ASSERT_NOT_REACHED();
1119 bool RenderLayer::hasAncestorWithFilterOutsets() const
1121 for (const RenderLayer* curr = this; curr; curr = curr->parent()) {
1122 RenderBoxModelObject* renderer = curr->renderer();
1123 if (renderer->style()->hasFilterOutsets())
1130 RenderLayer* RenderLayer::clippingRootForPainting() const
1132 #if USE(ACCELERATED_COMPOSITING)
1134 return const_cast<RenderLayer*>(this);
1137 const RenderLayer* current = this;
1139 if (current->isRootLayer())
1140 return const_cast<RenderLayer*>(current);
1142 current = compositingContainer(current);
1144 if (current->transform()
1145 #if USE(ACCELERATED_COMPOSITING)
1146 || (current->isComposited() && !current->backing()->paintsIntoCompositedAncestor())
1149 return const_cast<RenderLayer*>(current);
1152 ASSERT_NOT_REACHED();
1156 LayoutPoint RenderLayer::absoluteToContents(const LayoutPoint& absolutePoint) const
1158 // We don't use convertToLayerCoords because it doesn't know about transforms
1159 return roundedLayoutPoint(renderer()->absoluteToLocal(absolutePoint, false, true));
1162 bool RenderLayer::cannotBlitToWindow() const
1164 if (isTransparent() || hasReflection() || hasTransform())
1168 return parent()->cannotBlitToWindow();
1171 bool RenderLayer::isTransparent() const
1174 if (renderer()->node() && renderer()->node()->namespaceURI() == SVGNames::svgNamespaceURI)
1177 return renderer()->isTransparent() || renderer()->hasMask();
1180 RenderLayer* RenderLayer::transparentPaintingAncestor()
1185 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
1186 if (curr->isComposited())
1188 if (curr->isTransparent())
1194 static LayoutRect transparencyClipBox(const RenderLayer*, const RenderLayer* rootLayer, PaintBehavior);
1196 static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, const RenderLayer* layer, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
1198 // If we have a mask, then the clip is limited to the border box area (and there is
1199 // no need to examine child layers).
1200 if (!layer->renderer()->hasMask()) {
1201 // Note: we don't have to walk z-order lists since transparent elements always establish
1202 // a stacking context. This means we can just walk the layer tree directly.
1203 for (RenderLayer* curr = layer->firstChild(); curr; curr = curr->nextSibling()) {
1204 if (!layer->reflection() || layer->reflectionLayer() != curr)
1205 clipRect.unite(transparencyClipBox(curr, rootLayer, paintBehavior));
1209 // If we have a reflection, then we need to account for that when we push the clip. Reflect our entire
1210 // current transparencyClipBox to catch all child layers.
1211 // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this
1212 // size into the parent layer.
1213 if (layer->renderer()->hasReflection()) {
1215 layer->convertToLayerCoords(rootLayer, delta);
1216 clipRect.move(-delta.x(), -delta.y());
1217 clipRect.unite(layer->renderBox()->reflectedRect(clipRect));
1218 clipRect.moveBy(delta);
1222 static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
1224 // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
1225 // paintDirtyRect, and that should cut down on the amount we have to paint. Still it
1226 // would be better to respect clips.
1228 if (rootLayer != layer && layer->paintsWithTransform(paintBehavior)) {
1229 // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
1230 // the transformed layer and all of its children.
1232 layer->convertToLayerCoords(rootLayer, delta);
1234 TransformationMatrix transform;
1235 transform.translate(delta.x(), delta.y());
1236 transform = transform * *layer->transform();
1238 LayoutRect clipRect = layer->boundingBox(layer);
1239 expandClipRectForDescendantsAndReflection(clipRect, layer, layer, paintBehavior);
1240 return transform.mapRect(clipRect);
1243 LayoutRect clipRect = layer->boundingBox(rootLayer);
1244 expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, paintBehavior);
1248 LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior)
1250 return intersection(transparencyClipBox(this, rootLayer, paintBehavior), paintDirtyRect);
1253 void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior)
1255 if (context->paintingDisabled() || (paintsWithTransparency(paintBehavior) && m_usedTransparency))
1258 RenderLayer* ancestor = transparentPaintingAncestor();
1260 ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
1262 if (paintsWithTransparency(paintBehavior)) {
1263 m_usedTransparency = true;
1265 LayoutRect clipRect = paintingExtent(rootLayer, paintDirtyRect, paintBehavior);
1266 context->clip(clipRect);
1267 context->beginTransparencyLayer(renderer()->opacity());
1268 #ifdef REVEAL_TRANSPARENCY_LAYERS
1269 context->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f), ColorSpaceDeviceRGB);
1270 context->fillRect(clipRect);
1275 void* RenderLayer::operator new(size_t sz, RenderArena* renderArena)
1277 return renderArena->allocate(sz);
1280 void RenderLayer::operator delete(void* ptr, size_t sz)
1282 // Stash size where destroy can find it.
1283 *(size_t *)ptr = sz;
1286 void RenderLayer::destroy(RenderArena* renderArena)
1290 // Recover the size left there for us by operator delete and free the memory.
1291 renderArena->free(*(size_t *)this, this);
1294 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
1296 RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
1298 child->setPreviousSibling(prevSibling);
1299 prevSibling->setNextSibling(child);
1300 ASSERT(prevSibling != child);
1302 setFirstChild(child);
1305 beforeChild->setPreviousSibling(child);
1306 child->setNextSibling(beforeChild);
1307 ASSERT(beforeChild != child);
1309 setLastChild(child);
1311 child->setParent(this);
1313 if (child->isNormalFlowOnly())
1314 dirtyNormalFlowList();
1316 if (!child->isNormalFlowOnly() || child->firstChild()) {
1317 // Dirty the z-order list in which we are contained. The stackingContext() can be null in the
1318 // case where we're building up generated content layers. This is ok, since the lists will start
1319 // off dirty in that case anyway.
1320 child->dirtyStackingContextZOrderLists();
1323 child->updateDescendantDependentFlags();
1324 if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
1325 setAncestorChainHasVisibleDescendant();
1327 if (child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant())
1328 setAncestorChainHasSelfPaintingLayerDescendant();
1330 #if USE(ACCELERATED_COMPOSITING)
1331 compositor()->layerWasAdded(this, child);
1335 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
1337 #if USE(ACCELERATED_COMPOSITING)
1338 if (!renderer()->documentBeingDestroyed())
1339 compositor()->layerWillBeRemoved(this, oldChild);
1343 if (oldChild->previousSibling())
1344 oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
1345 if (oldChild->nextSibling())
1346 oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
1348 if (m_first == oldChild)
1349 m_first = oldChild->nextSibling();
1350 if (m_last == oldChild)
1351 m_last = oldChild->previousSibling();
1353 if (oldChild->isNormalFlowOnly())
1354 dirtyNormalFlowList();
1355 if (!oldChild->isNormalFlowOnly() || oldChild->firstChild()) {
1356 // Dirty the z-order list in which we are contained. When called via the
1357 // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
1358 // from the main layer tree, so we need to null-check the |stackingContext| value.
1359 oldChild->dirtyStackingContextZOrderLists();
1362 oldChild->setPreviousSibling(0);
1363 oldChild->setNextSibling(0);
1364 oldChild->setParent(0);
1366 oldChild->updateDescendantDependentFlags();
1367 if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
1368 dirtyAncestorChainVisibleDescendantStatus();
1370 if (oldChild->isSelfPaintingLayer() || oldChild->hasSelfPaintingLayerDescendant())
1371 dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
1376 void RenderLayer::removeOnlyThisLayer()
1381 // Mark that we are about to lose our layer. This makes render tree
1382 // walks ignore this layer while we're removing it.
1383 m_renderer->setHasLayer(false);
1385 #if USE(ACCELERATED_COMPOSITING)
1386 compositor()->layerWillBeRemoved(m_parent, this);
1389 // Dirty the clip rects.
1390 clearClipRectsIncludingDescendants();
1392 RenderLayer* nextSib = nextSibling();
1393 bool hasLayerOffset;
1394 const LayoutPoint offsetFromRootBeforeMove = computeOffsetFromRoot(hasLayerOffset);
1396 // Remove the child reflection layer before moving other child layers.
1397 // The reflection layer should not be moved to the parent.
1399 removeChild(reflectionLayer());
1401 // Now walk our kids and reattach them to our parent.
1402 RenderLayer* current = m_first;
1404 RenderLayer* next = current->nextSibling();
1405 removeChild(current);
1406 m_parent->addChild(current, nextSib);
1407 current->setRepaintStatus(NeedsFullRepaint);
1408 LayoutPoint offsetFromRoot = offsetFromRootBeforeMove;
1409 // updateLayerPositions depends on hasLayer() already being false for proper layout.
1410 ASSERT(!renderer()->hasLayer());
1411 current->updateLayerPositions(hasLayerOffset ? &offsetFromRoot : 0);
1415 // Remove us from the parent.
1416 m_parent->removeChild(this);
1417 m_renderer->destroyLayer();
1420 void RenderLayer::insertOnlyThisLayer()
1422 if (!m_parent && renderer()->parent()) {
1423 // We need to connect ourselves when our renderer() has a parent.
1424 // Find our enclosingLayer and add ourselves.
1425 RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
1426 ASSERT(parentLayer);
1427 RenderLayer* beforeChild = parentLayer->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0;
1428 parentLayer->addChild(this, beforeChild);
1431 // Remove all descendant layers from the hierarchy and add them to the new position.
1432 for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
1433 curr->moveLayers(m_parent, this);
1435 // Clear out all the clip rects.
1436 clearClipRectsIncludingDescendants();
1439 void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& roundedLocation) const
1441 LayoutPoint location = roundedLocation;
1442 convertToLayerCoords(ancestorLayer, location);
1443 roundedLocation = roundedIntPoint(location);
1446 void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntRect& roundedRect) const
1448 LayoutRect rect = roundedRect;
1449 convertToLayerCoords(ancestorLayer, rect);
1450 roundedRect = pixelSnappedIntRect(rect);
1453 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const
1455 if (ancestorLayer == this)
1458 EPosition position = renderer()->style()->position();
1460 // FIXME: Positioning of out-of-flow(fixed, absolute) elements collected in a RenderFlowThread
1461 // may need to be revisited in a future patch.
1462 // If the fixed renderer is inside a RenderFlowThread, we should not compute location using localToAbsolute,
1463 // since localToAbsolute maps the coordinates from named flow to regions coordinates and regions can be
1464 // positioned in a completely different place in the viewport (RenderView).
1465 if (position == FixedPosition && !renderer()->inRenderFlowThread() && (!ancestorLayer || ancestorLayer == renderer()->view()->layer())) {
1466 // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
1467 // localToAbsolute() on the RenderView.
1468 FloatPoint absPos = renderer()->localToAbsolute(FloatPoint(), true);
1469 location += flooredLayoutSize(absPos);
1473 // For the fixed positioned elements inside a render flow thread, we should also skip the code path below
1474 // Otherwise, for the case of ancestorLayer == rootLayer and fixed positioned element child of a transformed
1475 // element in render flow thread, we will hit the fixed positioned container before hitting the ancestor layer.
1476 if (position == FixedPosition && !renderer()->inRenderFlowThread()) {
1477 // For a fixed layers, we need to walk up to the root to see if there's a fixed position container
1478 // (e.g. a transformed layer). It's an error to call convertToLayerCoords() across a layer with a transform,
1479 // so we should always find the ancestor at or before we find the fixed position container.
1480 RenderLayer* fixedPositionContainerLayer = 0;
1481 bool foundAncestor = false;
1482 for (RenderLayer* currLayer = parent(); currLayer; currLayer = currLayer->parent()) {
1483 if (currLayer == ancestorLayer)
1484 foundAncestor = true;
1486 if (isFixedPositionedContainer(currLayer)) {
1487 fixedPositionContainerLayer = currLayer;
1488 ASSERT_UNUSED(foundAncestor, foundAncestor);
1493 ASSERT(fixedPositionContainerLayer); // We should have hit the RenderView's layer at least.
1495 if (fixedPositionContainerLayer != ancestorLayer) {
1496 LayoutPoint fixedContainerCoords;
1497 convertToLayerCoords(fixedPositionContainerLayer, fixedContainerCoords);
1499 LayoutPoint ancestorCoords;
1500 ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorCoords);
1502 location += (fixedContainerCoords - ancestorCoords);
1507 RenderLayer* parentLayer;
1508 if (position == AbsolutePosition || position == FixedPosition) {
1509 // Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way.
1510 parentLayer = parent();
1511 bool foundAncestorFirst = false;
1512 while (parentLayer) {
1513 // RenderFlowThread is a positioned container, child of RenderView, positioned at (0,0).
1514 // This implies that, for out-of-flow positioned elements inside a RenderFlowThread,
1515 // we are bailing out before reaching root layer.
1516 if (isPositionedContainer(parentLayer))
1519 if (parentLayer == ancestorLayer) {
1520 foundAncestorFirst = true;
1524 parentLayer = parentLayer->parent();
1527 // We should not reach RenderView layer past the RenderFlowThread layer for any
1528 // children of the RenderFlowThread.
1529 if (renderer()->inRenderFlowThread() && !renderer()->isRenderFlowThread())
1530 ASSERT(parentLayer != renderer()->view()->layer());
1532 if (foundAncestorFirst) {
1533 // Found ancestorLayer before the abs. positioned container, so compute offset of both relative
1534 // to enclosingPositionedAncestor and subtract.
1535 RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor();
1537 LayoutPoint thisCoords;
1538 convertToLayerCoords(positionedAncestor, thisCoords);
1540 LayoutPoint ancestorCoords;
1541 ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorCoords);
1543 location += (thisCoords - ancestorCoords);
1547 parentLayer = parent();
1552 parentLayer->convertToLayerCoords(ancestorLayer, location);
1554 location += toSize(m_topLeft);
1557 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1558 bool RenderLayer::hasAcceleratedTouchScrolling() const
1560 // FIXME: Previous condition.
1561 // return scrollsOverflow() && !(renderer()->style()->overflowX() == OHIDDEN && renderer()->style()->overflowY() == OHIDDEN);
1563 if (!scrollsOverflow())
1566 Settings* settings = renderer()->document()->settings();
1567 return renderer()->style()->useTouchOverflowScrolling() || settings->alwaysUseAcceleratedOverflowScroll();
1571 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect& rect) const
1574 convertToLayerCoords(ancestorLayer, delta);
1575 rect.move(-delta.x(), -delta.y());
1578 static inline int adjustedScrollDelta(int beginningDelta) {
1579 // This implemention matches Firefox's.
1580 // http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856.
1581 const int speedReducer = 12;
1583 int adjustedDelta = beginningDelta / speedReducer;
1584 if (adjustedDelta > 1)
1585 adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(adjustedDelta))) - 1;
1586 else if (adjustedDelta < -1)
1587 adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(-adjustedDelta))) + 1;
1589 return adjustedDelta;
1592 static inline IntSize adjustedScrollDelta(const IntSize& delta)
1594 return IntSize(adjustedScrollDelta(delta.width()), adjustedScrollDelta(delta.height()));
1597 void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
1599 Frame* frame = renderer()->frame();
1603 IntPoint currentMousePosition = frame->eventHandler()->currentMousePosition();
1605 // 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
1606 static IntPoint previousMousePosition;
1607 if (currentMousePosition.x() < 0 || currentMousePosition.y() < 0)
1608 currentMousePosition = previousMousePosition;
1610 previousMousePosition = currentMousePosition;
1612 IntSize delta = currentMousePosition - sourcePoint;
1614 if (abs(delta.width()) <= ScrollView::noPanScrollRadius) // at the center we let the space for the icon
1616 if (abs(delta.height()) <= ScrollView::noPanScrollRadius)
1619 scrollByRecursively(adjustedScrollDelta(delta), ScrollOffsetClamped);
1622 void RenderLayer::scrollByRecursively(const IntSize& delta, ScrollOffsetClamping clamp)
1627 bool restrictedByLineClamp = false;
1628 if (renderer()->parent())
1629 restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone();
1631 if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
1632 IntSize newScrollOffset = scrollOffset() + delta;
1633 scrollToOffset(newScrollOffset, clamp);
1635 // If this layer can't do the scroll we ask the next layer up that can scroll to try
1636 IntSize remainingScrollOffset = newScrollOffset - scrollOffset();
1637 if (!remainingScrollOffset.isZero() && renderer()->parent()) {
1638 if (RenderLayer* scrollableLayer = enclosingScrollableLayer())
1639 scrollableLayer->scrollByRecursively(remainingScrollOffset);
1641 Frame* frame = renderer()->frame();
1643 frame->eventHandler()->updateAutoscrollRenderer();
1645 } else if (renderer()->view()->frameView()) {
1646 // If we are here, we were called on a renderer that can be programmatically scrolled, but doesn't
1647 // have an overflow clip. Which means that it is a document node that can be scrolled.
1648 renderer()->view()->frameView()->scrollBy(delta);
1649 // FIXME: If we didn't scroll the whole way, do we want to try looking at the frames ownerElement?
1650 // https://bugs.webkit.org/show_bug.cgi?id=28237
1654 IntSize RenderLayer::clampScrollOffset(const IntSize& scrollOffset) const
1656 RenderBox* box = renderBox();
1659 int maxX = scrollWidth() - box->pixelSnappedClientWidth();
1660 int maxY = scrollHeight() - box->pixelSnappedClientHeight();
1662 int x = min(max(scrollOffset.width(), 0), maxX);
1663 int y = min(max(scrollOffset.height(), 0), maxY);
1664 return IntSize(x, y);
1667 void RenderLayer::scrollToOffset(const IntSize& scrollOffset, ScrollOffsetClamping clamp)
1669 IntSize newScrollOffset = clamp == ScrollOffsetClamped ? clampScrollOffset(scrollOffset) : scrollOffset;
1670 if (newScrollOffset != this->scrollOffset()) {
1671 scrollToOffsetWithoutAnimation(toPoint(newScrollOffset));
1672 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1673 if(hasAcceleratedTouchScrolling())
1674 setBackingNeedsRepaint();
1679 void RenderLayer::scrollTo(int x, int y)
1681 RenderBox* box = renderBox();
1685 if (box->style()->overflowX() != OMARQUEE) {
1686 // Ensure that the dimensions will be computed if they need to be (for overflow:hidden blocks).
1687 if (m_scrollDimensionsDirty)
1688 computeScrollDimensions();
1691 // FIXME: Eventually, we will want to perform a blit. For now never
1692 // blit, since the check for blitting is going to be very
1693 // complicated (since it will involve testing whether our layer
1694 // is either occluded by another layer or clipped by an enclosing
1695 // layer or contains fixed backgrounds, etc.).
1696 IntSize newScrollOffset = IntSize(x - scrollOrigin().x(), y - scrollOrigin().y());
1697 if (m_scrollOffset == newScrollOffset)
1699 m_scrollOffset = newScrollOffset;
1701 // Update the positions of our child layers (if needed as only fixed layers should be impacted by a scroll).
1702 // We don't update compositing layers, because we need to do a deep update from the compositing ancestor.
1703 updateLayerPositionsAfterScroll();
1705 RenderView* view = renderer()->view();
1707 // We should have a RenderView if we're trying to scroll.
1710 #if ENABLE(DASHBOARD_SUPPORT)
1711 // Update dashboard regions, scrolling may change the clip of a
1712 // particular region.
1713 view->frameView()->updateDashboardRegions();
1716 view->updateWidgetPositions();
1719 updateCompositingLayersAfterScroll();
1721 RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
1722 Frame* frame = renderer()->frame();
1724 // The caret rect needs to be invalidated after scrolling
1725 frame->selection()->setCaretRectNeedsUpdate();
1727 FloatQuad quadForFakeMouseMoveEvent = FloatQuad(m_repaintRect);
1728 if (repaintContainer)
1729 quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent);
1730 frame->eventHandler()->dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent);
1733 // Just schedule a full repaint of our object.
1734 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1735 if (view && !hasAcceleratedTouchScrolling())
1739 renderer()->repaintUsingContainer(repaintContainer, m_repaintRect);
1741 // Schedule the scroll DOM event.
1742 if (renderer()->node())
1743 renderer()->node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), DocumentEventQueue::ScrollEventElementTarget);
1746 void RenderLayer::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
1748 RenderLayer* parentLayer = 0;
1749 LayoutRect newRect = rect;
1751 // We may end up propagating a scroll event. It is important that we suspend events until
1752 // the end of the function since they could delete the layer or the layer's renderer().
1753 FrameView* frameView = renderer()->document()->view();
1755 frameView->pauseScheduledEvents();
1757 bool restrictedByLineClamp = false;
1758 if (renderer()->parent()) {
1759 parentLayer = renderer()->parent()->enclosingLayer();
1760 restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone();
1763 if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
1764 // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property.
1765 // This will prevent us from revealing text hidden by the slider in Safari RSS.
1766 RenderBox* box = renderBox();
1768 FloatPoint absPos = box->localToAbsolute();
1769 absPos.move(box->borderLeft(), box->borderTop());
1771 LayoutRect layerBounds = LayoutRect(absPos.x() + scrollXOffset(), absPos.y() + scrollYOffset(), box->clientWidth(), box->clientHeight());
1772 LayoutRect exposeRect = LayoutRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());
1773 LayoutRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);
1775 int roundedAdjustedX = roundToInt(r.x() - absPos.x());
1776 int roundedAdjustedY = roundToInt(r.y() - absPos.y());
1777 IntSize clampedScrollOffset = clampScrollOffset(IntSize(roundedAdjustedX, roundedAdjustedY));
1778 if (clampedScrollOffset != scrollOffset()) {
1779 IntSize oldScrollOffset = scrollOffset();
1780 scrollToOffset(clampedScrollOffset);
1781 IntSize scrollOffsetDifference = scrollOffset() - oldScrollOffset;
1782 newRect.move(-scrollOffsetDifference);
1784 } else if (!parentLayer && renderer()->isBox() && renderBox()->canBeProgramaticallyScrolled()) {
1786 Element* ownerElement = 0;
1787 if (renderer()->document())
1788 ownerElement = renderer()->document()->ownerElement();
1790 if (ownerElement && ownerElement->renderer()) {
1791 HTMLFrameElement* frameElement = 0;
1793 if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))
1794 frameElement = static_cast<HTMLFrameElement*>(ownerElement);
1796 if (frameElement && frameElement->scrollingMode() != ScrollbarAlwaysOff) {
1797 LayoutRect viewRect = frameView->visibleContentRect();
1798 LayoutRect exposeRect = getRectToExpose(viewRect, rect, alignX, alignY);
1800 int xOffset = roundToInt(exposeRect.x());
1801 int yOffset = roundToInt(exposeRect.y());
1802 // Adjust offsets if they're outside of the allowable range.
1803 xOffset = max(0, min(frameView->contentsWidth(), xOffset));
1804 yOffset = max(0, min(frameView->contentsHeight(), yOffset));
1806 frameView->setScrollPosition(IntPoint(xOffset, yOffset));
1807 if (frameView->safeToPropagateScrollToParent()) {
1808 parentLayer = ownerElement->renderer()->enclosingLayer();
1809 newRect.setX(rect.x() - frameView->scrollX() + frameView->x());
1810 newRect.setY(rect.y() - frameView->scrollY() + frameView->y());
1815 LayoutRect viewRect = frameView->visibleContentRect();
1816 LayoutRect r = getRectToExpose(viewRect, rect, alignX, alignY);
1818 frameView->setScrollPosition(roundedIntPoint(r.location()));
1820 // This is the outermost view of a web page, so after scrolling this view we
1821 // scroll its container by calling Page::scrollRectIntoView.
1822 // This only has an effect on the Mac platform in applications
1823 // that put web views into scrolling containers, such as Mac OS X Mail.
1824 // The canAutoscroll function in EventHandler also knows about this.
1825 if (Frame* frame = frameView->frame()) {
1826 if (Page* page = frame->page())
1827 page->chrome()->scrollRectIntoView(pixelSnappedIntRect(rect));
1834 parentLayer->scrollRectToVisible(newRect, alignX, alignY);
1837 frameView->resumeScheduledEvents();
1840 #if USE(ACCELERATED_COMPOSITING)
1841 static FrameView* frameViewFromLayer(const RenderLayer* layer)
1843 Frame* frame = layer->renderer()->frame();
1847 return frame->view();
1851 void RenderLayer::updateCompositingLayersAfterScroll()
1853 #if USE(ACCELERATED_COMPOSITING)
1854 if (compositor()->inCompositingMode()) {
1855 // If we're in the middle of layout, we'll just update compositiong once layout has finished.
1856 if (FrameView* frameView = frameViewFromLayer(this)) {
1857 if (frameView->isInLayout())
1861 // Our stacking context is guaranteed to contain all of our descendants that may need
1862 // repositioning, so update compositing layers from there.
1863 if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) {
1864 if (compositor()->compositingConsultsOverlap())
1865 compositor()->updateCompositingLayers(CompositingUpdateOnScroll, compositingAncestor);
1867 bool isUpdateRoot = true;
1868 compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants, isUpdateRoot);
1875 LayoutRect RenderLayer::getRectToExpose(const LayoutRect &visibleRect, const LayoutRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
1877 // Determine the appropriate X behavior.
1878 ScrollBehavior scrollX;
1879 LayoutRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height());
1880 LayoutUnit intersectWidth = intersection(visibleRect, exposeRectX).width();
1881 if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL)
1882 // If the rectangle is fully visible, use the specified visible behavior.
1883 // If the rectangle is partially visible, but over a certain threshold,
1884 // then treat it as fully visible to avoid unnecessary horizontal scrolling
1885 scrollX = ScrollAlignment::getVisibleBehavior(alignX);
1886 else if (intersectWidth == visibleRect.width()) {
1887 // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
1888 scrollX = ScrollAlignment::getVisibleBehavior(alignX);
1889 if (scrollX == alignCenter)
1891 } else if (intersectWidth > 0)
1892 // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior
1893 scrollX = ScrollAlignment::getPartialBehavior(alignX);
1895 scrollX = ScrollAlignment::getHiddenBehavior(alignX);
1896 // If we're trying to align to the closest edge, and the exposeRect is further right
1897 // than the visibleRect, and not bigger than the visible area, then align with the right.
1898 if (scrollX == alignToClosestEdge && exposeRect.maxX() > visibleRect.maxX() && exposeRect.width() < visibleRect.width())
1899 scrollX = alignRight;
1901 // Given the X behavior, compute the X coordinate.
1903 if (scrollX == noScroll)
1904 x = visibleRect.x();
1905 else if (scrollX == alignRight)
1906 x = exposeRect.maxX() - visibleRect.width();
1907 else if (scrollX == alignCenter)
1908 x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2;
1912 // Determine the appropriate Y behavior.
1913 ScrollBehavior scrollY;
1914 LayoutRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height());
1915 LayoutUnit intersectHeight = intersection(visibleRect, exposeRectY).height();
1916 if (intersectHeight == exposeRect.height())
1917 // If the rectangle is fully visible, use the specified visible behavior.
1918 scrollY = ScrollAlignment::getVisibleBehavior(alignY);
1919 else if (intersectHeight == visibleRect.height()) {
1920 // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
1921 scrollY = ScrollAlignment::getVisibleBehavior(alignY);
1922 if (scrollY == alignCenter)
1924 } else if (intersectHeight > 0)
1925 // If the rectangle is partially visible, use the specified partial behavior
1926 scrollY = ScrollAlignment::getPartialBehavior(alignY);
1928 scrollY = ScrollAlignment::getHiddenBehavior(alignY);
1929 // If we're trying to align to the closest edge, and the exposeRect is further down
1930 // than the visibleRect, and not bigger than the visible area, then align with the bottom.
1931 if (scrollY == alignToClosestEdge && exposeRect.maxY() > visibleRect.maxY() && exposeRect.height() < visibleRect.height())
1932 scrollY = alignBottom;
1934 // Given the Y behavior, compute the Y coordinate.
1936 if (scrollY == noScroll)
1937 y = visibleRect.y();
1938 else if (scrollY == alignBottom)
1939 y = exposeRect.maxY() - visibleRect.height();
1940 else if (scrollY == alignCenter)
1941 y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2;
1945 return LayoutRect(LayoutPoint(x, y), visibleRect.size());
1948 void RenderLayer::autoscroll()
1950 Frame* frame = renderer()->frame();
1954 FrameView* frameView = frame->view();
1958 #if ENABLE(DRAG_SUPPORT)
1959 frame->eventHandler()->updateSelectionForMouseDrag();
1962 IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition());
1963 scrollRectToVisible(LayoutRect(currentDocumentPosition, LayoutSize(1, 1)), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
1966 void RenderLayer::resize(const PlatformMouseEvent& evt, const LayoutSize& oldOffset)
1968 // FIXME: This should be possible on generated content but is not right now.
1969 if (!inResizeMode() || !renderer()->hasOverflowClip() || !renderer()->node())
1972 ASSERT(renderer()->node()->isElementNode());
1973 Element* element = static_cast<Element*>(renderer()->node());
1974 RenderBox* renderer = toRenderBox(element->renderer());
1976 EResize resize = renderer->style()->resize();
1977 if (resize == RESIZE_NONE)
1980 Document* document = element->document();
1981 if (!document->frame()->eventHandler()->mousePressed())
1984 float zoomFactor = renderer->style()->effectiveZoom();
1986 LayoutSize newOffset = offsetFromResizeCorner(document->view()->windowToContents(evt.position()));
1987 newOffset.setWidth(newOffset.width() / zoomFactor);
1988 newOffset.setHeight(newOffset.height() / zoomFactor);
1990 LayoutSize currentSize = LayoutSize(renderer->width() / zoomFactor, renderer->height() / zoomFactor);
1991 LayoutSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize);
1992 element->setMinimumSizeForResizing(minimumSize);
1994 LayoutSize adjustedOldOffset = LayoutSize(oldOffset.width() / zoomFactor, oldOffset.height() / zoomFactor);
1995 if (renderer->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
1996 newOffset.setWidth(-newOffset.width());
1997 adjustedOldOffset.setWidth(-adjustedOldOffset.width());
2000 LayoutSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize;
2002 ASSERT(element->isStyledElement());
2003 StyledElement* styledElement = static_cast<StyledElement*>(element);
2004 bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX;
2006 if (resize != RESIZE_VERTICAL && difference.width()) {
2007 if (element->isFormControlElement()) {
2008 // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
2009 styledElement->setInlineStyleProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false);
2010 styledElement->setInlineStyleProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false);
2012 LayoutUnit baseWidth = renderer->width() - (isBoxSizingBorder ? ZERO_LAYOUT_UNIT : renderer->borderAndPaddingWidth());
2013 baseWidth = baseWidth / zoomFactor;
2014 styledElement->setInlineStyleProperty(CSSPropertyWidth, String::number(roundToInt(baseWidth + difference.width())) + "px", false);
2017 if (resize != RESIZE_HORIZONTAL && difference.height()) {
2018 if (element->isFormControlElement()) {
2019 // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
2020 styledElement->setInlineStyleProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false);
2021 styledElement->setInlineStyleProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false);
2023 LayoutUnit baseHeight = renderer->height() - (isBoxSizingBorder ? ZERO_LAYOUT_UNIT : renderer->borderAndPaddingHeight());
2024 baseHeight = baseHeight / zoomFactor;
2025 styledElement->setInlineStyleProperty(CSSPropertyHeight, String::number(roundToInt(baseHeight + difference.height())) + "px", false);
2028 document->updateLayout();
2030 // FIXME (Radar 4118564): We should also autoscroll the window as necessary to keep the point under the cursor in view.
2033 int RenderLayer::scrollSize(ScrollbarOrientation orientation) const
2035 Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_hBar : m_vBar).get();
2036 return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0;
2039 void RenderLayer::setScrollOffset(const IntPoint& offset)
2041 scrollTo(offset.x(), offset.y());
2044 int RenderLayer::scrollPosition(Scrollbar* scrollbar) const
2046 if (scrollbar->orientation() == HorizontalScrollbar)
2047 return scrollXOffset();
2048 if (scrollbar->orientation() == VerticalScrollbar)
2049 return scrollYOffset();
2053 IntPoint RenderLayer::scrollPosition() const
2055 return scrollOrigin() + m_scrollOffset;
2058 IntPoint RenderLayer::minimumScrollPosition() const
2060 return scrollOrigin();
2063 IntPoint RenderLayer::maximumScrollPosition() const
2065 // FIXME: m_scrollSize may not be up-to-date if m_scrollDimensionsDirty is true.
2066 return scrollOrigin() + roundedIntSize(m_scrollSize) - visibleContentRect(true).size();
2069 IntRect RenderLayer::visibleContentRect(bool includeScrollbars) const
2071 int verticalScrollbarWidth = 0;
2072 int horizontalScrollbarHeight = 0;
2073 if (includeScrollbars) {
2074 verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->isOverlayScrollbar()) ? verticalScrollbar()->width() : 0;
2075 horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar()) ? horizontalScrollbar()->height() : 0;
2078 return IntRect(IntPoint(scrollXOffset(), scrollYOffset()),
2079 IntSize(max(0, m_layerSize.width() - verticalScrollbarWidth),
2080 max(0, m_layerSize.height() - horizontalScrollbarHeight)));
2083 IntSize RenderLayer::overhangAmount() const
2088 bool RenderLayer::isActive() const
2090 Page* page = renderer()->frame()->page();
2091 return page && page->focusController()->isActive();
2094 static int cornerStart(const RenderLayer* layer, int minX, int maxX, int thickness)
2096 if (layer->renderer()->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
2097 return minX + layer->renderer()->style()->borderLeftWidth();
2098 return maxX - thickness - layer->renderer()->style()->borderRightWidth();
2101 static IntRect cornerRect(const RenderLayer* layer, const IntRect& bounds)
2103 int horizontalThickness;
2104 int verticalThickness;
2105 if (!layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
2106 // FIXME: This isn't right. We need to know the thickness of custom scrollbars
2107 // even when they don't exist in order to set the resizer square size properly.
2108 horizontalThickness = ScrollbarTheme::theme()->scrollbarThickness();
2109 verticalThickness = horizontalThickness;
2110 } else if (layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
2111 horizontalThickness = layer->verticalScrollbar()->width();
2112 verticalThickness = horizontalThickness;
2113 } else if (layer->horizontalScrollbar() && !layer->verticalScrollbar()) {
2114 verticalThickness = layer->horizontalScrollbar()->height();
2115 horizontalThickness = verticalThickness;
2117 horizontalThickness = layer->verticalScrollbar()->width();
2118 verticalThickness = layer->horizontalScrollbar()->height();
2120 return IntRect(cornerStart(layer, bounds.x(), bounds.maxX(), horizontalThickness),
2121 bounds.maxY() - verticalThickness - layer->renderer()->style()->borderBottomWidth(),
2122 horizontalThickness, verticalThickness);
2125 IntRect RenderLayer::scrollCornerRect() const
2127 // We have a scrollbar corner when a scrollbar is visible and not filling the entire length of the box.
2128 // This happens when:
2129 // (a) A resizer is present and at least one scrollbar is present
2130 // (b) Both scrollbars are present.
2131 bool hasHorizontalBar = horizontalScrollbar();
2132 bool hasVerticalBar = verticalScrollbar();
2133 bool hasResizer = renderer()->style()->resize() != RESIZE_NONE;
2134 if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar)))
2135 return cornerRect(this, renderBox()->pixelSnappedBorderBoxRect());
2139 static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds)
2141 ASSERT(layer->renderer()->isBox());
2142 if (layer->renderer()->style()->resize() == RESIZE_NONE)
2144 return cornerRect(layer, bounds);
2147 IntRect RenderLayer::scrollCornerAndResizerRect() const
2149 RenderBox* box = renderBox();
2152 IntRect scrollCornerAndResizer = scrollCornerRect();
2153 if (scrollCornerAndResizer.isEmpty())
2154 scrollCornerAndResizer = resizerCornerRect(this, box->pixelSnappedBorderBoxRect());
2155 return scrollCornerAndResizer;
2158 bool RenderLayer::isScrollCornerVisible() const
2160 ASSERT(renderer()->isBox());
2161 return !scrollCornerRect().isEmpty();
2164 IntRect RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
2166 RenderView* view = renderer()->view();
2168 return scrollbarRect;
2170 IntRect rect = scrollbarRect;
2171 rect.move(scrollbarOffset(scrollbar));
2173 return view->frameView()->convertFromRenderer(renderer(), rect);
2176 IntRect RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
2178 RenderView* view = renderer()->view();
2182 IntRect rect = view->frameView()->convertToRenderer(renderer(), parentRect);
2183 rect.move(-scrollbarOffset(scrollbar));
2187 IntPoint RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
2189 RenderView* view = renderer()->view();
2191 return scrollbarPoint;
2193 IntPoint point = scrollbarPoint;
2194 point.move(scrollbarOffset(scrollbar));
2195 return view->frameView()->convertFromRenderer(renderer(), point);
2198 IntPoint RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
2200 RenderView* view = renderer()->view();
2204 IntPoint point = view->frameView()->convertToRenderer(renderer(), parentPoint);
2206 point.move(-scrollbarOffset(scrollbar));
2210 IntSize RenderLayer::contentsSize() const
2212 return IntSize(scrollWidth(), scrollHeight());
2215 int RenderLayer::visibleHeight() const
2217 return m_layerSize.height();
2220 int RenderLayer::visibleWidth() const
2222 return m_layerSize.width();
2225 bool RenderLayer::shouldSuspendScrollAnimations() const
2227 RenderView* view = renderer()->view();
2230 return view->frameView()->shouldSuspendScrollAnimations();
2233 bool RenderLayer::isOnActivePage() const
2235 return !m_renderer->document()->inPageCache();
2238 IntPoint RenderLayer::currentMousePosition() const
2240 return renderer()->frame() ? renderer()->frame()->eventHandler()->currentMousePosition() : IntPoint();
2243 LayoutUnit RenderLayer::verticalScrollbarStart(int minX, int maxX) const
2245 const RenderBox* box = renderBox();
2246 if (renderer()->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
2247 return minX + box->borderLeft();
2248 return maxX - box->borderRight() - m_vBar->width();
2251 LayoutUnit RenderLayer::horizontalScrollbarStart(int minX) const
2253 const RenderBox* box = renderBox();
2254 int x = minX + box->borderLeft();
2255 if (renderer()->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
2256 x += m_vBar ? m_vBar->width() : resizerCornerRect(this, box->pixelSnappedBorderBoxRect()).width();
2260 IntSize RenderLayer::scrollbarOffset(const Scrollbar* scrollbar) const
2262 RenderBox* box = renderBox();
2264 if (scrollbar == m_vBar.get())
2265 return IntSize(verticalScrollbarStart(0, box->width()), box->borderTop());
2267 if (scrollbar == m_hBar.get())
2268 return IntSize(horizontalScrollbarStart(0), box->height() - box->borderBottom() - scrollbar->height());
2270 ASSERT_NOT_REACHED();
2274 void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
2276 #if USE(ACCELERATED_COMPOSITING)
2277 if (scrollbar == m_vBar.get()) {
2278 if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
2279 layer->setNeedsDisplayInRect(rect);
2283 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
2284 layer->setNeedsDisplayInRect(rect);
2289 IntRect scrollRect = rect;
2290 RenderBox* box = renderBox();
2292 if (scrollbar == m_vBar.get())
2293 scrollRect.move(verticalScrollbarStart(0, box->width()), box->borderTop());
2295 scrollRect.move(horizontalScrollbarStart(0), box->height() - box->borderBottom() - scrollbar->height());
2296 renderer()->repaintRectangle(scrollRect);
2299 void RenderLayer::invalidateScrollCornerRect(const IntRect& rect)
2301 #if USE(ACCELERATED_COMPOSITING)
2302 if (GraphicsLayer* layer = layerForScrollCorner()) {
2303 layer->setNeedsDisplayInRect(rect);
2308 m_scrollCorner->repaintRectangle(rect);
2310 m_resizer->repaintRectangle(rect);
2313 PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation)
2315 RefPtr<Scrollbar> widget;
2316 RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
2317 bool hasCustomScrollbarStyle = actualRenderer->isBox() && actualRenderer->style()->hasPseudoStyle(SCROLLBAR);
2318 if (hasCustomScrollbarStyle)
2319 widget = RenderScrollbar::createCustomScrollbar(this, orientation, actualRenderer->node());
2321 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_SCROLLBAR)
2322 widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar, false);
2324 widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
2326 if (orientation == HorizontalScrollbar)
2327 didAddHorizontalScrollbar(widget.get());
2329 didAddVerticalScrollbar(widget.get());
2331 renderer()->document()->view()->addChild(widget.get());
2332 return widget.release();
2335 void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation)
2337 RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
2341 if (!scrollbar->isCustomScrollbar()) {
2342 if (orientation == HorizontalScrollbar)
2343 willRemoveHorizontalScrollbar(scrollbar.get());
2345 willRemoveVerticalScrollbar(scrollbar.get());
2348 scrollbar->removeFromParent();
2349 scrollbar->disconnectFromScrollableArea();
2353 bool RenderLayer::scrollsOverflow() const
2355 if (!renderer()->isBox())
2358 return toRenderBox(renderer())->scrollsOverflow();
2361 bool RenderLayer::allowsScrolling() const
2363 return (m_hBar && m_hBar->enabled()) || (m_vBar && m_vBar->enabled());
2366 void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
2368 if (hasScrollbar == hasHorizontalScrollbar())
2372 m_hBar = createScrollbar(HorizontalScrollbar);
2374 destroyScrollbar(HorizontalScrollbar);
2376 // Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style.
2378 m_hBar->styleChanged();
2380 m_vBar->styleChanged();
2382 #if ENABLE(DASHBOARD_SUPPORT)
2383 // Force an update since we know the scrollbars have changed things.
2384 if (renderer()->document()->hasDashboardRegions())
2385 renderer()->document()->setDashboardRegionsDirty(true);
2389 void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
2391 if (hasScrollbar == hasVerticalScrollbar())
2395 m_vBar = createScrollbar(VerticalScrollbar);
2397 destroyScrollbar(VerticalScrollbar);
2399 // Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style.
2401 m_hBar->styleChanged();
2403 m_vBar->styleChanged();
2405 #if ENABLE(DASHBOARD_SUPPORT)
2406 // Force an update since we know the scrollbars have changed things.
2407 if (renderer()->document()->hasDashboardRegions())
2408 renderer()->document()->setDashboardRegionsDirty(true);
2412 ScrollableArea* RenderLayer::enclosingScrollableArea() const
2414 if (RenderLayer* scrollableLayer = enclosingScrollableLayer())
2415 return scrollableLayer;
2417 // FIXME: We should return the frame view here (or possibly an ancestor frame view,
2418 // if the frame view isn't scrollable.
2422 int RenderLayer::verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy) const
2424 if (!m_vBar || (m_vBar->isOverlayScrollbar() && relevancy == IgnoreOverlayScrollbarSize))
2426 return m_vBar->width();
2429 int RenderLayer::horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy) const
2431 if (!m_hBar || (m_hBar->isOverlayScrollbar() && relevancy == IgnoreOverlayScrollbarSize))
2433 return m_hBar->height();
2436 IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const
2438 // Currently the resize corner is either the bottom right corner or the bottom left corner.
2439 // FIXME: This assumes the location is 0, 0. Is this guaranteed to always be the case?
2440 IntSize elementSize = size();
2441 if (renderer()->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
2442 elementSize.setWidth(0);
2443 IntPoint resizerPoint = toPoint(elementSize);
2444 IntPoint localPoint = roundedIntPoint(absoluteToContents(absolutePoint));
2445 return localPoint - resizerPoint;
2448 bool RenderLayer::hasOverflowControls() const
2450 return m_hBar || m_vBar || m_scrollCorner || renderer()->style()->resize() != RESIZE_NONE;
2453 void RenderLayer::positionOverflowControls(const IntSize& offsetFromLayer)
2455 if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
2458 RenderBox* box = renderBox();
2462 const IntRect borderBox = box->pixelSnappedBorderBoxRect();
2463 const IntRect& scrollCorner = scrollCornerRect();
2464 IntRect absBounds(borderBox.location() + offsetFromLayer, borderBox.size());
2466 m_vBar->setFrameRect(IntRect(verticalScrollbarStart(absBounds.x(), absBounds.maxX()),
2467 absBounds.y() + box->borderTop(),
2469 absBounds.height() - (box->borderTop() + box->borderBottom()) - scrollCorner.height()));
2472 m_hBar->setFrameRect(IntRect(horizontalScrollbarStart(absBounds.x()),
2473 absBounds.maxY() - box->borderBottom() - m_hBar->height(),
2474 absBounds.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(),
2477 #if USE(ACCELERATED_COMPOSITING)
2478 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
2480 layer->setPosition(m_hBar->frameRect().location() - offsetFromLayer);
2481 layer->setSize(m_hBar->frameRect().size());
2483 layer->setDrawsContent(m_hBar);
2485 if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
2487 layer->setPosition(m_vBar->frameRect().location() - offsetFromLayer);
2488 layer->setSize(m_vBar->frameRect().size());
2490 layer->setDrawsContent(m_vBar);
2493 if (GraphicsLayer* layer = layerForScrollCorner()) {
2494 const LayoutRect& scrollCornerAndResizer = scrollCornerAndResizerRect();
2495 layer->setPosition(scrollCornerAndResizer.location());
2496 layer->setSize(scrollCornerAndResizer.size());
2497 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
2502 m_scrollCorner->setFrameRect(scrollCorner);
2504 m_resizer->setFrameRect(resizerCornerRect(this, borderBox));
2507 int RenderLayer::scrollWidth() const
2509 ASSERT(renderBox());
2510 if (m_scrollDimensionsDirty)
2511 const_cast<RenderLayer*>(this)->computeScrollDimensions();
2512 return snapSizeToPixel(m_scrollSize.width(), renderBox()->clientLeft() + renderBox()->x());
2515 int RenderLayer::scrollHeight() const
2517 ASSERT(renderBox());
2518 if (m_scrollDimensionsDirty)
2519 const_cast<RenderLayer*>(this)->computeScrollDimensions();
2520 return snapSizeToPixel(m_scrollSize.height(), renderBox()->clientTop() + renderBox()->y());
2523 LayoutUnit RenderLayer::overflowTop() const
2525 RenderBox* box = renderBox();
2526 LayoutRect overflowRect(box->layoutOverflowRect());
2527 box->flipForWritingMode(overflowRect);
2528 return overflowRect.y();
2531 LayoutUnit RenderLayer::overflowBottom() const
2533 RenderBox* box = renderBox();
2534 LayoutRect overflowRect(box->layoutOverflowRect());
2535 box->flipForWritingMode(overflowRect);
2536 return overflowRect.maxY();
2539 LayoutUnit RenderLayer::overflowLeft() const
2541 RenderBox* box = renderBox();
2542 LayoutRect overflowRect(box->layoutOverflowRect());
2543 box->flipForWritingMode(overflowRect);
2544 return overflowRect.x();
2547 LayoutUnit RenderLayer::overflowRight() const
2549 RenderBox* box = renderBox();
2550 LayoutRect overflowRect(box->layoutOverflowRect());
2551 box->flipForWritingMode(overflowRect);
2552 return overflowRect.maxX();
2555 void RenderLayer::computeScrollDimensions()
2557 RenderBox* box = renderBox();
2560 m_scrollDimensionsDirty = false;
2562 m_scrollSize.setWidth(overflowRight() - overflowLeft());
2563 m_scrollSize.setHeight(overflowBottom() - overflowTop());
2565 int scrollableLeftOverflow = overflowLeft() - box->borderLeft();
2566 int scrollableTopOverflow = overflowTop() - box->borderTop();
2567 setScrollOrigin(IntPoint(-scrollableLeftOverflow, -scrollableTopOverflow));
2570 bool RenderLayer::hasHorizontalOverflow() const
2572 ASSERT(!m_scrollDimensionsDirty);
2574 return scrollWidth() > renderBox()->pixelSnappedClientWidth();
2577 bool RenderLayer::hasVerticalOverflow() const
2579 ASSERT(!m_scrollDimensionsDirty);
2581 return scrollHeight() > renderBox()->pixelSnappedClientHeight();
2584 void RenderLayer::updateScrollbarsAfterLayout()
2586 RenderBox* box = renderBox();
2589 bool hasHorizontalOverflow = this->hasHorizontalOverflow();
2590 bool hasVerticalOverflow = this->hasVerticalOverflow();
2592 // overflow:scroll should just enable/disable.
2593 if (m_hBar && renderer()->style()->overflowX() == OSCROLL)
2594 m_hBar->setEnabled(hasHorizontalOverflow);
2595 if (m_vBar && renderer()->style()->overflowY() == OSCROLL)
2596 m_vBar->setEnabled(hasVerticalOverflow);
2598 // overflow:auto may need to lay out again if scrollbars got added/removed.
2599 bool autoHorizontalScrollBarChanged = box->hasAutoHorizontalScrollbar() && (hasHorizontalScrollbar() != hasHorizontalOverflow);
2600 bool autoVerticalScrollBarChanged = box->hasAutoVerticalScrollbar() && (hasVerticalScrollbar() != hasVerticalOverflow);
2602 if (autoHorizontalScrollBarChanged || autoVerticalScrollBarChanged) {
2603 if (box->hasAutoHorizontalScrollbar())
2604 setHasHorizontalScrollbar(hasHorizontalOverflow);
2605 if (box->hasAutoVerticalScrollbar())
2606 setHasVerticalScrollbar(hasVerticalOverflow);
2608 updateSelfPaintingLayer();
2610 #if ENABLE(DASHBOARD_SUPPORT)
2611 // Force an update since we know the scrollbars have changed things.
2612 if (renderer()->document()->hasDashboardRegions())
2613 renderer()->document()->setDashboardRegionsDirty(true);
2616 renderer()->repaint();
2618 if (renderer()->style()->overflowX() == OAUTO || renderer()->style()->overflowY() == OAUTO) {
2619 if (!m_inOverflowRelayout) {
2620 // Our proprietary overflow: overlay value doesn't trigger a layout.
2621 m_inOverflowRelayout = true;
2622 renderer()->setNeedsLayout(true, MarkOnlyThis);
2623 if (renderer()->isRenderBlock()) {
2624 RenderBlock* block = toRenderBlock(renderer());
2625 block->scrollbarsChanged(autoHorizontalScrollBarChanged, autoVerticalScrollBarChanged);
2626 block->layoutBlock(true);
2628 renderer()->layout();
2629 m_inOverflowRelayout = false;
2634 // Set up the range (and page step/line step).
2636 int clientWidth = box->pixelSnappedClientWidth();
2637 int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1);
2638 m_hBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
2639 m_hBar->setProportion(clientWidth, m_scrollSize.width());
2642 int clientHeight = box->pixelSnappedClientHeight();
2643 int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1);
2644 m_vBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
2645 m_vBar->setProportion(clientHeight, m_scrollSize.height());
2648 updateScrollableAreaSet((hasHorizontalOverflow || hasVerticalOverflow) && scrollsOverflow());
2651 void RenderLayer::updateScrollInfoAfterLayout()
2653 RenderBox* box = renderBox();
2657 m_scrollDimensionsDirty = true;
2658 IntSize originalScrollOffset = scrollOffset();
2660 computeScrollDimensions();
2662 if (box->style()->overflowX() != OMARQUEE) {
2663 // Layout may cause us to be at an invalid scroll position. In this case we need
2664 // to pull our scroll offsets back to the max (or push them up to the min).
2665 IntSize clampedScrollOffset = clampScrollOffset(scrollOffset());
2666 if (clampedScrollOffset != scrollOffset())
2667 scrollToOffset(clampedScrollOffset);
2670 updateScrollbarsAfterLayout();
2672 if (originalScrollOffset != scrollOffset())
2673 scrollToOffsetWithoutAnimation(toPoint(scrollOffset()));
2676 void RenderLayer::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls)
2678 // Don't do anything if we have no overflow.
2679 if (!renderer()->hasOverflowClip())
2682 // Overlay scrollbars paint in a second pass through the layer tree so that they will paint
2683 // on top of everything else. If this is the normal painting pass, paintingOverlayControls
2684 // will be false, and we should just tell the root layer that there are overlay scrollbars
2685 // that need to be painted. That will cause the second pass through the layer tree to run,
2686 // and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the
2687 // second pass doesn't need to re-enter the RenderTree to get it right.
2688 #if !ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_SCROLLBAR)
2689 if (hasOverlayScrollbars() && !paintingOverlayControls) {
2690 m_cachedOverlayScrollbarOffset = paintOffset;
2691 #if USE(ACCELERATED_COMPOSITING)
2692 // It's not necessary to do the second pass if the scrollbars paint into layers.
2693 if ((m_hBar && layerForHorizontalScrollbar()) || (m_vBar && layerForVerticalScrollbar()))
2696 RenderView* renderView = renderer()->view();
2697 renderView->layer()->setContainsDirtyOverlayScrollbars(true);
2698 renderView->frameView()->setContainsScrollableAreaWithOverlayScrollbars(true);
2703 // This check is required to avoid painting custom CSS scrollbars twice.
2704 if (paintingOverlayControls && !hasOverlayScrollbars())
2707 IntPoint adjustedPaintOffset = paintOffset;
2708 if (paintingOverlayControls)
2709 adjustedPaintOffset = m_cachedOverlayScrollbarOffset;
2711 // Move the scrollbar widgets if necessary. We normally move and resize widgets during layout, but sometimes
2712 // widgets can move without layout occurring (most notably when you scroll a document that
2713 // contains fixed positioned elements).
2714 positionOverflowControls(toSize(adjustedPaintOffset));
2716 // Now that we're sure the scrollbars are in the right place, paint them.
2718 #if USE(ACCELERATED_COMPOSITING)
2719 && !layerForHorizontalScrollbar()
2722 m_hBar->paint(context, damageRect);
2724 #if USE(ACCELERATED_COMPOSITING)
2725 && !layerForVerticalScrollbar()
2728 m_vBar->paint(context, damageRect);
2730 #if USE(ACCELERATED_COMPOSITING)
2731 if (layerForScrollCorner())
2735 // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the
2737 paintScrollCorner(context, adjustedPaintOffset, damageRect);
2739 // Paint our resizer last, since it sits on top of the scroll corner.
2740 paintResizer(context, adjustedPaintOffset, damageRect);
2743 void RenderLayer::paintScrollCorner(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect)
2745 RenderBox* box = renderBox();
2748 IntRect absRect = scrollCornerRect();
2749 absRect.moveBy(paintOffset);
2750 if (!absRect.intersects(damageRect))
2753 if (context->updatingControlTints()) {
2754 updateScrollCornerStyle();
2758 if (m_scrollCorner) {
2759 m_scrollCorner->paintIntoRect(context, paintOffset, absRect);
2763 // We don't want to paint white if we have overlay scrollbars, since we need
2764 // to see what is behind it.
2765 if (!hasOverlayScrollbars())
2766 context->fillRect(absRect, Color::white, box->style()->colorSpace());
2769 void RenderLayer::drawPlatformResizerImage(GraphicsContext* context, IntRect resizerCornerRect)
2771 float deviceScaleFactor = WebCore::deviceScaleFactor(renderer()->frame());
2773 RefPtr<Image> resizeCornerImage;
2774 IntSize cornerResizerSize;
2775 if (deviceScaleFactor >= 2) {
2776 DEFINE_STATIC_LOCAL(Image*, resizeCornerImageHiRes, (Image::loadPlatformResource("textAreaResizeCorner@2x").leakRef()));
2777 resizeCornerImage = resizeCornerImageHiRes;
2778 cornerResizerSize = resizeCornerImage->size();
2779 cornerResizerSize.scale(0.5f);
2781 DEFINE_STATIC_LOCAL(Image*, resizeCornerImageLoRes, (Image::loadPlatformResource("textAreaResizeCorner").leakRef()));
2782 resizeCornerImage = resizeCornerImageLoRes;
2783 cornerResizerSize = resizeCornerImage->size();
2786 if (renderer()->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
2788 context->translate(resizerCornerRect.x() + cornerResizerSize.width(), resizerCornerRect.y() + resizerCornerRect.height() - cornerResizerSize.height());
2789 context->scale(FloatSize(-1.0, 1.0));
2790 context->drawImage(resizeCornerImage.get(), renderer()->style()->colorSpace(), IntRect(IntPoint(), cornerResizerSize));
2794 IntRect imageRect(resizerCornerRect.maxXMaxYCorner() - cornerResizerSize, cornerResizerSize);
2795 context->drawImage(resizeCornerImage.get(), renderer()->style()->colorSpace(), imageRect);
2798 void RenderLayer::paintResizer(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect)
2800 if (renderer()->style()->resize() == RESIZE_NONE)
2803 RenderBox* box = renderBox();
2806 IntRect absRect = resizerCornerRect(this, box->pixelSnappedBorderBoxRect());
2807 absRect.moveBy(paintOffset);
2808 if (!absRect.intersects(damageRect))
2811 if (context->updatingControlTints()) {
2812 updateResizerStyle();
2817 m_resizer->paintIntoRect(context, paintOffset, absRect);
2821 drawPlatformResizerImage(context, absRect);
2823 // Draw a frame around the resizer (1px grey line) if there are any scrollbars present.
2824 // Clipping will exclude the right and bottom edges of this frame.
2825 if (!hasOverlayScrollbars() && (m_vBar || m_hBar)) {
2826 GraphicsContextStateSaver stateSaver(*context);
2827 context->clip(absRect);
2828 IntRect largerCorner = absRect;
2829 largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1));
2830 context->setStrokeColor(Color(makeRGB(217, 217, 217)), ColorSpaceDeviceRGB);
2831 context->setStrokeThickness(1.0f);
2832 context->setFillColor(Color::transparent, ColorSpaceDeviceRGB);
2833 context->drawRect(largerCorner);
2837 bool RenderLayer::isPointInResizeControl(const IntPoint& absolutePoint) const
2839 if (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)
2842 RenderBox* box = renderBox();
2845 IntPoint localPoint = roundedIntPoint(absoluteToContents(absolutePoint));
2847 IntRect localBounds(0, 0, box->pixelSnappedWidth(), box->pixelSnappedHeight());
2848 return resizerCornerRect(this, localBounds).contains(localPoint);
2851 bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint)
2853 if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
2856 RenderBox* box = renderBox();
2859 IntRect resizeControlRect;
2860 if (renderer()->style()->resize() != RESIZE_NONE) {
2861 resizeControlRect = resizerCornerRect(this, box->pixelSnappedBorderBoxRect());
2862 if (resizeControlRect.contains(localPoint))
2866 int resizeControlSize = max(resizeControlRect.height(), 0);
2868 if (m_vBar && m_vBar->shouldParticipateInHitTesting()) {
2869 LayoutRect vBarRect(verticalScrollbarStart(0, box->width()),
2872 box->height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
2873 if (vBarRect.contains(localPoint)) {
2874 result.setScrollbar(m_vBar.get());
2879 resizeControlSize = max(resizeControlRect.width(), 0);
2880 if (m_hBar && m_hBar->shouldParticipateInHitTesting()) {
2881 LayoutRect hBarRect(horizontalScrollbarStart(0),
2882 box->height() - box->borderBottom() - m_hBar->height(),
2883 box->width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
2885 if (hBarRect.contains(localPoint)) {
2886 result.setScrollbar(m_hBar.get());
2894 bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
2896 return ScrollableArea::scroll(direction, granularity, multiplier);
2899 void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, RenderRegion* region, PaintLayerFlags paintFlags)
2901 OverlapTestRequestMap overlapTestRequests;
2902 paintLayer(this, context, damageRect, paintBehavior, paintingRoot, region, &overlapTestRequests, paintFlags);
2903 OverlapTestRequestMap::iterator end = overlapTestRequests.end();
2904 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
2905 it->first->setOverlapTestResult(false);
2908 void RenderLayer::paintOverlayScrollbars(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot)
2910 if (!m_containsDirtyOverlayScrollbars)
2912 paintLayer(this, context, damageRect, paintBehavior, paintingRoot, 0, 0, PaintLayerHaveTransparency | PaintLayerTemporaryClipRects
2913 | PaintLayerPaintingOverlayScrollbars);
2914 m_containsDirtyOverlayScrollbars = false;
2917 #ifndef DISABLE_ROUNDED_CORNER_CLIPPING
2918 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLayer)
2920 if (startLayer == endLayer)
2923 RenderView* view = startLayer->renderer()->view();
2924 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock(); currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlock()) {
2925 if (currentBlock->layer() == endLayer)
2933 void RenderLayer::clipToRect(RenderLayer* rootLayer, GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect,
2934 BorderRadiusClippingRule rule)
2936 if (clipRect.rect() == paintDirtyRect)
2939 context->clip(pixelSnappedIntRect(clipRect.rect()));
2941 if (!clipRect.hasRadius())
2944 #ifndef DISABLE_ROUNDED_CORNER_CLIPPING
2945 // If the clip rect has been tainted by a border radius, then we have to walk up our layer chain applying the clips from
2946 // any layers with overflow. The condition for being able to apply these clips is that the overflow object be in our
2947 // containing block chain so we check that also.
2948 for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? this : parent(); layer; layer = layer->parent()) {
2949 if (layer->renderer()->hasOverflowClip() && layer->renderer()->style()->hasBorderRadius() && inContainingBlockChain(this, layer)) {
2951 layer->convertToLayerCoords(rootLayer, delta);
2952 context->addRoundedRectClip(layer->renderer()->style()->getRoundedInnerBorderFor(LayoutRect(delta, layer->size())));
2955 if (layer == rootLayer)
2961 void RenderLayer::restoreClip(GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect)
2963 if (clipRect.rect() == paintDirtyRect)
2968 static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer)
2970 Vector<OverlapTestRequestClient*> overlappedRequestClients;
2971 OverlapTestRequestMap::iterator end = overlapTestRequests.end();
2972 LayoutRect boundingBox = layer->boundingBox(rootLayer);
2973 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) {
2974 if (!boundingBox.intersects(it->second))
2977 it->first->setOverlapTestResult(true);
2978 overlappedRequestClients.append(it->first);
2980 for (size_t i = 0; i < overlappedRequestClients.size(); ++i)
2981 overlapTestRequests.remove(overlappedRequestClients[i]);
2984 #if USE(ACCELERATED_COMPOSITING)
2985 static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection)
2987 return paintingReflection && !layer->has3DTransform();
2991 static inline bool shouldSuppressPaintingLayer(RenderLayer* layer)
2993 // Avoid painting descendants of the root layer when stylesheets haven't loaded. This eliminates FOUC.
2994 // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
2995 // will do a full repaint().
2996 if (layer->renderer()->document()->didLayoutWithPendingStylesheets() && !layer->isRootLayer() && !layer->renderer()->isRoot())
2999 // Avoid painting all layers if the document is in a state where visual updates aren't allowed.
3000 // A full repaint will occur in Document::implicitClose() if painting is suppressed here.
3001 if (!layer->renderer()->document()->visualUpdatesAllowed())
3008 void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* context,
3009 const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior,
3010 RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
3011 PaintLayerFlags paintFlags)
3013 #if USE(ACCELERATED_COMPOSITING)
3014 if (isComposited()) {
3015 // The updatingControlTints() painting pass goes through compositing layers,
3016 // but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
3017 if (context->updatingControlTints() || (paintBehavior & PaintBehaviorFlattenCompositingLayers))
3018 paintFlags |= PaintLayerTemporaryClipRects;
3019 else if (!backing()->paintsIntoWindow() && !backing()->paintsIntoCompositedAncestor() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection) && !(rootLayer->containsDirtyOverlayScrollbars() && (paintFlags & PaintLayerPaintingOverlayScrollbars))) {
3020 // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer().
3026 // Non self-painting leaf layers don't need to be painted as their renderer() should properly paint itself.
3027 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
3030 if (shouldSuppressPaintingLayer(this))
3033 // If this layer is totally invisible then there is nothing to paint.
3034 if (!renderer()->opacity())
3037 if (paintsWithTransparency(paintBehavior))
3038 paintFlags |= PaintLayerHaveTransparency;
3040 // PaintLayerAppliedTransform is used in RenderReplica, to avoid applying the transform twice.
3041 if (paintsWithTransform(paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) {
3042 TransformationMatrix layerTransform = renderableTransform(paintBehavior);
3043 // If the transform can't be inverted, then don't paint anything.
3044 if (!layerTransform.isInvertible())
3047 // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
3048 // layer from the parent now, assuming there is a parent
3049 if (paintFlags & PaintLayerHaveTransparency) {
3051 parent()->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
3053 beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
3056 // Make sure the parent's clip rects have been calculated.
3057 ClipRect clipRect = paintDirtyRect;
3059 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
3060 clipRect = backgroundClipRect(rootLayer, region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
3061 IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
3063 clipRect = backgroundClipRect(rootLayer, region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects);
3065 clipRect.intersect(paintDirtyRect);
3067 // Push the parent coordinate space's clip.
3068 parent()->clipToRect(rootLayer, context, paintDirtyRect, clipRect);
3071 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
3072 // This involves subtracting out the position of the layer in our current coordinate space.
3074 convertToLayerCoords(rootLayer, delta);
3075 TransformationMatrix transform(layerTransform);
3076 transform.translateRight(delta.x(), delta.y());
3078 // Apply the transform.
3080 GraphicsContextStateSaver stateSaver(*context);
3081 context->concatCTM(transform.toAffineTransform());
3083 // Now do a paint with the root layer shifted to be us.
3084 paintLayerContentsAndReflection(this, context, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
3087 // Restore the clip.
3089 parent()->restoreClip(context, paintDirtyRect, clipRect);
3094 paintLayerContentsAndReflection(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
3097 void RenderLayer::paintLayerContentsAndReflection(RenderLayer* rootLayer, GraphicsContext* context,
3098 const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior,
3099 RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
3100 PaintLayerFlags paintFlags)
3102 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
3104 PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform);
3106 // Paint the reflection first if we have one.
3107 if (m_reflection && !m_paintingInsideReflection) {
3108 // Mark that we are now inside replica painting.
3109 m_paintingInsideReflection = true;
3110 reflectionLayer()->paintLayer(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection);
3111 m_paintingInsideReflection = false;
3114 localPaintFlags |= PaintLayerPaintingCompositingAllPhases;
3115 paintLayerContents(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
3118 void RenderLayer::paintLayerContents(RenderLayer* rootLayer, GraphicsContext* context,
3119 const LayoutRect& parentPaintDirtyRect, PaintBehavior paintBehavior,
3120 RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
3121 PaintLayerFlags paintFlags)
3123 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
3125 PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform);
3126 bool haveTransparency = localPaintFlags & PaintLayerHaveTransparency;
3127 bool isSelfPaintingLayer = this->isSelfPaintingLayer();
3128 bool isPaintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScrollbars;
3129 // Outline always needs to be painted even if we have no visible content.
3130 bool shouldPaintOutline = isSelfPaintingLayer && !isPaintingOverlayScrollbars;
3131 bool shouldPaintContent = m_hasVisibleContent && isSelfPaintingLayer && !isPaintingOverlayScrollbars;
3133 // Calculate the clip rects we should use only when we need them.
3134 LayoutRect layerBounds;
3135 ClipRect damageRect, clipRectToApply, outlineRect;
3136 LayoutPoint paintOffset;
3137 LayoutRect paintDirtyRect = parentPaintDirtyRect;
3139 bool useClipRect = true;
3140 GraphicsContext* transparencyLayerContext = context;
3142 // Ensure our lists are up-to-date.
3143 updateLayerListsIfNeeded();
3145 // Apply clip-path to context.
3146 RenderStyle* style = renderer()->style();
3147 if (renderer()->hasClipPath() && !context->paintingDisabled() && style) {
3148 if (BasicShape* clipShape = style->clipPath()) {
3149 // FIXME: Investigate if it is better to store and update a Path object in RenderStyle.
3150 // https://bugs.webkit.org/show_bug.cgi?id=95619
3152 clipShape->path(clipPath, calculateLayerBounds(this, rootLayer, 0));
3153 transparencyLayerContext->clipPath(clipPath, clipShape->windRule());
3157 #if ENABLE(CSS_FILTERS)
3158 FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
3159 if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) {
3160 LayoutPoint rootLayerOffset;
3161 convertToLayerCoords(rootLayer, rootLayerOffset);
3162 RenderLayerFilterInfo* filterInfo = this->filterInfo();
3164 LayoutRect filterRepaintRect = filterInfo->dirtySourceRect();
3165 filterRepaintRect.move(rootLayerOffset.x(), rootLayerOffset.y());
3166 if (filterPainter.prepareFilterEffect(this, calculateLayerBounds(this, rootLayer, 0), parentPaintDirtyRect, filterRepaintRect)) {
3167 // Now we know for sure, that the source image will be updated, so we can revert our tracking repaint rect back to zero.
3168 filterInfo->resetDirtySourceRect();
3170 // Rewire the old context to a memory buffer, so that we can capture the contents of the layer.
3171 // NOTE: We saved the old context in the "transparencyLayerContext" local variable, to be able to start a transparency layer
3172 // on the original context and avoid duplicating "beginFilterEffect" after each transpareny layer call. Also, note that
3173 // beginTransparencyLayers will only create a single lazy transparency layer, even though it is called twice in this method.
3174 context = filterPainter.beginFilterEffect(context);
3176 // Check that we didn't fail to allocate the graphics context for the offscreen buffer.
3177 if (filterPainter.hasStartedFilterEffect()) {
3178 paintDirtyRect = filterPainter.repaintRect();
3179 // If the filter needs the full source image, we need to avoid using the clip rectangles.
3180 // Otherwise, if for example this layer has overflow:hidden, a drop shadow will not compute correctly.
3181 // Note that we will still apply the clipping on the final rendering of the filter.
3182 useClipRect = !filterRenderer()->hasFilterThatMovesPixels();
3188 if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
3189 calculateRects(rootLayer, region, (localPaintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect
3190 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
3191 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
3192 , IgnoreOverlayScrollbarSize, localPaintFlags & PaintLayerPaintingOverflowContents ? IgnoreOverflowClip : RespectOverflowClip
3194 , IgnoreOverlayScrollbarSize, paintFlags & PaintLayerPaintingOverflowContents
3198 paintOffset = toPoint(layerBounds.location() - renderBoxLocation());
3201 bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText;
3202 bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly;
3204 // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
3205 // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
3206 // Else, our renderer tree may or may not contain the painting root, so we pass that root along
3207 // so it will be tested against as we descend through the renderers.
3208 RenderObject* paintingRootForRenderer = 0;
3209 if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
3210 paintingRootForRenderer = paintingRoot;
3212 if (overlapTestRequests && isSelfPaintingLayer)
3213 performOverlapTests(*overlapTestRequests, rootLayer, this);
3215 // We want to paint our layer, but only if we intersect the damage rect.
3216 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
3217 if (this != rootLayer || !(localPaintFlags & PaintLayerPaintingOverflowContents))
3219 shouldPaintContent &= intersectsDamageRect(layerBounds, damageRect.rect(), rootLayer);
3221 if (localPaintFlags & PaintLayerPaintingCompositingBackgroundPhase) {
3222 if (shouldPaintContent && !selectionOnly) {
3223 // Begin transparency layers lazily now that we know we have to paint something.
3224 if (haveTransparency)
3225 beginTransparencyLayers(transparencyLayerContext, rootLayer, paintDirtyRect, paintBehavior);
3228 // Paint our background first, before painting any child layers.
3229 // Establish the clip used to paint our background.
3230 clipToRect(rootLayer, context, paintDirtyRect, damageRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
3233 // Paint the background.
3234 PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseBlockBackground, false, paintingRootForRenderer, region, 0);
3235 renderer()->paint(paintInfo, paintOffset);
3238 // Restore the clip.
3239 restoreClip(context, paintDirtyRect, damageRect);
3243 // Now walk the sorted list of children with negative z-indices.
3244 paintList(negZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
3247 if (localPaintFlags & PaintLayerPaintingCompositingForegroundPhase) {
3248 // Now establish the appropriate clip and paint our child RenderObjects.
3249 if (shouldPaintContent && !clipRectToApply.isEmpty()) {
3250 // Begin transparency layers lazily now that we know we have to paint something.
3251 if (haveTransparency)
3252 beginTransparencyLayers(transparencyLayerContext, rootLayer, paintDirtyRect, paintBehavior);
3255 // Set up the clip used when painting our children.
3256 clipToRect(rootLayer, context, paintDirtyRect, clipRectToApply);
3259 PaintInfo paintInfo(context, pixelSnappedIntRect(clipRectToApply.rect()),
3260 selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
3261 forceBlackText, paintingRootForRenderer, region, 0);
3262 renderer()->paint(paintInfo, paintOffset);
3263 if (!selectionOnly) {
3264 paintInfo.phase = PaintPhaseFloat;
3265 renderer()->paint(paintInfo, paintOffset);
3266 paintInfo.phase = PaintPhaseForeground;
3267 paintInfo.overlapTestRequests = overlapTestRequests;
3268 renderer()->paint(paintInfo, paintOffset);
3269 paintInfo.phase = PaintPhaseChildOutlines;
3270 renderer()->paint(paintInfo, paintOffset);
3274 // Now restore our clip.
3275 restoreClip(context, paintDirtyRect, clipRectToApply);
3279 if (shouldPaintOutline && !outlineRect.isEmpty()) {
3280 // Paint our own outline
3281 PaintInfo paintInfo(context, pixelSnappedIntRect(outlineRect.rect()), PaintPhaseSelfOutline, false, paintingRootForRenderer, region, 0);
3282 clipToRect(rootLayer, context, paintDirtyRect, outlineRect, DoNotIncludeSelfForBorderRadius);
3283 renderer()->paint(paintInfo, paintOffset);
3284 restoreClip(context, paintDirtyRect, outlineRect);
3287 // Paint any child layers that have overflow.
3288 paintList(m_normalFlowList, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
3290 // Now walk the sorted list of children with positive z-indices.
3291 paintList(posZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, localPaintFlags);
3294 if ((localPaintFlags & PaintLayerPaintingCompositingMaskPhase) && shouldPaintContent && renderer()->hasMask() && !selectionOnly) {
3296 clipToRect(rootLayer, context, paintDirtyRect, damageRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
3299 PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseMask, false, paintingRootForRenderer, region, 0);
3300 renderer()->paint(paintInfo, paintOffset);
3303 // Restore the clip.
3304 restoreClip(context, paintDirtyRect, damageRect);
3308 if (isPaintingOverlayScrollbars) {
3309 clipToRect(rootLayer, context, paintDirtyRect, damageRect);
3310 paintOverflowControls(context, roundedIntPoint(paintOffset), pixelSnappedIntRect(damageRect.rect()), true);
3311 restoreClip(context, paintDirtyRect, damageRect);
3314 #if ENABLE(CSS_FILTERS)
3315 if (filterPainter.hasStartedFilterEffect()) {
3316 // Apply the correct clipping (ie. overflow: hidden).
3317 clipToRect(rootLayer, transparencyLayerContext, paintDirtyRect, damageRect);
3318 context = filterPainter.applyFilterEffect();
3319 restoreClip(transparencyLayerContext, paintDirtyRect, damageRect);
3323 // Make sure that we now use the original transparency context.
3324 ASSERT(transparencyLayerContext == context);
3326 // End our transparency layer
3327 if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) {
3328 context->endTransparencyLayer();
3330 m_usedTransparency = false;
3334 void RenderLayer::paintList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, GraphicsContext* context,
3335 const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior,
3336 RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
3337 PaintLayerFlags paintFlags)
3342 if (!hasSelfPaintingLayerDescendant())
3345 #if !ASSERT_DISABLED
3346 LayerListMutationDetector mutationChecker(this);
3349 for (size_t i = 0; i < list->size(); ++i) {
3350 RenderLayer* childLayer = list->at(i);
3351 if (!childLayer->isPaginated())
3352 childLayer->paintLayer(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
3354 paintPaginatedChildLayer(childLayer, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
3358 void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context,
3359 const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior,
3360 RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
3361 PaintLayerFlags paintFlags)
3363 // We need to do multiple passes, breaking up our child layer into strips.
3364 Vector<RenderLayer*> columnLayers;
3365 RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext();
3366 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
3367 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
3368 columnLayers.append(curr);
3369 if (curr == ancestorLayer)
3373 // It is possible for paintLayer() to be called after the child layer ceases to be paginated but before
3374 // updateLayerPositions() is called and resets the isPaginated() flag, see <rdar://problem/10098679>.
3375 // If this is the case, just bail out, since the upcoming call to updateLayerPositions() will repaint the layer.
3376 if (!columnLayers.size())
3379 paintChildLayerIntoColumns(childLayer, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags, columnLayers, columnLayers.size() - 1);
3382 void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context,
3383 const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior,
3384 RenderObject* paintingRoot, RenderRegion* region, OverlapTestRequestMap* overlapTestRequests,
3385 PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex)
3387 RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer());
3389 ASSERT(columnBlock && columnBlock->hasColumns());
3390 if (!columnBlock || !columnBlock->hasColumns())
3393 LayoutPoint layerOffset;
3394 // FIXME: It looks suspicious to call convertToLayerCoords here
3395 // as canUseConvertToLayerCoords is true for this layer.
3396 columnBlock->layer()->convertToLayerCoords(rootLayer, layerOffset);
3398 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
3400 ColumnInfo* colInfo = columnBlock->columnInfo();
3401 unsigned colCount = columnBlock->columnCount(colInfo);
3402 LayoutUnit currLogicalTopOffset = 0;
3403 for (unsigned i = 0; i < colCount; i++) {
3404 // For each rect, we clip to the rect, and then we adjust our coords.
3405 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
3406 columnBlock->flipForWritingMode(colRect);
3407 LayoutUnit logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent();
3410 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
3411 offset = LayoutSize(logicalLeftOffset, currLogicalTopOffset);
3413 offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop());
3415 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
3416 offset = LayoutSize(currLogicalTopOffset, logicalLeftOffset);
3418 offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0);
3421 colRect.moveBy(layerOffset);
3423 LayoutRect localDirtyRect(paintDirtyRect);
3424 localDirtyRect.intersect(colRect);
3426 if (!localDirtyRect.isEmpty()) {
3427 GraphicsContextStateSaver stateSaver(*context);
3429 // Each strip pushes a clip, since column boxes are specified as being
3430 // like overflow:hidden.
3431 context->clip(pixelSnappedIntRect(colRect));
3434 // Apply a translation transform to change where the layer paints.
3435 TransformationMatrix oldTransform;
3436 bool oldHasTransform = childLayer->transform();
3437 if (oldHasTransform)
3438 oldTransform = *childLayer->transform();
3439 TransformationMatrix newTransform(oldTransform);
3440 newTransform.translateRight(roundToInt(offset.width()), roundToInt(offset.height()));
3442 childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
3443 childLayer->paintLayer(rootLayer, context, localDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
3444 if (oldHasTransform)
3445 childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
3447 childLayer->m_transform.clear();
3449 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
3450 // This involves subtracting out the position of the layer in our current coordinate space.
3451 LayoutPoint childOffset;
3452 columnLayers[colIndex - 1]->convertToLayerCoords(rootLayer, childOffset);
3453 TransformationMatrix transform;
3454 transform.translateRight(roundToInt(childOffset.x() + offset.width()), roundToInt(childOffset.y() + offset.height()));
3456 // Apply the transform.
3457 context->concatCTM(transform.toAffineTransform());
3459 // Now do a paint with the root layer shifted to be the next multicol block.
3460 paintChildLayerIntoColumns(childLayer, columnLayers[colIndex - 1], context, transform.inverse().mapRect(localDirtyRect), paintBehavior,
3461 paintingRoot, region, overlapTestRequests, paintFlags,
3462 columnLayers, colIndex - 1);
3466 // Move to the next position.
3467 LayoutUnit blockDelta = isHorizontal ? colRect.height() : colRect.width();
3468 if (columnBlock->style()->isFlippedBlocksWritingMode())
3469 currLogicalTopOffset += blockDelta;
3471 currLogicalTopOffset -= blockDelta;
3475 static inline LayoutRect frameVisibleRect(RenderObject* renderer)
3477 FrameView* frameView = renderer->document()->view();
3479 return LayoutRect();
3481 return frameView->visibleContentRect();
3484 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
3486 return hitTest(request, result.hitTestPoint(), result);
3489 bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestPoint& hitTestPoint, HitTestResult& result)
3491 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
3493 renderer()->document()->updateLayout();
3495 LayoutRect hitTestArea = renderer()->isRenderFlowThread() ? toRenderFlowThread(renderer())->borderBoxRect() : renderer()->view()->documentRect();
3496 if (!request.ignoreClipping())
3497 hitTestArea.intersect(frameVisibleRect(renderer()));
3499 RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, hitTestPoint, false);
3501 // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down,
3502 // return ourselves. We do this so mouse events continue getting delivered after a drag has
3503 // exited the WebView, and so hit testing over a scrollbar hits the content document.
3504 if ((request.active() || request.release()) && isRootLayer()) {
3505 renderer()->updateHitTestResult(result, toRenderView(renderer())->flipForWritingMode(result.point()));
3510 // Now determine if the result is inside an anchor - if the urlElement isn't already set.
3511 Node* node = result.innerNode();
3512 if (node && !result.URLElement())
3513 result.setURLElement(static_cast<Element*>(node->enclosingLinkEventParentOrSelf()));
3515 // Next set up the correct :hover/:active state along the new chain.
3516 updateHoverActiveState(request, result);
3518 // Now return whether we were inside this layer (this will always be true for the root
3523 Node* RenderLayer::enclosingElement() const
3525 for (RenderObject* r = renderer(); r; r = r->parent()) {
3526 if (Node* e = r->node())
3529 ASSERT_NOT_REACHED();
3533 // Compute the z-offset of the point in the transformState.
3534 // This is effectively projecting a ray normal to the plane of ancestor, finding where that
3535 // ray intersects target, and computing the z delta between those two points.
3536 static double computeZOffset(const HitTestingTransformState& transformState)
3538 // We got an affine transform, so no z-offset
3539 if (transformState.m_accumulatedTransform.isAffine())
3542 // Flatten the point into the target plane
3543 FloatPoint targetPoint = transformState.mappedPoint();
3545 // Now map the point back through the transform, which computes Z.
3546 FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoint(FloatPoint3D(targetPoint));
3547 return backmappedPoint.z();
3550 PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
3551 const LayoutRect& hitTestRect, const HitTestPoint& hitTestPoint,
3552 const HitTestingTransformState* containerTransformState) const
3554 RefPtr<HitTestingTransformState> transformState;
3556 if (containerTransformState) {
3557 // If we're already computing transform state, then it's relative to the container (which we know is non-null).
3558 transformState = HitTestingTransformState::create(*containerTransformState);
3559 convertToLayerCoords(containerLayer, offset);
3561 // If this is the first time we need to make transform state, then base it off of hitTestPoint,
3562 // which is relative to rootLayer.
3563 transformState = HitTestingTransformState::create(hitTestPoint.transformedPoint(), hitTestPoint.transformedRect(), FloatQuad(hitTestRect));
3564 convertToLayerCoords(rootLayer, offset);
3567 RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0;
3568 if (renderer()->shouldUseTransformFromContainer(containerRenderer)) {
3569 TransformationMatrix containerTransform;
3570 renderer()->getTransformFromContainer(containerRenderer, toLayoutSize(offset), containerTransform);
3571 transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform);
3573 transformState->translate(offset.x(), offset.y(), HitTestingTransformState::AccumulateTransform);
3576 return transformState;
3580 static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState)
3585 // The hit layer is depth-sorting with other layers, so just say that it was hit.
3589 // We need to look at z-depth to decide if this layer was hit.
3591 ASSERT(transformState);
3592 // This is actually computing our z, but that's OK because the hitLayer is coplanar with us.
3593 double childZOffset = computeZOffset(*transformState);
3594 if (childZOffset > *zOffset) {
3595 *zOffset = childZOffset;
3604 // hitTestPoint and hitTestRect are relative to rootLayer.
3605 // A 'flattening' layer is one preserves3D() == false.
3606 // transformState.m_accumulatedTransform holds the transform from the containing flattening layer.
3607 // transformState.m_lastPlanarPoint is the hitTestPoint in the plane of the containing flattening layer.
3608 // transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer.
3610 // If zOffset is non-null (which indicates that the caller wants z offset information),
3611 // *zOffset on return is the z offset of the hit point relative to the containing flattening layer.
3612 RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
3613 const LayoutRect& hitTestRect, const HitTestPoint& hitTestPoint, bool appliedTransform,
3614 const HitTestingTransformState* transformState, double* zOffset)
3616 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
3619 // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
3621 bool useTemporaryClipRects = renderer()->view()->frameView()->containsScrollableAreaWithOverlayScrollbars();
3623 // Apply a transform if we have one.
3624 if (transform() && !appliedTransform) {
3625 // Make sure the parent's clip rects have been calculated.
3627 ClipRect clipRect = backgroundClipRect(rootLayer, hitTestPoint.region(), useTemporaryClipRects ? TemporaryClipRects : RootRelativeClipRects, IncludeOverlayScrollbarSize);
3628 // Go ahead and test the enclosing clip now.
3629 if (!clipRect.intersects(hitTestPoint))
3633 // Create a transform state to accumulate this transform.
3634 RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
3636 // If the transform can't be inverted, then don't hit test this layer at all.
3637 if (!newTransformState->m_accumulatedTransform.isInvertible())
3640 // Compute the point and the hit test rect in the coords of this layer by using the values
3641 // from the transformState, which store the point and quad in the coords of the last flattened
3642 // layer, and the accumulated transform which lets up map through preserve-3d layers.
3644 // We can't just map hitTestPoint and hitTestRect because they may have been flattened (losing z)
3645 // by our container.
3646 FloatPoint localPoint = newTransformState->mappedPoint();
3647 FloatQuad localPointQuad = newTransformState->mappedQuad();
3648 LayoutRect localHitTestRect = newTransformState->boundsOfMappedArea();
3649 HitTestPoint newHitTestPoint;
3650 if (hitTestPoint.isRectBasedTest())
3651 newHitTestPoint = HitTestPoint(localPoint, localPointQuad);
3653 newHitTestPoint = HitTestPoint(localPoint);
3655 // Now do a hit test with the root layer shifted to be us.
3656 return hitTestLayer(this, containerLayer, request, result, localHitTestRect, newHitTestPoint, true, newTransformState.get(), zOffset);
3659 // Ensure our lists and 3d status are up-to-date.
3660 updateCompositingAndLayerListsIfNeeded();
3661 update3DTransformedDescendantStatus();
3663 RefPtr<HitTestingTransformState> localTransformState;
3664 if (appliedTransform) {
3665 // We computed the correct state in the caller (above code), so just reference it.
3666 ASSERT(transformState);
3667 localTransformState = const_cast<HitTestingTransformState*>(transformState);
3668 } else if (transformState || m_has3DTransformedDescendant || preserves3D()) {
3669 // We need transform state for the first time, or to offset the container state, so create it here.
3670 localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
3673 // Check for hit test on backface if backface-visibility is 'hidden'
3674 if (localTransformState && renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) {
3675 TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse();
3676 // If the z-vector of the matrix is negative, the back is facing towards the viewer.
3677 if (invertedMatrix.m33() < 0)
3681 RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState;
3682 if (localTransformState && !preserves3D()) {
3683 // Keep a copy of the pre-flattening state, for computing z-offsets for the container
3684 unflattenedTransformState = HitTestingTransformState::create(*localTransformState);
3685 // This layer is flattening, so flatten the state passed to descendants.
3686 localTransformState->flatten();
3689 // Calculate the clip rects we should use.
3690 LayoutRect layerBounds;
3693 ClipRect outlineRect;
3694 calculateRects(rootLayer, hitTestPoint.region(), useTemporaryClipRects ? TemporaryClipRects : RootRelativeClipRects, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, IncludeOverlayScrollbarSize);
3696 // The following are used for keeping track of the z-depth of the hit point of 3d-transformed
3698 double localZOffset = -numeric_limits<double>::infinity();
3699 double* zOffsetForDescendantsPtr = 0;
3700 double* zOffsetForContentsPtr = 0;
3702 bool depthSortDescendants = false;
3703 if (preserves3D()) {
3704 depthSortDescendants = true;
3705 // Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down.
3706 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
3707 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
3708 } else if (m_has3DTransformedDescendant) {
3709 // Flattening layer with 3d children; use a local zOffset pointer to depth-test children and foreground.
3710 depthSortDescendants = true;
3711 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
3712 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
3713 } else if (zOffset) {
3714 zOffsetForDescendantsPtr = 0;
3715 // Container needs us to give back a z offset for the hit layer.
3716 zOffsetForContentsPtr = zOffset;
3719 // This variable tracks which layer the mouse ends up being inside.
3720 RenderLayer* candidateLayer = 0;
3722 // Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
3723 RenderLayer* hitLayer = hitTestList(posZOrderList(), rootLayer, request, result, hitTestRect, hitTestPoint,
3724 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
3726 if (!depthSortDescendants)
3728 candidateLayer = hitLayer;
3731 // Now check our overflow objects.
3732 hitLayer = hitTestList(m_normalFlowList, rootLayer, request, result, hitTestRect, hitTestPoint,
3733 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
3735 if (!depthSortDescendants)
3737 candidateLayer = hitLayer;
3740 // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
3741 if (fgRect.intersects(hitTestPoint) && isSelfPaintingLayer()) {
3742 // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost.
3743 HitTestResult tempResult(result.hitTestPoint(), result.shadowContentFilterPolicy());
3744 if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) &&
3745 isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
3746 if (result.isRectBasedTest())
3747 result.append(tempResult);
3749 result = tempResult;
3750 if (!depthSortDescendants)
3752 // Foreground can depth-sort with descendant layers, so keep this as a candidate.
3753 candidateLayer = this;
3754 } else if (result.isRectBasedTest())
3755 result.append(tempResult);
3758 // Now check our negative z-index children.
3759 hitLayer = hitTestList(negZOrderList(), rootLayer, request, result, hitTestRect, hitTestPoint,
3760 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
3762 if (!depthSortDescendants)
3764 candidateLayer = hitLayer;
3767 // If we found a layer, return. Child layers, and foreground always render in front of background.
3769 return candidateLayer;
3771 if (bgRect.intersects(hitTestPoint) && isSelfPaintingLayer()) {
3772 HitTestResult tempResult(result.hitTestPoint(), result.shadowContentFilterPolicy());
3773 if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) &&
3774 isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
3775 if (result.isRectBasedTest())
3776 result.append(tempResult);
3778 result = tempResult;
3780 } else if (result.isRectBasedTest())
3781 result.append(tempResult);
3787 bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const LayoutRect& layerBounds, const HitTestPoint& hitTestPoint, HitTestFilter hitTestFilter) const
3789 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
3791 if (!renderer()->hitTest(request, result, hitTestPoint,
3792 toLayoutPoint(layerBounds.location() - renderBoxLocation()),
3794 // It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is
3795 // a rect-based test.
3796 ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBasedTestResult().size()));
3800 // For positioned generated content, we might still not have a
3801 // node by the time we get to the layer level, since none of
3802 // the content in the layer has an element. So just walk up
3804 if (!result.innerNode() || !result.innerNonSharedNode()) {
3805 Node* e = enclosingElement();
3806 if (!result.innerNode())
3807 result.setInnerNode(e);
3808 if (!result.innerNonSharedNode())
3809 result.setInnerNonSharedNode(e);
3815 RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* rootLayer,
3816 const HitTestRequest& request, HitTestResult& result,
3817 const LayoutRect& hitTestRect, const HitTestPoint& hitTestPoint,
3818 const HitTestingTransformState* transformState,
3819 double* zOffsetForDescendants, double* zOffset,
3820 const HitTestingTransformState* unflattenedTransformState,
3821 bool depthSortDescendants)
3826 if (!hasSelfPaintingLayerDescendant())
3829 RenderLayer* resultLayer = 0;
3830 for (int i = list->size() - 1; i >= 0; --i) {
3831 RenderLayer* childLayer = list->at(i);
3832 RenderLayer* hitLayer = 0;
3833 HitTestResult tempResult(result.hitTestPoint(), result.shadowContentFilterPolicy());
3834 if (childLayer->isPaginated())
3835 hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants);
3837 hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, transformState, zOffsetForDescendants);
3839 // If it a rect-based test, we can safely append the temporary result since it might had hit
3840 // nodes but not necesserily had hitLayer set.
3841 if (result.isRectBasedTest())
3842 result.append(tempResult);
3844 if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) {
3845 resultLayer = hitLayer;
3846 if (!result.isRectBasedTest())
3847 result = tempResult;
3848 if (!depthSortDescendants)
3856 RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
3857 const LayoutRect& hitTestRect, const HitTestPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset)
3859 Vector<RenderLayer*> columnLayers;
3860 RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext();
3861 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
3862 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
3863 columnLayers.append(curr);
3864 if (curr == ancestorLayer)
3868 ASSERT(columnLayers.size());
3869 return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestPoint, transformState, zOffset,
3870 columnLayers, columnLayers.size() - 1);
3873 RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
3874 const LayoutRect& hitTestRect, const HitTestPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset,
3875 const Vector<RenderLayer*>& columnLayers, size_t columnIndex)
3877 RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer());
3879 ASSERT(columnBlock && columnBlock->hasColumns());
3880 if (!columnBlock || !columnBlock->hasColumns())
3883 LayoutPoint layerOffset;
3884 columnBlock->layer()->convertToLayerCoords(rootLayer, layerOffset);
3886 ColumnInfo* colInfo = columnBlock->columnInfo();
3887 int colCount = columnBlock->columnCount(colInfo);
3889 // We have to go backwards from the last column to the first.
3890 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
3891 LayoutUnit logicalLeft = columnBlock->logicalLeftOffsetForContent();
3892 LayoutUnit currLogicalTopOffset = 0;
3894 for (i = 0; i < colCount; i++) {
3895 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
3896 LayoutUnit blockDelta = (isHorizontal ? colRect.height() : colRect.width());
3897 if (columnBlock->style()->isFlippedBlocksWritingMode())
3898 currLogicalTopOffset += blockDelta;
3900 currLogicalTopOffset -= blockDelta;
3902 for (i = colCount - 1; i >= 0; i--) {
3903 // For each rect, we clip to the rect, and then we adjust our coords.
3904 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
3905 columnBlock->flipForWritingMode(colRect);
3906 LayoutUnit currLogicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - logicalLeft;
3907 LayoutUnit blockDelta = (isHorizontal ? colRect.height() : colRect.width());
3908 if (columnBlock->style()->isFlippedBlocksWritingMode())
3909 currLogicalTopOffset -= blockDelta;
3911 currLogicalTopOffset += blockDelta;
3915 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
3916 offset = LayoutSize(currLogicalLeftOffset, currLogicalTopOffset);
3918 offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop());
3920 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
3921 offset = LayoutSize(currLogicalTopOffset, currLogicalLeftOffset);
3923 offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0);
3926 colRect.moveBy(layerOffset);
3928 LayoutRect localClipRect(hitTestRect);
3929 localClipRect.intersect(colRect);
3931 if (!localClipRect.isEmpty() && hitTestPoint.intersects(localClipRect)) {
3932 RenderLayer* hitLayer = 0;
3934 // Apply a translation transform to change where the layer paints.
3935 TransformationMatrix oldTransform;
3936 bool oldHasTransform = childLayer->transform();
3937 if (oldHasTransform)
3938 oldTransform = *childLayer->transform();
3939 TransformationMatrix newTransform(oldTransform);
3940 newTransform.translateRight(offset.width(), offset.height());
3942 childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
3943 hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestPoint, false, transformState, zOffset);
3944 if (oldHasTransform)
3945 childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
3947 childLayer->m_transform.clear();
3949 // Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space.
3950 // This involves subtracting out the position of the layer in our current coordinate space.
3951 RenderLayer* nextLayer = columnLayers[columnIndex - 1];
3952 RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestPoint, transformState);
3953 newTransformState->translate(offset.width(), offset.height(), HitTestingTransformState::AccumulateTransform);
3954 FloatPoint localPoint = newTransformState->mappedPoint();
3955 FloatQuad localPointQuad = newTransformState->mappedQuad();
3956 LayoutRect localHitTestRect = newTransformState->mappedArea().enclosingBoundingBox();
3957 HitTestPoint newHitTestPoint;
3958 if (hitTestPoint.isRectBasedTest())
3959 newHitTestPoint = HitTestPoint(localPoint, localPointQuad);
3961 newHitTestPoint = HitTestPoint(localPoint);
3962 newTransformState->flatten();
3964 hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, newHitTestPoint,
3965 newTransformState.get(), zOffset, columnLayers, columnIndex - 1);
3976 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
3977 void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip)
3979 void RenderLayer::updateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy)
3982 ASSERT(clipRectsType < NumCachedClipRectsTypes);
3983 if (m_clipRectsCache && m_clipRectsCache->m_clipRects[clipRectsType]) {
3984 ASSERT(rootLayer == m_clipRectsCache->m_clipRectsRoot[clipRectsType]);
3985 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
3986 ASSERT(m_clipRectsCache->m_respectingOverflowClip[clipRectsType] == (respectOverflowClip == RespectOverflowClip));
3988 return; // We have the correct cached value.
3991 // For transformed layers, the root layer was shifted to be us, so there is no need to
3992 // examine the parent. We want to cache clip rects with us as the root.
3993 RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
3995 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
3996 parentLayer->updateClipRects(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
3998 parentLayer->updateClipRects(rootLayer, region, clipRectsType, relevancy);
4001 ClipRects clipRects;
4002 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4003 calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy, respectOverflowClip);
4005 calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy);
4008 if (!m_clipRectsCache)
4009 m_clipRectsCache = adoptPtr(new ClipRectsCache);
4011 if (parentLayer && parentLayer->clipRects(clipRectsType) && clipRects == *parentLayer->clipRects(clipRectsType))
4012 m_clipRectsCache->m_clipRects[clipRectsType] = parentLayer->clipRects(clipRectsType);
4014 m_clipRectsCache->m_clipRects[clipRectsType] = ClipRects::create(clipRects);
4017 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4018 m_clipRectsCache->m_respectingOverflowClip[clipRectsType] = respectOverflowClip == RespectOverflowClip;
4020 m_clipRectsCache->m_clipRectsRoot[clipRectsType] = rootLayer;
4025 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4026 void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
4028 void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy) const
4032 // The root layer's clip rect is always infinite.
4033 clipRects.reset(PaintInfo::infiniteRect());
4037 bool useCached = clipRectsType != TemporaryClipRects;
4039 // For transformed layers, the root layer was shifted to be us, so there is no need to
4040 // examine the parent. We want to cache clip rects with us as the root.
4041 RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
4043 // Ensure that our parent's clip has been calculated so that we can examine the values.
4045 if (useCached && parentLayer->clipRects(clipRectsType))
4046 clipRects = *parentLayer->clipRects(clipRectsType);
4048 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4049 parentLayer->calculateClipRects(rootLayer, region, clipRectsType, clipRects, IgnoreOverlayScrollbarSize, respectOverflowClip);
4051 parentLayer->calculateClipRects(rootLayer, region, clipRectsType, clipRects);
4054 clipRects.reset(PaintInfo::infiniteRect());
4056 // A fixed object is essentially the root of its containing block hierarchy, so when
4057 // we encounter such an object, we reset our clip rects to the fixedClipRect.
4058 if (renderer()->style()->position() == FixedPosition) {
4059 clipRects.setPosClipRect(clipRects.fixedClipRect());
4060 clipRects.setOverflowClipRect(clipRects.fixedClipRect());
4061 clipRects.setFixed(true);
4063 else if (renderer()->style()->position() == RelativePosition)
4064 clipRects.setPosClipRect(clipRects.overflowClipRect());
4065 else if (renderer()->style()->position() == AbsolutePosition)
4066 clipRects.setOverflowClipRect(clipRects.posClipRect());
4068 // Update the clip rects that will be passed to child layers.
4069 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4070 if ((renderer()->hasOverflowClip() && (respectOverflowClip == RespectOverflowClip || this != rootLayer)) || renderer()->hasClip()) {
4072 if (renderer()->hasClipOrOverflowClip()) {
4074 // This layer establishes a clip of some kind.
4076 // This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across
4077 // some transformed layer boundary, for example, in the RenderLayerCompositor overlapMap, where
4078 // clipRects are needed in view space.
4080 offset = roundedIntPoint(renderer()->localToContainerPoint(FloatPoint(), rootLayer->renderer()));
4081 RenderView* view = renderer()->view();
4083 if (view && clipRects.fixed() && rootLayer->renderer() == view) {
4084 offset -= view->frameView()->scrollOffsetForFixedPosition();
4087 if (renderer()->hasOverflowClip()) {
4088 ClipRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(offset, region, relevancy);
4089 if (renderer()->style()->hasBorderRadius())
4090 newOverflowClip.setHasRadius(true);
4091 clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
4092 if (renderer()->isOutOfFlowPositioned() || renderer()->isRelPositioned())
4093 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
4095 if (renderer()->hasClip()) {
4096 LayoutRect newPosClip = toRenderBox(renderer())->clipRect(offset, region);
4097 clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
4098 clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
4099 clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
4104 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4105 void RenderLayer::parentClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
4107 void RenderLayer::parentClipRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, ClipRects& clipRects, OverlayScrollbarSizeRelevancy relevancy) const
4111 if (clipRectsType == TemporaryClipRects) {
4112 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4113 parent()->calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy, respectOverflowClip);
4115 parent()->calculateClipRects(rootLayer, region, clipRectsType, clipRects, relevancy);
4120 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4121 parent()->updateClipRects(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
4123 parent()->updateClipRects(rootLayer, region, clipRectsType, relevancy);
4125 clipRects = *parent()->clipRects(clipRectsType);
4128 static inline ClipRect backgroundClipRectForPosition(const ClipRects& parentRects, EPosition position)
4130 if (position == FixedPosition)
4131 return parentRects.fixedClipRect();
4133 if (position == AbsolutePosition)
4134 return parentRects.posClipRect();
4136 return parentRects.overflowClipRect();
4139 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4140 ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy, ShouldRespectOverflowClip respectOverflowClip) const
4142 ClipRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy relevancy) const
4146 ClipRects parentRects;
4147 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4148 parentClipRects(rootLayer, region, clipRectsType, parentRects, relevancy, respectOverflowClip);
4150 parentClipRects(rootLayer, region, clipRectsType, parentRects, relevancy);
4152 ClipRect backgroundClipRect = backgroundClipRectForPosition(parentRects, renderer()->style()->position());
4153 RenderView* view = renderer()->view();
4156 // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite.
4157 if (parentRects.fixed() && rootLayer->renderer() == view && backgroundClipRect != PaintInfo::infiniteRect())
4158 backgroundClipRect.move(view->frameView()->scrollOffsetForFixedPosition());
4160 return backgroundClipRect;
4163 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
4164 bool RenderLayer::hasOverflowAncestor() const
4166 RenderLayer* pAncestor = parent();
4167 while (pAncestor && pAncestor->renderer()) {
4168 if (pAncestor->renderer()->hasOverflowClip() && pAncestor->hasAcceleratedTouchScrolling())
4171 pAncestor = pAncestor->parent();
4178 void RenderLayer::calculateRects(const RenderLayer* rootLayer, RenderRegion* region, ClipRectsType clipRectsType, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
4179 ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, OverlayScrollbarSizeRelevancy relevancy
4180 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
4181 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4182 , ShouldRespectOverflowClip respectOverflowClip
4184 , bool dontClipToOverflow
4188 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
4189 // FIXME: This patch will be considered in future.
4190 // We can find optimize way for offscreen renderlayers to be painted
4191 // for overflow parents to have smooth scroll
4192 if (!parent() // root
4193 || (rootLayer == this) // Own Graphics Layer
4194 || hasOverflowAncestor()) { // parent with overflow set
4195 backgroundRect = paintDirtyRect;
4197 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4198 backgroundRect = backgroundClipRect(rootLayer, region, clipRectsType, relevancy, respectOverflowClip);
4200 backgroundRect = backgroundClipRect(rootLayer, region, clipRectsType, relevancy);
4202 backgroundRect.intersect(paintDirtyRect);
4205 if (rootLayer != this && parent()) {
4206 backgroundRect = backgroundClipRect(rootLayer, region, clipRectsType, relevancy);
4207 backgroundRect.intersect(paintDirtyRect);
4209 backgroundRect = paintDirtyRect;
4212 foregroundRect = backgroundRect;
4213 outlineRect = backgroundRect;
4216 convertToLayerCoords(rootLayer, offset);
4217 layerBounds = LayoutRect(offset, size());
4219 // Update the clip rects that will be passed to child layers.
4220 if (renderer()->hasClipOrOverflowClip()) {
4221 // This layer establishes a clip of some kind.
4222 if (renderer()->hasOverflowClip()
4223 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
4224 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4225 && (this != rootLayer || respectOverflowClip == RespectOverflowClip)
4227 && !dontClipToOverflow
4230 foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(offset, region, relevancy));
4231 if (renderer()->style()->hasBorderRadius())
4232 foregroundRect.setHasRadius(true);
4235 if (renderer()->hasClip()) {
4236 // Clip applies to *us* as well, so go ahead and update the damageRect.
4237 LayoutRect newPosClip = toRenderBox(renderer())->clipRect(offset, region);
4238 backgroundRect.intersect(newPosClip);
4239 foregroundRect.intersect(newPosClip);
4240 outlineRect.intersect(newPosClip);
4243 // If we establish a clip at all, then go ahead and make sure our background
4244 // rect is intersected with our layer's bounds including our visual overflow,
4245 // since any visual overflow like box-shadow or border-outset is not clipped by overflow:auto/hidden.
4246 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
4247 if (const ShadowData* boxShadow = renderer()->style()->boxShadow()) {
4248 IntRect overflow = pixelSnappedIntRect(layerBounds);
4250 if (boxShadow->style() == Normal) {
4251 IntRect shadowRect = pixelSnappedIntRect(layerBounds);
4252 shadowRect.move(boxShadow->x(), boxShadow->y());
4253 shadowRect.inflate(boxShadow->blur() + boxShadow->spread());
4254 overflow.unite(shadowRect);
4257 boxShadow = boxShadow->next();
4258 } while (boxShadow);
4259 // FIXME: fix for dontClipToOverflow
4260 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4261 if (this != rootLayer || respectOverflowClip == RespectOverflowClip)
4263 backgroundRect.intersect(overflow);
4265 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4266 if (this != rootLayer || respectOverflowClip == RespectOverflowClip)
4268 if (!dontClipToOverflow)
4270 backgroundRect.intersect(layerBounds);
4272 if (renderBox()->hasVisualOverflow()) {
4273 // FIXME: Does not do the right thing with CSS regions yet, since we don't yet factor in the
4274 // individual region boxes as overflow.
4275 LayoutRect layerBoundsWithVisualOverflow = renderBox()->visualOverflowRect();
4276 renderBox()->flipForWritingMode(layerBoundsWithVisualOverflow); // Layers are in physical coordinates, so the overflow has to be flipped.
4277 layerBoundsWithVisualOverflow.moveBy(offset);
4278 backgroundRect.intersect(layerBoundsWithVisualOverflow);
4280 // Shift the bounds to be for our region only.
4281 LayoutRect bounds = pixelSnappedIntRect(renderBox()->borderBoxRectInRegion(region));
4282 bounds.moveBy(offset);
4283 backgroundRect.intersect(bounds);
4289 LayoutRect RenderLayer::childrenClipRect() const
4291 // FIXME: border-radius not accounted for.
4292 // FIXME: Regions not accounted for.
4293 RenderView* renderView = renderer()->view();
4294 RenderLayer* clippingRootLayer = clippingRootForPainting();
4295 LayoutRect layerBounds;
4296 ClipRect backgroundRect, foregroundRect, outlineRect;
4297 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_FIX_WRONG_CLIPPING)
4298 // Need to use temporary clip rects, because the value of 'dontClipToOverflow' may be different from the painting path (<rdar://problem/11844909>).
4299 calculateRects(clippingRootLayer, 0, TemporaryClipRects, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
4301 calculateRects(clippingRootLayer, 0, PaintingClipRects, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
4303 return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect.rect())).enclosingBoundingBox();
4306 LayoutRect RenderLayer::selfClipRect() const
4308 // FIXME: border-radius not accounted for.
4309 // FIXME: Regions not accounted for.
4310 RenderView* renderView = renderer()->view();
4311 RenderLayer* clippingRootLayer = clippingRootForPainting();
4312 LayoutRect layerBounds;
4313 ClipRect backgroundRect, foregroundRect, outlineRect;
4314 calculateRects(clippingRootLayer, 0, PaintingClipRects, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
4315 return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect.rect())).enclosingBoundingBox();
4318 LayoutRect RenderLayer::localClipRect() const
4320 // FIXME: border-radius not accounted for.
4321 // FIXME: Regions not accounted for.
4322 RenderLayer* clippingRootLayer = clippingRootForPainting();
4323 LayoutRect layerBounds;
4324 ClipRect backgroundRect, foregroundRect, outlineRect;
4325 calculateRects(clippingRootLayer, 0, PaintingClipRects, PaintInfo::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
4327 LayoutRect clipRect = backgroundRect.rect();
4328 if (clipRect == PaintInfo::infiniteRect())
4331 LayoutPoint clippingRootOffset;
4332 convertToLayerCoords(clippingRootLayer, clippingRootOffset);
4333 clipRect.moveBy(-clippingRootOffset);
4338 void RenderLayer::addBlockSelectionGapsBounds(const LayoutRect& bounds)
4340 m_blockSelectionGapsBounds.unite(bounds);
4343 void RenderLayer::clearBlockSelectionGapsBounds()
4345 m_blockSelectionGapsBounds = LayoutRect();
4346 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
4347 child->clearBlockSelectionGapsBounds();
4350 void RenderLayer::repaintBlockSelectionGaps()
4352 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
4353 child->repaintBlockSelectionGaps();
4355 if (m_blockSelectionGapsBounds.isEmpty())
4358 LayoutRect rect = m_blockSelectionGapsBounds;
4359 rect.move(-scrolledContentOffset());
4360 if (renderer()->hasOverflowClip())
4361 rect.intersect(toRenderBox(renderer())->overflowClipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for.
4362 if (renderer()->hasClip())
4363 rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for.
4364 if (!rect.isEmpty())
4365 renderer()->repaintRectangle(rect);
4368 bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer) const
4370 // Always examine the canvas and the root.
4371 // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
4372 // paints the root's background.
4373 if (isRootLayer() || renderer()->isRoot()
4374 #if ENABLE(TIZEN_WEBKIT2) && ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
4375 || hasAcceleratedTouchScrolling()
4380 // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we
4381 // can go ahead and return true.
4382 RenderView* view = renderer()->view();
4384 if (view && !renderer()->isRenderInline()) {
4385 LayoutRect b = layerBounds;
4386 b.inflate(view->maximalOutlineSize());
4387 if (b.intersects(damageRect))
4391 // Otherwise we need to compute the bounding box of this single layer and see if it intersects
4393 return boundingBox(rootLayer).intersects(damageRect);
4396 LayoutRect RenderLayer::localBoundingBox() const
4398 // There are three special cases we need to consider.
4399 // (1) Inline Flows. For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
4400 // inline. In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the
4401 // line boxes of all three lines (including overflow on those lines).
4402 // (2) Left/Top Overflow. The width/height of layers already includes right/bottom overflow. However, in the case of left/top
4403 // overflow, we have to create a bounding box that will extend to include this overflow.
4404 // (3) Floats. When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats
4405 // as part of our bounding box. We do this because we are the responsible layer for both hit testing and painting those
4408 if (renderer()->isRenderInline())
4409 result = toRenderInline(renderer())->linesVisualOverflowBoundingBox();
4410 else if (renderer()->isTableRow()) {
4411 // Our bounding box is just the union of all of our cells' border/overflow rects.
4412 for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
4413 if (child->isTableCell()) {
4414 LayoutRect bbox = toRenderBox(child)->borderBoxRect();
4416 LayoutRect overflowRect = renderBox()->visualOverflowRect();
4417 if (bbox != overflowRect)
4418 result.unite(overflowRect);
4422 RenderBox* box = renderBox();
4424 if (box->hasMask()) {
4425 result = box->maskClipRect();
4426 box->flipForWritingMode(result); // The mask clip rect is in physical coordinates, so we have to flip, since localBoundingBox is not.
4428 LayoutRect bbox = box->borderBoxRect();
4430 LayoutRect overflowRect = box->visualOverflowRect();
4431 if (bbox != overflowRect)
4432 result.unite(overflowRect);
4436 RenderView* view = renderer()->view();
4439 result.inflate(view->maximalOutlineSize()); // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
4444 LayoutRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer) const
4446 LayoutRect result = localBoundingBox();
4447 if (renderer()->isBox())
4448 renderBox()->flipForWritingMode(result);
4450 renderer()->containingBlock()->flipForWritingMode(result);
4452 convertToLayerCoords(ancestorLayer, delta);
4453 result.moveBy(delta);
4457 IntRect RenderLayer::absoluteBoundingBox() const
4459 return pixelSnappedIntRect(boundingBox(root()));
4462 IntRect RenderLayer::calculateLayerBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer, CalculateLayerBoundsFlags flags)
4464 if (!layer->isSelfPaintingLayer())
4467 // FIXME: This could be improved to do a check like hasVisibleNonCompositingDescendantLayers() (bug 92580).
4468 if ((flags & ExcludeHiddenDescendants) && layer != ancestorLayer && !layer->hasVisibleContent() && !layer->hasVisibleDescendant())
4471 LayoutRect boundingBoxRect = layer->localBoundingBox();
4472 if (layer->renderer()->isBox())
4473 layer->renderBox()->flipForWritingMode(boundingBoxRect);
4475 layer->renderer()->containingBlock()->flipForWritingMode(boundingBoxRect);
4477 if (layer->renderer()->isRoot()) {
4478 // If the root layer becomes composited (e.g. because some descendant with negative z-index is composited),
4479 // then it has to be big enough to cover the viewport in order to display the background. This is akin
4480 // to the code in RenderBox::paintRootBoxFillLayers().
4481 if (FrameView* frameView = layer->renderer()->view()->frameView()) {
4482 LayoutUnit contentsWidth = frameView->contentsWidth();
4483 LayoutUnit contentsHeight = frameView->contentsHeight();
4485 boundingBoxRect.setWidth(max(boundingBoxRect.width(), contentsWidth - boundingBoxRect.x()));
4486 boundingBoxRect.setHeight(max(boundingBoxRect.height(), contentsHeight - boundingBoxRect.y()));
4490 LayoutRect unionBounds = boundingBoxRect;
4492 if (flags & UseLocalClipRectIfPossible) {
4493 LayoutRect localClipRect = layer->localClipRect();
4494 if (localClipRect != PaintInfo::infiniteRect()) {
4495 if ((flags & IncludeSelfTransform) && layer->paintsWithTransform(PaintBehaviorNormal))
4496 localClipRect = layer->transform()->mapRect(localClipRect);
4498 LayoutPoint ancestorRelOffset;
4499 layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset);
4500 localClipRect.moveBy(ancestorRelOffset);
4501 return pixelSnappedIntRect(localClipRect);
4505 // FIXME: should probably just pass 'flags' down to descendants.
4506 CalculateLayerBoundsFlags descendantFlags = DefaultCalculateLayerBoundsFlags | (flags & ExcludeHiddenDescendants);
4508 const_cast<RenderLayer*>(layer)->updateLayerListsIfNeeded();
4510 if (RenderLayer* reflection = layer->reflectionLayer()) {
4511 if (!reflection->isComposited()) {
4512 IntRect childUnionBounds = calculateLayerBounds(reflection, layer, descendantFlags);
4513 unionBounds.unite(childUnionBounds);
4517 ASSERT(layer->isStackingContext() || (!layer->posZOrderList() || !layer->posZOrderList()->size()));
4519 #if !ASSERT_DISABLED
4520 LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(layer));
4523 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
4524 size_t listSize = negZOrderList->size();
4525 for (size_t i = 0; i < listSize; ++i) {
4526 RenderLayer* curLayer = negZOrderList->at(i);
4527 if (!curLayer->isComposited()) {
4528 IntRect childUnionBounds = calculateLayerBounds(curLayer, layer, descendantFlags);
4529 unionBounds.unite(childUnionBounds);
4534 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
4535 size_t listSize = posZOrderList->size();
4536 for (size_t i = 0; i < listSize; ++i) {
4537 RenderLayer* curLayer = posZOrderList->at(i);
4538 if (!curLayer->isComposited()) {
4539 IntRect childUnionBounds = calculateLayerBounds(curLayer, layer, descendantFlags);
4540 unionBounds.unite(childUnionBounds);
4545 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
4546 size_t listSize = normalFlowList->size();
4547 for (size_t i = 0; i < listSize; ++i) {
4548 RenderLayer* curLayer = normalFlowList->at(i);
4549 if (!curLayer->isComposited()) {
4550 IntRect curAbsBounds = calculateLayerBounds(curLayer, layer, descendantFlags);
4551 unionBounds.unite(curAbsBounds);
4556 #if ENABLE(CSS_FILTERS)
4557 // FIXME: We can optimize the size of the composited layers, by not enlarging
4558 // filtered areas with the outsets if we know that the filter is going to render in hardware.
4559 // https://bugs.webkit.org/show_bug.cgi?id=81239
4560 if ((flags & IncludeLayerFilterOutsets) && layer->renderer()->style()->hasFilterOutsets()) {
4565 layer->renderer()->style()->getFilterOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
4566 unionBounds.move(-leftOutset, -topOutset);
4567 unionBounds.expand(leftOutset + rightOutset, topOutset + bottomOutset);
4571 if ((flags & IncludeSelfTransform) && layer->paintsWithTransform(PaintBehaviorNormal)) {
4572 TransformationMatrix* affineTrans = layer->transform();
4573 boundingBoxRect = affineTrans->mapRect(boundingBoxRect);
4574 unionBounds = affineTrans->mapRect(unionBounds);
4577 LayoutPoint ancestorRelOffset;
4578 layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset);
4579 unionBounds.moveBy(ancestorRelOffset);
4581 return pixelSnappedIntRect(unionBounds);
4584 void RenderLayer::clearClipRectsIncludingDescendants(ClipRectsType typeToClear)
4586 // FIXME: it's not clear how this layer not having clip rects guarantees that no descendants have any.
4587 if (!m_clipRectsCache)
4590 clearClipRects(typeToClear);
4592 for (RenderLayer* l = firstChild(); l; l = l->nextSibling())
4593 l->clearClipRectsIncludingDescendants(typeToClear);
4596 void RenderLayer::clearClipRects(ClipRectsType typeToClear)
4598 if (typeToClear == AllClipRectTypes)
4599 m_clipRectsCache = nullptr;
4601 ASSERT(typeToClear < NumCachedClipRectsTypes);
4602 m_clipRectsCache->m_clipRects[typeToClear] = nullptr;
4606 #if USE(ACCELERATED_COMPOSITING)
4607 RenderLayerBacking* RenderLayer::ensureBacking()
4610 m_backing = adoptPtr(new RenderLayerBacking(this));
4611 compositor()->layerBecameComposited(this);
4613 #if ENABLE(CSS_FILTERS)
4614 updateOrRemoveFilterEffect();
4617 return m_backing.get();
4620 void RenderLayer::clearBacking(bool layerBeingDestroyed)
4622 if (m_backing && !renderer()->documentBeingDestroyed())
4623 compositor()->layerBecameNonComposited(this);
4626 #if ENABLE(CSS_FILTERS)
4627 if (!layerBeingDestroyed)
4628 updateOrRemoveFilterEffect();
4630 UNUSED_PARAM(layerBeingDestroyed);
4634 bool RenderLayer::hasCompositedMask() const
4636 return m_backing && m_backing->hasMaskLayer();
4639 GraphicsLayer* RenderLayer::layerForHorizontalScrollbar() const
4641 return m_backing ? m_backing->layerForHorizontalScrollbar() : 0;
4644 GraphicsLayer* RenderLayer::layerForVerticalScrollbar() const
4646 return m_backing ? m_backing->layerForVerticalScrollbar() : 0;
4649 GraphicsLayer* RenderLayer::layerForScrollCorner() const
4651 return m_backing ? m_backing->layerForScrollCorner() : 0;
4654 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
4655 GraphicsLayer* RenderLayer::layerForScrollingContents() const
4657 return m_backing ? m_backing->scrollingContentsLayer() : 0;
4662 bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const
4664 #if USE(ACCELERATED_COMPOSITING)
4665 bool paintsToWindow = !isComposited() || backing()->paintsIntoWindow();
4667 bool paintsToWindow = true;
4669 return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || paintsToWindow);
4672 void RenderLayer::setParent(RenderLayer* parent)
4674 if (parent == m_parent)
4677 #if USE(ACCELERATED_COMPOSITING)
4678 if (m_parent && !renderer()->documentBeingDestroyed())
4679 compositor()->layerWillBeRemoved(m_parent, this);
4684 #if USE(ACCELERATED_COMPOSITING)
4685 if (m_parent && !renderer()->documentBeingDestroyed())
4686 compositor()->layerWasAdded(m_parent, this);
4690 static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
4695 for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor())
4696 for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor())
4697 if (currObj1 == currObj2)
4703 void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestResult& result)
4705 // We don't update :hover/:active state when the result is marked as readOnly.
4706 if (request.readOnly())
4709 Document* doc = renderer()->document();
4711 Node* activeNode = doc->activeNode();
4712 if (activeNode && !request.active()) {
4713 // We are clearing the :active chain because the mouse has been released.
4714 for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) {
4715 if (curr->node() && !curr->isText()) {
4716 curr->node()->setActive(false);
4717 curr->node()->clearInActiveChain();
4720 doc->setActiveNode(0);
4722 Node* newActiveNode = result.innerNode();
4723 if (!activeNode && newActiveNode && request.active() && !request.touchMove()) {
4724 // We are setting the :active chain and freezing it. If future moves happen, they
4725 // will need to reference this chain.
4726 for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) {
4727 if (curr->node() && !curr->isText())
4728 curr->node()->setInActiveChain();
4730 doc->setActiveNode(newActiveNode);
4733 // If the mouse has just been pressed, set :active on the chain. Those (and only those)
4734 // nodes should remain :active until the mouse is released.
4735 bool allowActiveChanges = !activeNode && doc->activeNode();
4737 // If the mouse is down and if this is a mouse move event, we want to restrict changes in
4738 // :hover/:active to only apply to elements that are in the :active chain that we froze
4739 // at the time the mouse went down.
4740 bool mustBeInActiveChain = request.active() && request.move();
4742 RefPtr<Node> oldHoverNode = doc->hoverNode();
4743 // Clear the :hover chain when the touch gesture is over.
4744 if (request.touchRelease()) {
4746 Node* newNode = result.innerNode();
4747 if (newNode && !newNode->renderer())
4748 newNode = result.innerNonSharedNode();
4750 // Clear the :hover chain only if current node is not same as oldHoverNode.
4751 if (oldHoverNode && oldHoverNode != newNode) {
4755 for (RenderObject* curr = oldHoverNode->renderer(); curr; curr = curr->parent()) {
4756 if (curr->node() && !curr->isText())
4757 curr->node()->setHovered(false);
4759 doc->setHoverNode(0);
4761 // A touch release can not set new hover or active target.
4765 // Check to see if the hovered node has changed.
4766 // If it hasn't, we do not need to do anything.
4767 Node* newHoverNode = result.innerNode();
4768 if (newHoverNode && !newHoverNode->renderer())
4769 newHoverNode = result.innerNonSharedNode();
4771 // Update our current hover node.
4772 doc->setHoverNode(newHoverNode);
4774 // We have two different objects. Fetch their renderers.
4775 RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
4776 RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;
4778 // Locate the common ancestor render object for the two renderers.
4779 RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
4781 Vector<RefPtr<Node>, 32> nodesToRemoveFromChain;
4782 Vector<RefPtr<Node>, 32> nodesToAddToChain;
4784 if (oldHoverObj != newHoverObj) {
4785 // The old hover path only needs to be cleared up to (and not including) the common ancestor;
4786 for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) {
4787 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain()))
4788 nodesToRemoveFromChain.append(curr->node());
4792 // Now set the hover state for our new object up to the root.
4793 for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
4794 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain()))
4795 nodesToAddToChain.append(curr->node());
4798 size_t removeCount = nodesToRemoveFromChain.size();
4799 for (size_t i = 0; i < removeCount; ++i) {
4800 nodesToRemoveFromChain[i]->setHovered(false);
4803 size_t addCount = nodesToAddToChain.size();
4804 for (size_t i = 0; i < addCount; ++i) {
4805 if (allowActiveChanges)
4806 nodesToAddToChain[i]->setActive(true);
4807 nodesToAddToChain[i]->setHovered(true);
4811 // Helper for the sorting of layers by z-index.
4812 static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
4814 return first->zIndex() < second->zIndex();
4817 void RenderLayer::dirtyZOrderLists()
4819 ASSERT(m_layerListMutationAllowed);
4820 ASSERT(isStackingContext());
4822 if (m_posZOrderList)
4823 m_posZOrderList->clear();
4824 if (m_negZOrderList)
4825 m_negZOrderList->clear();
4826 m_zOrderListsDirty = true;
4828 #if USE(ACCELERATED_COMPOSITING)
4829 if (!renderer()->documentBeingDestroyed())
4830 compositor()->setCompositingLayersNeedRebuild();
4834 void RenderLayer::dirtyStackingContextZOrderLists()
4836 RenderLayer* sc = stackingContext();
4838 sc->dirtyZOrderLists();
4841 void RenderLayer::dirtyNormalFlowList()
4843 ASSERT(m_layerListMutationAllowed);
4845 if (m_normalFlowList)
4846 m_normalFlowList->clear();
4847 m_normalFlowListDirty = true;
4849 #if USE(ACCELERATED_COMPOSITING)
4850 if (!renderer()->documentBeingDestroyed())
4851 compositor()->setCompositingLayersNeedRebuild();
4855 void RenderLayer::rebuildZOrderLists()
4857 ASSERT(m_layerListMutationAllowed);
4858 ASSERT(isDirtyStackingContext());
4860 #if USE(ACCELERATED_COMPOSITING)
4861 bool includeHiddenLayers = compositor()->inCompositingMode();
4863 bool includeHiddenLayers = false;
4865 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
4866 if (!m_reflection || reflectionLayer() != child)
4867 child->collectLayers(includeHiddenLayers, m_posZOrderList, m_negZOrderList);
4869 // Sort the two lists.
4870 if (m_posZOrderList)
4871 std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex);
4873 if (m_negZOrderList)
4874 std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
4876 m_zOrderListsDirty = false;
4879 void RenderLayer::updateNormalFlowList()
4881 if (!m_normalFlowListDirty)
4884 ASSERT(m_layerListMutationAllowed);
4886 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
4887 // Ignore non-overflow layers and reflections.
4888 if (child->isNormalFlowOnly() && (!m_reflection || reflectionLayer() != child)) {
4889 if (!m_normalFlowList)
4890 m_normalFlowList = new Vector<RenderLayer*>;
4891 m_normalFlowList->append(child);
4895 m_normalFlowListDirty = false;
4898 void RenderLayer::collectLayers(bool includeHiddenLayers, Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer)
4900 updateDescendantDependentFlags();
4902 // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
4903 bool includeHiddenLayer = includeHiddenLayers || (m_hasVisibleContent || (m_hasVisibleDescendant && isStackingContext()));
4904 if (includeHiddenLayer && !isNormalFlowOnly() && !renderer()->isRenderFlowThread()) {
4905 // Determine which buffer the child should be in.
4906 Vector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
4908 // Create the buffer if it doesn't exist yet.
4910 buffer = new Vector<RenderLayer*>;
4912 // Append ourselves at the end of the appropriate buffer.
4913 buffer->append(this);
4916 // Recur into our children to collect more layers, but only if we don't establish
4917 // a stacking context.
4918 if ((includeHiddenLayers || m_hasVisibleDescendant) && !isStackingContext()) {
4919 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
4920 // Ignore reflections.
4921 if (!m_reflection || reflectionLayer() != child)
4922 child->collectLayers(includeHiddenLayers, posBuffer, negBuffer);
4927 void RenderLayer::updateLayerListsIfNeeded()
4929 updateZOrderLists();
4930 updateNormalFlowList();
4932 if (RenderLayer* reflectionLayer = this->reflectionLayer()) {
4933 reflectionLayer->updateZOrderLists();
4934 reflectionLayer->updateNormalFlowList();
4938 void RenderLayer::updateCompositingAndLayerListsIfNeeded()
4940 #if USE(ACCELERATED_COMPOSITING)
4941 if (compositor()->inCompositingMode()) {
4942 if (isDirtyStackingContext() || m_normalFlowListDirty)
4943 compositor()->updateCompositingLayers(CompositingUpdateOnHitTest, this);
4947 updateLayerListsIfNeeded();
4950 void RenderLayer::repaintIncludingDescendants()
4952 renderer()->repaint();
4953 for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
4954 curr->repaintIncludingDescendants();
4957 #if USE(ACCELERATED_COMPOSITING)
4958 void RenderLayer::setBackingNeedsRepaint()
4960 ASSERT(isComposited());
4961 if (backing()->paintsIntoWindow()) {
4962 // If we're trying to repaint the placeholder document layer, propagate the
4963 // repaint to the native view system.
4964 RenderView* view = renderer()->view();
4966 view->repaintViewRectangle(absoluteBoundingBox());
4968 backing()->setContentsNeedDisplay();
4971 void RenderLayer::setBackingNeedsRepaintInRect(const LayoutRect& r)
4973 // https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible crash here,
4974 // so assert but check that the layer is composited.
4975 ASSERT(isComposited());
4976 if (!isComposited() || backing()->paintsIntoWindow()) {
4977 // If we're trying to repaint the placeholder document layer, propagate the
4978 // repaint to the native view system.
4979 LayoutRect absRect(r);
4981 convertToLayerCoords(root(), delta);
4982 absRect.moveBy(delta);
4984 RenderView* view = renderer()->view();
4986 view->repaintViewRectangle(absRect);
4988 backing()->setContentsNeedDisplayInRect(pixelSnappedIntRect(r));
4991 // Since we're only painting non-composited layers, we know that they all share the same repaintContainer.
4992 void RenderLayer::repaintIncludingNonCompositingDescendants(RenderBoxModelObject* repaintContainer)
4994 renderer()->repaintUsingContainer(repaintContainer, renderer()->clippedOverflowRectForRepaint(repaintContainer));
4996 for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling()) {
4997 if (!curr->isComposited())
4998 curr->repaintIncludingNonCompositingDescendants(repaintContainer);
5003 bool RenderLayer::shouldBeNormalFlowOnly() const
5005 return (renderer()->hasOverflowClip()
5006 || renderer()->hasReflection()
5007 || renderer()->hasMask()
5008 || renderer()->isCanvas()
5009 || renderer()->isVideo()
5010 || renderer()->isEmbeddedObject()
5011 || renderer()->isRenderIFrame()
5012 || renderer()->style()->specifiesColumns())
5013 && !renderer()->isOutOfFlowPositioned()
5014 && !renderer()->isRelPositioned()
5015 && !renderer()->hasTransform()
5016 && !renderer()->hasClipPath()
5017 #if ENABLE(CSS_FILTERS)
5018 && !renderer()->hasFilter()
5021 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
5022 && !hasAcceleratedTouchScrolling()
5027 bool RenderLayer::shouldBeSelfPaintingLayer() const
5029 return !isNormalFlowOnly()
5030 || hasOverlayScrollbars()
5031 || renderer()->hasReflection()
5032 || renderer()->hasMask()
5033 || renderer()->isTableRow()
5034 || renderer()->isCanvas()
5035 || renderer()->isVideo()
5036 || renderer()->isEmbeddedObject()
5037 || renderer()->isRenderIFrame();
5040 void RenderLayer::updateSelfPaintingLayer()
5042 bool isSelfPaintingLayer = shouldBeSelfPaintingLayer();
5043 if (m_isSelfPaintingLayer == isSelfPaintingLayer)
5046 m_isSelfPaintingLayer = isSelfPaintingLayer;
5049 if (isSelfPaintingLayer)
5050 parent()->setAncestorChainHasSelfPaintingLayerDescendant();
5052 parent()->dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
5055 void RenderLayer::updateStackingContextsAfterStyleChange(const RenderStyle* oldStyle)
5060 bool wasStackingContext = isStackingContext(oldStyle);
5061 bool isStackingContext = this->isStackingContext();
5062 if (isStackingContext != wasStackingContext) {
5063 dirtyStackingContextZOrderLists();
5064 if (isStackingContext)
5071 // FIXME: RenderLayer already handles visibility changes through our visiblity dirty bits. This logic could
5072 // likely be folded along with the rest.
5073 if (oldStyle->zIndex() != renderer()->style()->zIndex() || oldStyle->visibility() != renderer()->style()->visibility()) {
5074 dirtyStackingContextZOrderLists();
5075 if (isStackingContext)
5080 static bool overflowCanHaveAScrollbar(EOverflow overflow)
5082 return overflow == OAUTO || overflow == OSCROLL || overflow == OOVERLAY;
5085 void RenderLayer::updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle)
5087 // Overflow are a box concept.
5091 EOverflow overflowX = renderBox()->style()->overflowX();
5092 EOverflow overflowY = renderBox()->style()->overflowY();
5093 if (hasHorizontalScrollbar() && !overflowCanHaveAScrollbar(overflowX))
5094 setHasHorizontalScrollbar(false);
5095 if (hasVerticalScrollbar() && !overflowCanHaveAScrollbar(overflowY))
5096 setHasVerticalScrollbar(false);
5098 // With overflow: scroll, scrollbars are always visible but may be disabled.
5099 // When switching to another value, we need to re-enable them (see bug 11985).
5100 if (hasHorizontalScrollbar() && oldStyle->overflowX() == OSCROLL && overflowX != OSCROLL) {
5101 ASSERT(overflowCanHaveAScrollbar(overflowX));
5102 m_hBar->setEnabled(true);
5105 if (hasVerticalScrollbar() && oldStyle->overflowY() == OSCROLL && overflowY != OSCROLL) {
5106 ASSERT(overflowCanHaveAScrollbar(overflowY));
5107 m_vBar->setEnabled(true);
5110 if (!m_scrollDimensionsDirty)
5111 updateScrollableAreaSet((hasHorizontalOverflow() || hasVerticalOverflow()) && scrollsOverflow());
5114 void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
5116 bool isNormalFlowOnly = shouldBeNormalFlowOnly();
5117 if (isNormalFlowOnly != m_isNormalFlowOnly) {
5118 m_isNormalFlowOnly = isNormalFlowOnly;
5119 RenderLayer* p = parent();
5121 p->dirtyNormalFlowList();
5122 dirtyStackingContextZOrderLists();
5125 if (renderer()->style()->overflowX() == OMARQUEE && renderer()->style()->marqueeBehavior() != MNONE && renderer()->isBox()) {
5127 m_marquee = new RenderMarquee(this);
5128 m_marquee->updateMarqueeStyle();
5130 else if (m_marquee) {
5135 updateStackingContextsAfterStyleChange(oldStyle);
5136 updateScrollbarsAfterStyleChange(oldStyle);
5137 // Overlay scrollbars can make this layer self-painting so we need
5138 // to recompute the bit once scrollbars have been updated.
5139 updateSelfPaintingLayer();
5141 if (!hasReflection() && m_reflection)
5143 else if (hasReflection()) {
5146 updateReflectionStyle();
5149 // FIXME: Need to detect a swap from custom to native scrollbars (and vice versa).
5151 m_hBar->styleChanged();
5153 m_vBar->styleChanged();
5155 updateScrollCornerStyle();
5156 updateResizerStyle();
5158 #if ENABLE(CSS_FILTERS)
5159 bool backingDidCompositeLayers = isComposited() && backing()->canCompositeFilters();
5162 updateDescendantDependentFlags();
5165 #if USE(ACCELERATED_COMPOSITING)
5166 if (compositor()->updateLayerCompositingState(this))
5167 compositor()->setCompositingLayersNeedRebuild();
5168 else if (oldStyle && (oldStyle->clip() != renderer()->style()->clip() || oldStyle->hasClip() != renderer()->style()->hasClip()))
5169 compositor()->setCompositingLayersNeedRebuild();
5171 m_backing->updateGraphicsLayerGeometry();
5172 else if (oldStyle && oldStyle->overflowX() != renderer()->style()->overflowX()) {
5173 if (stackingContext()->hasCompositingDescendant())
5174 compositor()->setCompositingLayersNeedRebuild();
5178 #if ENABLE(CSS_FILTERS)
5179 updateOrRemoveFilterEffect();
5180 if (isComposited() && backingDidCompositeLayers && !backing()->canCompositeFilters()) {
5181 // The filters used to be drawn by platform code, but now the platform cannot draw them anymore.
5182 // Fallback to drawing them in software.
5183 setBackingNeedsRepaint();
5188 void RenderLayer::updateScrollableAreaSet(bool hasOverflow)
5190 Frame* frame = renderer()->frame();
5194 FrameView* frameView = frame->view();
5198 bool isVisibleToHitTest = renderer()->visibleToHitTesting();
5199 if (HTMLFrameOwnerElement* owner = frame->ownerElement())
5200 isVisibleToHitTest &= owner->renderer() && owner->renderer()->visibleToHitTesting();
5202 if (hasOverflow && isVisibleToHitTest)
5203 frameView->addScrollableArea(this);
5205 frameView->removeScrollableArea(this);
5208 void RenderLayer::updateScrollCornerStyle()
5210 RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
5211 RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, actualRenderer->style()) : PassRefPtr<RenderStyle>(0);
5213 if (!m_scrollCorner) {
5214 m_scrollCorner = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
5215 m_scrollCorner->setParent(renderer());
5217 m_scrollCorner->setStyle(corner.release());
5218 } else if (m_scrollCorner) {
5219 m_scrollCorner->destroy();
5224 void RenderLayer::updateResizerStyle()
5226 RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
5227 RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RESIZER, actualRenderer->style()) : PassRefPtr<RenderStyle>(0);
5230 m_resizer = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
5231 m_resizer->setParent(renderer());
5233 m_resizer->setStyle(resizer.release());
5234 } else if (m_resizer) {
5235 m_resizer->destroy();
5240 RenderLayer* RenderLayer::reflectionLayer() const
5242 return m_reflection ? m_reflection->layer() : 0;
5245 void RenderLayer::createReflection()
5247 ASSERT(!m_reflection);
5248 m_reflection = new (renderer()->renderArena()) RenderReplica(renderer()->document());
5249 m_reflection->setParent(renderer()); // We create a 1-way connection.
5252 void RenderLayer::removeReflection()
5254 if (!m_reflection->documentBeingDestroyed())
5255 m_reflection->removeLayers(this);
5257 m_reflection->setParent(0);
5258 m_reflection->destroy();
5262 void RenderLayer::updateReflectionStyle()
5264 RefPtr<RenderStyle> newStyle = RenderStyle::create();
5265 newStyle->inheritFrom(renderer()->style());
5267 // Map in our transform.
5268 TransformOperations transform;
5269 switch (renderer()->style()->boxReflect()->direction()) {
5270 case ReflectionBelow:
5271 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
5272 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
5273 transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
5275 case ReflectionAbove:
5276 transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
5277 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
5278 transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
5280 case ReflectionRight:
5281 transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
5282 transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
5283 transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
5285 case ReflectionLeft:
5286 transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
5287 transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
5288 transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
5291 newStyle->setTransform(transform);
5294 newStyle->setMaskBoxImage(renderer()->style()->boxReflect()->mask());
5296 m_reflection->setStyle(newStyle.release());
5299 #if ENABLE(CSS_FILTERS)
5300 void RenderLayer::updateOrRemoveFilterEffect()
5303 removeFilterInfoIfNeeded();
5307 #if ENABLE(CSS_SHADERS)
5308 if (renderer()->style()->filter().hasCustomFilter())
5309 ensureFilterInfo()->updateCustomFilterClients(renderer()->style()->filter());
5310 else if (hasFilterInfo())
5311 filterInfo()->removeCustomFilterClients();
5315 if (renderer()->style()->filter().hasReferenceFilter())
5316 ensureFilterInfo()->updateReferenceFilterClients(renderer()->style()->filter());
5317 else if (hasFilterInfo())
5318 filterInfo()->removeReferenceFilterClients();
5321 if (!paintsWithFilters()) {
5322 // Don't delete the whole filter info here, because we might use it
5323 // for loading CSS shader files.
5324 if (RenderLayerFilterInfo* filterInfo = this->filterInfo())
5325 filterInfo->setRenderer(0);
5329 RenderLayerFilterInfo* filterInfo = ensureFilterInfo();
5330 if (!filterInfo->renderer()) {
5331 RefPtr<FilterEffectRenderer> filterRenderer = FilterEffectRenderer::create();
5332 RenderingMode renderingMode = renderer()->frame()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
5333 filterRenderer->setRenderingMode(renderingMode);
5334 filterInfo->setRenderer(filterRenderer.release());
5337 // If the filter fails to build, remove it from the layer. It will still attempt to
5338 // go through regular processing (e.g. compositing), but never apply anything.
5339 if (!filterInfo->renderer()->build(renderer()->document(), renderer()->style()->filter()))
5340 filterInfo->setRenderer(0);
5343 void RenderLayer::filterNeedsRepaint()
5345 renderer()->node()->setNeedsStyleRecalc(SyntheticStyleChange);
5346 if (renderer()->view())
5347 renderer()->repaint();
5351 } // namespace WebCore
5354 void showLayerTree(const WebCore::RenderLayer* layer)
5359 if (WebCore::Frame* frame = layer->renderer()->frame()) {
5360 WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass | WebCore::RenderAsTextDontUpdateLayout | WebCore::RenderAsTextShowLayoutState);
5361 fprintf(stderr, "%s\n", output.utf8().data());
5365 void showLayerTree(const WebCore::RenderObject* renderer)
5369 showLayerTree(renderer->enclosingLayer());