| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "config.h" |
| #include "GraphicsLayerAndroid.h" |
| |
| #if USE(ACCELERATED_COMPOSITING) |
| |
| #include "AndroidAnimation.h" |
| #include "Animation.h" |
| #include "CString.h" |
| #include "FloatRect.h" |
| #include "GraphicsContext.h" |
| #include "Image.h" |
| #include "Length.h" |
| #include "SkLayer.h" |
| #include "PlatformBridge.h" |
| #include "PlatformGraphicsContext.h" |
| #include "RenderLayerBacking.h" |
| #include "RenderView.h" |
| #include "RotateTransformOperation.h" |
| #include "ScaleTransformOperation.h" |
| #include "SkCanvas.h" |
| #include "TransformationMatrix.h" |
| #include "TranslateTransformOperation.h" |
| |
| #include <cutils/log.h> |
| #include <wtf/CurrentTime.h> |
| |
| #undef LOG |
| #define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) |
| #define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) |
| #define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__) |
| |
| #undef LOG |
| #define LOG(...) |
| #undef MLOG |
| #define MLOG(...) |
| #undef TLOG |
| #define TLOG(...) |
| #undef LAYER_DEBUG |
| |
| using namespace std; |
| |
| static bool gPaused; |
| static double gPausedDelay; |
| |
| namespace WebCore { |
| |
| static int gDebugGraphicsLayerAndroidInstances = 0; |
| inline int GraphicsLayerAndroid::instancesCount() |
| { |
| return gDebugGraphicsLayerAndroidInstances; |
| } |
| |
| 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 ""; |
| } |
| |
| GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation() |
| { |
| return CompositingCoordinatesBottomUp; |
| } |
| |
| PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) |
| { |
| return new GraphicsLayerAndroid(client); |
| } |
| |
| SkLength convertLength(Length l) { |
| SkLength length; |
| length.type = SkLength::Undefined; |
| length.value = 0; |
| if (l.type() == WebCore::Percent) { |
| length.type = SkLength::Percent; |
| length.value = l.percent(); |
| } if (l.type() == WebCore::Fixed) { |
| length.type = SkLength::Fixed; |
| length.value = l.value(); |
| } |
| return length; |
| } |
| |
| GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) : |
| GraphicsLayer(client), |
| m_needsSyncChildren(false), |
| m_needsSyncMask(false), |
| m_needsRepaint(false), |
| m_needsDisplay(false), |
| m_needsNotifyClient(false), |
| m_haveContents(false), |
| m_haveImage(false), |
| m_translateX(0), |
| m_translateY(0), |
| m_currentTranslateX(0), |
| m_currentTranslateY(0), |
| m_currentPosition(0, 0) |
| { |
| m_contentLayer = adoptRef(new LayerAndroid(true)); |
| if (client) { |
| RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(client); |
| RenderLayer* renderLayer = backing->owningLayer(); |
| m_contentLayer->setIsRootLayer(renderLayer->isRootLayer()); |
| RenderView* view = static_cast<RenderView*>(renderLayer->renderer()); |
| if (view->isPositioned() && view->style()->position() == FixedPosition) { |
| SkLength left, top, right, bottom; |
| left = convertLength(view->style()->left()); |
| top = convertLength(view->style()->top()); |
| right = convertLength(view->style()->right()); |
| bottom = convertLength(view->style()->bottom()); |
| m_contentLayer->setFixedPosition(left, top, right, bottom); |
| } |
| } |
| gDebugGraphicsLayerAndroidInstances++; |
| } |
| |
| GraphicsLayerAndroid::~GraphicsLayerAndroid() |
| { |
| gDebugGraphicsLayerAndroidInstances--; |
| } |
| |
| void GraphicsLayerAndroid::setName(const String& name) |
| { |
| GraphicsLayer::setName(name); |
| } |
| |
| NativeLayer GraphicsLayerAndroid::nativeLayer() const |
| { |
| LOG("(%x) nativeLayer", this); |
| return 0; |
| } |
| |
| bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children) |
| { |
| bool childrenChanged = GraphicsLayer::setChildren(children); |
| if (childrenChanged) { |
| m_needsSyncChildren = true; |
| askForSync(); |
| } |
| |
| return childrenChanged; |
| } |
| |
| void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer) |
| { |
| #ifndef NDEBUG |
| const char* n = (static_cast<GraphicsLayerAndroid*>(childLayer))->m_name.latin1().data(); |
| LOG("(%x) addChild: %x (%s)", this, childLayer, n); |
| #endif |
| GraphicsLayer::addChild(childLayer); |
| m_needsSyncChildren = true; |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index) |
| { |
| LOG("(%x) addChild %x AtIndex %d", this, childLayer, index); |
| GraphicsLayer::addChildAtIndex(childLayer, index); |
| m_needsSyncChildren = true; |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) |
| { |
| LOG("(%x) addChild %x Below %x", this, childLayer, sibling); |
| GraphicsLayer::addChildBelow(childLayer, sibling); |
| m_needsSyncChildren = true; |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) |
| { |
| LOG("(%x) addChild %x Above %x", this, childLayer, sibling); |
| GraphicsLayer::addChildAbove(childLayer, sibling); |
| m_needsSyncChildren = true; |
| askForSync(); |
| } |
| |
| bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) |
| { |
| LOG("(%x) replaceChild %x by %x", this, oldChild, newChild); |
| bool ret = GraphicsLayer::replaceChild(oldChild, newChild); |
| m_needsSyncChildren = true; |
| askForSync(); |
| return ret; |
| } |
| |
| void GraphicsLayerAndroid::removeFromParent() |
| { |
| LOG("(%x) removeFromParent()", this); |
| if (m_parent) |
| static_cast<GraphicsLayerAndroid*>(m_parent)->needsSyncChildren(); |
| GraphicsLayer::removeFromParent(); |
| m_needsSyncChildren = true; |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::needsSyncChildren() |
| { |
| m_needsSyncChildren = true; |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::setPosition(const FloatPoint& point) |
| { |
| m_currentPosition = point; |
| m_needsDisplay = true; |
| #ifdef LAYER_DEBUG_2 |
| LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)", |
| this, point.x(), point.y(), m_currentPosition.x(), m_currentPosition.y(), |
| m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height()); |
| #endif |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point) |
| { |
| GraphicsLayer::setAnchorPoint(point); |
| m_contentLayer->setAnchorPoint(point.x(), point.y()); |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::setSize(const FloatSize& size) |
| { |
| if ((size.width() != m_size.width()) |
| || (size.height() != m_size.height())) { |
| MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height()); |
| GraphicsLayer::setSize(size); |
| m_contentLayer->setSize(size.width(), size.height()); |
| askForSync(); |
| } |
| } |
| |
| void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t) |
| { |
| TransformationMatrix::DecomposedType tDecomp; |
| t.decompose(tDecomp); |
| LOG("(%x) setTransform, translate (%.2f, %.2f), mpos(%.2f,%.2f)", |
| this, tDecomp.translateX, tDecomp.translateY, |
| m_position.x(), m_position.y()); |
| |
| if ((m_currentTranslateX != tDecomp.translateX) |
| || (m_currentTranslateY != tDecomp.translateY)) { |
| m_currentTranslateX = tDecomp.translateX; |
| m_currentTranslateY = tDecomp.translateY; |
| m_needsDisplay = true; |
| askForSync(); |
| } |
| } |
| |
| void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t) |
| { |
| if (t == m_childrenTransform) |
| return; |
| LOG("(%x) setChildrenTransform", this); |
| |
| GraphicsLayer::setChildrenTransform(t); |
| for (unsigned int i = 0; i < m_children.size(); i++) { |
| GraphicsLayer* layer = m_children[i]; |
| layer->setTransform(t); |
| if (layer->children().size()) |
| layer->setChildrenTransform(t); |
| } |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer) |
| { |
| if (layer == m_maskLayer) |
| return; |
| |
| GraphicsLayer::setMaskLayer(layer); |
| m_needsSyncMask = true; |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds) |
| { |
| GraphicsLayer::setMasksToBounds(masksToBounds); |
| m_needsSyncMask = true; |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::setDrawsContent(bool drawsContent) |
| { |
| GraphicsLayer::setDrawsContent(drawsContent); |
| m_contentLayer->setDrawsContent(m_drawsContent); |
| |
| if (m_drawsContent) { |
| m_haveContents = true; |
| m_contentLayer->setHaveContents(true); |
| setNeedsDisplay(); |
| } |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::setBackgroundColor(const Color& color) |
| { |
| LOG("(%x) setBackgroundColor", this); |
| GraphicsLayer::setBackgroundColor(color); |
| SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue()); |
| m_contentLayer->setBackgroundColor(c); |
| m_haveContents = true; |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::clearBackgroundColor() |
| { |
| LOG("(%x) clearBackgroundColor", this); |
| GraphicsLayer::clearBackgroundColor(); |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::setContentsOpaque(bool opaque) |
| { |
| LOG("(%x) setContentsOpaque (%d)", this, opaque); |
| GraphicsLayer::setContentsOpaque(opaque); |
| m_haveContents = true; |
| m_contentLayer->setHaveContents(true); |
| m_contentLayer->setDrawsContent(true); |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::setOpacity(float opacity) |
| { |
| LOG("(%x) setOpacity: %.2f", this, opacity); |
| float clampedOpacity = max(0.0f, min(opacity, 1.0f)); |
| |
| if (clampedOpacity == m_opacity) |
| return; |
| |
| MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this, |
| opacity, clampedOpacity, m_opacity); |
| GraphicsLayer::setOpacity(clampedOpacity); |
| m_contentLayer->setOpacity(clampedOpacity); |
| askForSync(); |
| } |
| |
| bool GraphicsLayerAndroid::repaintAll() |
| { |
| LOG("(%x) repaintAll", this); |
| bool ret = false; |
| for (unsigned int i = 0; i < m_children.size(); i++) { |
| GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]); |
| if (layer && layer->repaintAll()) |
| ret = true; |
| } |
| int nbRects = m_invalidatedRects.size(); |
| |
| for (int i = 0; !gPaused && i < nbRects; i++) { |
| FloatRect rect = m_invalidatedRects[i]; |
| if (repaint(rect)) |
| ret = true; |
| } |
| if (!gPaused) { |
| m_needsRepaint = false; |
| m_invalidatedRects.clear(); |
| } |
| return ret; |
| } |
| |
| void GraphicsLayerAndroid::setNeedsDisplay() |
| { |
| LOG("(%x) setNeedsDisplay()", this); |
| FloatRect rect(0, 0, m_size.width(), m_size.height()); |
| setNeedsDisplayInRect(rect); |
| } |
| |
| void GraphicsLayerAndroid::setFrame(Frame* f) |
| { |
| m_frame = f; |
| } |
| |
| void GraphicsLayerAndroid::sendImmediateRepaint() |
| { |
| LOG("(%x) sendImmediateRepaint()", this); |
| GraphicsLayerAndroid* rootGraphicsLayer = this; |
| |
| while (rootGraphicsLayer->parent()) |
| rootGraphicsLayer = static_cast<GraphicsLayerAndroid*>(rootGraphicsLayer->parent()); |
| |
| if (rootGraphicsLayer->m_frame |
| && rootGraphicsLayer->m_frame->view()) { |
| LayerAndroid* copyLayer = new LayerAndroid(m_contentLayer.get()); |
| TLOG("(%x) sendImmediateRepaint, copy the layer, (%.2f,%.2f => %.2f,%.2f)", |
| this, m_contentLayer->size().width(), m_contentLayer->size().height(), |
| copyLayer->size().width(), copyLayer->size().height()); |
| PlatformBridge::setRootLayer(m_frame->view(), (int)copyLayer); |
| PlatformBridge::immediateRepaint(m_frame->view()); |
| } |
| } |
| |
| bool GraphicsLayerAndroid::repaint(const FloatRect& rect) |
| { |
| LOG("(%x) repaint(%.2f,%.2f,%.2f,%.2f), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ", |
| this, rect.x(), rect.y(), rect.width(), rect.height(), |
| gPaused, m_needsRepaint, m_haveContents); |
| |
| m_contentLayer->setDrawsContent(true); |
| |
| if (!gPaused && m_haveContents && m_needsRepaint) { |
| SkAutoPictureRecord arp(m_contentLayer->recordContext(), m_size.width(), m_size.height()); |
| SkCanvas* recordingCanvas = arp.getRecordingCanvas(); |
| |
| if (!recordingCanvas) |
| return false; |
| |
| if ((rect.width() > 0.5) && (rect.height() > 0.5)) { |
| IntRect r((int)rect.x(), (int)rect.y(), |
| (int)rect.width(), (int)rect.height()); |
| |
| PlatformGraphicsContext pgc(recordingCanvas, 0); |
| GraphicsContext gc(&pgc); |
| |
| // with SkPicture, we request the entire layer's content. |
| r.setX(0); |
| r.setY(0); |
| r.setWidth(m_contentLayer->size().width()); |
| r.setHeight(m_contentLayer->size().height()); |
| paintGraphicsLayerContents(gc, r); |
| |
| TLOG("(%x) repaint(%.2f,%.2f,%.2f,%.2f) on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!", |
| this, rect.x(), rect.y(), rect.width(), |
| rect.height(), m_size.width(), m_size.height(), |
| m_contentLayer->position().x(), |
| m_contentLayer->position().y(), |
| m_contentLayer->size().width(), |
| m_contentLayer->size().height()); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect) |
| { |
| for (unsigned int i = 0; i < m_children.size(); i++) { |
| GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]); |
| if (layer) { |
| FloatRect childrenRect(m_position.x() + m_translateX + rect.x(), |
| m_position.y() + m_translateY + rect.y(), |
| rect.width(), rect.height()); |
| layer->setNeedsDisplayInRect(childrenRect); |
| } |
| } |
| if (!m_haveImage && !drawsContent()) { |
| LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...", |
| this, rect.x(), rect.y(), rect.width(), rect.height()); |
| return; |
| } |
| |
| const size_t maxDirtyRects = 8; |
| for (size_t i = 0; i < m_invalidatedRects.size(); ++i) { |
| if (m_invalidatedRects[i].contains(rect)) |
| return; |
| } |
| |
| #ifdef LAYER_DEBUG |
| LOG("(%x) setNeedsDisplayInRect(%d) - (%.2f, %.2f, %.2f, %.2f)", this, |
| m_needsRepaint, rect.x(), rect.y(), rect.width(), rect.height()); |
| #endif |
| |
| if (m_invalidatedRects.size() < maxDirtyRects) |
| m_invalidatedRects.append(rect); |
| else |
| m_invalidatedRects[0].unite(rect); |
| |
| m_needsRepaint = true; |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::pauseDisplay(bool state) |
| { |
| gPaused = state; |
| if (gPaused) |
| gPausedDelay = WTF::currentTime() + 1; |
| } |
| |
| bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList, |
| const IntSize& boxSize, |
| const Animation* anim, |
| const String& keyframesName, |
| double beginTime) |
| { |
| if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) |
| return false; |
| |
| bool createdAnimations = false; |
| if (valueList.property() == AnimatedPropertyWebkitTransform) { |
| createdAnimations = createTransformAnimationsFromKeyframes(valueList, |
| anim, |
| keyframesName, |
| beginTime, |
| boxSize); |
| } else { |
| createdAnimations = createAnimationFromKeyframes(valueList, |
| anim, |
| keyframesName, |
| beginTime); |
| } |
| askForSync(); |
| return createdAnimations; |
| } |
| |
| bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList, |
| const Animation* animation, const String& keyframesName, double beginTime) |
| { |
| bool isKeyframe = valueList.size() > 2; |
| TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)", |
| isKeyframe, keyframesName.latin1().data(), beginTime); |
| // TODO: handles keyframe animations correctly |
| |
| switch (valueList.property()) { |
| case AnimatedPropertyInvalid: break; |
| case AnimatedPropertyWebkitTransform: break; |
| case AnimatedPropertyBackgroundColor: break; |
| case AnimatedPropertyOpacity: { |
| MLOG("ANIMATEDPROPERTYOPACITY"); |
| const FloatAnimationValue* startVal = |
| static_cast<const FloatAnimationValue*>(valueList.at(0)); |
| const FloatAnimationValue* endVal = |
| static_cast<const FloatAnimationValue*>(valueList.at(1)); |
| RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(startVal->value(), |
| endVal->value(), |
| animation, |
| beginTime); |
| if (keyframesName.isEmpty()) |
| anim->setName(propertyIdToString(valueList.property())); |
| else |
| anim->setName(keyframesName); |
| |
| m_contentLayer->addAnimation(anim.release()); |
| needsNotifyClient(); |
| return true; |
| } break; |
| } |
| return false; |
| } |
| |
| void GraphicsLayerAndroid::needsNotifyClient() |
| { |
| m_needsNotifyClient = true; |
| askForSync(); |
| } |
| |
| bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, |
| const Animation* animation, |
| const String& keyframesName, |
| double beginTime, |
| const IntSize& boxSize) |
| { |
| ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); |
| TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)", |
| keyframesName.latin1().data(), beginTime); |
| |
| TransformOperationList functionList; |
| bool listsMatch, hasBigRotation; |
| fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation); |
| |
| // 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; |
| size_t numAnimations = isMatrixAnimation ? 1 : functionList.size(); |
| bool isKeyframe = valueList.size() > 2; |
| |
| float fromTranslateX = 0; |
| float fromTranslateY = 0; |
| float fromTranslateZ = 0; |
| float toTranslateX = 0; |
| float toTranslateY = 0; |
| float toTranslateZ = 0; |
| float fromAngle = 0; |
| float toAngle = 0; |
| float fromScaleX = 1; |
| float fromScaleY = 1; |
| float fromScaleZ = 1; |
| float toScaleX = 1; |
| float toScaleY = 1; |
| float toScaleZ = 1; |
| |
| bool doTranslation = false; |
| bool doRotation = false; |
| bool doScaling = false; |
| |
| TLOG("(%x) animateTransform, valueList(%d) functionList(%d) duration(%.2f)", this, |
| valueList.size(), functionList.size(), animation->duration()); |
| |
| // FIXME: add support for the translate 3d operations (when |
| // we'll have an OpenGL backend) |
| |
| for (unsigned int i = 0; i < valueList.size(); i++) { |
| const TransformOperations* operation = ((TransformAnimationValue*)valueList.at(i))->value(); |
| Vector<RefPtr<TransformOperation> > ops = operation->operations(); |
| TLOG("(%x) animateTransform, dealing with the %d operation, with %d ops", this, i, ops.size()); |
| for (unsigned int j = 0; j < ops.size(); j++) { |
| TransformOperation* op = ops[j].get(); |
| TLOG("(%x) animateTransform, dealing with the %d:%d operation, current op: %d (translate is %d, rotate %d, scale %d)", |
| this, i, j, op->getOperationType(), TransformOperation::TRANSLATE, TransformOperation::ROTATE, TransformOperation::SCALE); |
| if ((op->getOperationType() == TransformOperation::TRANSLATE) || |
| (op->getOperationType() == TransformOperation::TRANSLATE_3D)) { |
| TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op; |
| IntSize bounds(m_size.width(), m_size.height()); |
| float x = translateOperation->x(bounds); |
| float y = translateOperation->y(bounds); |
| float z = translateOperation->z(bounds); |
| if (!i) { |
| fromTranslateX = x; |
| fromTranslateY = y; |
| fromTranslateZ = z; |
| } else { |
| toTranslateX = x; |
| toTranslateY = y; |
| toTranslateZ = z; |
| } |
| TLOG("(%x) animateTransform, the %d operation is a translation(%.2f,%.2f,%.2f)", |
| this, j, x, y, z); |
| doTranslation = true; |
| } else if (op->getOperationType() == TransformOperation::TRANSLATE_X) { |
| TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op; |
| IntSize bounds(m_size.width(), m_size.height()); |
| float x = translateOperation->x(bounds); |
| if (!i) |
| fromTranslateX = x; |
| else |
| toTranslateX = x; |
| TLOG("(%x) animateTransform, the %d operation is a translation_x(%.2f)", |
| this, j, x); |
| doTranslation = true; |
| } else if (op->getOperationType() == TransformOperation::TRANSLATE_Y) { |
| TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op; |
| IntSize bounds(m_size.width(), m_size.height()); |
| float y = translateOperation->y(bounds); |
| if (!i) |
| fromTranslateY = y; |
| else |
| toTranslateY = y; |
| TLOG("(%x) animateTransform, the %d operation is a translation_y(%.2f)", |
| this, j, y); |
| doTranslation = true; |
| } else if (op->getOperationType() == TransformOperation::TRANSLATE_Z) { |
| TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op; |
| IntSize bounds(m_size.width(), m_size.height()); |
| float z = translateOperation->z(bounds); |
| if (!i) |
| fromTranslateZ = z; |
| else |
| toTranslateZ = z; |
| TLOG("(%x) animateTransform, the %d operation is a translation_z(%.2f)", |
| this, j, z); |
| doTranslation = true; |
| } else if ((op->getOperationType() == TransformOperation::ROTATE) |
| || (op->getOperationType() == TransformOperation::ROTATE_X) |
| || (op->getOperationType() == TransformOperation::ROTATE_Y)) { |
| LOG("(%x) animateTransform, the %d operation is a rotation", this, j); |
| RotateTransformOperation* rotateOperation = (RotateTransformOperation*) op; |
| float angle = rotateOperation->angle(); |
| TLOG("(%x) animateTransform, the %d operation is a rotation (%d), of angle %.2f", |
| this, j, op->getOperationType(), angle); |
| |
| if (!i) |
| fromAngle = angle; |
| else |
| toAngle = angle; |
| doRotation = true; |
| } else if (op->getOperationType() == TransformOperation::SCALE_X) { |
| ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op; |
| if (!i) |
| fromScaleX = scaleOperation->x(); |
| else |
| toScaleX = scaleOperation->x(); |
| doScaling = true; |
| } else if (op->getOperationType() == TransformOperation::SCALE_Y) { |
| ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op; |
| if (!i) |
| fromScaleY = scaleOperation->y(); |
| else |
| toScaleY = scaleOperation->y(); |
| doScaling = true; |
| } else if (op->getOperationType() == TransformOperation::SCALE_Z) { |
| ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op; |
| if (!i) |
| fromScaleZ = scaleOperation->z(); |
| else |
| toScaleZ = scaleOperation->z(); |
| doScaling = true; |
| } else if (op->getOperationType() == TransformOperation::SCALE) { |
| ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op; |
| if (!i) { |
| fromScaleX = scaleOperation->x(); |
| fromScaleY = scaleOperation->y(); |
| fromScaleZ = scaleOperation->z(); |
| } else { |
| toScaleX = scaleOperation->x(); |
| toScaleY = scaleOperation->y(); |
| toScaleZ = scaleOperation->z(); |
| } |
| doScaling = true; |
| } else { |
| TLOG("(%x) animateTransform, the %d operation is not a rotation (%d)", |
| this, j, op->getOperationType()); |
| } |
| } |
| } |
| |
| RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation, beginTime); |
| |
| if (keyframesName.isEmpty()) |
| anim->setName(propertyIdToString(valueList.property())); |
| else |
| anim->setName(keyframesName); |
| |
| anim->setOriginalPosition(m_position); |
| |
| if (doTranslation) |
| anim->setTranslation(fromTranslateX, fromTranslateY, fromTranslateZ, |
| toTranslateX, toTranslateY, toTranslateZ); |
| if (doRotation) |
| anim->setRotation(fromAngle, toAngle); |
| if (doScaling) |
| anim->setScale(fromScaleX, fromScaleY, fromScaleZ, |
| toScaleX, toScaleY, toScaleZ); |
| m_contentLayer->addAnimation(anim.release()); |
| |
| needsNotifyClient(); |
| return true; |
| } |
| |
| void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID) |
| { |
| TLOG("NRO removeAnimationsForProperty(%d)", anID); |
| m_contentLayer->removeAnimation(propertyIdToString(anID)); |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName) |
| { |
| TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data()); |
| m_contentLayer->removeAnimation(keyframesName); |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName) |
| { |
| TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data()); |
| } |
| |
| void GraphicsLayerAndroid::suspendAnimations(double time) |
| { |
| TLOG("NRO suspendAnimations(%.2f)", time); |
| } |
| |
| void GraphicsLayerAndroid::resumeAnimations() |
| { |
| TLOG("NRO resumeAnimations()"); |
| } |
| |
| void GraphicsLayerAndroid::setContentsToImage(Image* image) |
| { |
| TLOG("(%x) setContentsToImage", this, image); |
| if (image) { |
| m_haveContents = true; |
| m_contentLayer->setHaveContents(true); |
| m_contentLayer->setDrawsContent(true); |
| m_contentLayer->setHaveImage(true); |
| if (!m_haveImage) { |
| m_haveImage = true; |
| setNeedsDisplay(); |
| askForSync(); |
| } |
| } else |
| m_contentLayer->setHaveImage(false); |
| } |
| |
| PlatformLayer* GraphicsLayerAndroid::platformLayer() const |
| { |
| LOG("platformLayer"); |
| return (PlatformLayer*) m_contentLayer.get(); |
| } |
| |
| #ifndef NDEBUG |
| void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color) |
| { |
| } |
| |
| void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth) |
| { |
| } |
| #endif |
| |
| void GraphicsLayerAndroid::setZPosition(float position) |
| { |
| LOG("(%x) setZPosition: %.2f", this, position); |
| GraphicsLayer::setZPosition(position); |
| askForSync(); |
| } |
| |
| void GraphicsLayerAndroid::askForSync() |
| { |
| if (m_client) |
| m_client->notifySyncRequired(this); |
| } |
| |
| void GraphicsLayerAndroid::syncChildren() |
| { |
| if (m_needsSyncChildren) { |
| m_contentLayer->removeAllChildren(); |
| for (unsigned int i = 0; i < m_children.size(); i++) { |
| m_contentLayer->addChildren( |
| (static_cast<GraphicsLayerAndroid*>(m_children[i]))->contentLayer()); |
| } |
| m_needsSyncChildren = false; |
| } |
| } |
| |
| void GraphicsLayerAndroid::syncMask() |
| { |
| if (m_needsSyncMask) { |
| if (m_maskLayer) { |
| GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_maskLayer); |
| LayerAndroid* mask = reinterpret_cast<LayerAndroid*>(layer->platformLayer()); |
| m_contentLayer->setMaskLayer(mask); |
| } else |
| m_contentLayer->setMaskLayer(0); |
| |
| m_contentLayer->setMasksToBounds(m_masksToBounds); |
| m_needsSyncMask = false; |
| } |
| } |
| |
| void GraphicsLayerAndroid::syncPositionState() |
| { |
| if (m_needsDisplay) { |
| m_translateX = m_currentTranslateX; |
| m_translateY = m_currentTranslateY; |
| m_position = m_currentPosition; |
| m_contentLayer->setTranslation(m_currentTranslateX, m_currentTranslateY); |
| m_contentLayer->setPosition(m_currentPosition.x(), m_currentPosition.y()); |
| m_needsDisplay = false; |
| } |
| } |
| |
| void GraphicsLayerAndroid::syncCompositingState() |
| { |
| for (unsigned int i = 0; i < m_children.size(); i++) { |
| GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]); |
| layer->syncCompositingState(); |
| } |
| |
| syncChildren(); |
| syncMask(); |
| syncPositionState(); |
| |
| if (!gPaused || WTF::currentTime() >= gPausedDelay) |
| repaintAll(); |
| } |
| |
| void GraphicsLayerAndroid::notifyClientAnimationStarted() |
| { |
| for (unsigned int i = 0; i < m_children.size(); i++) { |
| GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]); |
| layer->notifyClientAnimationStarted(); |
| } |
| |
| if (m_needsNotifyClient) { |
| if (client()) |
| client()->notifyAnimationStarted(this, WTF::currentTime()); |
| m_needsNotifyClient = false; |
| } |
| } |
| |
| } // namespace WebCore |
| |
| #endif // USE(ACCELERATED_COMPOSITING) |