| /* |
| * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. |
| * Copyright (C) 2010 Google Inc. All rights reserved. |
| * 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: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * 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. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "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 THE COPYRIGHT |
| * OWNER 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. |
| */ |
| |
| |
| /** FIXME |
| * This file borrows code heavily from platform/graphics/win/GraphicsLayerCACF.cpp |
| * (and hence it includes both copyrights) |
| * Ideally the common code (mostly the code that keeps track of the layer hierarchy) |
| * should be kept separate and shared between platforms. It would be a well worthwhile |
| * effort once the Windows implementation (binaries and headers) of CoreAnimation is |
| * checked in to the WebKit repository. Until then only Apple can make this happen. |
| */ |
| |
| #include "config.h" |
| |
| #if USE(ACCELERATED_COMPOSITING) |
| |
| #include "GraphicsLayerBlackBerry.h" |
| |
| #include "FloatConversion.h" |
| #include "FloatRect.h" |
| #include "Image.h" |
| #include "LayerAnimation.h" |
| #include "LayerWebKitThread.h" |
| #include "NotImplemented.h" |
| |
| namespace WebCore { |
| |
| static void setLayerBorderColor(LayerWebKitThread& layer, const Color& color) |
| { |
| layer.setBorderColor(color); |
| } |
| |
| static void clearBorderColor(LayerWebKitThread& layer) |
| { |
| layer.setBorderColor(Color::transparent); |
| } |
| |
| static void setLayerBackgroundColor(LayerWebKitThread& layer, const Color& color) |
| { |
| layer.setBackgroundColor(color); |
| } |
| |
| static void clearLayerBackgroundColor(LayerWebKitThread& layer) |
| { |
| layer.setBackgroundColor(Color::transparent); |
| } |
| |
| PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) |
| { |
| return adoptPtr(new GraphicsLayerBlackBerry(client)); |
| } |
| |
| GraphicsLayerBlackBerry::GraphicsLayerBlackBerry(GraphicsLayerClient* client) |
| : GraphicsLayer(client) |
| , m_suspendTime(0) |
| , m_contentsLayerPurpose(NoContentsLayer) |
| , m_contentsLayerHasBackgroundColor(false) |
| { |
| m_layer = LayerWebKitThread::create(LayerData::Layer, this); |
| |
| updateDebugIndicators(); |
| } |
| |
| GraphicsLayerBlackBerry::~GraphicsLayerBlackBerry() |
| { |
| // Do cleanup while we can still safely call methods on the derived class. |
| willBeDestroyed(); |
| } |
| |
| void GraphicsLayerBlackBerry::willBeDestroyed() |
| { |
| if (m_layer) |
| m_layer->setOwner(0); |
| if (m_contentsLayer) |
| m_contentsLayer->setOwner(0); |
| if (m_transformLayer) |
| m_transformLayer->setOwner(0); |
| } |
| |
| void GraphicsLayerBlackBerry::setName(const String& inName) |
| { |
| String name = String::format("GraphicsLayerBlackBerry(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName; |
| GraphicsLayer::setName(name); |
| } |
| |
| bool GraphicsLayerBlackBerry::setChildren(const Vector<GraphicsLayer*>& children) |
| { |
| bool childrenChanged = GraphicsLayer::setChildren(children); |
| // FIXME: GraphicsLayer::setChildren calls addChild() for each sublayer, which |
| // will end up calling updateSublayerList() N times. |
| if (childrenChanged) |
| updateSublayerList(); |
| |
| return childrenChanged; |
| } |
| |
| void GraphicsLayerBlackBerry::addChild(GraphicsLayer* childLayer) |
| { |
| GraphicsLayer::addChild(childLayer); |
| updateSublayerList(); |
| } |
| |
| void GraphicsLayerBlackBerry::addChildAtIndex(GraphicsLayer* childLayer, int index) |
| { |
| GraphicsLayer::addChildAtIndex(childLayer, index); |
| updateSublayerList(); |
| } |
| |
| void GraphicsLayerBlackBerry::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) |
| { |
| GraphicsLayer::addChildBelow(childLayer, sibling); |
| updateSublayerList(); |
| } |
| |
| void GraphicsLayerBlackBerry::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling) |
| { |
| GraphicsLayer::addChildAbove(childLayer, sibling); |
| updateSublayerList(); |
| } |
| |
| bool GraphicsLayerBlackBerry::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) |
| { |
| if (!GraphicsLayer::replaceChild(oldChild, newChild)) |
| return false; |
| |
| updateSublayerList(); |
| return true; |
| } |
| |
| void GraphicsLayerBlackBerry::removeFromParent() |
| { |
| GraphicsLayer::removeFromParent(); |
| layerForSuperlayer()->removeFromSuperlayer(); |
| } |
| |
| void GraphicsLayerBlackBerry::setPosition(const FloatPoint& point) |
| { |
| GraphicsLayer::setPosition(point); |
| updateLayerPosition(); |
| } |
| |
| void GraphicsLayerBlackBerry::setAnchorPoint(const FloatPoint3D& point) |
| { |
| if (point == m_anchorPoint) |
| return; |
| |
| GraphicsLayer::setAnchorPoint(point); |
| updateAnchorPoint(); |
| } |
| |
| void GraphicsLayerBlackBerry::setSize(const FloatSize& size) |
| { |
| if (size == m_size) |
| return; |
| |
| GraphicsLayer::setSize(size); |
| updateLayerSize(); |
| } |
| |
| void GraphicsLayerBlackBerry::setTransform(const TransformationMatrix& transform) |
| { |
| if (transform == m_transform) |
| return; |
| |
| GraphicsLayer::setTransform(transform); |
| updateTransform(); |
| } |
| |
| void GraphicsLayerBlackBerry::setChildrenTransform(const TransformationMatrix& transform) |
| { |
| if (transform == m_childrenTransform) |
| return; |
| |
| GraphicsLayer::setChildrenTransform(transform); |
| updateChildrenTransform(); |
| } |
| |
| void GraphicsLayerBlackBerry::setPreserves3D(bool preserves3D) |
| { |
| if (preserves3D == m_preserves3D) |
| return; |
| |
| GraphicsLayer::setPreserves3D(preserves3D); |
| updateLayerPreserves3D(); |
| } |
| |
| void GraphicsLayerBlackBerry::setMasksToBounds(bool masksToBounds) |
| { |
| if (masksToBounds == m_masksToBounds) |
| return; |
| |
| GraphicsLayer::setMasksToBounds(masksToBounds); |
| updateMasksToBounds(); |
| } |
| |
| void GraphicsLayerBlackBerry::setDrawsContent(bool drawsContent) |
| { |
| // Note carefully this early-exit is only correct because we also properly initialize |
| // LayerWebKitThread::isDrawable() whenever m_contentsLayer is set to a new layer in setupContentsLayer(). |
| if (drawsContent == m_drawsContent) |
| return; |
| |
| GraphicsLayer::setDrawsContent(drawsContent); |
| updateLayerIsDrawable(); |
| } |
| |
| void GraphicsLayerBlackBerry::setContentsVisible(bool contentsVisible) |
| { |
| // Note carefully this early-exit is only correct because we also properly initialize |
| // LayerWebKitThread::isDrawable() whenever m_contentsLayer is set to a new layer in setupContentsLayer(). |
| if (contentsVisible == m_contentsVisible) |
| return; |
| |
| GraphicsLayer::setContentsVisible(contentsVisible); |
| updateLayerIsDrawable(); |
| } |
| |
| void GraphicsLayerBlackBerry::setMaskLayer(GraphicsLayer* maskLayer) |
| { |
| if (maskLayer == m_maskLayer) |
| return; |
| |
| GraphicsLayer::setMaskLayer(maskLayer); |
| |
| LayerWebKitThread* maskLayerWebKit = m_maskLayer ? m_maskLayer->platformLayer() : 0; |
| if (maskLayerWebKit) |
| maskLayerWebKit->setIsMask(true); |
| m_layer->setMaskLayer(maskLayerWebKit); |
| } |
| |
| void GraphicsLayerBlackBerry::setReplicatedByLayer(GraphicsLayer* layer) |
| { |
| GraphicsLayerBlackBerry* layerWebKit = static_cast<GraphicsLayerBlackBerry*>(layer); |
| GraphicsLayer::setReplicatedByLayer(layer); |
| LayerWebKitThread* replicaLayer = layerWebKit ? layerWebKit->primaryLayer() : 0; |
| primaryLayer()->setReplicaLayer(replicaLayer); |
| } |
| |
| void GraphicsLayerBlackBerry::setFixedPosition(bool fixed) |
| { |
| if (fixed == m_fixedPosition) |
| return; |
| |
| GraphicsLayer::setFixedPosition(fixed); |
| updateFixedPosition(); |
| } |
| |
| void GraphicsLayerBlackBerry::setHasFixedContainer(bool hasFixedContainer) |
| { |
| if (hasFixedContainer == m_hasFixedContainer) |
| return; |
| |
| GraphicsLayer::setHasFixedContainer(hasFixedContainer); |
| updateHasFixedContainer(); |
| } |
| |
| void GraphicsLayerBlackBerry::setHasFixedAncestorInDOMTree(bool hasFixedAncestorInDOMTree) |
| { |
| if (hasFixedAncestorInDOMTree == m_hasFixedAncestorInDOMTree) |
| return; |
| |
| GraphicsLayer::setHasFixedAncestorInDOMTree(hasFixedAncestorInDOMTree); |
| updateHasFixedAncestorInDOMTree(); |
| } |
| |
| #if ENABLE(CSS_FILTERS) |
| bool GraphicsLayerBlackBerry::setFilters(const FilterOperations& filters) |
| { |
| if (m_filters == filters) |
| return true; |
| |
| bool canCompositeFilters = LayerWebKitThread::filtersCanBeComposited(filters); |
| if (canCompositeFilters) { |
| m_filters = filters; |
| GraphicsLayer::setFilters(filters); |
| updateFilters(); |
| } else { |
| m_filters.clear(); |
| notImplemented(); |
| } |
| |
| return canCompositeFilters; |
| } |
| #endif |
| |
| void GraphicsLayerBlackBerry::setBackgroundColor(const Color& color) |
| { |
| if (m_backgroundColorSet && m_backgroundColor == color) |
| return; |
| |
| GraphicsLayer::setBackgroundColor(color); |
| |
| m_contentsLayerHasBackgroundColor = true; |
| updateLayerBackgroundColor(); |
| } |
| |
| void GraphicsLayerBlackBerry::clearBackgroundColor() |
| { |
| if (!m_backgroundColorSet) |
| return; |
| |
| GraphicsLayer::clearBackgroundColor(); |
| clearLayerBackgroundColor(*m_contentsLayer); |
| } |
| |
| void GraphicsLayerBlackBerry::setContentsOpaque(bool opaque) |
| { |
| if (m_contentsOpaque == opaque) |
| return; |
| |
| GraphicsLayer::setContentsOpaque(opaque); |
| updateContentsOpaque(); |
| } |
| |
| void GraphicsLayerBlackBerry::setBackfaceVisibility(bool visible) |
| { |
| if (m_backfaceVisibility == visible) |
| return; |
| |
| GraphicsLayer::setBackfaceVisibility(visible); |
| updateBackfaceVisibility(); |
| } |
| |
| void GraphicsLayerBlackBerry::setOpacity(float opacity) |
| { |
| float clampedOpacity = clampTo(opacity, 0.0f, 1.0f); |
| |
| if (m_opacity == clampedOpacity) |
| return; |
| |
| GraphicsLayer::setOpacity(clampedOpacity); |
| primaryLayer()->setOpacity(opacity); |
| } |
| |
| void GraphicsLayerBlackBerry::setContentsNeedsDisplay() |
| { |
| if (m_contentsLayer) |
| m_contentsLayer->setNeedsDisplay(); |
| } |
| |
| void GraphicsLayerBlackBerry::setNeedsDisplay() |
| { |
| if (drawsContent()) |
| m_layer->setNeedsDisplay(); |
| } |
| |
| void GraphicsLayerBlackBerry::setNeedsDisplayInRect(const FloatRect& rect) |
| { |
| if (drawsContent()) |
| m_layer->setNeedsDisplayInRect(rect); |
| } |
| |
| void GraphicsLayerBlackBerry::setContentsRect(const IntRect& rect) |
| { |
| if (rect == m_contentsRect) |
| return; |
| |
| GraphicsLayer::setContentsRect(rect); |
| updateContentsRect(); |
| } |
| |
| static PassRefPtr<LayerAnimation> removeAnimationByIdAndProperty(int id, AnimatedPropertyID property, Vector<RefPtr<LayerAnimation> >& list) |
| { |
| for (size_t i = 0; i < list.size(); ++i) { |
| if (list[i]->id() == id && list[i]->property() == property) { |
| RefPtr<LayerAnimation> layerAnimation = list[i]; |
| list.remove(i); |
| return layerAnimation; |
| } |
| } |
| |
| return PassRefPtr<LayerAnimation>(); |
| } |
| |
| static PassRefPtr<LayerAnimation> removeAnimationByName(const String& animationName, Vector<RefPtr<LayerAnimation> >& list) |
| { |
| for (size_t i = 0; i < list.size(); ++i) { |
| if (list[i]->name() == animationName) { |
| RefPtr<LayerAnimation> layerAnimation = list[i]; |
| list.remove(i); |
| return layerAnimation; |
| } |
| } |
| |
| return PassRefPtr<LayerAnimation>(); |
| } |
| |
| bool GraphicsLayerBlackBerry::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& animationName, double timeOffset) |
| { |
| // This is what GraphicsLayerCA checks for. |
| if (!animation || animation->isEmptyOrZeroDuration() || values.size() < 2) |
| return false; |
| |
| // We only support these two kinds of properties at the moment. |
| if (values.property() != AnimatedPropertyWebkitTransform && values.property() != AnimatedPropertyOpacity) |
| return false; |
| |
| // Remove any running animation for the same property. |
| // FIXME: Maybe this is superstition, I got the idea from GraphicsLayerQt |
| // WebCore might be adding an animation with the same name, but for a different property |
| removeAnimationByIdAndProperty(LayerAnimation::idFromAnimation(animation), values.property(), m_runningAnimations); |
| removeAnimationByIdAndProperty(LayerAnimation::idFromAnimation(animation), values.property(), m_suspendedAnimations); |
| |
| RefPtr<LayerAnimation> layerAnimation = LayerAnimation::create(values, boxSize, animation, animationName, timeOffset); |
| |
| #if DEBUG_LAYER_ANIMATION |
| fprintf(stderr, "LayerAnimation 0x%08x: Adding animation %s for property %d\n", layerAnimation.get(), animationName.latin1().data(), values.property()); |
| #endif |
| |
| m_runningAnimations.append(layerAnimation); |
| |
| updateAnimations(); |
| |
| return true; |
| } |
| |
| void GraphicsLayerBlackBerry::pauseAnimation(const String& animationName, double timeOffset) |
| { |
| // WebCore might have added several animations with the same name, but for different properties |
| |
| while (RefPtr<LayerAnimation> animation = removeAnimationByName(animationName, m_runningAnimations)) { |
| #if DEBUG_LAYER_ANIMATION |
| fprintf(stderr, "LayerAnimation 0x%08x: Pausing animation %s\n", animation.get(), animation->name().latin1().data()); |
| #endif |
| |
| // LayerAnimation is readonly. Create a new animation with the same data except for timeOffset. |
| // WebCore will adjust the timeOffset for paused animations so it can be used to calculate the |
| // progress for the paused animation without knowing the exact timestamp when the animation was |
| // paused. |
| // If an animation was started with a timeOffset dt_orig and paused dt_pause seconds later, the |
| // cloned animation will have a timeOffset of dt_pause + dt_orig. |
| animation = animation->clone(timeOffset); |
| m_suspendedAnimations.append(animation); |
| |
| #if DEBUG_LAYER_ANIMATION |
| fprintf(stderr, "LayerAnimation 0x%08x: Paused animation %s\n", animation.get(), animation->name().latin1().data()); |
| #endif |
| }; |
| |
| updateAnimations(); |
| } |
| |
| void GraphicsLayerBlackBerry::removeAnimation(const String& animationName) |
| { |
| // WebCore might have added several animations with the same name, but for different properties |
| |
| #if DEBUG_LAYER_ANIMATION |
| fprintf(stderr, "LayerAnimation: Removing animation %s\n", animationName.latin1().data()); |
| #endif |
| |
| while (removeAnimationByName(animationName, m_runningAnimations)) { } |
| while (removeAnimationByName(animationName, m_suspendedAnimations)) { } |
| |
| updateAnimations(); |
| } |
| |
| void GraphicsLayerBlackBerry::suspendAnimations(double time) |
| { |
| #if DEBUG_LAYER_ANIMATION |
| fprintf(stderr, "LayerAnimation: Suspending animations\n"); |
| #endif |
| m_suspendTime = time; |
| } |
| |
| void GraphicsLayerBlackBerry::resumeAnimations() |
| { |
| #if DEBUG_LAYER_ANIMATION |
| fprintf(stderr, "LayerAnimation: Resuming animations\n"); |
| #endif |
| m_suspendTime = 0; |
| } |
| |
| void GraphicsLayerBlackBerry::setContentsToImage(Image* image) |
| { |
| bool childrenChanged = false; |
| if (image) { |
| m_contentsLayerPurpose = ContentsLayerForImage; |
| if (!m_contentsLayer) |
| childrenChanged = true; |
| } else { |
| m_contentsLayerPurpose = NoContentsLayer; |
| if (m_contentsLayer) |
| childrenChanged = true; |
| } |
| |
| updateContentsImage(image); |
| |
| if (childrenChanged) |
| updateSublayerList(); |
| } |
| |
| void GraphicsLayerBlackBerry::updateContentsImage(Image* image) |
| { |
| if (image) { |
| if (!m_contentsLayer.get()) { |
| RefPtr<LayerWebKitThread> imageLayer = LayerWebKitThread::create(LayerData::Layer, this); |
| |
| setupContentsLayer(imageLayer.get()); |
| m_contentsLayer = imageLayer; |
| // m_contentsLayer will be parented by updateSublayerList. |
| } |
| m_contentsLayer->setContents(image); |
| |
| updateContentsRect(); |
| } else { |
| // No image. m_contentsLayer will be removed via updateSublayerList. |
| m_contentsLayer = 0; |
| } |
| } |
| |
| void GraphicsLayerBlackBerry::setContentsToCanvas(PlatformLayer* platformLayer) |
| { |
| bool childrenChanged = false; |
| if (platformLayer) { |
| platformLayer->setOwner(this); |
| if (m_contentsLayer.get() != platformLayer) { |
| setupContentsLayer(platformLayer); |
| m_contentsLayer = platformLayer; |
| m_contentsLayerPurpose = ContentsLayerForCanvas; |
| childrenChanged = true; |
| } |
| m_contentsLayer->setNeedsDisplay(); |
| updateContentsRect(); |
| } else { |
| if (m_contentsLayer) { |
| childrenChanged = true; |
| |
| // The old contents layer will be removed via updateSublayerList. |
| m_contentsLayer = 0; |
| } |
| } |
| |
| if (childrenChanged) |
| updateSublayerList(); |
| } |
| |
| void GraphicsLayerBlackBerry::setContentsToMedia(PlatformLayer* layer) |
| { |
| bool childrenChanged = false; |
| if (layer) { |
| if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForVideo) { |
| setupContentsLayer(layer); |
| m_contentsLayer = layer; |
| m_contentsLayerPurpose = ContentsLayerForVideo; |
| childrenChanged = true; |
| } |
| layer->setOwner(this); |
| layer->setNeedsDisplay(); |
| updateContentsRect(); |
| } else { |
| if (m_contentsLayer) { |
| childrenChanged = true; |
| |
| // The old contents layer will be removed via updateSublayerList. |
| m_contentsLayer = 0; |
| } |
| } |
| |
| if (childrenChanged) |
| updateSublayerList(); |
| } |
| |
| PlatformLayer* GraphicsLayerBlackBerry::hostLayerForSublayers() const |
| { |
| return m_transformLayer ? m_transformLayer.get() : m_layer.get(); |
| } |
| |
| PlatformLayer* GraphicsLayerBlackBerry::layerForSuperlayer() const |
| { |
| return m_transformLayer ? m_transformLayer.get() : m_layer.get(); |
| } |
| |
| PlatformLayer* GraphicsLayerBlackBerry::platformLayer() const |
| { |
| return primaryLayer(); |
| } |
| |
| void GraphicsLayerBlackBerry::setDebugBackgroundColor(const Color& color) |
| { |
| if (color.isValid()) |
| setLayerBackgroundColor(*m_layer, color); |
| else |
| clearLayerBackgroundColor(*m_layer); |
| } |
| |
| void GraphicsLayerBlackBerry::setDebugBorder(const Color& color, float borderWidth) |
| { |
| if (color.isValid()) { |
| setLayerBorderColor(*m_layer, color); |
| m_layer->setBorderWidth(borderWidth); |
| } else { |
| clearBorderColor(*m_layer); |
| m_layer->setBorderWidth(0); |
| } |
| } |
| |
| void GraphicsLayerBlackBerry::updateSublayerList() |
| { |
| Vector<RefPtr<LayerWebKitThread> > newSublayers; |
| |
| if (m_transformLayer) { |
| // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind. |
| newSublayers.append(m_layer.get()); |
| } 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.get()); |
| } |
| |
| const Vector<GraphicsLayer*>& childLayers = children(); |
| size_t numChildren = childLayers.size(); |
| for (size_t i = 0; i < numChildren; ++i) { |
| GraphicsLayerBlackBerry* curChild = static_cast<GraphicsLayerBlackBerry*>(childLayers[i]); |
| |
| LayerWebKitThread* childLayer = curChild->layerForSuperlayer(); |
| newSublayers.append(childLayer); |
| } |
| |
| for (size_t i = 0; i < newSublayers.size(); ++i) |
| newSublayers[i]->removeFromSuperlayer(); |
| |
| if (m_transformLayer) { |
| m_transformLayer->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->addSublayer(m_contentsLayer); |
| } |
| } else |
| m_layer->setSublayers(newSublayers); |
| } |
| |
| void GraphicsLayerBlackBerry::updateLayerPosition() |
| { |
| // Position is offset on the layer by the layer anchor point. |
| FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(), |
| m_position.y() + m_anchorPoint.y() * m_size.height()); |
| |
| primaryLayer()->setPosition(layerPosition); |
| } |
| |
| void GraphicsLayerBlackBerry::updateLayerSize() |
| { |
| IntSize layerSize(m_size.width(), m_size.height()); |
| if (m_transformLayer) { |
| m_transformLayer->setBounds(layerSize); |
| // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative. |
| FloatPoint centerPoint(m_size.width() / 2, m_size.height() / 2); |
| m_layer->setPosition(centerPoint); |
| } |
| |
| m_layer->setBounds(layerSize); |
| |
| // 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 GraphicsLayerBlackBerry::updateAnchorPoint() |
| { |
| primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y())); |
| primaryLayer()->setAnchorPointZ(m_anchorPoint.z()); |
| updateLayerPosition(); |
| } |
| |
| void GraphicsLayerBlackBerry::updateTransform() |
| { |
| primaryLayer()->setTransform(m_transform); |
| } |
| |
| void GraphicsLayerBlackBerry::updateChildrenTransform() |
| { |
| primaryLayer()->setSublayerTransform(m_childrenTransform); |
| } |
| |
| void GraphicsLayerBlackBerry::updateMasksToBounds() |
| { |
| m_layer->setMasksToBounds(m_masksToBounds); |
| updateDebugIndicators(); |
| } |
| |
| void GraphicsLayerBlackBerry::updateContentsOpaque() |
| { |
| m_layer->setOpaque(m_contentsOpaque); |
| } |
| |
| void GraphicsLayerBlackBerry::updateBackfaceVisibility() |
| { |
| m_layer->setDoubleSided(m_backfaceVisibility); |
| } |
| |
| void GraphicsLayerBlackBerry::updateLayerPreserves3D() |
| { |
| if (m_preserves3D && !m_transformLayer) { |
| // Create the transform layer. |
| m_transformLayer = LayerWebKitThread::create(LayerData::TransformLayer, this); |
| |
| // Copy the position from this layer. |
| updateLayerPosition(); |
| updateLayerSize(); |
| updateAnchorPoint(); |
| updateTransform(); |
| updateChildrenTransform(); |
| updateAnimations(); |
| |
| m_layer->setPosition(FloatPoint(m_size.width() / 2.0f, m_size.height() / 2.0f)); |
| |
| m_layer->setAnchorPoint(FloatPoint(0.5f, 0.5f)); |
| TransformationMatrix identity; |
| m_layer->setTransform(identity); |
| |
| // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer. |
| m_layer->setOpacity(1); |
| |
| // Move this layer to be a child of the transform layer. |
| if (m_layer->superlayer()) |
| m_layer->superlayer()->replaceSublayer(m_layer.get(), m_transformLayer.get()); |
| m_transformLayer->addSublayer(m_layer.get()); |
| |
| m_transformLayer->setPreserves3D(true); |
| m_layer->setPreserves3D(true); |
| |
| updateSublayerList(); |
| } else if (!m_preserves3D && m_transformLayer) { |
| // Relace the transformLayer in the parent with this layer. |
| m_layer->removeFromSuperlayer(); |
| if (m_transformLayer->superlayer()) |
| m_transformLayer->superlayer()->replaceSublayer(m_transformLayer.get(), m_layer.get()); |
| |
| // Release the transform layer. |
| m_transformLayer = 0; |
| |
| updateLayerPosition(); |
| updateLayerSize(); |
| updateAnchorPoint(); |
| updateTransform(); |
| updateChildrenTransform(); |
| updateAnimations(); |
| |
| m_layer->setPreserves3D(false); |
| |
| updateSublayerList(); |
| } |
| |
| updateOpacityOnLayer(); |
| } |
| |
| void GraphicsLayerBlackBerry::updateLayerIsDrawable() |
| { |
| // For the rest of the accelerated compositor code, there is no reason to make a |
| // distinction between drawsContent and contentsVisible. So, for m_layer, these two |
| // flags are combined here. m_contentsLayer shouldn't receive the drawsContent flag |
| // so it is only given contentsVisible. |
| m_layer->setDrawable(m_drawsContent && m_contentsVisible); |
| |
| if (m_contentsLayer) |
| m_contentsLayer->setDrawable(m_contentsVisible); |
| |
| if (m_drawsContent) |
| m_layer->setNeedsDisplay(); |
| |
| updateDebugIndicators(); |
| } |
| |
| void GraphicsLayerBlackBerry::updateFixedPosition() |
| { |
| m_layer->setFixedPosition(m_fixedPosition); |
| } |
| |
| void GraphicsLayerBlackBerry::updateHasFixedContainer() |
| { |
| m_layer->setHasFixedContainer(m_hasFixedContainer); |
| } |
| |
| void GraphicsLayerBlackBerry::updateHasFixedAncestorInDOMTree() |
| { |
| m_layer->setHasFixedAncestorInDOMTree(m_hasFixedAncestorInDOMTree); |
| } |
| |
| void GraphicsLayerBlackBerry::updateLayerBackgroundColor() |
| { |
| if (!m_contentsLayer) |
| return; |
| |
| // We never create the contents layer just for background color yet. |
| if (m_backgroundColorSet) |
| setLayerBackgroundColor(*m_contentsLayer, m_backgroundColor); |
| else |
| clearLayerBackgroundColor(*m_contentsLayer); |
| } |
| |
| #if ENABLE(CSS_FILTERS) |
| void GraphicsLayerBlackBerry::updateFilters() |
| { |
| if (!m_filters.size()) |
| return; |
| |
| primaryLayer()->setFilters(m_filters); |
| } |
| #endif |
| |
| void GraphicsLayerBlackBerry::updateAnimations() |
| { |
| // When there is a transform layer, the transform must be set on that layer |
| // instead of the content layer. Opacity can be set on the transform layer or the |
| // layer with equal outcome, but currently it is also set on the transform |
| // layer. Since we only accelerate animations of these two properties, it |
| // is safe to move all accelerated animations to the transform layer, and |
| // remove them from the layer proper. |
| // So the following code, while it looks strange, is correct: |
| // we transfer all animations to the transform layer if it exists. |
| // FIXME: If other properties become animated, it may not be equivalent to |
| // move them to the transform layer. Then this code needs to be revisited |
| // to only move the transform animations to the transform layer. |
| primaryLayer()->setRunningAnimations(m_runningAnimations); |
| primaryLayer()->setSuspendedAnimations(m_suspendedAnimations); |
| |
| // We need to move the animations to the transform layer if there is one. |
| if (m_transformLayer) { |
| m_layer->setRunningAnimations(Vector<RefPtr<LayerAnimation> >()); |
| m_layer->setSuspendedAnimations(Vector<RefPtr<LayerAnimation> >()); |
| } |
| } |
| |
| void GraphicsLayerBlackBerry::updateContentsVideo() |
| { |
| // FIXME: Implement |
| } |
| |
| void GraphicsLayerBlackBerry::updateContentsRect() |
| { |
| if (!m_contentsLayer) |
| return; |
| |
| m_contentsLayer->setPosition(m_contentsRect.location()); |
| m_contentsLayer->setBounds(m_contentsRect.size()); |
| } |
| |
| void GraphicsLayerBlackBerry::setupContentsLayer(LayerWebKitThread* contentsLayer) |
| { |
| if (contentsLayer == m_contentsLayer) |
| return; |
| |
| if (m_contentsLayer) { |
| m_contentsLayer->removeFromSuperlayer(); |
| m_contentsLayer = 0; |
| } |
| |
| if (contentsLayer) { |
| m_contentsLayer = contentsLayer; |
| |
| m_contentsLayer->setAnchorPoint(FloatPoint::zero()); |
| |
| // It is necessary to update setDrawable as soon as we receive the new contentsLayer, for |
| // the correctness of early exit conditions in setDrawsContent() and setContentsVisible(). |
| m_contentsLayer->setDrawable(m_contentsVisible); |
| |
| // Insert the content layer first. Video elements require this, because they have |
| // shadow content that must display in front of the video. |
| m_layer->insertSublayer(m_contentsLayer.get(), 0); |
| |
| updateContentsRect(); |
| |
| if (showDebugBorders()) { |
| setLayerBorderColor(*m_contentsLayer, Color(0, 0, 128, 180)); |
| m_contentsLayer->setBorderWidth(1); |
| } |
| } |
| updateDebugIndicators(); |
| } |
| |
| // This function simply mimics the operation of GraphicsLayerCA |
| void GraphicsLayerBlackBerry::updateOpacityOnLayer() |
| { |
| primaryLayer()->setOpacity(m_opacity); |
| } |
| |
| bool GraphicsLayerBlackBerry::contentsVisible(const IntRect& contentRect) const |
| { |
| if (!m_client) |
| return false; |
| |
| return m_client->contentsVisible(this, contentRect); |
| } |
| |
| } // namespace WebCore |
| |
| #endif // USE(ACCELERATED_COMPOSITING) |