diff options
Diffstat (limited to 'WebCore/platform/graphics/ca/GraphicsLayerCA.cpp')
-rw-r--r-- | WebCore/platform/graphics/ca/GraphicsLayerCA.cpp | 2300 |
1 files changed, 0 insertions, 2300 deletions
diff --git a/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp deleted file mode 100644 index 8bde9fd..0000000 --- a/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp +++ /dev/null @@ -1,2300 +0,0 @@ -/* - * Copyright (C) 2010 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 "GraphicsLayerCA.h" - -#include "Animation.h" -#include "FloatConversion.h" -#include "FloatRect.h" -#include "PlatformCALayer.h" -#include "PlatformString.h" -#include "RotateTransformOperation.h" -#include "ScaleTransformOperation.h" -#include "SystemTime.h" -#include "TranslateTransformOperation.h" -#include <QuartzCore/QuartzCore.h> -#include <limits.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/StringConcatenate.h> - -using namespace std; - -#define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)) - -namespace WebCore { - -// The threshold width or height above which a tiled layer will be used. This should be -// large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL -// texture size limit on all supported hardware. -static const int cMaxPixelDimension = 2000; - -// If we send a duration of 0 to CA, then it will use the default duration -// of 250ms. So send a very small value instead. -static const float cAnimationAlmostZeroDuration = 1e-3f; - -// CACurrentMediaTime() is a time since boot. These methods convert between that and -// WebCore time, which is system time (UTC). -static CFTimeInterval currentTimeToMediaTime(double t) -{ - return CACurrentMediaTime() + t - WTF::currentTime(); -} - -static bool isTransformTypeTransformationMatrix(TransformOperation::OperationType transformType) -{ - switch (transformType) { - case TransformOperation::SKEW_X: - case TransformOperation::SKEW_Y: - case TransformOperation::SKEW: - case TransformOperation::MATRIX: - case TransformOperation::ROTATE_3D: - case TransformOperation::MATRIX_3D: - case TransformOperation::PERSPECTIVE: - case TransformOperation::IDENTITY: - case TransformOperation::NONE: - return true; - default: - return false; - } -} - -static bool isTransformTypeFloatPoint3D(TransformOperation::OperationType transformType) -{ - switch (transformType) { - case TransformOperation::SCALE: - case TransformOperation::SCALE_3D: - case TransformOperation::TRANSLATE: - case TransformOperation::TRANSLATE_3D: - return true; - default: - return false; - } -} - -static bool isTransformTypeNumber(TransformOperation::OperationType transformType) -{ - return !isTransformTypeTransformationMatrix(transformType) && !isTransformTypeFloatPoint3D(transformType); -} - -static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, float& value) -{ - switch (transformType) { - case TransformOperation::ROTATE: - case TransformOperation::ROTATE_X: - case TransformOperation::ROTATE_Y: - value = transformOp ? narrowPrecisionToFloat(deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle())) : 0; - break; - case TransformOperation::SCALE_X: - value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1; - break; - case TransformOperation::SCALE_Y: - value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1; - break; - case TransformOperation::SCALE_Z: - value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1; - break; - case TransformOperation::TRANSLATE_X: - value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0; - break; - case TransformOperation::TRANSLATE_Y: - value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0; - break; - case TransformOperation::TRANSLATE_Z: - value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0; - break; - default: - break; - } -} - -static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, FloatPoint3D& value) -{ - switch (transformType) { - case TransformOperation::SCALE: - case TransformOperation::SCALE_3D: - value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1); - value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1); - value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1); - break; - case TransformOperation::TRANSLATE: - case TransformOperation::TRANSLATE_3D: - value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0); - value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0); - value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0); - break; - default: - break; - } -} - -static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, TransformationMatrix& value) -{ - switch (transformType) { - case TransformOperation::SKEW_X: - case TransformOperation::SKEW_Y: - case TransformOperation::SKEW: - case TransformOperation::MATRIX: - case TransformOperation::ROTATE_3D: - case TransformOperation::MATRIX_3D: - case TransformOperation::PERSPECTIVE: - case TransformOperation::IDENTITY: - case TransformOperation::NONE: - if (transformOp) - transformOp->apply(value, size); - else - value.makeIdentity(); - break; - default: - break; - } -} - -#if HAVE_MODERN_QUARTZCORE -static PlatformCAAnimation::ValueFunctionType getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType) -{ - // Use literal strings to avoid link-time dependency on those symbols. - switch (transformType) { - case TransformOperation::ROTATE_X: - return PlatformCAAnimation::RotateX; - case TransformOperation::ROTATE_Y: - return PlatformCAAnimation::RotateY; - case TransformOperation::ROTATE: - return PlatformCAAnimation::RotateZ; - case TransformOperation::SCALE_X: - return PlatformCAAnimation::ScaleX; - case TransformOperation::SCALE_Y: - return PlatformCAAnimation::ScaleY; - case TransformOperation::SCALE_Z: - return PlatformCAAnimation::ScaleZ; - case TransformOperation::TRANSLATE_X: - return PlatformCAAnimation::TranslateX; - case TransformOperation::TRANSLATE_Y: - return PlatformCAAnimation::TranslateY; - case TransformOperation::TRANSLATE_Z: - return PlatformCAAnimation::TranslateZ; - case TransformOperation::SCALE: - case TransformOperation::SCALE_3D: - return PlatformCAAnimation::Scale; - case TransformOperation::TRANSLATE: - case TransformOperation::TRANSLATE_3D: - return PlatformCAAnimation::Translate; - default: - return PlatformCAAnimation::NoValueFunction; - } -} -#endif - -static String propertyIdToString(AnimatedPropertyID property) -{ - switch (property) { - case AnimatedPropertyWebkitTransform: - return "transform"; - case AnimatedPropertyOpacity: - return "opacity"; - case AnimatedPropertyBackgroundColor: - return "backgroundColor"; - case AnimatedPropertyInvalid: - ASSERT_NOT_REACHED(); - } - ASSERT_NOT_REACHED(); - return ""; -} - -static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index) -{ - return makeString(animationName, '_', String::number(property), '_', String::number(index)); -} - -static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, const Animation* anim) -{ - if (anim->timingFunction()->isStepsTimingFunction()) - return true; - - for (unsigned i = 0; i < valueList.size(); ++i) { - const TimingFunction* timingFunction = valueList.at(i)->timingFunction(); - if (timingFunction && timingFunction->isStepsTimingFunction()) - return true; - } - - return false; -} - -PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) -{ - return new GraphicsLayerCA(client); -} - -GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client) - : GraphicsLayer(client) - , m_contentsLayerPurpose(NoContentsLayer) - , m_contentsLayerHasBackgroundColor(false) - , m_uncommittedChanges(NoChange) -{ - m_layer = PlatformCALayer::create(PlatformCALayer::LayerTypeWebLayer, this); - -#if !HAVE_MODERN_QUARTZCORE - setContentsOrientation(defaultContentsOrientation()); -#endif - - updateDebugIndicators(); -} - -GraphicsLayerCA::~GraphicsLayerCA() -{ - // We release our references to the PlatformCALayers here, but do not actively unparent them, - // since that will cause a commit and break our batched commit model. The layers will - // get released when the rootmost modified GraphicsLayerCA rebuilds its child layers. - - // Clean up the layer. - if (m_layer) - m_layer->setOwner(0); - - if (m_contentsLayer) - m_contentsLayer->setOwner(0); - - if (m_structuralLayer) - m_structuralLayer->setOwner(0); - - removeCloneLayers(); -} - -void GraphicsLayerCA::setName(const String& name) -{ - String longName = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + name; - GraphicsLayer::setName(longName); - noteLayerPropertyChanged(NameChanged); -} - -PlatformLayer* GraphicsLayerCA::platformLayer() const -{ - return primaryLayer()->platformLayer(); -} - -bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children) -{ - bool childrenChanged = GraphicsLayer::setChildren(children); - if (childrenChanged) - noteSublayersChanged(); - - return childrenChanged; -} - -void GraphicsLayerCA::addChild(GraphicsLayer* childLayer) -{ - GraphicsLayer::addChild(childLayer); - noteSublayersChanged(); -} - -void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index) -{ - GraphicsLayer::addChildAtIndex(childLayer, index); - noteSublayersChanged(); -} - -void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) -{ - GraphicsLayer::addChildBelow(childLayer, sibling); - noteSublayersChanged(); -} - -void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) -{ - GraphicsLayer::addChildAbove(childLayer, sibling); - noteSublayersChanged(); -} - -bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) -{ - if (GraphicsLayer::replaceChild(oldChild, newChild)) { - noteSublayersChanged(); - return true; - } - return false; -} - -void GraphicsLayerCA::removeFromParent() -{ - if (m_parent) - static_cast<GraphicsLayerCA*>(m_parent)->noteSublayersChanged(); - GraphicsLayer::removeFromParent(); -} - -void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer) -{ - if (layer == m_maskLayer) - return; - - GraphicsLayer::setMaskLayer(layer); - noteLayerPropertyChanged(MaskLayerChanged); - - propagateLayerChangeToReplicas(); - - if (m_replicatedLayer) - static_cast<GraphicsLayerCA*>(m_replicatedLayer)->propagateLayerChangeToReplicas(); -} - -void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer) -{ - if (layer == m_replicatedLayer) - return; - - GraphicsLayer::setReplicatedLayer(layer); - noteLayerPropertyChanged(ReplicatedLayerChanged); -} - -void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer) -{ - if (layer == m_replicaLayer) - return; - - GraphicsLayer::setReplicatedByLayer(layer); - noteSublayersChanged(); - noteLayerPropertyChanged(ReplicatedLayerChanged); -} - -void GraphicsLayerCA::setPosition(const FloatPoint& point) -{ - if (point == m_position) - return; - - GraphicsLayer::setPosition(point); - noteLayerPropertyChanged(PositionChanged); -} - -void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point) -{ - if (point == m_anchorPoint) - return; - - GraphicsLayer::setAnchorPoint(point); - noteLayerPropertyChanged(AnchorPointChanged); -} - -void GraphicsLayerCA::setSize(const FloatSize& size) -{ - if (size == m_size) - return; - - GraphicsLayer::setSize(size); - noteLayerPropertyChanged(SizeChanged); -} - -void GraphicsLayerCA::setTransform(const TransformationMatrix& t) -{ - if (t == m_transform) - return; - - GraphicsLayer::setTransform(t); - noteLayerPropertyChanged(TransformChanged); -} - -void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t) -{ - if (t == m_childrenTransform) - return; - - GraphicsLayer::setChildrenTransform(t); - noteLayerPropertyChanged(ChildrenTransformChanged); -} - -void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer) -{ - RefPtr<PlatformCAAnimation> anim = fromLayer->animationForKey(animationIdentifier); - if (!anim) - return; - - switch (operation) { - case Move: - fromLayer->removeAnimationForKey(animationIdentifier); - toLayer->addAnimationForKey(animationIdentifier, anim.get()); - break; - - case Copy: - toLayer->addAnimationForKey(animationIdentifier, anim.get()); - break; - } -} - -void GraphicsLayerCA::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, PlatformCALayer *fromLayer, PlatformCALayer *toLayer) -{ - // Look for running animations affecting this property. - AnimationsMap::const_iterator end = m_runningAnimations.end(); - for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) { - const Vector<LayerPropertyAnimation>& propertyAnimations = it->second; - size_t numAnimations = propertyAnimations.size(); - for (size_t i = 0; i < numAnimations; ++i) { - const LayerPropertyAnimation& currAnimation = propertyAnimations[i]; - if (currAnimation.m_property == property) - moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index), fromLayer, toLayer); - } - } -} - -void GraphicsLayerCA::setPreserves3D(bool preserves3D) -{ - if (preserves3D == m_preserves3D) - return; - - GraphicsLayer::setPreserves3D(preserves3D); - noteLayerPropertyChanged(Preserves3DChanged); -} - -void GraphicsLayerCA::setMasksToBounds(bool masksToBounds) -{ - if (masksToBounds == m_masksToBounds) - return; - - GraphicsLayer::setMasksToBounds(masksToBounds); - noteLayerPropertyChanged(MasksToBoundsChanged); -} - -void GraphicsLayerCA::setDrawsContent(bool drawsContent) -{ - if (drawsContent == m_drawsContent) - return; - - GraphicsLayer::setDrawsContent(drawsContent); - noteLayerPropertyChanged(DrawsContentChanged); -} - -void GraphicsLayerCA::setAcceleratesDrawing(bool acceleratesDrawing) -{ - if (acceleratesDrawing == m_acceleratesDrawing) - return; - - GraphicsLayer::setAcceleratesDrawing(acceleratesDrawing); - noteLayerPropertyChanged(DrawsContentChanged); -} - -void GraphicsLayerCA::setBackgroundColor(const Color& color) -{ - if (m_backgroundColorSet && m_backgroundColor == color) - return; - - GraphicsLayer::setBackgroundColor(color); - - m_contentsLayerHasBackgroundColor = true; - noteLayerPropertyChanged(BackgroundColorChanged); -} - -void GraphicsLayerCA::clearBackgroundColor() -{ - if (!m_backgroundColorSet) - return; - - GraphicsLayer::clearBackgroundColor(); - m_contentsLayerHasBackgroundColor = false; - noteLayerPropertyChanged(BackgroundColorChanged); -} - -void GraphicsLayerCA::setContentsOpaque(bool opaque) -{ - if (m_contentsOpaque == opaque) - return; - - GraphicsLayer::setContentsOpaque(opaque); - noteLayerPropertyChanged(ContentsOpaqueChanged); -} - -void GraphicsLayerCA::setBackfaceVisibility(bool visible) -{ - if (m_backfaceVisibility == visible) - return; - - GraphicsLayer::setBackfaceVisibility(visible); - noteLayerPropertyChanged(BackfaceVisibilityChanged); -} - -void GraphicsLayerCA::setOpacity(float opacity) -{ - float clampedOpacity = max(0.0f, min(opacity, 1.0f)); - - if (clampedOpacity == m_opacity) - return; - - GraphicsLayer::setOpacity(clampedOpacity); - noteLayerPropertyChanged(OpacityChanged); -} - -void GraphicsLayerCA::setNeedsDisplay() -{ - FloatRect hugeRect(-numeric_limits<float>::max() / 2, -numeric_limits<float>::max() / 2, - numeric_limits<float>::max(), numeric_limits<float>::max()); - - setNeedsDisplayInRect(hugeRect); -} - -void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& rect) -{ - if (!drawsContent()) - return; - - const size_t maxDirtyRects = 32; - - for (size_t i = 0; i < m_dirtyRects.size(); ++i) { - if (m_dirtyRects[i].contains(rect)) - return; - } - - if (m_dirtyRects.size() < maxDirtyRects) - m_dirtyRects.append(rect); - else - m_dirtyRects[0].unite(rect); - - noteLayerPropertyChanged(DirtyRectsChanged); -} - -void GraphicsLayerCA::setContentsNeedsDisplay() -{ - noteLayerPropertyChanged(ContentsNeedsDisplay); -} - -void GraphicsLayerCA::setContentsRect(const IntRect& rect) -{ - if (rect == m_contentsRect) - return; - - GraphicsLayer::setContentsRect(rect); - noteLayerPropertyChanged(ContentsRectChanged); -} - -bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& animationName, double timeOffset) -{ - ASSERT(!animationName.isEmpty()); - - if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) - return false; - -#if !HAVE_MODERN_QUARTZCORE - // Older versions of QuartzCore do not handle opacity in transform layers properly, so we will - // always do software animation in that case. - if (valueList.property() == AnimatedPropertyOpacity) - return false; -#endif - - // CoreAnimation does not handle the steps() timing function. Fall back - // to software animation in that case. - if (animationHasStepsTimingFunction(valueList, anim)) - return false; - - bool createdAnimations = false; - if (valueList.property() == AnimatedPropertyWebkitTransform) - createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize); - else - createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, timeOffset); - - if (createdAnimations) - noteLayerPropertyChanged(AnimationChanged); - - return createdAnimations; -} - -void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset) -{ - if (!animationIsRunning(animationName)) - return; - - AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName); - if (it != m_animationsToProcess.end()) { - AnimationProcessingAction& processingInfo = it->second; - // If an animation is scheduled to be removed, don't change the remove to a pause. - if (processingInfo.action != Remove) - processingInfo.action = Pause; - } else - m_animationsToProcess.add(animationName, AnimationProcessingAction(Pause, timeOffset)); - - noteLayerPropertyChanged(AnimationChanged); -} - -void GraphicsLayerCA::removeAnimation(const String& animationName) -{ - if (!animationIsRunning(animationName)) - return; - - m_animationsToProcess.add(animationName, AnimationProcessingAction(Remove)); - noteLayerPropertyChanged(AnimationChanged); -} - -void GraphicsLayerCA::animationStarted(CFTimeInterval startTime) -{ - if (m_client) - m_client->notifyAnimationStarted(this, startTime); -} - -void GraphicsLayerCA::setContentsToImage(Image* image) -{ - if (image) { - CGImageRef newImage = image->nativeImageForCurrentFrame(); - if (!newImage) - return; - - // Check to see if the image changed; we have to do this because the call to - // CGImageCreateCopyWithColorSpace() below can create a new image every time. - if (m_uncorrectedContentsImage && m_uncorrectedContentsImage.get() == newImage) - return; - - m_uncorrectedContentsImage = newImage; - m_pendingContentsImage = newImage; - CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get()); - - static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB(); - if (colorSpace && CFEqual(colorSpace, deviceRGB)) { - // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such - // images to CA we need to tag them similarly so CA rendering matches CG rendering. - static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay); - m_pendingContentsImage.adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB)); - } - m_contentsLayerPurpose = ContentsLayerForImage; - if (!m_contentsLayer) - noteSublayersChanged(); - } else { - m_uncorrectedContentsImage = 0; - m_pendingContentsImage = 0; - m_contentsLayerPurpose = NoContentsLayer; - if (m_contentsLayer) - noteSublayersChanged(); - } - - noteLayerPropertyChanged(ContentsImageChanged); -} - -void GraphicsLayerCA::setContentsToMedia(PlatformLayer* mediaLayer) -{ - if (m_contentsLayer && mediaLayer == m_contentsLayer->platformLayer()) - return; - - // Create the PlatformCALayer to wrap the incoming layer - m_contentsLayer = mediaLayer ? PlatformCALayer::create(mediaLayer, this) : 0; - - m_contentsLayerPurpose = mediaLayer ? ContentsLayerForMedia : NoContentsLayer; - - noteSublayersChanged(); - noteLayerPropertyChanged(ContentsMediaLayerChanged); -} - -void GraphicsLayerCA::setContentsToCanvas(PlatformLayer* canvasLayer) -{ - if (m_contentsLayer && canvasLayer == m_contentsLayer->platformLayer()) - return; - - // Create the PlatformCALayer to wrap the incoming layer - m_contentsLayer = canvasLayer ? PlatformCALayer::create(canvasLayer, this) : 0; - - m_contentsLayerPurpose = canvasLayer ? ContentsLayerForCanvas : NoContentsLayer; - - noteSublayersChanged(); - noteLayerPropertyChanged(ContentsCanvasLayerChanged); -} - -void GraphicsLayerCA::didDisplay(PlatformLayer* layer) -{ - PlatformCALayer* currentLayer = PlatformCALayer::platformCALayer(layer); - PlatformCALayer* sourceLayer; - LayerMap* layerCloneMap; - - if (currentLayer == m_layer) { - sourceLayer = m_layer.get(); - layerCloneMap = m_layerClones.get(); - } else if (currentLayer == m_contentsLayer) { - sourceLayer = m_contentsLayer.get(); - layerCloneMap = m_contentsLayerClones.get(); - } else - return; - - if (layerCloneMap) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* currClone = it->second.get(); - if (!currClone) - continue; - - if (currClone->contents() != sourceLayer->contents()) - currClone->setContents(sourceLayer->contents()); - else - currClone->setContentsChanged(); - } - } -} - -void GraphicsLayerCA::syncCompositingState() -{ - recursiveCommitChanges(); -} - -void GraphicsLayerCA::syncCompositingStateForThisLayerOnly() -{ - commitLayerChangesBeforeSublayers(); - commitLayerChangesAfterSublayers(); -} - -void GraphicsLayerCA::recursiveCommitChanges() -{ - commitLayerChangesBeforeSublayers(); - - if (m_maskLayer) - static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesBeforeSublayers(); - - const Vector<GraphicsLayer*>& childLayers = children(); - size_t numChildren = childLayers.size(); - for (size_t i = 0; i < numChildren; ++i) { - GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); - curChild->recursiveCommitChanges(); - } - - if (m_replicaLayer) - static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveCommitChanges(); - - if (m_maskLayer) - static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesAfterSublayers(); - - commitLayerChangesAfterSublayers(); -} - -void GraphicsLayerCA::commitLayerChangesBeforeSublayers() -{ - if (!m_uncommittedChanges) - return; - - // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to - if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged)) - updateStructuralLayer(); - - if (m_uncommittedChanges & NameChanged) - updateLayerNames(); - - if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged - updateContentsImage(); - - if (m_uncommittedChanges & ContentsMediaLayerChanged) // Needs to happen before ChildrenChanged - updateContentsMediaLayer(); - - if (m_uncommittedChanges & ContentsCanvasLayerChanged) // Needs to happen before ChildrenChanged - updateContentsCanvasLayer(); - - if (m_uncommittedChanges & BackgroundColorChanged) // Needs to happen before ChildrenChanged, and after updating image or video - updateLayerBackgroundColor(); - - if (m_uncommittedChanges & ChildrenChanged) - updateSublayerList(); - - if (m_uncommittedChanges & PositionChanged) - updateLayerPosition(); - - if (m_uncommittedChanges & AnchorPointChanged) - updateAnchorPoint(); - - if (m_uncommittedChanges & SizeChanged) - updateLayerSize(); - - if (m_uncommittedChanges & TransformChanged) - updateTransform(); - - if (m_uncommittedChanges & ChildrenTransformChanged) - updateChildrenTransform(); - - if (m_uncommittedChanges & MasksToBoundsChanged) - updateMasksToBounds(); - - if (m_uncommittedChanges & DrawsContentChanged) - updateLayerDrawsContent(); - - if (m_uncommittedChanges & ContentsOpaqueChanged) - updateContentsOpaque(); - - if (m_uncommittedChanges & BackfaceVisibilityChanged) - updateBackfaceVisibility(); - - if (m_uncommittedChanges & OpacityChanged) - updateOpacityOnLayer(); - - if (m_uncommittedChanges & AnimationChanged) - updateLayerAnimations(); - - if (m_uncommittedChanges & DirtyRectsChanged) - repaintLayerDirtyRects(); - - if (m_uncommittedChanges & ContentsRectChanged) - updateContentsRect(); - - if (m_uncommittedChanges & MaskLayerChanged) - updateMaskLayer(); - - if (m_uncommittedChanges & ContentsNeedsDisplay) - updateContentsNeedsDisplay(); - - if (m_uncommittedChanges & AcceleratesDrawingChanged) - updateAcceleratesDrawing(); -} - -void GraphicsLayerCA::commitLayerChangesAfterSublayers() -{ - if (!m_uncommittedChanges) - return; - - if (m_uncommittedChanges & ReplicatedLayerChanged) - updateReplicatedLayers(); - - m_uncommittedChanges = NoChange; -} - -void GraphicsLayerCA::updateLayerNames() -{ - switch (structuralLayerPurpose()) { - case StructuralLayerForPreserves3D: - m_structuralLayer->setName("Transform layer " + name()); - break; - case StructuralLayerForReplicaFlattening: - m_structuralLayer->setName("Replica flattening layer " + name()); - break; - case NoStructuralLayer: - break; - } - m_layer->setName(name()); -} - -void GraphicsLayerCA::updateSublayerList() -{ - PlatformCALayerList newSublayers; - const Vector<GraphicsLayer*>& childLayers = children(); - - if (m_structuralLayer || m_contentsLayer || childLayers.size() > 0) { - if (m_structuralLayer) { - // Add the replica layer first. - if (m_replicaLayer) - newSublayers.append(static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer()); - // Add the primary layer. Even if we have negative z-order children, the primary layer always comes behind. - newSublayers.append(m_layer); - } else if (m_contentsLayer) { - // FIXME: add the contents layer in the correct order with negative z-order children. - // This does not cause visible rendering issues because currently contents layers are only used - // for replaced elements that don't have children. - newSublayers.append(m_contentsLayer); - } - - size_t numChildren = childLayers.size(); - for (size_t i = 0; i < numChildren; ++i) { - GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); - PlatformCALayer* childLayer = curChild->layerForSuperlayer(); - newSublayers.append(childLayer); - } - - for (size_t i = 0; i < newSublayers.size(); ++i) - newSublayers[i]->removeFromSuperlayer(); - } - - if (m_structuralLayer) { - m_structuralLayer->setSublayers(newSublayers); - - if (m_contentsLayer) { - // If we have a transform layer, then the contents layer is parented in the - // primary layer (which is itself a child of the transform layer). - m_layer->removeAllSublayers(); - m_layer->appendSublayer(m_contentsLayer.get()); - } - } else - m_layer->setSublayers(newSublayers); -} - -void GraphicsLayerCA::updateLayerPosition() -{ - FloatSize usedSize = m_usingTiledLayer ? constrainedSize() : m_size; - - // Position is offset on the layer by the layer anchor point. - FloatPoint posPoint(m_position.x() + m_anchorPoint.x() * usedSize.width(), - m_position.y() + m_anchorPoint.y() * usedSize.height()); - - primaryLayer()->setPosition(posPoint); - - if (LayerMap* layerCloneMap = primaryLayerClones()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - FloatPoint clonePosition = posPoint; - if (m_replicaLayer && isReplicatedRootClone(it->first)) { - // Maintain the special-case position for the root of a clone subtree, - // which we set up in replicatedLayerRoot(). - clonePosition = positionForCloneRootLayer(); - } - it->second->setPosition(clonePosition); - } - } -} - -void GraphicsLayerCA::updateLayerSize() -{ - FloatRect rect(0, 0, m_size.width(), m_size.height()); - if (m_structuralLayer) { - m_structuralLayer->setBounds(rect); - - if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setBounds(rect); - } - - // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative. - CGPoint centerPoint = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f); - m_layer->setPosition(centerPoint); - - if (LayerMap* layerCloneMap = m_layerClones.get()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setPosition(centerPoint); - } - } - - bool needTiledLayer = requiresTiledLayer(m_size); - if (needTiledLayer != m_usingTiledLayer) - swapFromOrToTiledLayer(needTiledLayer); - - if (m_usingTiledLayer) { - FloatSize sizeToUse = constrainedSize(); - rect = CGRectMake(0, 0, sizeToUse.width(), sizeToUse.height()); - } - - m_layer->setBounds(rect); - if (LayerMap* layerCloneMap = m_layerClones.get()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setBounds(rect); - } - - // Contents transform may depend on height. - updateContentsTransform(); - - // Note that we don't resize m_contentsLayer. It's up the caller to do that. - - // if we've changed the bounds, we need to recalculate the position - // of the layer, taking anchor point into account. - updateLayerPosition(); -} - -void GraphicsLayerCA::updateAnchorPoint() -{ - primaryLayer()->setAnchorPoint(m_anchorPoint); - - if (LayerMap* layerCloneMap = primaryLayerClones()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* currLayer = it->second.get(); - currLayer->setAnchorPoint(m_anchorPoint); - } - } - - updateLayerPosition(); -} - -void GraphicsLayerCA::updateTransform() -{ - primaryLayer()->setTransform(m_transform); - - if (LayerMap* layerCloneMap = primaryLayerClones()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* currLayer = it->second.get(); - if (m_replicaLayer && isReplicatedRootClone(it->first)) { - // Maintain the special-case transform for the root of a clone subtree, - // which we set up in replicatedLayerRoot(). - currLayer->setTransform(TransformationMatrix()); - } else - currLayer->setTransform(m_transform); - } - } -} - -void GraphicsLayerCA::updateChildrenTransform() -{ - primaryLayer()->setSublayerTransform(m_childrenTransform); - - if (LayerMap* layerCloneMap = primaryLayerClones()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setSublayerTransform(m_childrenTransform); - } -} - -void GraphicsLayerCA::updateMasksToBounds() -{ - m_layer->setMasksToBounds(m_masksToBounds); - - if (LayerMap* layerCloneMap = m_layerClones.get()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setMasksToBounds(m_masksToBounds); - } - - updateDebugIndicators(); -} - -void GraphicsLayerCA::updateContentsOpaque() -{ - m_layer.get()->setOpaque(m_contentsOpaque); - - if (LayerMap* layerCloneMap = m_layerClones.get()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setOpaque(m_contentsOpaque); - } -} - -void GraphicsLayerCA::updateBackfaceVisibility() -{ - if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) { - m_structuralLayer->setDoubleSided(m_backfaceVisibility); - - if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setDoubleSided(m_backfaceVisibility); - } - } - - m_layer->setDoubleSided(m_backfaceVisibility); - - if (LayerMap* layerCloneMap = m_layerClones.get()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setDoubleSided(m_backfaceVisibility); - } -} - -void GraphicsLayerCA::updateStructuralLayer() -{ - ensureStructuralLayer(structuralLayerPurpose()); -} - -void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose) -{ - if (purpose == NoStructuralLayer) { - if (m_structuralLayer) { - // Replace the transformLayer in the parent with this layer. - m_layer->removeFromSuperlayer(); - m_structuralLayer->superlayer()->replaceSublayer(m_structuralLayer.get(), m_layer.get()); - - moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_structuralLayer.get(), m_layer.get()); - moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_structuralLayer.get(), m_layer.get()); - - // Release the structural layer. - m_structuralLayer = 0; - - // Update the properties of m_layer now that we no longer have a structural layer. - updateLayerPosition(); - updateLayerSize(); - updateAnchorPoint(); - updateTransform(); - updateChildrenTransform(); - - updateSublayerList(); - updateOpacityOnLayer(); - } - return; - } - - bool structuralLayerChanged = false; - - if (purpose == StructuralLayerForPreserves3D) { - if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeTransformLayer) - m_structuralLayer = 0; - - if (!m_structuralLayer) { - m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeTransformLayer, this); - structuralLayerChanged = true; - } - } else { - if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeLayer) - m_structuralLayer = 0; - - if (!m_structuralLayer) { - m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); - structuralLayerChanged = true; - } - } - - if (!structuralLayerChanged) - return; - - updateLayerNames(); - - // Update the properties of the structural layer. - updateLayerPosition(); - updateLayerSize(); - updateAnchorPoint(); - updateTransform(); - updateChildrenTransform(); - updateBackfaceVisibility(); - - // Set properties of m_layer to their default values, since these are expressed on on the structural layer. - FloatPoint point(m_size.width() / 2.0f, m_size.height() / 2.0f); - FloatPoint3D anchorPoint(0.5f, 0.5f, 0); - m_layer->setPosition(point); - m_layer->setAnchorPoint(anchorPoint); - m_layer->setTransform(TransformationMatrix()); - m_layer->setOpacity(1); - if (m_layerClones) { - LayerMap::const_iterator end = m_layerClones->end(); - for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) { - PlatformCALayer* currLayer = it->second.get(); - currLayer->setPosition(point); - currLayer->setAnchorPoint(anchorPoint); - currLayer->setTransform(TransformationMatrix()); - currLayer->setOpacity(1); - } - } - - // Move this layer to be a child of the transform layer. - m_layer->superlayer()->replaceSublayer(m_layer.get(), m_structuralLayer.get()); - m_structuralLayer->appendSublayer(m_layer.get()); - - moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_layer.get(), m_structuralLayer.get()); - moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_layer.get(), m_structuralLayer.get()); - - updateSublayerList(); - updateOpacityOnLayer(); -} - -GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const -{ - if (preserves3D()) - return StructuralLayerForPreserves3D; - - if (isReplicated()) - return StructuralLayerForReplicaFlattening; - - return NoStructuralLayer; -} - -void GraphicsLayerCA::updateLayerDrawsContent() -{ - bool needTiledLayer = requiresTiledLayer(m_size); - if (needTiledLayer != m_usingTiledLayer) - swapFromOrToTiledLayer(needTiledLayer); - - if (m_drawsContent) - m_layer->setNeedsDisplay(); - else - m_layer->setContents(0); - - updateDebugIndicators(); -} - -void GraphicsLayerCA::updateAcceleratesDrawing() -{ - m_layer->setAcceleratesDrawing(m_acceleratesDrawing); -} - -void GraphicsLayerCA::updateLayerBackgroundColor() -{ - if (!m_contentsLayer) - return; - - // We never create the contents layer just for background color yet. - if (m_backgroundColorSet) - m_contentsLayer->setBackgroundColor(m_backgroundColor); - else - m_contentsLayer->setBackgroundColor(Color::transparent); -} - -void GraphicsLayerCA::updateContentsImage() -{ - if (m_pendingContentsImage) { - if (!m_contentsLayer.get()) { - m_contentsLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); -#ifndef NDEBUG - m_contentsLayer->setName("Image Layer"); -#endif - setupContentsLayer(m_contentsLayer.get()); - // m_contentsLayer will be parented by updateSublayerList - } - - // FIXME: maybe only do trilinear if the image is being scaled down, - // but then what if the layer size changes? -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - m_contentsLayer->setMinificationFilter(PlatformCALayer::Trilinear); -#endif - m_contentsLayer->setContents(m_pendingContentsImage.get()); - m_pendingContentsImage = 0; - - if (m_contentsLayerClones) { - LayerMap::const_iterator end = m_contentsLayerClones->end(); - for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) - it->second->setContents(m_contentsLayer->contents()); - } - - updateContentsRect(); - } else { - // No image. - // m_contentsLayer will be removed via updateSublayerList. - m_contentsLayer = 0; - } -} - -void GraphicsLayerCA::updateContentsMediaLayer() -{ - // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList(). - if (m_contentsLayer) { - setupContentsLayer(m_contentsLayer.get()); - updateContentsRect(); - } -} - -void GraphicsLayerCA::updateContentsCanvasLayer() -{ - // CanvasLayer was set as m_contentsLayer, and will get parented in updateSublayerList(). - if (m_contentsLayer) { - setupContentsLayer(m_contentsLayer.get()); - m_contentsLayer->setNeedsDisplay(); - updateContentsRect(); - } -} - -void GraphicsLayerCA::updateContentsRect() -{ - if (!m_contentsLayer) - return; - - FloatPoint point(m_contentsRect.x(), m_contentsRect.y()); - FloatRect rect(0, 0, m_contentsRect.width(), m_contentsRect.height()); - - m_contentsLayer->setPosition(point); - m_contentsLayer->setBounds(rect); - - if (m_contentsLayerClones) { - LayerMap::const_iterator end = m_contentsLayerClones->end(); - for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) { - it->second->setPosition(point); - it->second->setBounds(rect); - } - } -} - -void GraphicsLayerCA::updateMaskLayer() -{ - PlatformCALayer* maskCALayer = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayer() : 0; - m_layer->setMask(maskCALayer); - - LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayerClones() : 0; - - if (LayerMap* layerCloneMap = m_layerClones.get()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->first).get() : 0; - it->second->setMask(maskClone); - } - } -} - -void GraphicsLayerCA::updateReplicatedLayers() -{ - // Clone the descendants of the replicated layer, and parent under us. - ReplicaState replicaState(ReplicaState::ReplicaBranch); - - RefPtr<PlatformCALayer>replicaRoot = replicatedLayerRoot(replicaState); - if (!replicaRoot) - return; - - if (m_structuralLayer) - m_structuralLayer->insertSublayer(replicaRoot.get(), 0); - else - m_layer->insertSublayer(replicaRoot.get(), 0); -} - -// For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1. -GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const -{ - size_t depth = m_replicaBranches.size(); - - const size_t bitsPerUChar = sizeof(UChar) * 8; - size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar; - - Vector<UChar> result(vectorSize); - result.fill(0); - - // Create a string from the bit sequence which we can use to identify the clone. - // Note that the string may contain embedded nulls, but that's OK. - for (size_t i = 0; i < depth; ++i) { - UChar& currChar = result[i / bitsPerUChar]; - currChar = (currChar << 1) | m_replicaBranches[i]; - } - - return String::adopt(result); -} - -PassRefPtr<PlatformCALayer> GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState) -{ - // Limit replica nesting, to avoid 2^N explosion of replica layers. - if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth) - return 0; - - GraphicsLayerCA* replicatedLayer = static_cast<GraphicsLayerCA*>(m_replicatedLayer); - - RefPtr<PlatformCALayer> clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel); - FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer(); - - // Replica root has no offset or transform - clonedLayerRoot->setPosition(cloneRootPosition); - clonedLayerRoot->setTransform(TransformationMatrix()); - - return clonedLayerRoot; -} - -void GraphicsLayerCA::updateLayerAnimations() -{ - if (m_animationsToProcess.size()) { - AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end(); - for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) { - const String& currAnimationName = it->first; - AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName); - if (animationIt == m_runningAnimations.end()) - continue; - - const AnimationProcessingAction& processingInfo = it->second; - const Vector<LayerPropertyAnimation>& animations = animationIt->second; - for (size_t i = 0; i < animations.size(); ++i) { - const LayerPropertyAnimation& currAnimation = animations[i]; - switch (processingInfo.action) { - case Remove: - removeCAAnimationFromLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index); - break; - case Pause: - pauseCAAnimationOnLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, processingInfo.timeOffset); - break; - } - } - - if (processingInfo.action == Remove) - m_runningAnimations.remove(currAnimationName); - } - - m_animationsToProcess.clear(); - } - - size_t numAnimations; - if ((numAnimations = m_uncomittedAnimations.size())) { - for (size_t i = 0; i < numAnimations; ++i) { - const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i]; - setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_timeOffset); - - AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name); - if (it == m_runningAnimations.end()) { - Vector<LayerPropertyAnimation> animations; - animations.append(pendingAnimation); - m_runningAnimations.add(pendingAnimation.m_name, animations); - } else { - Vector<LayerPropertyAnimation>& animations = it->second; - animations.append(pendingAnimation); - } - } - - m_uncomittedAnimations.clear(); - } -} - -void GraphicsLayerCA::setAnimationOnLayer(PlatformCAAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, double timeOffset) -{ - PlatformCALayer* layer = animatedLayer(property); - - if (timeOffset) - caAnim->setBeginTime(CACurrentMediaTime() - timeOffset); - - String animationID = animationIdentifier(animationName, property, index); - - layer->removeAnimationForKey(animationID); - layer->addAnimationForKey(animationID, caAnim); - - if (LayerMap* layerCloneMap = animatedLayerClones(property)) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - // Skip immediate replicas, since they move with the original. - if (m_replicaLayer && isReplicatedRootClone(it->first)) - continue; - - it->second->removeAnimationForKey(animationID); - it->second->addAnimationForKey(animationID, caAnim); - } - } -} - -// Workaround for <rdar://problem/7311367> -static void bug7311367Workaround(PlatformCALayer* transformLayer, const TransformationMatrix& transform) -{ - if (!transformLayer) - return; - - TransformationMatrix caTransform = transform; - caTransform.setM41(caTransform.m41() + 1); - transformLayer->setTransform(caTransform); - - caTransform.setM41(caTransform.m41() - 1); - transformLayer->setTransform(caTransform); -} - -bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index) -{ - PlatformCALayer* layer = animatedLayer(property); - - String animationID = animationIdentifier(animationName, property, index); - - if (!layer->animationForKey(animationID)) - return false; - - layer->removeAnimationForKey(animationID); - bug7311367Workaround(m_structuralLayer.get(), m_transform); - - if (LayerMap* layerCloneMap = animatedLayerClones(property)) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - // Skip immediate replicas, since they move with the original. - if (m_replicaLayer && isReplicatedRootClone(it->first)) - continue; - - it->second ->removeAnimationForKey(animationID); - } - } - return true; -} - -void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, double timeOffset) -{ - PlatformCALayer* layer = animatedLayer(property); - - String animationID = animationIdentifier(animationName, property, index); - - RefPtr<PlatformCAAnimation> curAnim = layer->animationForKey(animationID); - if (!curAnim) - return; - - // Animations on the layer are immutable, so we have to clone and modify. - RefPtr<PlatformCAAnimation> newAnim = PlatformCAAnimation::create(curAnim.get()); - - newAnim->setSpeed(0); - newAnim->setTimeOffset(timeOffset); - - layer->addAnimationForKey(animationID, newAnim.get()); // This will replace the running animation. - - // Pause the animations on the clones too. - if (LayerMap* layerCloneMap = animatedLayerClones(property)) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - // Skip immediate replicas, since they move with the original. - if (m_replicaLayer && isReplicatedRootClone(it->first)) - continue; - it->second->addAnimationForKey(animationID, newAnim.get()); - } - } -} - -void GraphicsLayerCA::repaintLayerDirtyRects() -{ - if (!m_dirtyRects.size()) - return; - - for (size_t i = 0; i < m_dirtyRects.size(); ++i) - m_layer->setNeedsDisplay(&(m_dirtyRects[i])); - - m_dirtyRects.clear(); -} - -void GraphicsLayerCA::updateContentsNeedsDisplay() -{ - if (m_contentsLayer) - m_contentsLayer->setNeedsDisplay(); -} - -bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset) -{ - ASSERT(valueList.property() != AnimatedPropertyWebkitTransform); - - bool isKeyframe = valueList.size() > 2; - bool valuesOK; - - bool additive = false; - int animationIndex = 0; - - RefPtr<PlatformCAAnimation> caAnimation; - - if (isKeyframe) { - caAnimation = createKeyframeAnimation(animation, valueList.property(), additive); - valuesOK = setAnimationKeyframes(valueList, animation, caAnimation.get()); - } else { - caAnimation = createBasicAnimation(animation, valueList.property(), additive); - valuesOK = setAnimationEndpoints(valueList, animation, caAnimation.get()); - } - - if (!valuesOK) - return false; - - m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset)); - - return true; -} - -bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize) -{ - ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); - - TransformOperationList functionList; - bool listsMatch, hasBigRotation; - fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation); - - // We need to fall back to software animation if we don't have setValueFunction:, and - // we would need to animate each incoming transform function separately. This is the - // case if we have a rotation >= 180 or we have more than one transform function. - if ((hasBigRotation || functionList.size() > 1) && !PlatformCAAnimation::supportsValueFunction()) - return false; - - bool validMatrices = true; - - // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation. - // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation - // if that's not true as well. - bool isMatrixAnimation = !listsMatch || !PlatformCAAnimation::supportsValueFunction(); - - size_t numAnimations = isMatrixAnimation ? 1 : functionList.size(); - bool isKeyframe = valueList.size() > 2; - - // Iterate through the transform functions, sending an animation for each one. - for (size_t animationIndex = 0; animationIndex < numAnimations; ++animationIndex) { - TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : functionList[animationIndex]; - RefPtr<PlatformCAAnimation> caAnimation; - -#if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) - // CA applies animations in reverse order (<rdar://problem/7095638>) so we need the last one we add (per property) - // to be non-additive. - bool additive = animationIndex < (numAnimations - 1); -#else - bool additive = animationIndex > 0; -#endif - if (isKeyframe) { - caAnimation = createKeyframeAnimation(animation, valueList.property(), additive); - validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize); - } else { - caAnimation = createBasicAnimation(animation, valueList.property(), additive); - validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize); - } - - if (!validMatrices) - break; - - m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset)); - } - - return validMatrices; -} - -PassRefPtr<PlatformCAAnimation> GraphicsLayerCA::createBasicAnimation(const Animation* anim, AnimatedPropertyID property, bool additive) -{ - RefPtr<PlatformCAAnimation> basicAnim = PlatformCAAnimation::create(PlatformCAAnimation::Basic, propertyIdToString(property)); - setupAnimation(basicAnim.get(), anim, additive); - return basicAnim; -} - -PassRefPtr<PlatformCAAnimation>GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, AnimatedPropertyID property, bool additive) -{ - RefPtr<PlatformCAAnimation> keyframeAnim = PlatformCAAnimation::create(PlatformCAAnimation::Keyframe, propertyIdToString(property)); - setupAnimation(keyframeAnim.get(), anim, additive); - return keyframeAnim; -} - -void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const Animation* anim, bool additive) -{ - double duration = anim->duration(); - if (duration <= 0) - duration = cAnimationAlmostZeroDuration; - - float repeatCount = anim->iterationCount(); - if (repeatCount == Animation::IterationCountInfinite) - repeatCount = FLT_MAX; - else if (anim->direction() == Animation::AnimationDirectionAlternate) - repeatCount /= 2; - - PlatformCAAnimation::FillModeType fillMode = PlatformCAAnimation::NoFillMode; - switch (anim->fillMode()) { - case AnimationFillModeNone: - fillMode = PlatformCAAnimation::Forwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash. - break; - case AnimationFillModeBackwards: - fillMode = PlatformCAAnimation::Both; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash. - break; - case AnimationFillModeForwards: - fillMode = PlatformCAAnimation::Forwards; - break; - case AnimationFillModeBoth: - fillMode = PlatformCAAnimation::Both; - break; - } - - propertyAnim->setDuration(duration); - propertyAnim->setRepeatCount(repeatCount); - propertyAnim->setAutoreverses(anim->direction()); - propertyAnim->setRemovedOnCompletion(false); - propertyAnim->setAdditive(additive); - propertyAnim->setFillMode(fillMode); -} - -const TimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue* animValue, const Animation* anim) -{ - if (animValue->timingFunction()) - return animValue->timingFunction(); - if (anim->isTimingFunctionSet()) - return anim->timingFunction().get(); - - return 0; -} - -bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim) -{ - switch (valueList.property()) { - case AnimatedPropertyOpacity: { - basicAnim->setFromValue(static_cast<const FloatAnimationValue*>(valueList.at(0))->value()); - basicAnim->setToValue(static_cast<const FloatAnimationValue*>(valueList.at(1))->value()); - break; - } - default: - ASSERT_NOT_REACHED(); // we don't animate color yet - break; - } - - // This codepath is used for 2-keyframe animations, so we still need to look in the start - // for a timing function. - const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim); - if (timingFunction) - basicAnim->setTimingFunction(timingFunction); - - return true; -} - -bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* keyframeAnim) -{ - Vector<float> keyTimes; - Vector<float> values; - Vector<const TimingFunction*> timingFunctions; - - for (unsigned i = 0; i < valueList.size(); ++i) { - const AnimationValue* curValue = valueList.at(i); - keyTimes.append(curValue->keyTime()); - - switch (valueList.property()) { - case AnimatedPropertyOpacity: { - const FloatAnimationValue* floatValue = static_cast<const FloatAnimationValue*>(curValue); - values.append(floatValue->value()); - break; - } - default: - ASSERT_NOT_REACHED(); // we don't animate color yet - break; - } - - timingFunctions.append(timingFunctionForAnimationValue(curValue, anim)); - } - - // We toss the last tfArray value because it has to one shorter than the others. - timingFunctions.removeLast(); - - keyframeAnim->setKeyTimes(keyTimes); - keyframeAnim->setValues(values); - keyframeAnim->setTimingFunctions(timingFunctions); - - return true; -} - -bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize) -{ - ASSERT(valueList.size() == 2); - const TransformAnimationValue* startValue = static_cast<const TransformAnimationValue*>(valueList.at(0)); - const TransformAnimationValue* endValue = static_cast<const TransformAnimationValue*>(valueList.at(1)); - - if (isMatrixAnimation) { - TransformationMatrix fromTransform, toTransform; - startValue->value()->apply(boxSize, fromTransform); - endValue->value()->apply(boxSize, toTransform); - - // If any matrix is singular, CA won't animate it correctly. So fall back to software animation - if (!fromTransform.isInvertible() || !toTransform.isInvertible()) - return false; - - basicAnim->setFromValue(fromTransform); - basicAnim->setToValue(toTransform); - } else { - if (isTransformTypeNumber(transformOpType)) { - float value; - getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, value); - basicAnim->setFromValue(value); - getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, value); - basicAnim->setToValue(value); - } else if (isTransformTypeFloatPoint3D(transformOpType)) { - FloatPoint3D value; - getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, value); - basicAnim->setFromValue(value); - getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, value); - basicAnim->setToValue(value); - } else { - TransformationMatrix value; - getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, value); - basicAnim->setFromValue(value); - getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, value); - basicAnim->setToValue(value); - } - } - - // This codepath is used for 2-keyframe animations, so we still need to look in the start - // for a timing function. - const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim); - basicAnim->setTimingFunction(timingFunction); - -#if HAVE_MODERN_QUARTZCORE - PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType); - if (valueFunction != PlatformCAAnimation::NoValueFunction) - basicAnim->setValueFunction(valueFunction); -#endif - - return true; -} - -bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize) -{ - Vector<float> keyTimes; - Vector<float> floatValues; - Vector<FloatPoint3D> floatPoint3DValues; - Vector<TransformationMatrix> transformationMatrixValues; - Vector<const TimingFunction*> timingFunctions; - - for (unsigned i = 0; i < valueList.size(); ++i) { - const TransformAnimationValue* curValue = static_cast<const TransformAnimationValue*>(valueList.at(i)); - keyTimes.append(curValue->keyTime()); - - if (isMatrixAnimation) { - TransformationMatrix transform; - curValue->value()->apply(boxSize, transform); - - // If any matrix is singular, CA won't animate it correctly. So fall back to software animation - if (!transform.isInvertible()) - return false; - - transformationMatrixValues.append(transform); - } else { - const TransformOperation* transformOp = curValue->value()->at(functionIndex); - if (isTransformTypeNumber(transformOpType)) { - float value; - getTransformFunctionValue(transformOp, transformOpType, boxSize, value); - floatValues.append(value); - } else if (isTransformTypeFloatPoint3D(transformOpType)) { - FloatPoint3D value; - getTransformFunctionValue(transformOp, transformOpType, boxSize, value); - floatPoint3DValues.append(value); - } else { - TransformationMatrix value; - getTransformFunctionValue(transformOp, transformOpType, boxSize, value); - transformationMatrixValues.append(value); - } - } - - const TimingFunction* timingFunction = timingFunctionForAnimationValue(curValue, animation); - timingFunctions.append(timingFunction); - } - - // We toss the last tfArray value because it has to one shorter than the others. - timingFunctions.removeLast(); - - keyframeAnim->setKeyTimes(keyTimes); - - if (isTransformTypeNumber(transformOpType)) - keyframeAnim->setValues(floatValues); - else if (isTransformTypeFloatPoint3D(transformOpType)) - keyframeAnim->setValues(floatPoint3DValues); - else - keyframeAnim->setValues(transformationMatrixValues); - - keyframeAnim->setTimingFunctions(timingFunctions); - -#if HAVE_MODERN_QUARTZCORE - PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType); - if (valueFunction != PlatformCAAnimation::NoValueFunction) - keyframeAnim->setValueFunction(valueFunction); -#endif - return true; -} - -void GraphicsLayerCA::suspendAnimations(double time) -{ - double t = currentTimeToMediaTime(time ? time : currentTime()); - primaryLayer()->setSpeed(0); - primaryLayer()->setTimeOffset(t); - - // Suspend the animations on the clones too. - if (LayerMap* layerCloneMap = primaryLayerClones()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - it->second->setSpeed(0); - it->second->setTimeOffset(t); - } - } -} - -void GraphicsLayerCA::resumeAnimations() -{ - primaryLayer()->setSpeed(1); - primaryLayer()->setTimeOffset(0); - - // Resume the animations on the clones too. - if (LayerMap* layerCloneMap = primaryLayerClones()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - it->second->setSpeed(1); - it->second->setTimeOffset(0); - } - } -} - -PlatformCALayer* GraphicsLayerCA::hostLayerForSublayers() const -{ - return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); -} - -PlatformCALayer* GraphicsLayerCA::layerForSuperlayer() const -{ - return m_structuralLayer ? m_structuralLayer.get() : m_layer.get(); -} - -PlatformCALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const -{ - return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer(); -} - -GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const -{ - return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones(); -} - -void GraphicsLayerCA::setDebugBackgroundColor(const Color& color) -{ - if (color.isValid()) - m_layer->setBackgroundColor(color); - else - m_layer->setBackgroundColor(Color::transparent); -} - -void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth) -{ - if (color.isValid()) { - m_layer->setBorderColor(color); - m_layer->setBorderWidth(borderWidth); - } else { - m_layer->setBorderColor(Color::transparent); - m_layer->setBorderWidth(0); - } -} - -FloatSize GraphicsLayerCA::constrainedSize() const -{ - float tileColumns = ceilf(m_size.width() / kTiledLayerTileSize); - float tileRows = ceilf(m_size.height() / kTiledLayerTileSize); - double numTiles = tileColumns * tileRows; - - FloatSize constrainedSize = m_size; - const unsigned cMaxTileCount = 512; - while (numTiles > cMaxTileCount) { - // Constrain the wider dimension. - if (constrainedSize.width() >= constrainedSize.height()) { - tileColumns = max(floorf(cMaxTileCount / tileRows), 1.0f); - constrainedSize.setWidth(tileColumns * kTiledLayerTileSize); - } else { - tileRows = max(floorf(cMaxTileCount / tileColumns), 1.0f); - constrainedSize.setHeight(tileRows * kTiledLayerTileSize); - } - numTiles = tileColumns * tileRows; - } - - return constrainedSize; -} - -bool GraphicsLayerCA::requiresTiledLayer(const FloatSize& size) const -{ - if (!m_drawsContent) - return false; - - // FIXME: catch zero-size height or width here (or earlier)? - return size.width() > cMaxPixelDimension || size.height() > cMaxPixelDimension; -} - -void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer) -{ - if (useTiledLayer == m_usingTiledLayer) - return; - - RefPtr<PlatformCALayer> oldLayer = m_layer; - - m_layer = PlatformCALayer::create(useTiledLayer ? PlatformCALayer::LayerTypeWebTiledLayer : PlatformCALayer::LayerTypeWebLayer, this); - - m_usingTiledLayer = useTiledLayer; - - if (useTiledLayer) { -#if !HAVE_MODERN_QUARTZCORE - // Tiled layer has issues with flipped coordinates. - setContentsOrientation(CompositingCoordinatesTopDown); -#endif - } else { -#if !HAVE_MODERN_QUARTZCORE - setContentsOrientation(GraphicsLayerCA::defaultContentsOrientation()); -#endif - } - - m_layer->adoptSublayers(oldLayer.get()); - - oldLayer->superlayer()->replaceSublayer(oldLayer.get(), m_layer.get()); - - updateContentsTransform(); - - updateLayerPosition(); - updateLayerSize(); - updateAnchorPoint(); - updateTransform(); - updateChildrenTransform(); - updateMasksToBounds(); - updateContentsOpaque(); - updateBackfaceVisibility(); - updateLayerBackgroundColor(); - - updateOpacityOnLayer(); - -#ifndef NDEBUG - String name = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + m_name; - m_layer->setName(name); -#endif - - // move over animations - moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, oldLayer.get(), m_layer.get()); - moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, oldLayer.get(), m_layer.get()); - moveOrCopyAnimationsForProperty(Move, AnimatedPropertyBackgroundColor, oldLayer.get(), m_layer.get()); - - // need to tell new layer to draw itself - setNeedsDisplay(); - - updateDebugIndicators(); -} - -GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const -{ -#if !HAVE_MODERN_QUARTZCORE - // Older QuartzCore does not support -geometryFlipped, so we manually flip the root - // layer geometry, and then flip the contents of each layer back so that the CTM for CG - // is unflipped, allowing it to do the correct font auto-hinting. - return CompositingCoordinatesBottomUp; -#else - return CompositingCoordinatesTopDown; -#endif -} - -void GraphicsLayerCA::updateContentsTransform() -{ -#if !HAVE_MODERN_QUARTZCORE - if (contentsOrientation() == CompositingCoordinatesBottomUp) { - CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1); - contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -m_layer->bounds().size().height()); - m_layer->setContentsTransform(TransformationMatrix(contentsTransform)); - } -#endif -} - -void GraphicsLayerCA::setupContentsLayer(PlatformCALayer* contentsLayer) -{ - // Turn off implicit animations on the inner layer. - contentsLayer->setMasksToBounds(true); - - if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) { - TransformationMatrix flipper( - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, -1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); - contentsLayer->setTransform(flipper); - contentsLayer->setAnchorPoint(FloatPoint3D(0, 1, 0)); - } else - contentsLayer->setAnchorPoint(FloatPoint3D()); - - if (showDebugBorders()) { - contentsLayer->setBorderColor(Color(0, 0, 128, 180)); - contentsLayer->setBorderWidth(1.0f); - } -} - -PassRefPtr<PlatformCALayer> GraphicsLayerCA::findOrMakeClone(CloneID cloneID, PlatformCALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel) -{ - if (!sourceLayer) - return 0; - - RefPtr<PlatformCALayer> resultLayer; - - // Add with a dummy value to get an iterator for the insertion position, and a boolean that tells - // us whether there's an item there. This technique avoids two hash lookups. - RefPtr<PlatformCALayer> dummy; - pair<LayerMap::iterator, bool> addResult = clones->add(cloneID, dummy); - if (!addResult.second) { - // Value was not added, so it exists already. - resultLayer = addResult.first->second.get(); - } else { - resultLayer = cloneLayer(sourceLayer, cloneLevel); -#ifndef NDEBUG - resultLayer->setName(String::format("Clone %d of layer %p", cloneID[0U], sourceLayer)); -#endif - addResult.first->second = resultLayer; - } - - return resultLayer; -} - -void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer, RefPtr<PlatformCALayer>& contentsLayer, CloneLevel cloneLevel) -{ - structuralLayer = 0; - contentsLayer = 0; - - if (!m_layerClones) - m_layerClones = new LayerMap; - - if (!m_structuralLayerClones && m_structuralLayer) - m_structuralLayerClones = new LayerMap; - - if (!m_contentsLayerClones && m_contentsLayer) - m_contentsLayerClones = new LayerMap; - - primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel); - structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel); - contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel); -} - -void GraphicsLayerCA::removeCloneLayers() -{ - m_layerClones = 0; - m_structuralLayerClones = 0; - m_contentsLayerClones = 0; -} - -FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const -{ - // This can get called during a sync when we've just removed the m_replicaLayer. - if (!m_replicaLayer) - return FloatPoint(); - - FloatPoint replicaPosition = m_replicaLayer->replicatedLayerPosition(); - return FloatPoint(replicaPosition.x() + m_anchorPoint.x() * m_size.width(), - replicaPosition.y() + m_anchorPoint.y() * m_size.height()); -} - -void GraphicsLayerCA::propagateLayerChangeToReplicas() -{ - for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) { - GraphicsLayerCA* currLayerCA = static_cast<GraphicsLayerCA*>(currLayer); - if (!currLayerCA->hasCloneLayers()) - break; - - if (currLayerCA->replicaLayer()) - static_cast<GraphicsLayerCA*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged); - } -} - -PassRefPtr<PlatformCALayer> GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel) -{ - RefPtr<PlatformCALayer> primaryLayer; - RefPtr<PlatformCALayer> structuralLayer; - RefPtr<PlatformCALayer> contentsLayer; - ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, cloneLevel); - - if (m_maskLayer) { - RefPtr<PlatformCALayer> maskClone = static_cast<GraphicsLayerCA*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); - primaryLayer->setMask(maskClone.get()); - } - - if (m_replicatedLayer) { - // We are a replica being asked for clones of our layers. - RefPtr<PlatformCALayer> replicaRoot = replicatedLayerRoot(replicaState); - if (!replicaRoot) - return 0; - - if (structuralLayer) { - structuralLayer->insertSublayer(replicaRoot.get(), 0); - return structuralLayer; - } - - primaryLayer->insertSublayer(replicaRoot.get(), 0); - return primaryLayer; - } - - const Vector<GraphicsLayer*>& childLayers = children(); - Vector<RefPtr<PlatformCALayer> > clonalSublayers; - - RefPtr<PlatformCALayer> replicaLayer; - - if (m_replicaLayer && m_replicaLayer != replicaRoot) { - // We have nested replicas. Ask the replica layer for a clone of its contents. - replicaState.setBranchType(ReplicaState::ReplicaBranch); - replicaLayer = static_cast<GraphicsLayerCA*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel); - replicaState.setBranchType(ReplicaState::ChildBranch); - } - - if (replicaLayer || structuralLayer || contentsLayer || childLayers.size() > 0) { - if (structuralLayer) { - // Replicas render behind the actual layer content. - if (replicaLayer) - clonalSublayers.append(replicaLayer); - - // Add the primary layer next. Even if we have negative z-order children, the primary layer always comes behind. - clonalSublayers.append(primaryLayer); - } else if (contentsLayer) { - // FIXME: add the contents layer in the correct order with negative z-order children. - // This does not cause visible rendering issues because currently contents layers are only used - // for replaced elements that don't have children. - clonalSublayers.append(contentsLayer); - } - - replicaState.push(ReplicaState::ChildBranch); - - size_t numChildren = childLayers.size(); - for (size_t i = 0; i < numChildren; ++i) { - GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); - - RefPtr<PlatformCALayer> childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); - if (childLayer) - clonalSublayers.append(childLayer); - } - - replicaState.pop(); - - for (size_t i = 0; i < clonalSublayers.size(); ++i) - clonalSublayers[i]->removeFromSuperlayer(); - } - - RefPtr<PlatformCALayer> result; - if (structuralLayer) { - structuralLayer->setSublayers(clonalSublayers); - - if (contentsLayer) { - // If we have a transform layer, then the contents layer is parented in the - // primary layer (which is itself a child of the transform layer). - primaryLayer->removeAllSublayers(); - primaryLayer->appendSublayer(contentsLayer.get()); - } - - result = structuralLayer; - } else { - primaryLayer->setSublayers(clonalSublayers); - result = primaryLayer; - } - - return result; -} - -PassRefPtr<PlatformCALayer> GraphicsLayerCA::cloneLayer(PlatformCALayer *layer, CloneLevel cloneLevel) -{ - PlatformCALayer::LayerType layerType = (layer->layerType() == PlatformCALayer::LayerTypeTransformLayer) ? - PlatformCALayer::LayerTypeTransformLayer : PlatformCALayer::LayerTypeLayer; - RefPtr<PlatformCALayer> newLayer = PlatformCALayer::create(layerType, this); - - newLayer->setPosition(layer->position()); - newLayer->setBounds(layer->bounds()); - newLayer->setAnchorPoint(layer->anchorPoint()); - newLayer->setTransform(layer->transform()); - newLayer->setSublayerTransform(layer->sublayerTransform()); - newLayer->setContents(layer->contents()); - newLayer->setMasksToBounds(layer->masksToBounds()); - newLayer->setDoubleSided(layer->isDoubleSided()); - newLayer->setOpaque(layer->isOpaque()); - newLayer->setBackgroundColor(layer->backgroundColor()); - - if (cloneLevel == IntermediateCloneLevel) { - newLayer->setOpacity(layer->opacity()); - moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyWebkitTransform, layer, newLayer.get()); - moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyOpacity, layer, newLayer.get()); - } - - if (showDebugBorders()) { - newLayer->setBorderColor(Color(255, 122, 251)); - newLayer->setBorderWidth(2); - } - - return newLayer; -} - -void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity) -{ - LayerMap* layerCloneMap = 0; - - if (preserves3D()) { - m_layer->setOpacity(accumulatedOpacity); - layerCloneMap = m_layerClones.get(); - } else { - primaryLayer()->setOpacity(accumulatedOpacity); - layerCloneMap = primaryLayerClones(); - } - - if (layerCloneMap) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - if (m_replicaLayer && isReplicatedRootClone(it->first)) - continue; - it->second->setOpacity(m_opacity); - } - } -} - -void GraphicsLayerCA::updateOpacityOnLayer() -{ -#if !HAVE_MODERN_QUARTZCORE - // Distribute opacity either to our own layer or to our children. We pass in the - // contribution from our parent(s). - distributeOpacity(parent() ? parent()->accumulatedOpacity() : 1); -#else - primaryLayer()->setOpacity(m_opacity); - - if (LayerMap* layerCloneMap = primaryLayerClones()) { - LayerMap::const_iterator end = layerCloneMap->end(); - for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - if (m_replicaLayer && isReplicatedRootClone(it->first)) - continue; - - it->second->setOpacity(m_opacity); - } - - } -#endif -} - -void GraphicsLayerCA::noteSublayersChanged() -{ - noteLayerPropertyChanged(ChildrenChanged); - propagateLayerChangeToReplicas(); -} - -void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags) -{ - if (!m_uncommittedChanges && m_client) - m_client->notifySyncRequired(this); - - m_uncommittedChanges |= flags; -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) |