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"
29 #include "MediaLayer.h"
30 #include "PlatformBridge.h"
31 #include "PlatformGraphicsContext.h"
32 #include "RenderLayerBacking.h"
33 #include "RenderView.h"
34 #include "RotateTransformOperation.h"
35 #include "ScaleTransformOperation.h"
36 #include "ScrollableLayerAndroid.h"
39 #include "TransformationMatrix.h"
40 #include "TranslateTransformOperation.h"
42 #include <cutils/log.h>
43 #include <wtf/CurrentTime.h>
44 #include <wtf/text/CString.h>
47 #define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
48 #define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
49 #define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
62 static double gPausedDelay;
66 static int gDebugGraphicsLayerAndroidInstances = 0;
67 inline int GraphicsLayerAndroid::instancesCount()
69 return gDebugGraphicsLayerAndroidInstances;
72 static String propertyIdToString(AnimatedPropertyID property)
75 case AnimatedPropertyWebkitTransform:
77 case AnimatedPropertyOpacity:
79 case AnimatedPropertyBackgroundColor:
80 return "backgroundColor";
81 case AnimatedPropertyInvalid:
88 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
90 return new GraphicsLayerAndroid(client);
93 SkLength convertLength(Length len)
96 length.type = SkLength::Undefined;
98 if (len.type() == WebCore::Percent) {
99 length.type = SkLength::Percent;
100 length.value = len.percent();
102 if (len.type() == WebCore::Fixed) {
103 length.type = SkLength::Fixed;
104 length.value = len.value();
109 static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client)
111 return client ? client->owningLayer() : 0;
114 GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
115 GraphicsLayer(client),
116 m_needsSyncChildren(false),
117 m_needsSyncMask(false),
118 m_needsRepaint(false),
119 m_needsNotifyClient(false),
120 m_haveContents(false),
123 m_foregroundLayer(0),
124 m_foregroundClipLayer(0)
126 RenderLayer* renderLayer = renderLayerFromClient(m_client);
127 m_contentLayer = new LayerAndroid(renderLayer);
128 m_dirtyRegion.setEmpty();
129 gDebugGraphicsLayerAndroidInstances++;
132 GraphicsLayerAndroid::~GraphicsLayerAndroid()
134 m_contentLayer->unref();
135 SkSafeUnref(m_foregroundLayer);
136 SkSafeUnref(m_foregroundClipLayer);
137 gDebugGraphicsLayerAndroidInstances--;
140 void GraphicsLayerAndroid::setName(const String& name)
142 GraphicsLayer::setName(name);
145 NativeLayer GraphicsLayerAndroid::nativeLayer() const
147 LOG("(%x) nativeLayer", this);
151 bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children)
153 bool childrenChanged = GraphicsLayer::setChildren(children);
154 if (childrenChanged) {
155 m_needsSyncChildren = true;
159 return childrenChanged;
162 void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer)
165 const String& name = childLayer->name();
166 LOG("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data());
168 GraphicsLayer::addChild(childLayer);
169 m_needsSyncChildren = true;
173 void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index)
175 LOG("(%x) addChild %x AtIndex %d", this, childLayer, index);
176 GraphicsLayer::addChildAtIndex(childLayer, index);
177 m_needsSyncChildren = true;
181 void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
183 LOG("(%x) addChild %x Below %x", this, childLayer, sibling);
184 GraphicsLayer::addChildBelow(childLayer, sibling);
185 m_needsSyncChildren = true;
189 void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
191 LOG("(%x) addChild %x Above %x", this, childLayer, sibling);
192 GraphicsLayer::addChildAbove(childLayer, sibling);
193 m_needsSyncChildren = true;
197 bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
199 LOG("(%x) replaceChild %x by %x", this, oldChild, newChild);
200 bool ret = GraphicsLayer::replaceChild(oldChild, newChild);
202 m_needsSyncChildren = true;
208 void GraphicsLayerAndroid::removeFromParent()
210 LOG("(%x) removeFromParent()", this);
211 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
212 GraphicsLayer::removeFromParent();
213 // Update the parent's children.
215 parent->m_needsSyncChildren = true;
220 void GraphicsLayerAndroid::updateFixedPosition()
222 RenderLayer* renderLayer = renderLayerFromClient(m_client);
225 RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
230 // We will need the Iframe flag in the LayerAndroid tree for fixed position
231 if (view->isRenderIFrame())
232 m_contentLayer->setIsIframe(true);
233 // If we are a fixed position layer, just set it
234 if (view->isPositioned() && view->style()->position() == FixedPosition) {
235 // We need to get the passed CSS properties for the element
236 SkLength left, top, right, bottom;
237 left = convertLength(view->style()->left());
238 top = convertLength(view->style()->top());
239 right = convertLength(view->style()->right());
240 bottom = convertLength(view->style()->bottom());
242 // We also need to get the margin...
243 SkLength marginLeft, marginTop, marginRight, marginBottom;
244 marginLeft = convertLength(view->style()->marginLeft());
245 marginTop = convertLength(view->style()->marginTop());
246 marginRight = convertLength(view->style()->marginRight());
247 marginBottom = convertLength(view->style()->marginBottom());
249 // In order to compute the fixed element's position, we need the width
250 // and height of the element when bottom or right is defined.
251 // And here we should use the non-overflowed value, that means, the
252 // overflowed content (e.g. outset shadow) will not be counted into the
254 int w = view->width();
255 int h = view->height();
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 RenderLayer* layer = renderLayerFromClient(m_client);
318 if (layer && m_contentLayer->isMedia()) {
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());
331 void GraphicsLayerAndroid::setBackfaceVisibility(bool b)
333 GraphicsLayer::setBackfaceVisibility(b);
334 m_contentLayer->setBackfaceVisibility(b);
338 void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t)
340 if (t == m_transform)
343 GraphicsLayer::setTransform(t);
344 m_contentLayer->setTransform(t);
348 void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t)
350 if (t == m_childrenTransform)
352 LOG("(%x) setChildrenTransform", this);
354 GraphicsLayer::setChildrenTransform(t);
355 m_contentLayer->setChildrenTransform(t);
356 for (unsigned int i = 0; i < m_children.size(); i++) {
357 GraphicsLayer* layer = m_children[i];
358 layer->setTransform(t);
359 if (layer->children().size())
360 layer->setChildrenTransform(t);
365 void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer)
367 if (layer == m_maskLayer)
370 GraphicsLayer::setMaskLayer(layer);
371 m_needsSyncMask = true;
375 void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds)
377 if (masksToBounds == m_masksToBounds)
379 GraphicsLayer::setMasksToBounds(masksToBounds);
380 m_needsSyncMask = true;
384 void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
386 if (drawsContent == m_drawsContent)
388 GraphicsLayer::setDrawsContent(drawsContent);
389 m_contentLayer->setVisible(drawsContent);
390 if (m_drawsContent) {
391 m_haveContents = true;
397 void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
399 if (color == m_backgroundColor)
401 LOG("(%x) setBackgroundColor", this);
402 GraphicsLayer::setBackgroundColor(color);
403 SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue());
404 m_contentLayer->setBackgroundColor(c);
405 m_haveContents = true;
409 void GraphicsLayerAndroid::clearBackgroundColor()
411 LOG("(%x) clearBackgroundColor", this);
412 GraphicsLayer::clearBackgroundColor();
416 void GraphicsLayerAndroid::setContentsOpaque(bool opaque)
418 if (opaque == m_contentsOpaque)
420 LOG("(%x) setContentsOpaque (%d)", this, opaque);
421 GraphicsLayer::setContentsOpaque(opaque);
422 m_haveContents = true;
426 void GraphicsLayerAndroid::setOpacity(float opacity)
428 LOG("(%x) setOpacity: %.2f", this, opacity);
429 float clampedOpacity = max(0.0f, min(opacity, 1.0f));
431 if (clampedOpacity == m_opacity)
434 MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
435 opacity, clampedOpacity, m_opacity);
436 GraphicsLayer::setOpacity(clampedOpacity);
437 m_contentLayer->setOpacity(clampedOpacity);
441 void GraphicsLayerAndroid::setNeedsDisplay()
443 LOG("(%x) setNeedsDisplay()", this);
444 FloatRect rect(0, 0, m_size.width(), m_size.height());
445 setNeedsDisplayInRect(rect);
448 // Helper to set and clear the painting phase as well as auto restore the
450 class PaintingPhase {
452 PaintingPhase(GraphicsLayer* layer)
454 , m_originalPhase(layer->paintingPhase()) {}
458 m_layer->setPaintingPhase(m_originalPhase);
461 void set(GraphicsLayerPaintingPhase phase)
463 m_layer->setPaintingPhase(phase);
466 void clear(GraphicsLayerPaintingPhase phase)
468 m_layer->setPaintingPhase(
469 (GraphicsLayerPaintingPhase) (m_originalPhase & ~phase));
472 GraphicsLayer* m_layer;
473 GraphicsLayerPaintingPhase m_originalPhase;
476 void GraphicsLayerAndroid::updateScrollingLayers()
478 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
479 RenderLayer* layer = renderLayerFromClient(m_client);
480 if (!layer || !m_haveContents)
482 bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable();
483 bool layerNeedsOverflow = layer->hasOverflowScroll();
484 bool iframeNeedsOverflow = layer->isRootLayer() &&
485 layer->renderer()->frame()->ownerRenderer() &&
486 layer->renderer()->frame()->view()->hasOverflowScroll();
488 if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) {
489 // Already has overflow layers.
492 if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) {
493 // Does not need overflow layers.
496 if (layerNeedsOverflow || iframeNeedsOverflow) {
497 ASSERT(!hasOverflowScroll);
498 if (layerNeedsOverflow) {
499 ASSERT(!m_foregroundLayer && !m_foregroundClipLayer);
500 m_foregroundLayer = new ScrollableLayerAndroid(layer);
501 m_foregroundClipLayer = new LayerAndroid(layer);
502 m_foregroundClipLayer->setMasksToBounds(true);
503 m_foregroundClipLayer->addChild(m_foregroundLayer);
504 m_contentLayer->addChild(m_foregroundClipLayer);
505 m_contentLayer->setHasOverflowChildren(true);
507 ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable());
508 // No need to copy the children as they will be removed and synced.
509 m_contentLayer->removeChildren();
510 // Replace the content layer with a scrollable layer.
511 LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer);
512 m_contentLayer->unref();
513 m_contentLayer = layer;
515 // The content layer has changed so the parent needs to sync
517 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
520 // Need to rebuild our children based on the new structure.
521 m_needsSyncChildren = true;
523 ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow);
524 ASSERT(m_contentLayer);
525 // Remove the foreground layers.
526 if (m_foregroundLayer) {
527 m_foregroundLayer->unref();
528 m_foregroundLayer = 0;
529 m_foregroundClipLayer->unref();
530 m_foregroundClipLayer = 0;
532 // No need to copy over children.
533 m_contentLayer->removeChildren();
534 LayerAndroid* layer = new LayerAndroid(*m_contentLayer);
535 m_contentLayer->unref();
536 m_contentLayer = layer;
538 // The content layer has changed so the parent needs to sync
540 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
542 // Children are all re-parented.
543 m_needsSyncChildren = true;
548 bool GraphicsLayerAndroid::repaint()
550 LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
551 this, gPaused, m_needsRepaint, m_haveContents);
553 if (!gPaused && m_haveContents && m_needsRepaint && !m_haveImage) {
554 // with SkPicture, we request the entire layer's content.
555 IntRect layerBounds(0, 0, m_size.width(), m_size.height());
557 RenderLayer* layer = renderLayerFromClient(m_client);
560 if (m_foregroundLayer) {
561 PaintingPhase phase(this);
562 // Paint the background into a separate context.
563 phase.set(GraphicsLayerPaintBackground);
564 if (!paintContext(m_contentLayer->recordContext(), layerBounds))
567 // Construct the foreground layer and draw.
568 RenderBox* box = layer->renderBox();
569 int outline = box->view()->maximalOutlineSize();
570 IntRect contentsRect(0, 0,
571 box->borderLeft() + box->borderRight() + layer->scrollWidth(),
572 box->borderTop() + box->borderBottom() + layer->scrollHeight());
573 contentsRect.inflate(outline);
574 // Update the foreground layer size.
575 m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height());
576 // Paint everything else into the main recording canvas.
577 phase.clear(GraphicsLayerPaintBackground);
580 IntSize scroll = layer->scrolledContentOffset();
581 layer->scrollToOffset(0, 0);
582 // At this point, it doesn't matter if painting failed.
583 (void) paintContext(m_foregroundLayer->recordContext(), contentsRect);
584 layer->scrollToOffset(scroll.width(), scroll.height());
586 // Construct the clip layer for masking the contents.
587 IntRect clip = layer->renderer()->absoluteBoundingBoxRect();
588 // absoluteBoundingBoxRect does not include the outline so we need
589 // to offset the position.
590 int x = box->borderLeft() + outline;
591 int y = box->borderTop() + outline;
592 int width = clip.width() - box->borderLeft() - box->borderRight();
593 int height = clip.height() - box->borderTop() - box->borderBottom();
594 m_foregroundClipLayer->setPosition(x, y);
595 m_foregroundClipLayer->setSize(width, height);
597 // Need to offset the foreground layer by the clip layer in order
598 // for the contents to be in the correct position.
599 m_foregroundLayer->setPosition(-x, -y);
600 // Set the scrollable bounds of the layer.
601 m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height());
602 m_foregroundLayer->markAsDirty(m_dirtyRegion);
603 m_foregroundLayer->needsRepaint();
605 // If there is no contents clip, we can draw everything into one
607 if (!paintContext(m_contentLayer->recordContext(), layerBounds))
609 // Check for a scrollable iframe and report the scrolling
610 // limits based on the view size.
611 if (m_contentLayer->contentIsScrollable()) {
612 FrameView* view = layer->renderer()->frame()->view();
613 static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits(
614 m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight());
618 LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
619 this, m_size.width(), m_size.height(),
620 m_contentLayer->getPosition().fX,
621 m_contentLayer->getPosition().fY,
622 m_contentLayer->getSize().width(),
623 m_contentLayer->getSize().height());
625 m_contentLayer->markAsDirty(m_dirtyRegion);
626 m_dirtyRegion.setEmpty();
627 m_contentLayer->needsRepaint();
628 m_needsRepaint = false;
632 if (m_needsRepaint && m_haveImage && m_newImage) {
633 // We need to tell the GL thread that we will need to repaint the
634 // texture. Only do so if we effectively have a new image!
635 m_contentLayer->markAsDirty(m_dirtyRegion);
636 m_dirtyRegion.setEmpty();
637 m_contentLayer->needsRepaint();
639 m_needsRepaint = false;
645 bool GraphicsLayerAndroid::paintContext(SkPicture* context,
648 SkAutoPictureRecord arp(context, rect.width(), rect.height());
649 SkCanvas* canvas = arp.getRecordingCanvas();
654 PlatformGraphicsContext platformContext(canvas, 0);
655 GraphicsContext graphicsContext(&platformContext);
657 paintGraphicsLayerContents(graphicsContext, rect);
661 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
663 // rect is in the render object coordinates
665 if (!m_haveImage && !drawsContent()) {
666 LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
667 this, rect.x(), rect.y(), rect.width(), rect.height());
672 region.setRect(rect.x(), rect.y(),
673 rect.x() + rect.width(),
674 rect.y() + rect.height());
675 m_dirtyRegion.op(region, SkRegion::kUnion_Op);
677 m_needsRepaint = true;
681 void GraphicsLayerAndroid::pauseDisplay(bool state)
685 gPausedDelay = WTF::currentTime() + 1;
688 bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
689 const IntSize& boxSize,
690 const Animation* anim,
691 const String& keyframesName,
694 // For now, let webkit deals with the animations -- the current UI-side
695 // animation code has some annoying bugs, and we improved communication
696 // between webkit and UI enough that performance-wise it's not so much
697 // a problem to let webkit do everything.
698 // TODO: re-enable UI-side animations
701 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
704 bool createdAnimations = false;
705 if (valueList.property() == AnimatedPropertyWebkitTransform) {
706 createdAnimations = createTransformAnimationsFromKeyframes(valueList,
712 createdAnimations = createAnimationFromKeyframes(valueList,
717 if (createdAnimations)
719 return createdAnimations;
722 bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList,
723 const Animation* animation, const String& keyframesName, double beginTime)
725 bool isKeyframe = valueList.size() > 2;
726 TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
727 isKeyframe, keyframesName.latin1().data(), beginTime);
729 switch (valueList.property()) {
730 case AnimatedPropertyInvalid: break;
731 case AnimatedPropertyWebkitTransform: break;
732 case AnimatedPropertyBackgroundColor: break;
733 case AnimatedPropertyOpacity: {
734 MLOG("ANIMATEDPROPERTYOPACITY");
736 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity);
737 for (unsigned int i = 0; i < valueList.size(); i++) {
738 FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i);
739 PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
740 FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(),
741 originalValue->value(),
743 operationsList->insert(value);
746 RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation,
749 if (keyframesName.isEmpty())
750 anim->setName(propertyIdToString(valueList.property()));
752 anim->setName(keyframesName);
754 m_contentLayer->addAnimation(anim.release());
762 void GraphicsLayerAndroid::needsNotifyClient()
764 m_needsNotifyClient = true;
768 bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList,
769 const Animation* animation,
770 const String& keyframesName,
772 const IntSize& boxSize)
774 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
775 TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
776 keyframesName.latin1().data(), beginTime);
778 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform);
779 for (unsigned int i = 0; i < valueList.size(); i++) {
780 TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i);
781 PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
782 TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(),
783 originalValue->value(),
785 operationsList->insert(value);
788 RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation,
792 if (keyframesName.isEmpty())
793 anim->setName(propertyIdToString(valueList.property()));
795 anim->setName(keyframesName);
798 m_contentLayer->addAnimation(anim.release());
804 void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
806 TLOG("NRO removeAnimationsForProperty(%d)", anID);
807 m_contentLayer->removeAnimationsForProperty(anID);
811 void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
813 TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data());
814 m_contentLayer->removeAnimationsForKeyframes(keyframesName);
818 void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
820 TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data());
823 void GraphicsLayerAndroid::suspendAnimations(double time)
825 TLOG("NRO suspendAnimations(%.2f)", time);
828 void GraphicsLayerAndroid::resumeAnimations()
830 TLOG("NRO resumeAnimations()");
833 void GraphicsLayerAndroid::setContentsToImage(Image* image)
835 TLOG("(%x) setContentsToImage", this, image);
837 m_haveContents = true;
840 m_contentLayer->setContentsImage(image->nativeImageForCurrentFrame());
842 if (m_haveImage && !image)
843 m_contentLayer->setContentsImage(0);
849 void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer)
851 // Only fullscreen video on Android, so media doesn't get it's own layer.
852 // We might still have other layers though.
853 if (m_contentLayer != mediaLayer && mediaLayer) {
855 // TODO add a copy method to LayerAndroid to sync everything
856 // copy data from the original content layer to the new one
857 mediaLayer->setPosition(m_contentLayer->getPosition().fX,
858 m_contentLayer->getPosition().fY);
859 mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight());
860 mediaLayer->setDrawTransform(*m_contentLayer->drawTransform());
863 m_contentLayer->unref();
864 m_contentLayer = mediaLayer;
866 // If the parent exists then notify it to re-sync it's children
868 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
869 parent->m_needsSyncChildren = true;
871 m_needsSyncChildren = true;
878 PlatformLayer* GraphicsLayerAndroid::platformLayer() const
880 LOG("platformLayer");
881 return m_contentLayer;
885 void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color)
889 void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth)
894 void GraphicsLayerAndroid::setZPosition(float position)
896 if (position == m_zPosition)
898 LOG("(%x) setZPosition: %.2f", this, position);
899 GraphicsLayer::setZPosition(position);
903 void GraphicsLayerAndroid::askForSync()
909 m_client->notifySyncRequired(this);
912 void GraphicsLayerAndroid::syncChildren()
914 if (m_needsSyncChildren) {
915 m_contentLayer->removeChildren();
916 LayerAndroid* layer = m_contentLayer;
917 if (m_foregroundClipLayer) {
918 m_contentLayer->addChild(m_foregroundClipLayer);
919 // Use the scrollable content layer as the parent of the children so
920 // that they move with the content.
921 layer = m_foregroundLayer;
922 layer->removeChildren();
924 for (unsigned int i = 0; i < m_children.size(); i++)
925 layer->addChild(m_children[i]->platformLayer());
926 m_needsSyncChildren = false;
930 void GraphicsLayerAndroid::syncMask()
932 if (m_needsSyncMask) {
934 LayerAndroid* mask = m_maskLayer->platformLayer();
935 m_contentLayer->setMaskLayer(mask);
937 m_contentLayer->setMaskLayer(0);
939 m_contentLayer->setMasksToBounds(m_masksToBounds);
940 m_needsSyncMask = false;
944 void GraphicsLayerAndroid::syncCompositingState()
946 for (unsigned int i = 0; i < m_children.size(); i++)
947 m_children[i]->syncCompositingState();
949 updateScrollingLayers();
950 updateFixedPosition();
954 if (!gPaused || WTF::currentTime() >= gPausedDelay)
958 void GraphicsLayerAndroid::notifyClientAnimationStarted()
960 for (unsigned int i = 0; i < m_children.size(); i++)
961 static_cast<GraphicsLayerAndroid*>(m_children[i])->notifyClientAnimationStarted();
963 if (m_needsNotifyClient) {
965 client()->notifyAnimationStarted(this, WTF::currentTime());
966 m_needsNotifyClient = false;
970 } // namespace WebCore
972 #endif // USE(ACCELERATED_COMPOSITING)