2 * Copyright (C) 2009 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "GraphicsLayerAndroid.h"
20 #if USE(ACCELERATED_COMPOSITING)
22 #include "AndroidAnimation.h"
23 #include "Animation.h"
24 #include "FloatRect.h"
25 #include "GraphicsContext.h"
28 #include "MediaLayer.h"
29 #include "PlatformBridge.h"
30 #include "PlatformGraphicsContext.h"
31 #include "RenderLayerBacking.h"
32 #include "RenderView.h"
33 #include "RotateTransformOperation.h"
34 #include "ScaleTransformOperation.h"
35 #include "ScrollableLayerAndroid.h"
38 #include "TransformationMatrix.h"
39 #include "TranslateTransformOperation.h"
41 #include <cutils/log.h>
42 #include <wtf/CurrentTime.h>
43 #include <wtf/text/CString.h>
46 #define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
47 #define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
48 #define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
61 static double gPausedDelay;
65 static int gDebugGraphicsLayerAndroidInstances = 0;
66 inline int GraphicsLayerAndroid::instancesCount()
68 return gDebugGraphicsLayerAndroidInstances;
71 static String propertyIdToString(AnimatedPropertyID property)
74 case AnimatedPropertyWebkitTransform:
76 case AnimatedPropertyOpacity:
78 case AnimatedPropertyBackgroundColor:
79 return "backgroundColor";
80 case AnimatedPropertyInvalid:
87 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
89 return new GraphicsLayerAndroid(client);
92 SkLength convertLength(Length len)
95 length.type = SkLength::Undefined;
97 if (len.type() == WebCore::Percent) {
98 length.type = SkLength::Percent;
99 length.value = len.percent();
101 if (len.type() == WebCore::Fixed) {
102 length.type = SkLength::Fixed;
103 length.value = len.value();
108 static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client)
111 return static_cast<RenderLayerBacking*>(client)->owningLayer();
115 GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
116 GraphicsLayer(client),
117 m_needsSyncChildren(false),
118 m_needsSyncMask(false),
119 m_needsRepaint(false),
120 m_needsNotifyClient(false),
121 m_haveContents(false),
125 m_foregroundLayer(0),
126 m_foregroundClipLayer(0)
128 RenderLayer* renderLayer = renderLayerFromClient(m_client);
129 m_contentLayer = new LayerAndroid(renderLayer);
130 gDebugGraphicsLayerAndroidInstances++;
133 GraphicsLayerAndroid::~GraphicsLayerAndroid()
135 m_contentLayer->unref();
136 SkSafeUnref(m_foregroundLayer);
137 SkSafeUnref(m_foregroundClipLayer);
138 gDebugGraphicsLayerAndroidInstances--;
141 void GraphicsLayerAndroid::setName(const String& name)
143 GraphicsLayer::setName(name);
146 NativeLayer GraphicsLayerAndroid::nativeLayer() const
148 LOG("(%x) nativeLayer", this);
152 bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children)
154 bool childrenChanged = GraphicsLayer::setChildren(children);
155 if (childrenChanged) {
156 m_needsSyncChildren = true;
160 return childrenChanged;
163 void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer)
166 const String& name = childLayer->name();
167 LOG("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data());
169 GraphicsLayer::addChild(childLayer);
170 m_needsSyncChildren = true;
174 void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index)
176 LOG("(%x) addChild %x AtIndex %d", this, childLayer, index);
177 GraphicsLayer::addChildAtIndex(childLayer, index);
178 m_needsSyncChildren = true;
182 void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
184 LOG("(%x) addChild %x Below %x", this, childLayer, sibling);
185 GraphicsLayer::addChildBelow(childLayer, sibling);
186 m_needsSyncChildren = true;
190 void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
192 LOG("(%x) addChild %x Above %x", this, childLayer, sibling);
193 GraphicsLayer::addChildAbove(childLayer, sibling);
194 m_needsSyncChildren = true;
198 bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
200 LOG("(%x) replaceChild %x by %x", this, oldChild, newChild);
201 bool ret = GraphicsLayer::replaceChild(oldChild, newChild);
203 m_needsSyncChildren = true;
209 void GraphicsLayerAndroid::removeFromParent()
211 LOG("(%x) removeFromParent()", this);
212 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
213 GraphicsLayer::removeFromParent();
214 // Update the parent's children.
216 parent->m_needsSyncChildren = true;
221 void GraphicsLayerAndroid::updateFixedPosition()
226 RenderLayer* renderLayer = renderLayerFromClient(m_client);
227 RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
229 // We will need the Iframe flag in the LayerAndroid tree for fixed position
230 if (view && view->isRenderIFrame())
231 m_contentLayer->setIsIframe(true);
232 // If we are a fixed position layer, just set it
233 if (view->isPositioned() && view->style()->position() == FixedPosition) {
234 // We need to get the passed CSS properties for the element
235 SkLength left, top, right, bottom;
236 left = convertLength(view->style()->left());
237 top = convertLength(view->style()->top());
238 right = convertLength(view->style()->right());
239 bottom = convertLength(view->style()->bottom());
241 // We also need to get the margin...
242 SkLength marginLeft, marginTop, marginRight, marginBottom;
243 marginLeft = convertLength(view->style()->marginLeft());
244 marginTop = convertLength(view->style()->marginTop());
245 marginRight = convertLength(view->style()->marginRight());
246 marginBottom = convertLength(view->style()->marginBottom());
248 // The layer can be bigger than the element we want to draw;
249 // not only that, the layout rect of the element might also be
250 // different from the visible rect of that element (i.e. the element
251 // has a CSS shadow property -- the shadow is "outside" the element).
253 // 1/ get the size of the element (w,h), using the layoutOverflow rect
254 // 2/ pass the current offset of the painting relative to the layer
255 int w = view->rightLayoutOverflow() - view->leftLayoutOverflow();
256 int h = view->bottomLayoutOverflow() - view->topLayoutOverflow();
257 int paintingOffsetX = - offsetFromRenderer().width();
258 int paintingOffsetY = - offsetFromRenderer().height();
261 viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h);
262 IntPoint renderLayerPos(renderLayer->x(), renderLayer->y());
263 m_contentLayer->setFixedPosition(left, top, right, bottom,
264 marginLeft, marginTop,
265 marginRight, marginBottom,
271 void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
273 if (point == m_position)
276 GraphicsLayer::setPosition(point);
279 LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
280 this, point.x(), point.y(), m_position.x(), m_position.y(),
281 m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height());
283 m_contentLayer->setPosition(point.x(), point.y());
287 void GraphicsLayerAndroid::setPreserves3D(bool preserves3D)
289 if (preserves3D == m_preserves3D)
292 GraphicsLayer::setPreserves3D(preserves3D);
293 m_contentLayer->setPreserves3D(preserves3D);
297 void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point)
299 if (point == m_anchorPoint)
301 GraphicsLayer::setAnchorPoint(point);
302 m_contentLayer->setAnchorPoint(point.x(), point.y());
303 m_contentLayer->setAnchorPointZ(point.z());
307 void GraphicsLayerAndroid::setSize(const FloatSize& size)
311 MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height());
312 GraphicsLayer::setSize(size);
314 // If it is a media layer the size may have changed as a result of the media
315 // element (e.g. plugin) gaining focus. Therefore, we must sync the size of
316 // the focus' outline so that our UI thread can draw accordingly.
317 if (m_contentLayer->isMedia() && m_client) {
318 RenderLayer* layer = renderLayerFromClient(m_client);
319 RenderBox* box = layer->renderBox();
320 int outline = box->view()->maximalOutlineSize();
321 static_cast<MediaLayer*>(m_contentLayer)->setOutlineSize(outline);
322 LOG("Media Outline: %d %p %p %p", outline, m_client, layer, box);
323 LOG("Media Size: %g,%g", size.width(), size.height());
326 m_contentLayer->setSize(size.width(), size.height());
330 void GraphicsLayerAndroid::setBackfaceVisibility(bool b)
332 GraphicsLayer::setBackfaceVisibility(b);
333 m_contentLayer->setBackfaceVisibility(b);
337 void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t)
339 if (t == m_transform)
342 GraphicsLayer::setTransform(t);
343 m_contentLayer->setTransform(t);
347 void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t)
349 if (t == m_childrenTransform)
351 LOG("(%x) setChildrenTransform", this);
353 GraphicsLayer::setChildrenTransform(t);
354 m_contentLayer->setChildrenTransform(t);
355 for (unsigned int i = 0; i < m_children.size(); i++) {
356 GraphicsLayer* layer = m_children[i];
357 layer->setTransform(t);
358 if (layer->children().size())
359 layer->setChildrenTransform(t);
364 void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer)
366 if (layer == m_maskLayer)
369 GraphicsLayer::setMaskLayer(layer);
370 m_needsSyncMask = true;
374 void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds)
376 if (masksToBounds == m_masksToBounds)
378 GraphicsLayer::setMasksToBounds(masksToBounds);
379 m_needsSyncMask = true;
383 void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
385 if (drawsContent == m_drawsContent)
387 GraphicsLayer::setDrawsContent(drawsContent);
388 if (m_drawsContent) {
389 m_haveContents = true;
395 void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
397 if (color == m_backgroundColor)
399 LOG("(%x) setBackgroundColor", this);
400 GraphicsLayer::setBackgroundColor(color);
401 SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue());
402 m_contentLayer->setBackgroundColor(c);
403 m_haveContents = true;
407 void GraphicsLayerAndroid::clearBackgroundColor()
409 LOG("(%x) clearBackgroundColor", this);
410 GraphicsLayer::clearBackgroundColor();
414 void GraphicsLayerAndroid::setContentsOpaque(bool opaque)
416 if (opaque == m_contentsOpaque)
418 LOG("(%x) setContentsOpaque (%d)", this, opaque);
419 GraphicsLayer::setContentsOpaque(opaque);
420 m_haveContents = true;
424 void GraphicsLayerAndroid::setOpacity(float opacity)
426 LOG("(%x) setOpacity: %.2f", this, opacity);
427 float clampedOpacity = max(0.0f, min(opacity, 1.0f));
429 if (clampedOpacity == m_opacity)
432 MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
433 opacity, clampedOpacity, m_opacity);
434 GraphicsLayer::setOpacity(clampedOpacity);
435 m_contentLayer->setOpacity(clampedOpacity);
439 void GraphicsLayerAndroid::setNeedsDisplay()
441 LOG("(%x) setNeedsDisplay()", this);
442 FloatRect rect(0, 0, m_size.width(), m_size.height());
443 setNeedsDisplayInRect(rect);
446 // Helper to set and clear the painting phase as well as auto restore the
448 class PaintingPhase {
450 PaintingPhase(GraphicsLayer* layer)
452 , m_originalPhase(layer->paintingPhase()) {}
456 m_layer->setPaintingPhase(m_originalPhase);
459 void set(GraphicsLayerPaintingPhase phase)
461 m_layer->setPaintingPhase(phase);
464 void clear(GraphicsLayerPaintingPhase phase)
466 m_layer->setPaintingPhase(
467 (GraphicsLayerPaintingPhase) (m_originalPhase & ~phase));
470 GraphicsLayer* m_layer;
471 GraphicsLayerPaintingPhase m_originalPhase;
474 void GraphicsLayerAndroid::updateScrollingLayers()
476 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
477 RenderLayer* layer = renderLayerFromClient(m_client);
478 if (!layer || !m_haveContents)
480 bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable();
481 bool layerNeedsOverflow = layer->hasOverflowScroll();
482 bool iframeNeedsOverflow = layer->isRootLayer() &&
483 layer->renderer()->frame()->ownerRenderer() &&
484 layer->renderer()->frame()->view()->hasOverflowScroll();
486 if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) {
487 // Already has overflow layers.
490 if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) {
491 // Does not need overflow layers.
494 if (layerNeedsOverflow || iframeNeedsOverflow) {
495 ASSERT(!hasOverflowScroll);
496 if (layerNeedsOverflow) {
497 ASSERT(!m_foregroundLayer && !m_foregroundClipLayer);
498 m_foregroundLayer = new ScrollableLayerAndroid(layer);
499 m_foregroundClipLayer = new LayerAndroid(layer);
500 m_foregroundClipLayer->setMasksToBounds(true);
501 m_foregroundClipLayer->addChild(m_foregroundLayer);
502 m_contentLayer->addChild(m_foregroundClipLayer);
504 ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable());
505 // No need to copy the children as they will be removed and synced.
506 m_contentLayer->removeChildren();
507 // Replace the content layer with a scrollable layer.
508 LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer);
509 m_contentLayer->unref();
510 m_contentLayer = layer;
512 // The content layer has changed so the parent needs to sync
514 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
517 // Need to rebuild our children based on the new structure.
518 m_needsSyncChildren = true;
520 ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow);
521 ASSERT(m_contentLayer);
522 // Remove the foreground layers.
523 if (m_foregroundLayer) {
524 m_foregroundLayer->unref();
525 m_foregroundLayer = 0;
526 m_foregroundClipLayer->unref();
527 m_foregroundClipLayer = 0;
529 // No need to copy over children.
530 m_contentLayer->removeChildren();
531 LayerAndroid* layer = new LayerAndroid(*m_contentLayer);
532 m_contentLayer->unref();
533 m_contentLayer = layer;
535 // The content layer has changed so the parent needs to sync
537 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
539 // Children are all re-parented.
540 m_needsSyncChildren = true;
545 bool GraphicsLayerAndroid::repaint()
547 LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
548 this, gPaused, m_needsRepaint, m_haveContents);
550 if (!gPaused && m_haveContents && m_needsRepaint && !m_haveImage) {
551 // with SkPicture, we request the entire layer's content.
552 IntRect layerBounds(0, 0, m_size.width(), m_size.height());
554 RenderLayer* layer = renderLayerFromClient(m_client);
555 if (m_foregroundLayer) {
556 PaintingPhase phase(this);
557 // Paint the background into a separate context.
558 phase.set(GraphicsLayerPaintBackground);
559 if (!paintContext(m_contentLayer->recordContext(), layerBounds))
562 // Construct the foreground layer and draw.
563 RenderBox* box = layer->renderBox();
564 int outline = box->view()->maximalOutlineSize();
565 IntRect contentsRect(0, 0,
566 box->borderLeft() + box->borderRight() + layer->scrollWidth(),
567 box->borderTop() + box->borderBottom() + layer->scrollHeight());
568 contentsRect.inflate(outline);
569 // Update the foreground layer size.
570 m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height());
571 // Paint everything else into the main recording canvas.
572 phase.clear(GraphicsLayerPaintBackground);
575 IntSize scroll = layer->scrolledContentOffset();
576 layer->scrollToOffset(0, 0, true, false);
577 // At this point, it doesn't matter if painting failed.
578 (void) paintContext(m_foregroundLayer->recordContext(), contentsRect);
579 layer->scrollToOffset(scroll.width(), scroll.height(), true, false);
581 // Construct the clip layer for masking the contents.
582 IntRect clip = layer->renderer()->absoluteBoundingBoxRect();
583 // absoluteBoundingBoxRect does not include the outline so we need
584 // to offset the position.
585 int x = box->borderLeft() + outline;
586 int y = box->borderTop() + outline;
587 int width = clip.width() - box->borderLeft() - box->borderRight();
588 int height = clip.height() - box->borderTop() - box->borderBottom();
589 m_foregroundClipLayer->setPosition(x, y);
590 m_foregroundClipLayer->setSize(width, height);
592 // Need to offset the foreground layer by the clip layer in order
593 // for the contents to be in the correct position.
594 m_foregroundLayer->setPosition(-x, -y);
595 // Set the scrollable bounds of the layer.
596 m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height());
597 m_foregroundLayer->needsRepaint();
599 // If there is no contents clip, we can draw everything into one
601 if (!paintContext(m_contentLayer->recordContext(), layerBounds))
603 // Check for a scrollable iframe and report the scrolling
604 // limits based on the view size.
605 if (m_contentLayer->contentIsScrollable()) {
606 FrameView* view = layer->renderer()->frame()->view();
607 static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits(
608 m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight());
612 LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
613 this, m_size.width(), m_size.height(),
614 m_contentLayer->getPosition().fX,
615 m_contentLayer->getPosition().fY,
616 m_contentLayer->getSize().width(),
617 m_contentLayer->getSize().height());
619 m_contentLayer->needsRepaint();
620 m_needsRepaint = false;
621 m_invalidatedRects.clear();
625 if (m_needsRepaint && m_haveImage && m_newImage) {
626 // We need to tell the GL thread that we will need to repaint the
627 // texture. Only do so if we effectively have a new image!
628 m_contentLayer->needsRepaint();
630 m_needsRepaint = false;
636 bool GraphicsLayerAndroid::paintContext(SkPicture* context,
639 SkAutoPictureRecord arp(context, rect.width(), rect.height());
640 SkCanvas* canvas = arp.getRecordingCanvas();
645 PlatformGraphicsContext platformContext(canvas, 0);
646 GraphicsContext graphicsContext(&platformContext);
648 paintGraphicsLayerContents(graphicsContext, rect);
652 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
654 for (unsigned int i = 0; i < m_children.size(); i++) {
655 GraphicsLayer* layer = m_children[i];
657 FloatRect childrenRect = m_transform.mapRect(rect);
658 layer->setNeedsDisplayInRect(childrenRect);
662 if (!m_haveImage && !drawsContent()) {
663 LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
664 this, rect.x(), rect.y(), rect.width(), rect.height());
668 bool addInval = true;
669 const size_t maxDirtyRects = 8;
670 for (size_t i = 0; i < m_invalidatedRects.size(); ++i) {
671 if (m_invalidatedRects[i].contains(rect)) {
678 LOG("(%x) layer %d setNeedsDisplayInRect(%d) - (%.2f, %.2f, %.2f, %.2f)", this,
679 m_contentLayer->uniqueId(), m_needsRepaint, rect.x(), rect.y(), rect.width(), rect.height());
683 if (m_invalidatedRects.size() < maxDirtyRects)
684 m_invalidatedRects.append(rect);
686 m_invalidatedRects[0].unite(rect);
689 m_needsRepaint = true;
693 void GraphicsLayerAndroid::pauseDisplay(bool state)
697 gPausedDelay = WTF::currentTime() + 1;
700 bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
701 const IntSize& boxSize,
702 const Animation* anim,
703 const String& keyframesName,
706 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
709 bool createdAnimations = false;
710 if (valueList.property() == AnimatedPropertyWebkitTransform) {
711 createdAnimations = createTransformAnimationsFromKeyframes(valueList,
717 createdAnimations = createAnimationFromKeyframes(valueList,
722 if (createdAnimations)
724 return createdAnimations;
727 bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList,
728 const Animation* animation, const String& keyframesName, double beginTime)
730 bool isKeyframe = valueList.size() > 2;
731 TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
732 isKeyframe, keyframesName.latin1().data(), beginTime);
734 switch (valueList.property()) {
735 case AnimatedPropertyInvalid: break;
736 case AnimatedPropertyWebkitTransform: break;
737 case AnimatedPropertyBackgroundColor: break;
738 case AnimatedPropertyOpacity: {
739 MLOG("ANIMATEDPROPERTYOPACITY");
741 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity);
742 for (unsigned int i = 0; i < valueList.size(); i++) {
743 FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i);
744 PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
745 FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(),
746 originalValue->value(),
748 operationsList->insert(value);
751 RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation,
754 if (keyframesName.isEmpty())
755 anim->setName(propertyIdToString(valueList.property()));
757 anim->setName(keyframesName);
759 m_contentLayer->addAnimation(anim.release());
767 void GraphicsLayerAndroid::needsNotifyClient()
769 m_needsNotifyClient = true;
773 bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList,
774 const Animation* animation,
775 const String& keyframesName,
777 const IntSize& boxSize)
779 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
780 TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
781 keyframesName.latin1().data(), beginTime);
783 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform);
784 for (unsigned int i = 0; i < valueList.size(); i++) {
785 TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i);
786 PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
787 TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(),
788 originalValue->value(),
790 operationsList->insert(value);
793 RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation,
797 if (keyframesName.isEmpty())
798 anim->setName(propertyIdToString(valueList.property()));
800 anim->setName(keyframesName);
803 m_contentLayer->addAnimation(anim.release());
809 void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
811 TLOG("NRO removeAnimationsForProperty(%d)", anID);
812 m_contentLayer->removeAnimationsForProperty(anID);
816 void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
818 TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data());
819 m_contentLayer->removeAnimationsForKeyframes(keyframesName);
823 void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
825 TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data());
828 void GraphicsLayerAndroid::suspendAnimations(double time)
830 TLOG("NRO suspendAnimations(%.2f)", time);
833 void GraphicsLayerAndroid::resumeAnimations()
835 TLOG("NRO resumeAnimations()");
838 void GraphicsLayerAndroid::setContentsToImage(Image* image)
840 TLOG("(%x) setContentsToImage", this, image);
842 m_haveContents = true;
844 // Only pass the new image if it's a different one
845 if (image->nativeImageForCurrentFrame() != m_imageRef) {
847 m_contentLayer->setContentsImage(image->nativeImageForCurrentFrame());
848 // remember the passed image.
849 m_imageRef = image->nativeImageForCurrentFrame();
856 void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer)
858 // Only fullscreen video on Android, so media doesn't get it's own layer.
859 // We might still have other layers though.
860 if (m_contentLayer != mediaLayer && mediaLayer) {
862 // TODO add a copy method to LayerAndroid to sync everything
863 // copy data from the original content layer to the new one
864 mediaLayer->setPosition(m_contentLayer->getPosition().fX,
865 m_contentLayer->getPosition().fY);
866 mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight());
867 mediaLayer->setDrawTransform(m_contentLayer->drawTransform());
870 m_contentLayer->unref();
871 m_contentLayer = mediaLayer;
873 // If the parent exists then notify it to re-sync it's children
875 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
876 parent->m_needsSyncChildren = true;
878 m_needsSyncChildren = true;
885 PlatformLayer* GraphicsLayerAndroid::platformLayer() const
887 LOG("platformLayer");
888 return m_contentLayer;
892 void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color)
896 void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth)
901 void GraphicsLayerAndroid::setZPosition(float position)
903 if (position == m_zPosition)
905 LOG("(%x) setZPosition: %.2f", this, position);
906 GraphicsLayer::setZPosition(position);
910 void GraphicsLayerAndroid::askForSync()
916 m_client->notifySyncRequired(this);
919 void GraphicsLayerAndroid::syncChildren()
921 if (m_needsSyncChildren) {
922 m_contentLayer->removeChildren();
923 LayerAndroid* layer = m_contentLayer;
924 if (m_foregroundClipLayer) {
925 m_contentLayer->addChild(m_foregroundClipLayer);
926 // Use the scrollable content layer as the parent of the children so
927 // that they move with the content.
928 layer = m_foregroundLayer;
929 layer->removeChildren();
931 for (unsigned int i = 0; i < m_children.size(); i++)
932 layer->addChild(m_children[i]->platformLayer());
933 m_needsSyncChildren = false;
937 void GraphicsLayerAndroid::syncMask()
939 if (m_needsSyncMask) {
941 LayerAndroid* mask = m_maskLayer->platformLayer();
942 m_contentLayer->setMaskLayer(mask);
944 m_contentLayer->setMaskLayer(0);
946 m_contentLayer->setMasksToBounds(m_masksToBounds);
947 m_needsSyncMask = false;
951 void GraphicsLayerAndroid::syncCompositingState()
953 for (unsigned int i = 0; i < m_children.size(); i++)
954 m_children[i]->syncCompositingState();
956 updateScrollingLayers();
957 updateFixedPosition();
961 if (!gPaused || WTF::currentTime() >= gPausedDelay)
965 void GraphicsLayerAndroid::notifyClientAnimationStarted()
967 for (unsigned int i = 0; i < m_children.size(); i++)
968 static_cast<GraphicsLayerAndroid*>(m_children[i])->notifyClientAnimationStarted();
970 if (m_needsNotifyClient) {
972 client()->notifyAnimationStarted(this, WTF::currentTime());
973 m_needsNotifyClient = false;
977 } // namespace WebCore
979 #endif // USE(ACCELERATED_COMPOSITING)