📄 renderlayerbacking.cpp
字号:
/* * Copyright (C) 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#if USE(ACCELERATED_COMPOSITING)#include "AnimationController.h"#include "CSSPropertyNames.h"#include "CSSStyleSelector.h"#include "FrameView.h"#include "GraphicsContext.h"#include "GraphicsLayer.h"#include "HTMLNames.h"#include "RenderBox.h"#include "RenderImage.h"#include "RenderLayerCompositor.h"#include "RenderVideo.h"#include "RenderView.h"#include "RenderLayerBacking.h"using namespace std;namespace WebCore {RenderLayerBacking::RenderLayerBacking(RenderLayer* layer) : m_owningLayer(layer) , m_ancestorClippingLayer(0) , m_graphicsLayer(0) , m_contentsLayer(0) , m_clippingLayer(0) , m_forceCompositingLayer(false) , m_isSimpleContainerCompositingLayer(false) , m_simpleCompositingLayerStatusDirty(true) , m_compositingContentOffsetDirty(true){ createGraphicsLayer();}RenderLayerBacking::~RenderLayerBacking(){ updateClippingLayers(false, false); updateContentsLayer(false); destroyGraphicsLayer();}void RenderLayerBacking::createGraphicsLayer(){ m_graphicsLayer = GraphicsLayer::createGraphicsLayer(this); #ifndef NDEBUG if (renderer()->node()->isDocumentNode()) m_graphicsLayer->setName("Document Node"); else { if (renderer()->node()->isHTMLElement() && renderer()->node()->hasID()) m_graphicsLayer->setName(renderer()->renderName() + String(" ") + static_cast<HTMLElement*>(renderer()->node())->id()); else m_graphicsLayer->setName(renderer()->renderName()); }#endif // NDEBUG updateLayerOpacity(); updateLayerTransform();}void RenderLayerBacking::destroyGraphicsLayer(){ if (m_graphicsLayer) m_graphicsLayer->removeFromParent(); delete m_graphicsLayer; m_graphicsLayer = 0; delete m_contentsLayer; m_contentsLayer = 0; delete m_clippingLayer; m_clippingLayer = 0;}void RenderLayerBacking::updateLayerOpacity(){ m_graphicsLayer->setOpacity(compositingOpacity(renderer()->opacity()), 0, 0);}void RenderLayerBacking::updateLayerTransform(){ RenderStyle* style = renderer()->style(); // FIXME: This could use m_owningLayer->transform(), but that currently has transform-origin // baked into it, and we don't want that. TransformationMatrix t; if (m_owningLayer->hasTransform()) style->applyTransform(t, toRenderBox(renderer())->borderBoxRect().size(), RenderStyle::ExcludeTransformOrigin); m_graphicsLayer->setTransform(t);}void RenderLayerBacking::updateAfterLayout(){ invalidateDrawingOptimizations(); detectDrawingOptimizations(); updateGraphicsLayerGeometry();}bool RenderLayerBacking::updateGraphicsLayers(bool needsContentsLayer, bool needsUpperClippingLayer, bool needsLowerClippingLayer, bool needsRepaint){ bool layerConfigChanged = false; if (updateContentsLayer(needsContentsLayer)) layerConfigChanged = true; if (updateClippingLayers(needsUpperClippingLayer, needsLowerClippingLayer)) layerConfigChanged = true; // See if we can now use any drawing optimizations. bool didDrawContent = graphicsLayer()->drawsContent(); invalidateDrawingOptimizations(); detectDrawingOptimizations(); if (!didDrawContent && graphicsLayer()->drawsContent()) needsRepaint = true; // Set opacity, if it is not animating. if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyOpacity)) updateLayerOpacity(); RenderStyle* style = renderer()->style(); m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D); m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible); updateGraphicsLayerGeometry(); m_graphicsLayer->updateContentsRect(); if (needsRepaint) { m_graphicsLayer->setNeedsDisplay(); if (m_contentsLayer) m_contentsLayer->setNeedsDisplay(); } return layerConfigChanged;}void RenderLayerBacking::updateGraphicsLayerGeometry(){ // If we haven't built z-order lists yet, wait until later. if (m_owningLayer->isStackingContext() && m_owningLayer->m_zOrderListsDirty) return; // Set transform property, if it is not animating. We have to do this here because the transform // is affected by the layer dimensions. if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyWebkitTransform)) updateLayerTransform(); m_compositingContentOffsetDirty = true; RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer(); // We compute everything relative to the enclosing compositing layer. IntRect ancestorCompositingBounds; if (compAncestor) ancestorCompositingBounds = compositor()->calculateCompositedBounds(compAncestor, compAncestor); IntRect localCompositingBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer); IntRect relativeCompositingBounds(localCompositingBounds); int deltaX = 0, deltaY = 0; m_owningLayer->convertToLayerCoords(compAncestor, deltaX, deltaY); relativeCompositingBounds.move(deltaX, deltaY); IntPoint graphicsLayerParentLocation; if (compAncestor && compAncestor->backing()->hasClippingLayer()) { // If the compositing ancestor has a layer to clip children, we parent in that, and therefore // position relative to it. graphicsLayerParentLocation = toRenderBox(compAncestor->renderer())->overflowClipRect(0, 0).location(); } else graphicsLayerParentLocation = ancestorCompositingBounds.location(); if (compAncestor && m_ancestorClippingLayer) { // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects // for a compositing layer, rootLayer is the layer itself. IntRect infiniteRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX); IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; m_owningLayer->calculateRects(compAncestor, infiniteRect, layerBounds, backgroundRect, foregroundRect, outlineRect, true); m_ancestorClippingLayer->setPosition(FloatPoint() + (backgroundRect.location() - graphicsLayerParentLocation)); m_ancestorClippingLayer->setSize(backgroundRect.size()); // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords. IntSize rendererOffset(backgroundRect.location().x() - deltaX, backgroundRect.location().y() - deltaY); m_ancestorClippingLayer->setOffsetFromRenderer(rendererOffset); // The primary layer is then parented in, and positioned relative to this clipping layer. graphicsLayerParentLocation = backgroundRect.location(); } m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation)); m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - IntPoint()); FloatSize oldSize = m_graphicsLayer->size(); FloatSize newSize = relativeCompositingBounds.size(); if (oldSize != newSize) { m_graphicsLayer->setSize(newSize); // A bounds change will almost always require redisplay. Usually that redisplay // will happen because of a repaint elsewhere, but not always: // e.g. see RenderView::setMaximalOutlineSize() m_graphicsLayer->setNeedsDisplay(); } // If we have a layer that clips children, position it. if (m_clippingLayer) { IntRect clippingBox = toRenderBox(renderer())->overflowClipRect(0, 0); m_clippingLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location())); m_clippingLayer->setSize(clippingBox.size()); m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint()); } if (m_owningLayer->hasTransform()) { const IntRect borderBox = toRenderBox(renderer())->borderBoxRect(); IntRect layerBounds = IntRect(m_owningLayer->x(), m_owningLayer->y(), borderBox.width(), borderBox.height()); // Convert to absolute coords to match bbox. int x = 0, y = 0; m_owningLayer->convertToLayerCoords(compAncestor, x, y); layerBounds.move(x - m_owningLayer->x(), y - m_owningLayer->y()); // Update properties that depend on layer dimensions FloatPoint3D transformOrigin = computeTransformOrigin(borderBox); // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set. FloatPoint3D anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f, relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f, transformOrigin.z()); m_graphicsLayer->setAnchorPoint(anchor); RenderStyle* style = renderer()->style(); if (style->hasPerspective()) { TransformationMatrix t = owningLayer()->perspectiveTransform(); if (m_clippingLayer) { m_clippingLayer->setChildrenTransform(t); m_graphicsLayer->setChildrenTransform(TransformationMatrix()); } else m_graphicsLayer->setChildrenTransform(t); } else { if (m_clippingLayer) m_clippingLayer->setChildrenTransform(TransformationMatrix()); else m_graphicsLayer->setChildrenTransform(TransformationMatrix()); } } else { m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0)); } if (m_contentsLayer) { // The contents layer is always coincidental with the graphicsLayer for now. m_contentsLayer->setPosition(IntPoint(0, 0)); m_contentsLayer->setSize(newSize); m_contentsLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer()); } m_graphicsLayer->updateContentsRect();}void RenderLayerBacking::updateInternalHierarchy(){ // m_contentsLayer has to be inserted in the correct order with child layers, // so it's not inserted here. if (m_ancestorClippingLayer) { m_ancestorClippingLayer->removeAllChildren(); m_graphicsLayer->removeFromParent(); m_ancestorClippingLayer->addChild(m_graphicsLayer); } if (m_clippingLayer) { m_clippingLayer->removeFromParent(); m_graphicsLayer->addChild(m_clippingLayer); }}// Return true if the layers changed.bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip){ bool layersChanged = false; if (needsAncestorClip) { if (!m_ancestorClippingLayer) { m_ancestorClippingLayer = GraphicsLayer::createGraphicsLayer(this);#ifndef NDEBUG m_ancestorClippingLayer->setName("Ancestor clipping Layer");#endif m_ancestorClippingLayer->setMasksToBounds(true); layersChanged = true; } } else if (m_ancestorClippingLayer) { m_ancestorClippingLayer->removeFromParent(); delete m_ancestorClippingLayer; m_ancestorClippingLayer = 0; layersChanged = true; } if (needsDescendantClip) { if (!m_clippingLayer) { m_clippingLayer = GraphicsLayer::createGraphicsLayer(0);#ifndef NDEBUG m_clippingLayer->setName("Child clipping Layer");#endif m_clippingLayer->setMasksToBounds(true); layersChanged = true; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -