RenderLayer.cpp 151 KB
Newer Older
gramps's avatar
gramps committed
1
/*
2
 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3
 *
gramps's avatar
gramps committed
4 5 6 7 8 9 10 11 12 13 14
 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
 *
 * Other contributors:
 *   Robert O'Callahan <roc+@cs.cmu.edu>
 *   David Baron <dbaron@fas.harvard.edu>
 *   Christian Biesinger <cbiesinger@web.de>
 *   Randall Jesup <rjesup@wgate.com>
 *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
 *   Josh Soref <timeless@mac.com>
 *   Boris Zbarsky <bzbarsky@mit.edu>
 *
15
 * This library is free software; you can redistribute it and/or
gramps's avatar
gramps committed
16
 * modify it under the terms of the GNU Lesser General Public
17
 * License as published by the Free Software Foundation; either
gramps's avatar
gramps committed
18
 * version 2.1 of the License, or (at your option) any later version.
19 20 21 22
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
gramps's avatar
gramps committed
23
 * Lesser General Public License for more details.
24
 *
gramps's avatar
gramps committed
25 26
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
ddkilzer's avatar
ddkilzer committed
27
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28
 *
gramps's avatar
gramps committed
29 30 31 32 33 34 35 36 37 38 39 40 41
 * Alternatively, the contents of this file may be used under the terms
 * of either the Mozilla Public License Version 1.1, found at
 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
 * (the "GPL"), in which case the provisions of the MPL or the GPL are
 * applicable instead of those above.  If you wish to allow use of your
 * version of this file only under the terms of one of those two
 * licenses (the MPL or the GPL) and not to allow others to use your
 * version of this file under the LGPL, indicate your decision by
 * deletingthe provisions above and replace them with the notice and
 * other provisions required by the MPL or the GPL, as the case may be.
 * If you do not delete the provisions above, a recipient may use your
 * version of this file under any of the LGPL, the MPL or the GPL.
42 43
 */

mjs's avatar
mjs committed
44
#include "config.h"
darin's avatar
darin committed
45
#include "RenderLayer.h"
darin's avatar
darin committed
46

adele's avatar
adele committed
47
#include "CSSPropertyNames.h"
darin@apple.com's avatar
darin@apple.com committed
48
#include "CSSStyleDeclaration.h"
49
#include "CSSStyleSelector.h"
50
#include "Chrome.h"
weinig's avatar
 
weinig committed
51
#include "Document.h"
darin's avatar
darin committed
52
#include "EventHandler.h"
mjs's avatar
mjs committed
53
#include "EventNames.h"
54
#include "FloatPoint3D.h"
mjs's avatar
mjs committed
55
#include "FloatRect.h"
56
#include "FocusController.h"
adele's avatar
adele committed
57
#include "Frame.h"
mjs's avatar
mjs committed
58
#include "FrameTree.h"
darin@apple.com's avatar
darin@apple.com committed
59
#include "FrameView.h"
hyatt@apple.com's avatar
hyatt@apple.com committed
60
#include "Gradient.h"
darin's avatar
darin committed
61
#include "GraphicsContext.h"
62
#include "HTMLFrameOwnerElement.h"
darin's avatar
darin committed
63
#include "HTMLNames.h"
bdakin's avatar
bdakin committed
64
#include "HitTestRequest.h"
bdakin's avatar
bdakin committed
65
#include "HitTestResult.h"
andersca's avatar
andersca committed
66
#include "OverflowEvent.h"
mitz@apple.com's avatar
mitz@apple.com committed
67
#include "OverlapTestRequestClient.h"
68
#include "Page.h"
adele's avatar
adele committed
69
#include "PlatformMouseEvent.h"
darin's avatar
darin committed
70 71
#include "RenderArena.h"
#include "RenderInline.h"
72
#include "RenderMarquee.h"
hyatt@apple.com's avatar
hyatt@apple.com committed
73
#include "RenderReplica.h"
hyatt@apple.com's avatar
hyatt@apple.com committed
74
#include "RenderScrollbar.h"
75
#include "RenderScrollbarPart.h"
darin's avatar
darin committed
76
#include "RenderTheme.h"
77
#include "RenderTreeAsText.h"
weinig's avatar
 
weinig committed
78
#include "RenderView.h"
79
#include "ScaleTransformOperation.h"
80
#include "Scrollbar.h"
81
#include "ScrollbarTheme.h"
hyatt@apple.com's avatar
hyatt@apple.com committed
82
#include "SelectionController.h"
83
#include "TextStream.h"
84
#include "TransformState.h"
85
#include "TransformationMatrix.h"
86
#include "TranslateTransformOperation.h"
87
#include <wtf/StdLibExtras.h>
88
#include <wtf/UnusedParam.h>
89
#include <wtf/text/CString.h>
90

91 92 93 94 95
#if USE(ACCELERATED_COMPOSITING)
#include "RenderLayerBacking.h"
#include "RenderLayerCompositor.h"
#endif

mjs's avatar
mjs committed
96
#if ENABLE(SVG)
eseidel's avatar
eseidel committed
97 98 99
#include "SVGNames.h"
#endif

adele's avatar
adele committed
100 101
#define MIN_INTERSECT_FOR_REVEAL 32

darin's avatar
darin committed
102 103
using namespace std;

104
namespace WebCore {
darin's avatar
darin committed
105

106
using namespace HTMLNames;
107

adele's avatar
adele committed
108 109 110
const int MinimumWidthWhileResizing = 100;
const int MinimumHeightWhileResizing = 40;

111 112 113 114 115 116 117
void* ClipRects::operator new(size_t sz, RenderArena* renderArena) throw()
{
    return renderArena->allocate(sz);
}

void ClipRects::operator delete(void* ptr, size_t sz)
{
harrison's avatar
harrison committed
118
    // Stash size where destroy can find it.
119 120 121
    *(size_t *)ptr = sz;
}

harrison's avatar
harrison committed
122
void ClipRects::destroy(RenderArena* renderArena)
123 124 125 126 127 128 129
{
    delete this;
    
    // Recover the size left there for us by operator delete and free the memory.
    renderArena->free(*(size_t *)this, this);
}

130
RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
131
    : m_renderer(renderer)
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    , m_parent(0)
    , m_previous(0)
    , m_next(0)
    , m_first(0)
    , m_last(0)
    , m_relX(0)
    , m_relY(0)
    , m_x(0)
    , m_y(0)
    , m_width(0)
    , m_height(0)
    , m_scrollX(0)
    , m_scrollY(0)
    , m_scrollOriginX(0)
    , m_scrollLeftOverflow(0)
    , m_scrollWidth(0)
    , m_scrollHeight(0)
    , m_inResizeMode(false)
    , m_posZOrderList(0)
    , m_negZOrderList(0)
152
    , m_normalFlowList(0)
153
    , m_clipRects(0) 
154 155 156
#ifndef NDEBUG    
    , m_clipRectsRoot(0)
#endif
157 158
    , m_scrollDimensionsDirty(true)
    , m_zOrderListsDirty(true)
159 160
    , m_normalFlowListDirty(true)
    , m_isNormalFlowOnly(shouldBeNormalFlowOnly())
161
    , m_usedTransparency(false)
hyatt@apple.com's avatar
hyatt@apple.com committed
162
    , m_paintingInsideReflection(false)
163
    , m_inOverflowRelayout(false)
thatcher's avatar
thatcher committed
164
    , m_needsFullRepaint(false)
165 166 167 168 169
    , m_overflowStatusDirty(true)
    , m_visibleContentStatusDirty(true)
    , m_hasVisibleContent(false)
    , m_visibleDescendantStatusDirty(false)
    , m_hasVisibleDescendant(false)
170
    , m_isPaginated(false)
171 172
    , m_3DTransformedDescendantStatusDirty(true)
    , m_has3DTransformedDescendant(false)
173 174
#if USE(ACCELERATED_COMPOSITING)
    , m_hasCompositingDescendant(false)
175
    , m_mustOverlapCompositedLayers(false)
176
#endif
177
    , m_marquee(0)
antti's avatar
antti committed
178 179
    , m_staticX(0)
    , m_staticY(0)
hyatt@apple.com's avatar
hyatt@apple.com committed
180
    , m_reflection(0)
181 182
    , m_scrollCorner(0)
    , m_resizer(0)
183
{
184
    if (!renderer->firstChild() && renderer->style()) {
antti's avatar
antti committed
185
        m_visibleContentStatusDirty = false;
186
        m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
antti's avatar
antti committed
187
    }
188 189 190 191
}

RenderLayer::~RenderLayer()
{
192
    if (inResizeMode() && !renderer()->documentBeingDestroyed()) {
193
        if (Frame* frame = renderer()->frame())
mitz@apple.com's avatar
mitz@apple.com committed
194 195 196
            frame->eventHandler()->resizeLayerDestroyed();
    }

ggaren's avatar
ggaren committed
197 198 199
    destroyScrollbar(HorizontalScrollbar);
    destroyScrollbar(VerticalScrollbar);

200
    // Child layers will be deleted by their corresponding render objects, so
ggaren's avatar
ggaren committed
201 202
    // we don't need to delete them ourselves.

203 204
    delete m_posZOrderList;
    delete m_negZOrderList;
205
    delete m_normalFlowList;
206
    delete m_marquee;
207

208 209 210 211
#if USE(ACCELERATED_COMPOSITING)
    clearBacking();
#endif
    
212
    // Make sure we have no lingering clip rects.
ggaren's avatar
ggaren committed
213
    ASSERT(!m_clipRects);
hyatt@apple.com's avatar
hyatt@apple.com committed
214
    
215 216
    if (m_reflection)
        removeReflection();
217 218 219 220 221
    
    if (m_scrollCorner)
        m_scrollCorner->destroy();
    if (m_resizer)
        m_resizer->destroy();
222 223
}

224 225 226
#if USE(ACCELERATED_COMPOSITING)
RenderLayerCompositor* RenderLayer::compositor() const
{
227
    ASSERT(renderer()->view());
228 229
    return renderer()->view()->compositor();
}
230

231 232
void RenderLayer::rendererContentChanged()
{
233 234
    // This can get called when video becomes accelerated, so the layers may change.
    if (compositor()->updateLayerCompositingState(this))
235
        compositor()->setCompositingLayersNeedRebuild();
236

237 238
    if (m_backing)
        m_backing->rendererContentChanged();
239
}
240 241
#endif // USE(ACCELERATED_COMPOSITING)

242 243 244 245 246 247 248 249 250
bool RenderLayer::hasAcceleratedCompositing() const
{
#if USE(ACCELERATED_COMPOSITING)
    return compositor()->hasAcceleratedCompositing();
#else
    return false;
#endif
}

251
void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint* cachedOffset)
252
{
253
    if (flags & DoFullRepaint) {
254
        renderer()->repaint();
255
#if USE(ACCELERATED_COMPOSITING)
256
        flags &= ~CheckForRepaint;
257 258
        // We need the full repaint to propagate to child layers if we are hardware compositing.
        if (!compositor()->inCompositingMode())
259
            flags &= ~DoFullRepaint;
260
#else
261
        flags &= ~(CheckForRepaint | DoFullRepaint);
262
#endif
263 264
    }
    
265

266 267 268
    updateLayerPosition(); // For relpositioned layers or non-positioned layers,
                           // we need to keep in sync, since we may have shifted relative
                           // to our parent layer.
269 270 271
    IntPoint oldCachedOffset;
    if (cachedOffset) {
        // We can't cache our offset to the repaint container if the mapping is anything more complex than a simple translation
272 273 274 275
        bool disableOffsetCache = renderer()->hasColumns() || renderer()->hasTransform() || isComposited();
#if ENABLE(SVG)
        disableOffsetCache = disableOffsetCache || renderer()->isSVGRoot();
#endif
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
        if (disableOffsetCache)
            cachedOffset = 0; // If our cached offset is invalid make sure it's not passed to any of our children
        else {
            oldCachedOffset = *cachedOffset;
            // Frequently our parent layer's renderer will be the same as our renderer's containing block.  In that case,
            // we just update the cache using our offset to our parent (which is m_x / m_y).  Otherwise, regenerated cached
            // offsets to the root from the render tree.
            if (!m_parent || m_parent->renderer() == renderer()->containingBlock())
                cachedOffset->move(m_x, m_y); // Fast case
            else {
                int x = 0;
                int y = 0;
                convertToLayerCoords(root(), x, y);
                *cachedOffset = IntPoint(x, y);
            }
        }
    }
293

294 295
    int x = 0;
    int y = 0;
296 297 298 299 300 301 302 303 304 305 306 307
    if (cachedOffset) {
        x += cachedOffset->x();
        y += cachedOffset->y();
#ifndef NDEBUG
        int nonCachedX = 0;
        int nonCachedY = 0;
        convertToLayerCoords(root(), nonCachedX, nonCachedY);
        ASSERT(x == nonCachedX);
        ASSERT(y == nonCachedY);
#endif
    } else
        convertToLayerCoords(root(), x, y);
308
    positionOverflowControls(x, y);
309

antti's avatar
antti committed
310
    updateVisibilityStatus();
311 312

    updateTransform();
313 314 315 316 317 318

    if (flags & UpdatePagination)
        updatePagination();
    else
        m_isPaginated = false;

antti's avatar
antti committed
319
    if (m_hasVisibleContent) {
320
        RenderView* view = renderer()->view();
weinig's avatar
weinig committed
321 322 323
        ASSERT(view);
        // FIXME: Optimize using LayoutState and remove the disableLayoutState() call
        // from updateScrollInfoAfterLayout().
324
        ASSERT(!view->layoutStateEnabled());
weinig's avatar
weinig committed
325

326
        RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
327
        IntRect newRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
328
        IntRect newOutlineBox = renderer()->outlineBoundsForRepaint(repaintContainer, cachedOffset);
329 330
        // FIXME: Should ASSERT that value calculated for newOutlineBox using the cached offset is the same
        // as the value not using the cached offset, but we can't due to https://bugs.webkit.org/show_bug.cgi?id=37048
331
        if (flags & CheckForRepaint) {
332
            if (view && !view->printing()) {
thatcher's avatar
thatcher committed
333
                if (m_needsFullRepaint) {
334
                    renderer()->repaintUsingContainer(repaintContainer, m_repaintRect);
thatcher's avatar
thatcher committed
335
                    if (newRect != m_repaintRect)
336
                        renderer()->repaintUsingContainer(repaintContainer, newRect);
thatcher's avatar
thatcher committed
337
                } else
338
                    renderer()->repaintAfterLayoutIfNeeded(repaintContainer, m_repaintRect, m_outlineBox, &newRect, &newOutlineBox);
339 340
            }
        }
ddkilzer's avatar
ddkilzer committed
341
        m_repaintRect = newRect;
342
        m_outlineBox = newOutlineBox;
ddkilzer's avatar
ddkilzer committed
343 344
    } else {
        m_repaintRect = IntRect();
345
        m_outlineBox = IntRect();
346
    }
thatcher's avatar
thatcher committed
347 348

    m_needsFullRepaint = false;
hyatt@apple.com's avatar
hyatt@apple.com committed
349 350 351 352 353

    // Go ahead and update the reflection's position and size.
    if (m_reflection)
        m_reflection->layout();

354 355 356 357 358 359 360
#if USE(ACCELERATED_COMPOSITING)
    // Clear the IsCompositingUpdateRoot flag once we've found the first compositing layer in this update.
    bool isUpdateRoot = (flags & IsCompositingUpdateRoot);
    if (isComposited())
        flags &= ~IsCompositingUpdateRoot;
#endif

361 362 363
    if (renderer()->hasColumns())
        flags |= UpdatePagination;

364
    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
365
        child->updateLayerPositions(flags, cachedOffset);
366 367

#if USE(ACCELERATED_COMPOSITING)
368
    if ((flags & UpdateCompositingLayers) && isComposited())
369
        backing()->updateAfterLayout(RenderLayerBacking::CompositingChildren, isUpdateRoot);
370
#endif
371 372 373 374
        
    // With all our children positioned, now update our marquee if we need to.
    if (m_marquee)
        m_marquee->updateMarqueePosition();
375 376 377

    if (cachedOffset)
        *cachedOffset = oldCachedOffset;
378 379
}

380 381 382 383 384 385 386 387
IntRect RenderLayer::repaintRectIncludingDescendants() const
{
    IntRect repaintRect = m_repaintRect;
    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
        repaintRect.unite(child->repaintRectIncludingDescendants());
    return repaintRect;
}

388 389 390 391 392 393 394
void RenderLayer::computeRepaintRects()
{
    RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
    m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
    m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
}

395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
void RenderLayer::updateRepaintRectsAfterScroll(bool fixed)
{
    if (fixed || renderer()->style()->position() == FixedPosition) {
        computeRepaintRects();
        fixed = true;
    } else if (renderer()->hasTransform()) {
        // Transforms act as fixed position containers, so nothing inside a
        // transformed element can be fixed relative to the viewport if the
        // transformed element is not fixed itself or child of a fixed element.
        return;
    }

    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
        child->updateRepaintRectsAfterScroll(fixed);
}

411 412
void RenderLayer::updateTransform()
{
413 414 415
    // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
    // so check style too.
    bool hasTransform = renderer()->hasTransform() && renderer()->style()->hasTransform();
416 417
    bool had3DTransform = has3DTransform();

418 419 420
    bool hadTransform = m_transform;
    if (hasTransform != hadTransform) {
        if (hasTransform)
421
            m_transform.set(new TransformationMatrix);
422 423 424 425 426
        else
            m_transform.clear();
    }
    
    if (hasTransform) {
427 428
        RenderBox* box = renderBox();
        ASSERT(box);
429
        m_transform->makeIdentity();
430
        box->style()->applyTransform(*m_transform, box->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
431
        makeMatrixRenderable(*m_transform, hasAcceleratedCompositing());
432
    }
433 434 435

    if (had3DTransform != has3DTransform())
        dirty3DTransformedDescendantStatus();
436 437
}

438 439 440 441 442 443 444 445 446 447
TransformationMatrix RenderLayer::currentTransform() const
{
    if (!m_transform)
        return TransformationMatrix();

#if USE(ACCELERATED_COMPOSITING)
    if (renderer()->style()->isRunningAcceleratedAnimation()) {
        TransformationMatrix currTransform;
        RefPtr<RenderStyle> style = renderer()->animation()->getAnimatedStyleForRenderer(renderer());
        style->applyTransform(currTransform, renderBox()->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
448
        makeMatrixRenderable(currTransform, hasAcceleratedCompositing());
449 450 451 452 453 454 455
        return currTransform;
    }
#endif

    return *m_transform;
}

456 457 458 459 460 461 462 463 464 465 466 467 468 469
TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const
{
    if (!m_transform)
        return TransformationMatrix();
    
    if (paintBehavior & PaintBehaviorFlattenCompositingLayers) {
        TransformationMatrix matrix = *m_transform;
        makeMatrixRenderable(matrix, false /* flatten 3d */);
        return matrix;
    }

    return *m_transform;
}

470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
void RenderLayer::updatePagination()
{
    m_isPaginated = false;
    if (isComposited() || !parent() || renderer()->isPositioned())
        return; // FIXME: We will have to deal with paginated compositing layers someday.
                // FIXME: For now the RenderView can't be paginated.  Eventually printing will move to a model where it is though.
    
    if (isNormalFlowOnly()) {
        m_isPaginated = parent()->renderer()->hasColumns();
        return;
    }

    // If we're not normal flow, then we need to look for a multi-column object between us and our stacking context.
    RenderLayer* ancestorStackingContext = stackingContext();
    for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
        if (curr->renderer()->hasColumns()) {
            m_isPaginated = true;
            return;
        }
        if (curr == ancestorStackingContext || (curr->parent() && curr->parent()->renderer()->isPositioned()))
            return;
    }
}

mitz@apple.com's avatar
mitz@apple.com committed
494
void RenderLayer::setHasVisibleContent(bool b)
antti's avatar
antti committed
495 496 497 498 499
{ 
    if (m_hasVisibleContent == b && !m_visibleContentStatusDirty)
        return;
    m_visibleContentStatusDirty = false; 
    m_hasVisibleContent = b;
pewtermoose's avatar
pewtermoose committed
500
    if (m_hasVisibleContent) {
501
        RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
502 503
        m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
        m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
504
        if (!isNormalFlowOnly())
505
            dirtyStackingContextZOrderLists();
pewtermoose's avatar
pewtermoose committed
506
    }
antti's avatar
antti committed
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
    if (parent())
        parent()->childVisibilityChanged(m_hasVisibleContent);
}

void RenderLayer::dirtyVisibleContentStatus() 
{ 
    m_visibleContentStatusDirty = true; 
    if (parent())
        parent()->dirtyVisibleDescendantStatus();
}

void RenderLayer::childVisibilityChanged(bool newVisibility) 
{ 
    if (m_hasVisibleDescendant == newVisibility || m_visibleDescendantStatusDirty)
        return;
    if (newVisibility) {
        RenderLayer* l = this;
        while (l && !l->m_visibleDescendantStatusDirty && !l->m_hasVisibleDescendant) {
            l->m_hasVisibleDescendant = true;
            l = l->parent();
        }
    } else 
        dirtyVisibleDescendantStatus();
}

void RenderLayer::dirtyVisibleDescendantStatus()
{
    RenderLayer* l = this;
    while (l && !l->m_visibleDescendantStatusDirty) {
        l->m_visibleDescendantStatusDirty = true;
        l = l->parent();
    }
}

void RenderLayer::updateVisibilityStatus()
{
    if (m_visibleDescendantStatusDirty) {
        m_hasVisibleDescendant = false;
        for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
            child->updateVisibilityStatus();        
            if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) {
                m_hasVisibleDescendant = true;
                break;
            }
        }
        m_visibleDescendantStatusDirty = false;
    }

    if (m_visibleContentStatusDirty) {
556
        if (renderer()->style()->visibility() == VISIBLE)
antti's avatar
antti committed
557 558 559 560
            m_hasVisibleContent = true;
        else {
            // layer may be hidden but still have some visible content, check for this
            m_hasVisibleContent = false;
561
            RenderObject* r = renderer()->firstChild();
antti's avatar
antti committed
562
            while (r) {
darin's avatar
darin committed
563
                if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
antti's avatar
antti committed
564 565 566
                    m_hasVisibleContent = true;
                    break;
                }
darin's avatar
darin committed
567
                if (r->firstChild() && !r->hasLayer())
antti's avatar
antti committed
568
                    r = r->firstChild();
antti's avatar
antti committed
569
                else if (r->nextSibling())
antti's avatar
antti committed
570 571
                    r = r->nextSibling();
                else {
antti's avatar
antti committed
572
                    do {
antti's avatar
antti committed
573
                        r = r->parent();
574
                        if (r == renderer())
antti's avatar
antti committed
575
                            r = 0;
antti's avatar
antti committed
576
                    } while (r && !r->nextSibling());
antti's avatar
antti committed
577 578 579 580 581 582 583 584 585
                    if (r)
                        r = r->nextSibling();
                }
            }
        }    
        m_visibleContentStatusDirty = false; 
    }
}

586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
void RenderLayer::dirty3DTransformedDescendantStatus()
{
    RenderLayer* curr = stackingContext();
    if (curr)
        curr->m_3DTransformedDescendantStatusDirty = true;
        
    // This propagates up through preserve-3d hierarchies to the enclosing flattening layer.
    // Note that preserves3D() creates stacking context, so we can just run up the stacking contexts.
    while (curr && curr->preserves3D()) {
        curr->m_3DTransformedDescendantStatusDirty = true;
        curr = curr->stackingContext();
    }
}

// Return true if this layer or any preserve-3d descendants have 3d.
bool RenderLayer::update3DTransformedDescendantStatus()
{
    if (m_3DTransformedDescendantStatusDirty) {
        m_has3DTransformedDescendant = false;

        // Transformed or preserve-3d descendants can only be in the z-order lists, not
        // in the normal flow list, so we only need to check those.
        if (m_posZOrderList) {
            for (unsigned i = 0; i < m_posZOrderList->size(); ++i)
                m_has3DTransformedDescendant |= m_posZOrderList->at(i)->update3DTransformedDescendantStatus();
        }

        // Now check our negative z-index children.
        if (m_negZOrderList) {
            for (unsigned i = 0; i < m_negZOrderList->size(); ++i)
                m_has3DTransformedDescendant |= m_negZOrderList->at(i)->update3DTransformedDescendantStatus();
        }
618 619
        
        m_3DTransformedDescendantStatusDirty = false;
620 621 622 623 624 625 626 627 628 629
    }
    
    // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs
    // the m_has3DTransformedDescendant set.
    if (preserves3D())
        return has3DTransform() || m_has3DTransformedDescendant;

    return has3DTransform();
}

630 631
void RenderLayer::updateLayerPosition()
{
632 633 634 635 636 637 638 639 640 641 642 643
    IntPoint localPoint;
    IntSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done.
    if (renderer()->isRenderInline()) {
        RenderInline* inlineFlow = toRenderInline(renderer());
        IntRect lineBox = inlineFlow->linesBoundingBox();
        setWidth(lineBox.width());
        setHeight(lineBox.height());
        inlineBoundingBoxOffset = IntSize(lineBox.x(), lineBox.y());
        localPoint += inlineBoundingBoxOffset;
    } else if (RenderBox* box = renderBox()) {
        setWidth(box->width());
        setHeight(box->height());
644

645 646 647 648 649 650 651 652 653
        if (!box->hasOverflowClip()) {
            if (box->rightLayoutOverflow() > box->width())
                setWidth(box->rightLayoutOverflow());
            if (box->bottomLayoutOverflow() > box->height())
                setHeight(box->bottomLayoutOverflow());
        }
        
        localPoint += box->locationOffset();
    }
654

655 656 657
    // Clear our cached clip rect information.
    clearClipRects();
 
658
    if (!renderer()->isPositioned() && renderer()->parent()) {
659 660
        // We must adjust our position by walking up the render tree looking for the
        // nearest enclosing object with a layer.
661
        RenderObject* curr = renderer()->parent();
darin's avatar
darin committed
662
        while (curr && !curr->hasLayer()) {
663
            if (curr->isBox() && !curr->isTableRow()) {
664 665
                // Rows and cells share the same coordinate space (that of the section).
                // Omit them when computing our xpos/ypos.
666
                localPoint += toRenderBox(curr)->locationOffset();
667
            }
668
            curr = curr->parent();
669
        }
670
        if (curr->isBox() && curr->isTableRow()) {
671
            // Put ourselves into the row coordinate space.
672
            localPoint -= toRenderBox(curr)->locationOffset();
673
        }
674
    }
675
    
676
    // Subtract our parent's scroll offset.
677
    if (renderer()->isPositioned() && enclosingPositionedAncestor()) {
678 679
        RenderLayer* positionedParent = enclosingPositionedAncestor();

680
        // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
681
        IntSize offset = positionedParent->scrolledContentOffset();
682
        localPoint -= offset;
683
        
684
        if (renderer()->isPositioned() && positionedParent->renderer()->isRelPositioned() && positionedParent->renderer()->isRenderInline()) {
685
            IntSize offset = toRenderInline(positionedParent->renderer())->relativePositionedInlineOffset(toRenderBox(renderer()));
686
            localPoint += offset;
687
        }
688
    } else if (parent()) {
689 690 691 692 693 694 695 696
        if (isComposited()) {
            // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column.
            // They won't split across columns properly.
            IntSize columnOffset;
            parent()->renderer()->adjustForColumns(columnOffset, localPoint);
            localPoint += columnOffset;
        }

697 698
        IntSize scrollOffset = parent()->scrolledContentOffset();
        localPoint -= scrollOffset;
699
    }
700 701 702 703 704 705
        
    m_relX = m_relY = 0;
    if (renderer()->isRelPositioned()) {
        m_relX = renderer()->relativePositionOffsetX();
        m_relY = renderer()->relativePositionOffsetY();
        localPoint.move(m_relX, m_relY);
adele's avatar
adele committed
706
    }
707 708 709 710

    // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
    localPoint -= inlineBoundingBoxOffset;
    setLocation(localPoint.x(), localPoint.y());
711 712
}

713 714 715 716 717 718
TransformationMatrix RenderLayer::perspectiveTransform() const
{
    if (!renderer()->hasTransform())
        return TransformationMatrix();

    RenderStyle* style = renderer()->style();
719
    if (!style->hasPerspective())
720 721 722 723 724 725 726 727 728 729
        return TransformationMatrix();

    // Maybe fetch the perspective from the backing?
    const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
    const float boxWidth = borderBox.width();
    const float boxHeight = borderBox.height();

    float perspectiveOriginX = style->perspectiveOriginX().calcFloatValue(boxWidth);
    float perspectiveOriginY = style->perspectiveOriginY().calcFloatValue(boxHeight);

730 731
    // A perspective origin of 0,0 makes the vanishing point in the center of the element.
    // We want it to be in the top-left, so subtract half the height and width.
732 733 734 735 736 737 738 739 740 741 742
    perspectiveOriginX -= boxWidth / 2.0f;
    perspectiveOriginY -= boxHeight / 2.0f;
    
    TransformationMatrix t;
    t.translate(perspectiveOriginX, perspectiveOriginY);
    t.applyPerspective(style->perspective());
    t.translate(-perspectiveOriginX, -perspectiveOriginY);
    
    return t;
}

743 744 745 746 747 748 749 750 751 752 753 754
FloatPoint RenderLayer::perspectiveOrigin() const
{
    if (!renderer()->hasTransform())
        return FloatPoint();

    const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
    RenderStyle* style = renderer()->style();

    return FloatPoint(style->perspectiveOriginX().calcFloatValue(borderBox.width()),
                      style->perspectiveOriginY().calcFloatValue(borderBox.height()));
}

eric@webkit.org's avatar
eric@webkit.org committed
755
RenderLayer* RenderLayer::stackingContext() const
756
{
eric@webkit.org's avatar
eric@webkit.org committed
757 758 759 760
    RenderLayer* layer = parent();
    while (layer && !layer->renderer()->isRenderView() && !layer->renderer()->isRoot() && layer->renderer()->style()->hasAutoZIndex())
        layer = layer->parent();
    return layer;
761 762
}

763 764 765 766 767 768
static inline bool isPositionedContainer(RenderLayer* layer)
{
    RenderObject* o = layer->renderer();
    return o->isRenderView() || o->isPositioned() || o->isRelPositioned() || layer->hasTransform();
}

769 770 771 772 773 774
static inline bool isFixedPositionedContainer(RenderLayer* layer)
{
    RenderObject* o = layer->renderer();
    return o->isRenderView() || layer->hasTransform();
}

hyatt@apple.com's avatar
hyatt@apple.com committed
775
RenderLayer* RenderLayer::enclosingPositionedAncestor() const
776 777
{
    RenderLayer* curr = parent();
778 779 780
    while (curr && !isPositionedContainer(curr))
        curr = curr->parent();

781 782 783
    return curr;
}

hyatt@apple.com's avatar
hyatt@apple.com committed
784 785 786
RenderLayer* RenderLayer::enclosingTransformedAncestor() const
{
    RenderLayer* curr = parent();
787 788 789
    while (curr && !curr->renderer()->isRenderView() && !curr->transform())
        curr = curr->parent();

hyatt@apple.com's avatar
hyatt@apple.com committed
790 791 792
    return curr;
}

793 794 795 796 797
static inline const RenderLayer* compositingContainer(const RenderLayer* layer)
{
    return layer->isNormalFlowOnly() ? layer->parent() : layer->stackingContext();
}

798 799 800 801 802 803
#if USE(ACCELERATED_COMPOSITING)
RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const
{
    if (includeSelf && isComposited())
        return const_cast<RenderLayer*>(this);

804 805 806
    for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
        if (curr->isComposited())
            return const_cast<RenderLayer*>(curr);
807 808 809 810 811 812
    }
         
    return 0;
}
#endif

813 814
RenderLayer* RenderLayer::clippingRoot() const
{
815 816 817 818 819
#if USE(ACCELERATED_COMPOSITING)
    if (isComposited())
        return const_cast<RenderLayer*>(this);
#endif

820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
    const RenderLayer* current = this;
    while (current) {
        if (current->renderer()->isRenderView())
            return const_cast<RenderLayer*>(current);

        current = compositingContainer(current);
        ASSERT(current);
        if (current->transform()
#if USE(ACCELERATED_COMPOSITING)
            || current->isComposited()
#endif
        )
            return const_cast<RenderLayer*>(current);
    }

    ASSERT_NOT_REACHED();
    return 0;
}

839 840 841 842 843 844
IntPoint RenderLayer::absoluteToContents(const IntPoint& absolutePoint) const
{
    // We don't use convertToLayerCoords because it doesn't know about transforms
    return roundedIntPoint(renderer()->absoluteToLocal(absolutePoint, false, true));
}

845 846 847 848 849 850 851 852 853
bool RenderLayer::requiresSlowRepaints() const
{
    if (isTransparent() || hasReflection() || hasTransform())
        return true;
    if (!parent())
        return false;
    return parent()->requiresSlowRepaints();
}

hyatt@apple.com's avatar
hyatt@apple.com committed
854
bool RenderLayer::isTransparent() const
855
{
mjs's avatar
mjs committed
856
#if ENABLE(SVG)
857
    if (renderer()->node() && renderer()->node()->namespaceURI() == SVGNames::svgNamespaceURI)
eseidel's avatar
eseidel committed
858 859
        return false;
#endif
860
    return renderer()->isTransparent() || renderer()->hasMask();
861 862
}

863
RenderLayer* RenderLayer::transparentPaintingAncestor()
864
{
865 866 867 868 869 870 871 872 873 874
    if (isComposited())
        return 0;

    for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
        if (curr->isComposited())
            return 0;
        if (curr->isTransparent())
            return curr;
    }
    return 0;
875
}
876

877
static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior);
878

879
static void expandClipRectForDescendantsAndReflection(IntRect& clipRect, const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
880
{
hyatt@apple.com's avatar
hyatt@apple.com committed
881 882
    // If we have a mask, then the clip is limited to the border box area (and there is
    // no need to examine child layers).
883
    if (!l->renderer()->hasMask()) {
884 885
        // Note: we don't have to walk z-order lists since transparent elements always establish
        // a stacking context.  This means we can just walk the layer tree directly.
hyatt@apple.com's avatar
hyatt@apple.com committed
886 887
        for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) {
            if (!l->reflection() || l->reflectionLayer() != curr)
888
                clipRect.unite(transparencyClipBox(curr, rootLayer, paintBehavior));
hyatt@apple.com's avatar
hyatt@apple.com committed
889 890
        }
    }
891

892 893 894 895 896 897 898 899 900 901 902 903
    // If we have a reflection, then we need to account for that when we push the clip.  Reflect our entire
    // current transparencyClipBox to catch all child layers.
    // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this
    // size into the parent layer.
    if (l->renderer()->hasReflection()) {
        int deltaX = 0;
        int deltaY = 0;
        l->convertToLayerCoords(rootLayer, deltaX, deltaY);
        clipRect.move(-deltaX, -deltaY);
        clipRect.unite(l->renderBox()->reflectedRect(clipRect));
        clipRect.move(deltaX, deltaY);
    }
904 905
}

906
static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
907 908 909 910 911
{
    // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
    // paintDirtyRect, and that should cut down on the amount we have to paint.  Still it
    // would be better to respect clips.
    
912
    if (rootLayer != l && l->paintsWithTransform(paintBehavior)) {
913 914 915 916 917
        // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
        // the transformed layer and all of its children.
        int x = 0;
        int y = 0;
        l->convertToLayerCoords(rootLayer, x, y);
918

919 920 921 922 923
        TransformationMatrix transform;
        transform.translate(x, y);
        transform = *l->transform() * transform;

        IntRect clipRect = l->boundingBox(l);
924
        expandClipRectForDescendantsAndReflection(clipRect, l, l, paintBehavior);
925 926 927 928
        return transform.mapRect(clipRect);
    }
    
    IntRect clipRect = l->boundingBox(rootLayer);
929
    expandClipRectForDescendantsAndReflection(clipRect, l, rootLayer, paintBehavior);
930
    return clipRect;
931 932
}

933
void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
934
{
935
    if (p->paintingDisabled() || (paintsWithTransparency(paintBehavior) && m_usedTransparency))
936 937
        return;
    
938
    RenderLayer* ancestor = transparentPaintingAncestor();
939
    if (ancestor)
940
        ancestor->beginTransparencyLayers(p, rootLayer, paintBehavior);
941
    
942
    if (paintsWithTransparency(paintBehavior)) {
943
        m_usedTransparency = true;
944
        p->save();
945
        IntRect clipRect = transparencyClipBox(this, rootLayer, paintBehavior);
946
        p->clip(clipRect);
947
        p->beginTransparencyLayer(renderer()->opacity());
948
#ifdef REVEAL_TRANSPARENCY_LAYERS
949
        p->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f), DeviceColorSpace);
950 951
        p->fillRect(clipRect);
#endif
952 953 954
    }
}

955 956 957 958 959
void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
{
    return renderArena->allocate(sz);
}

darin's avatar
darin committed
960 961
void RenderLayer::operator delete(void* ptr, size_t sz)
{
harrison's avatar
harrison committed
962
    // Stash size where destroy can find it.
darin's avatar
darin committed
963
    *(size_t *)ptr = sz;
964 965
}

harrison's avatar
harrison committed
966
void RenderLayer::destroy(RenderArena* renderArena)
eric@webkit.org's avatar
eric@webkit.org committed
967
{
968
    delete this;
hyatt@apple.com's avatar
hyatt@apple.com committed
969

darin's avatar
darin committed
970 971
    // Recover the size left there for us by operator delete and free the memory.
    renderArena->free(*(size_t *)this, this);
972 973
}

mitz@apple.com's avatar
mitz@apple.com committed
974
void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)