1bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)/*
2bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
3bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *
4bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * Portions are Copyright (C) 1998 Netscape Communications Corporation.
5bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *
6bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * Other contributors:
7bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *   Robert O'Callahan <roc+@cs.cmu.edu>
8bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *   David Baron <dbaron@fas.harvard.edu>
9bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *   Christian Biesinger <cbiesinger@web.de>
10bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *   Randall Jesup <rjesup@wgate.com>
11bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
12bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *   Josh Soref <timeless@mac.com>
13bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *   Boris Zbarsky <bzbarsky@mit.edu>
14bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *
15bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * This library is free software; you can redistribute it and/or
16bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * modify it under the terms of the GNU Lesser General Public
17bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * License as published by the Free Software Foundation; either
18bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * version 2.1 of the License, or (at your option) any later version.
19bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *
20bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
21bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
22bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * Lesser General Public License for more details.
24bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *
25bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * You should have received a copy of the GNU Lesser General Public
26bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * License along with this library; if not, write to the Free Software
27bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) *
29bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * Alternatively, the contents of this file may be used under the terms
30bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * of either the Mozilla Public License Version 1.1, found at
31bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
32bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
33bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * (the "GPL"), in which case the provisions of the MPL or the GPL are
34bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * applicable instead of those above.  If you wish to allow use of your
35bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * version of this file only under the terms of one of those two
36bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * licenses (the MPL or the GPL) and not to allow others to use your
37bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * version of this file under the LGPL, indicate your decision by
38bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * deletingthe provisions above and replace them with the notice and
39bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * other provisions required by the MPL or the GPL, as the case may be.
40bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * If you do not delete the provisions above, a recipient may use your
41bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) * version of this file under any of the LGPL, the MPL or the GPL.
42bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) */
43bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
44bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "config.h"
45bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "core/rendering/RenderLayerClipper.h"
46bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
47bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "core/rendering/RenderLayer.h"
48bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "core/rendering/RenderView.h"
49bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
50c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
51bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
52197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstatic void adjustClipRectsForChildren(const RenderObject& renderer, ClipRects& clipRects)
53bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
54197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    EPosition position = renderer.style()->position();
55197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // A fixed object is essentially the root of its containing block hierarchy, so when
56197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // we encounter such an object, we reset our clip rects to the fixedClipRect.
57197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (position == FixedPosition) {
58197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        clipRects.setPosClipRect(clipRects.fixedClipRect());
59197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        clipRects.setOverflowClipRect(clipRects.fixedClipRect());
60197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        clipRects.setFixed(true);
61197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    } else if (position == RelativePosition) {
62197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        clipRects.setPosClipRect(clipRects.overflowClipRect());
63197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    } else if (position == AbsolutePosition) {
64197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        clipRects.setOverflowClipRect(clipRects.posClipRect());
65197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
66197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
67bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
68197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstatic void applyClipRects(const ClipRectsContext& context, RenderObject& renderer, LayoutPoint offset, ClipRects& clipRects)
69197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
70197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(renderer.hasOverflowClip() || renderer.hasClip());
71197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
72197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    RenderView* view = renderer.view();
73197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(view);
74197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (clipRects.fixed() && context.rootLayer->renderer() == view)
75197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        offset -= view->frameView()->scrollOffsetForFixedPosition();
76197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (renderer.hasOverflowClip()) {
78197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ClipRect newOverflowClip = toRenderBox(renderer).overflowClipRect(offset, context.scrollbarRelevancy);
79197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        newOverflowClip.setHasRadius(renderer.style()->hasBorderRadius());
80197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
81197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (renderer.isPositioned())
82197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
83bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
84bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
85197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (renderer.hasClip()) {
86197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        LayoutRect newClip = toRenderBox(renderer).clipRect(offset);
87197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()));
88197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect()));
89197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect()));
90197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
91197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
92bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
93197021e6b966cfb06891637935ef33fff06433d1Ben MurdochRenderLayerClipper::RenderLayerClipper(RenderLayerModelObject& renderer)
94197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    : m_renderer(renderer)
95197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
96197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
97bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
98197021e6b966cfb06891637935ef33fff06433d1Ben MurdochClipRects* RenderLayerClipper::clipRectsIfCached(const ClipRectsContext& context) const
99197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
100197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(context.usesCache());
101197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (!m_cache)
102197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return 0;
103197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ClipRectsCache::Entry& entry = m_cache->get(context.cacheSlot);
104197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // FIXME: We used to ASSERT that we always got a consistent root layer.
105197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // We should add a test that has an inconsistent root. See
106197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // http://crbug.com/366118 for an example.
107197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (context.rootLayer != entry.root)
108197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return 0;
109197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(entry.scrollbarRelevancy == context.scrollbarRelevancy);
110bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
111197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#ifdef CHECK_CACHED_CLIP_RECTS
112197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // This code is useful to check cached clip rects, but is too expensive to leave enabled in debug builds by default.
113197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ClipRectsContext tempContext(context);
114197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    tempContext.cacheSlot = UncachedClipRects;
115197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ClipRects clipRects;
116197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    calculateClipRects(tempContext, clipRects);
117197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(clipRects == *entry.clipRects);
118197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
119197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
120197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return entry.clipRects.get();
121197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
122bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
123197021e6b966cfb06891637935ef33fff06433d1Ben MurdochClipRects* RenderLayerClipper::storeClipRectsInCache(const ClipRectsContext& context, ClipRects* parentClipRects, const ClipRects& clipRects) const
124197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
125197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ClipRectsCache::Entry& entry = cache().get(context.cacheSlot);
126197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    entry.root = context.rootLayer;
127197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
128197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    entry.scrollbarRelevancy = context.scrollbarRelevancy;
129bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#endif
130197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
131197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (parentClipRects) {
132197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // If our clip rects match the clip rects of our parent, we share storage.
133197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (clipRects == *parentClipRects) {
134197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            entry.clipRects = parentClipRects;
135197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            return parentClipRects;
136197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        }
137197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
138197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
139197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    entry.clipRects = ClipRects::create(clipRects);
140197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return entry.clipRects.get();
141bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
142bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
143197021e6b966cfb06891637935ef33fff06433d1Ben MurdochClipRects* RenderLayerClipper::getClipRects(const ClipRectsContext& context) const
144197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
145197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (ClipRects* result = clipRectsIfCached(context))
146197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return result;
147197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
148197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // Note that it's important that we call getClipRects on our parent
149197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // before we call calculateClipRects so that calculateClipRects will hit
150197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // the cache.
151197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ClipRects* parentClipRects = 0;
152197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (context.rootLayer != m_renderer.layer() && m_renderer.layer()->parent())
153197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        parentClipRects = m_renderer.layer()->parent()->clipper().getClipRects(context);
154197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
155197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ClipRects clipRects;
156197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    calculateClipRects(context, clipRects);
157197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return storeClipRectsInCache(context, parentClipRects, clipRects);
158197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
159197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
160197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid RenderLayerClipper::clearClipRectsIncludingDescendants()
161bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
162197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    m_cache = nullptr;
163bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
164f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    for (RenderLayer* layer = m_renderer.layer()->firstChild(); layer; layer = layer->nextSibling())
165197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        layer->clipper().clearClipRectsIncludingDescendants();
166bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
167bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
168197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid RenderLayerClipper::clearClipRectsIncludingDescendants(ClipRectsCacheSlot cacheSlot)
169bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
1707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (m_cache)
1717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_cache->clear(cacheSlot);
172197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
173197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    for (RenderLayer* layer = m_renderer.layer()->firstChild(); layer; layer = layer->nextSibling())
174197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        layer->clipper().clearClipRectsIncludingDescendants(cacheSlot);
175bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
176bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
17709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)LayoutRect RenderLayerClipper::childrenClipRect() const
17809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
17909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // FIXME: border-radius not accounted for.
18009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // FIXME: Regions not accounted for.
18109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RenderLayer* clippingRootLayer = clippingRootForPainting();
18209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    LayoutRect layerBounds;
18309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ClipRect backgroundRect, foregroundRect, outlineRect;
184197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // Need to use uncached clip rects, because the value of 'dontClipToOverflow' may be different from the painting path (<rdar://problem/11844909>).
185197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ClipRectsContext context(clippingRootLayer, UncachedClipRects);
186197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    calculateRects(context, m_renderer.view()->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
18709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect.rect())).enclosingBoundingBox();
18809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
18909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
19009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)LayoutRect RenderLayerClipper::localClipRect() const
19109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
19209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // FIXME: border-radius not accounted for.
19309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RenderLayer* clippingRootLayer = clippingRootForPainting();
19409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    LayoutRect layerBounds;
19509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ClipRect backgroundRect, foregroundRect, outlineRect;
196197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ClipRectsContext context(clippingRootLayer, PaintingClipRects);
197197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    calculateRects(context, PaintInfo::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
19809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
19909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    LayoutRect clipRect = backgroundRect.rect();
20009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (clipRect == PaintInfo::infiniteRect())
20109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return clipRect;
20209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
20309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    LayoutPoint clippingRootOffset;
204f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    m_renderer.layer()->convertToLayerCoords(clippingRootLayer, clippingRootOffset);
20509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    clipRect.moveBy(-clippingRootOffset);
20609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
20709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return clipRect;
20809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
20909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
210197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid RenderLayerClipper::calculateRects(const ClipRectsContext& context, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
21109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot) const
21209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
213197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    bool isClippingRoot = m_renderer.layer() == context.rootLayer;
21407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
215f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (!isClippingRoot && m_renderer.layer()->parent()) {
216197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        backgroundRect = backgroundClipRect(context);
217197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        backgroundRect.move(roundedIntSize(context.subPixelAccumulation));
21809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        backgroundRect.intersect(paintDirtyRect);
21909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else {
22009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        backgroundRect = paintDirtyRect;
22109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
22209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
22309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    foregroundRect = backgroundRect;
22409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    outlineRect = backgroundRect;
22509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
22609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    LayoutPoint offset;
22709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (offsetFromRoot)
22809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        offset = *offsetFromRoot;
22909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    else
230197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_renderer.layer()->convertToLayerCoords(context.rootLayer, offset);
231f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    layerBounds = LayoutRect(offset, m_renderer.layer()->size());
23209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Update the clip rects that will be passed to child layers.
234f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (m_renderer.hasOverflowClip()) {
23509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // This layer establishes a clip of some kind.
236197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (!isClippingRoot || context.respectOverflowClip == RespectOverflowClip) {
237197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            foregroundRect.intersect(toRenderBox(m_renderer).overflowClipRect(offset, context.scrollbarRelevancy));
238f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            if (m_renderer.style()->hasBorderRadius())
23909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                foregroundRect.setHasRadius(true);
24009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
24109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
24209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // If we establish an overflow clip at all, then go ahead and make sure our background
24309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // rect is intersected with our layer's bounds including our visual overflow,
24409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // since any visual overflow like box-shadow or border-outset is not clipped by overflow:auto/hidden.
245f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        if (toRenderBox(m_renderer).hasVisualOverflow()) {
24609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            // FIXME: Perhaps we should be propagating the borderbox as the clip rect for children, even though
24709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            //        we may need to inflate our clip specifically for shadows or outsets.
24809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            // FIXME: Does not do the right thing with CSS regions yet, since we don't yet factor in the
24909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            // individual region boxes as overflow.
250f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            LayoutRect layerBoundsWithVisualOverflow = toRenderBox(m_renderer).visualOverflowRect();
251f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            toRenderBox(m_renderer).flipForWritingMode(layerBoundsWithVisualOverflow); // Layers are in physical coordinates, so the overflow has to be flipped.
25209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            layerBoundsWithVisualOverflow.moveBy(offset);
253197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            if (!isClippingRoot || context.respectOverflowClip == RespectOverflowClip)
25409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                backgroundRect.intersect(layerBoundsWithVisualOverflow);
25509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        } else {
256f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            LayoutRect bounds = toRenderBox(m_renderer).borderBoxRect();
25709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            bounds.moveBy(offset);
258197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            if (!isClippingRoot || context.respectOverflowClip == RespectOverflowClip)
25909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                backgroundRect.intersect(bounds);
26009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
26109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
26209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
26309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // CSS clip (different than clipping due to overflow) can clip to any box, even if it falls outside of the border box.
264f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (m_renderer.hasClip()) {
26509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // Clip applies to *us* as well, so go ahead and update the damageRect.
266f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        LayoutRect newPosClip = toRenderBox(m_renderer).clipRect(offset);
26709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        backgroundRect.intersect(newPosClip);
26809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        foregroundRect.intersect(newPosClip);
26909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        outlineRect.intersect(newPosClip);
27009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
27109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
27209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
273197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid RenderLayerClipper::calculateClipRects(const ClipRectsContext& context, ClipRects& clipRects) const
274bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
275f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (!m_renderer.layer()->parent()) {
276bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        // The root layer's clip rect is always infinite.
277bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        clipRects.reset(PaintInfo::infiniteRect());
278bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return;
279bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
280bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
281197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    bool isClippingRoot = m_renderer.layer() == context.rootLayer;
28207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
283bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    // For transformed layers, the root layer was shifted to be us, so there is no need to
284bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    // examine the parent. We want to cache clip rects with us as the root.
285f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    RenderLayer* parentLayer = !isClippingRoot ? m_renderer.layer()->parent() : 0;
286bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
287bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    // Ensure that our parent's clip has been calculated so that we can examine the values.
288bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (parentLayer) {
289197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // FIXME: Why don't we just call getClipRects here?
290197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (context.usesCache() && parentLayer->clipper().cachedClipRects(context)) {
291197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            clipRects = *parentLayer->clipper().cachedClipRects(context);
292bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        } else {
293197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            parentLayer->clipper().calculateClipRects(context, clipRects);
294bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        }
295bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    } else {
296bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        clipRects.reset(PaintInfo::infiniteRect());
297bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
298bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
299197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    adjustClipRectsForChildren(m_renderer, clipRects);
300bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
301197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // FIXME: This logic looks wrong. We'll apply overflow clip rects even if we were told to IgnoreOverflowClip if m_renderer.hasClip().
302197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if ((m_renderer.hasOverflowClip() && (context.respectOverflowClip == RespectOverflowClip || !isClippingRoot)) || m_renderer.hasClip()) {
303bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        // This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across
304bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        // some transformed layer boundary, for example, in the RenderLayerCompositor overlapMap, where
305bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        // clipRects are needed in view space.
306197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        applyClipRects(context, m_renderer, roundedLayoutPoint(m_renderer.localToContainerPoint(FloatPoint(), context.rootLayer->renderer())), clipRects);
307bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
308bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
309bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
310197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstatic ClipRect backgroundClipRectForPosition(const ClipRects& parentRects, EPosition position)
31109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
31209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (position == FixedPosition)
31309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return parentRects.fixedClipRect();
31409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
31509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (position == AbsolutePosition)
31609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return parentRects.posClipRect();
31709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
31809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return parentRects.overflowClipRect();
31909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
32009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
321197021e6b966cfb06891637935ef33fff06433d1Ben MurdochClipRect RenderLayerClipper::backgroundClipRect(const ClipRectsContext& context) const
32209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
323f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    ASSERT(m_renderer.layer()->parent());
324197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(m_renderer.view());
32509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
326197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ClipRects parentClipRects;
327197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (m_renderer.layer() == context.rootLayer)
328197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        parentClipRects.reset(PaintInfo::infiniteRect());
329197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    else
330197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_renderer.layer()->parent()->clipper().getOrCalculateClipRects(context, parentClipRects);
33109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
332197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ClipRect result = backgroundClipRectForPosition(parentClipRects, m_renderer.style()->position());
33309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
33409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite.
335197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (parentClipRects.fixed() && context.rootLayer->renderer() == m_renderer.view() && result != PaintInfo::infiniteRect())
336197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        result.move(m_renderer.view()->frameView()->scrollOffsetForFixedPosition());
33709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
338197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return result;
33909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
34009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
341197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid RenderLayerClipper::getOrCalculateClipRects(const ClipRectsContext& context, ClipRects& clipRects) const
34207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch{
343197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (context.usesCache())
344197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        clipRects = *getClipRects(context);
345197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    else
346197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        calculateClipRects(context, clipRects);
34709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
34809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
34909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)RenderLayer* RenderLayerClipper::clippingRootForPainting() const
35009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
351f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    const RenderLayer* current = m_renderer.layer();
352197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // FIXME: getting rid of current->hasCompositedLayerMapping() here breaks the
353197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // compositing/backing/no-backing-for-clip.html layout test, because there is a
354197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // "composited but paints into ancestor" layer involved. However, it doesn't make sense that
355197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // that check would be appropriate here but not inside the while loop below.
356197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (current->isPaintInvalidationContainer() || current->hasCompositedLayerMapping())
357197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return const_cast<RenderLayer*>(current);
358197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
35909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    while (current) {
36009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (current->isRootLayer())
36109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return const_cast<RenderLayer*>(current);
36209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
36309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        current = current->compositingContainer();
36409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT(current);
365197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (current->transform() || current->isPaintInvalidationContainer())
36609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return const_cast<RenderLayer*>(current);
36709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
36809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
36909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT_NOT_REACHED();
37009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return 0;
37109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
37209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
373c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
374