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"
27 #include "ImagesManager.h"
30 #include "MediaLayer.h"
31 #include "PlatformBridge.h"
32 #include "PlatformGraphicsContext.h"
33 #include "RenderLayerBacking.h"
34 #include "RenderView.h"
35 #include "RotateTransformOperation.h"
36 #include "ScaleTransformOperation.h"
37 #include "ScrollableLayerAndroid.h"
40 #include "TransformationMatrix.h"
41 #include "TranslateTransformOperation.h"
43 #include <cutils/log.h>
44 #include <wtf/CurrentTime.h>
45 #include <wtf/text/CString.h>
48 #define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
49 #define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
50 #define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
63 static double gPausedDelay;
67 static int gDebugGraphicsLayerAndroidInstances = 0;
68 inline int GraphicsLayerAndroid::instancesCount()
70 return gDebugGraphicsLayerAndroidInstances;
73 static String propertyIdToString(AnimatedPropertyID property)
76 case AnimatedPropertyWebkitTransform:
78 case AnimatedPropertyOpacity:
80 case AnimatedPropertyBackgroundColor:
81 return "backgroundColor";
82 case AnimatedPropertyInvalid:
89 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
91 return new GraphicsLayerAndroid(client);
94 SkLength convertLength(Length len)
97 length.type = SkLength::Undefined;
99 if (len.type() == WebCore::Percent) {
100 length.type = SkLength::Percent;
101 length.value = len.percent();
103 if (len.type() == WebCore::Fixed) {
104 length.type = SkLength::Fixed;
105 length.value = len.value();
110 static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client)
112 return client ? client->owningLayer() : 0;
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),
124 m_foregroundLayer(0),
125 m_foregroundClipLayer(0)
127 RenderLayer* renderLayer = renderLayerFromClient(m_client);
128 m_contentLayer = new LayerAndroid(renderLayer);
129 m_dirtyRegion.setEmpty();
130 gDebugGraphicsLayerAndroidInstances++;
133 GraphicsLayerAndroid::~GraphicsLayerAndroid()
138 m_contentLayer->unref();
139 SkSafeUnref(m_foregroundLayer);
140 SkSafeUnref(m_foregroundClipLayer);
141 gDebugGraphicsLayerAndroidInstances--;
144 void GraphicsLayerAndroid::setName(const String& name)
146 GraphicsLayer::setName(name);
149 NativeLayer GraphicsLayerAndroid::nativeLayer() const
151 LOG("(%x) nativeLayer", this);
155 bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children)
157 bool childrenChanged = GraphicsLayer::setChildren(children);
158 if (childrenChanged) {
159 m_needsSyncChildren = true;
163 return childrenChanged;
166 void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer)
169 const String& name = childLayer->name();
170 LOG("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data());
172 GraphicsLayer::addChild(childLayer);
173 m_needsSyncChildren = true;
177 void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index)
179 LOG("(%x) addChild %x AtIndex %d", this, childLayer, index);
180 GraphicsLayer::addChildAtIndex(childLayer, index);
181 m_needsSyncChildren = true;
185 void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
187 LOG("(%x) addChild %x Below %x", this, childLayer, sibling);
188 GraphicsLayer::addChildBelow(childLayer, sibling);
189 m_needsSyncChildren = true;
193 void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
195 LOG("(%x) addChild %x Above %x", this, childLayer, sibling);
196 GraphicsLayer::addChildAbove(childLayer, sibling);
197 m_needsSyncChildren = true;
201 bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
203 LOG("(%x) replaceChild %x by %x", this, oldChild, newChild);
204 bool ret = GraphicsLayer::replaceChild(oldChild, newChild);
206 m_needsSyncChildren = true;
212 void GraphicsLayerAndroid::removeFromParent()
214 LOG("(%x) removeFromParent()", this);
215 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
216 GraphicsLayer::removeFromParent();
217 // Update the parent's children.
219 parent->m_needsSyncChildren = true;
224 void GraphicsLayerAndroid::updateFixedPosition()
226 RenderLayer* renderLayer = renderLayerFromClient(m_client);
229 RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
234 // We will need the Iframe flag in the LayerAndroid tree for fixed position
235 if (view->isRenderIFrame())
236 m_contentLayer->setIsIframe(true);
237 // If we are a fixed position layer, just set it
238 if (view->isPositioned() && view->style()->position() == FixedPosition) {
239 // We need to get the passed CSS properties for the element
240 SkLength left, top, right, bottom;
241 left = convertLength(view->style()->left());
242 top = convertLength(view->style()->top());
243 right = convertLength(view->style()->right());
244 bottom = convertLength(view->style()->bottom());
246 // We also need to get the margin...
247 SkLength marginLeft, marginTop, marginRight, marginBottom;
248 marginLeft = convertLength(view->style()->marginLeft());
249 marginTop = convertLength(view->style()->marginTop());
250 marginRight = convertLength(view->style()->marginRight());
251 marginBottom = convertLength(view->style()->marginBottom());
253 // In order to compute the fixed element's position, we need the width
254 // and height of the element when bottom or right is defined.
255 // And here we should use the non-overflowed value, that means, the
256 // overflowed content (e.g. outset shadow) will not be counted into the
258 int w = view->width();
259 int h = view->height();
261 int paintingOffsetX = - offsetFromRenderer().width();
262 int paintingOffsetY = - offsetFromRenderer().height();
265 viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h);
266 IntPoint renderLayerPos(renderLayer->x(), renderLayer->y());
267 m_contentLayer->setFixedPosition(left, top, right, bottom,
268 marginLeft, marginTop,
269 marginRight, marginBottom,
275 void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
277 if (point == m_position)
280 GraphicsLayer::setPosition(point);
283 LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
284 this, point.x(), point.y(), m_position.x(), m_position.y(),
285 m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height());
287 m_contentLayer->setPosition(point.x(), point.y());
291 void GraphicsLayerAndroid::setPreserves3D(bool preserves3D)
293 if (preserves3D == m_preserves3D)
296 GraphicsLayer::setPreserves3D(preserves3D);
297 m_contentLayer->setPreserves3D(preserves3D);
301 void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point)
303 if (point == m_anchorPoint)
305 GraphicsLayer::setAnchorPoint(point);
306 m_contentLayer->setAnchorPoint(point.x(), point.y());
307 m_contentLayer->setAnchorPointZ(point.z());
311 void GraphicsLayerAndroid::setSize(const FloatSize& size)
315 MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height());
316 GraphicsLayer::setSize(size);
318 // If it is a media layer the size may have changed as a result of the media
319 // element (e.g. plugin) gaining focus. Therefore, we must sync the size of
320 // the focus' outline so that our UI thread can draw accordingly.
321 RenderLayer* layer = renderLayerFromClient(m_client);
322 if (layer && m_contentLayer->isMedia()) {
323 RenderBox* box = layer->renderBox();
324 int outline = box->view()->maximalOutlineSize();
325 static_cast<MediaLayer*>(m_contentLayer)->setOutlineSize(outline);
326 LOG("Media Outline: %d %p %p %p", outline, m_client, layer, box);
327 LOG("Media Size: %g,%g", size.width(), size.height());
330 m_contentLayer->setSize(size.width(), size.height());
335 void GraphicsLayerAndroid::setBackfaceVisibility(bool b)
337 if (b == m_backfaceVisibility)
340 GraphicsLayer::setBackfaceVisibility(b);
341 m_contentLayer->setBackfaceVisibility(b);
345 void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t)
347 if (t == m_transform)
350 GraphicsLayer::setTransform(t);
351 m_contentLayer->setTransform(t);
355 void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t)
357 if (t == m_childrenTransform)
359 LOG("(%x) setChildrenTransform", this);
361 GraphicsLayer::setChildrenTransform(t);
362 m_contentLayer->setChildrenTransform(t);
363 for (unsigned int i = 0; i < m_children.size(); i++) {
364 GraphicsLayer* layer = m_children[i];
365 layer->setTransform(t);
366 if (layer->children().size())
367 layer->setChildrenTransform(t);
372 void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer)
374 if (layer == m_maskLayer)
377 GraphicsLayer::setMaskLayer(layer);
378 m_needsSyncMask = true;
382 void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds)
384 if (masksToBounds == m_masksToBounds)
386 GraphicsLayer::setMasksToBounds(masksToBounds);
387 m_needsSyncMask = true;
391 void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
393 if (drawsContent == m_drawsContent)
395 GraphicsLayer::setDrawsContent(drawsContent);
396 m_contentLayer->setVisible(drawsContent);
397 if (m_drawsContent) {
398 m_haveContents = true;
404 void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
406 if (color == m_backgroundColor && m_backgroundColorSet)
408 LOG("(%x) setBackgroundColor", this);
409 GraphicsLayer::setBackgroundColor(color);
410 SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue());
411 m_contentLayer->setBackgroundColor(c);
412 m_haveContents = true;
416 void GraphicsLayerAndroid::clearBackgroundColor()
418 if (!m_backgroundColorSet)
421 LOG("(%x) clearBackgroundColor", this);
422 GraphicsLayer::clearBackgroundColor();
426 void GraphicsLayerAndroid::setContentsOpaque(bool opaque)
428 if (opaque == m_contentsOpaque)
430 LOG("(%x) setContentsOpaque (%d)", this, opaque);
431 GraphicsLayer::setContentsOpaque(opaque);
432 m_haveContents = true;
436 void GraphicsLayerAndroid::setOpacity(float opacity)
438 LOG("(%x) setOpacity: %.2f", this, opacity);
439 float clampedOpacity = max(0.0f, min(opacity, 1.0f));
441 if (clampedOpacity == m_opacity)
444 MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
445 opacity, clampedOpacity, m_opacity);
446 GraphicsLayer::setOpacity(clampedOpacity);
447 m_contentLayer->setOpacity(clampedOpacity);
451 void GraphicsLayerAndroid::setNeedsDisplay()
453 LOG("(%x) setNeedsDisplay()", this);
454 FloatRect rect(0, 0, m_size.width(), m_size.height());
455 setNeedsDisplayInRect(rect);
458 // Helper to set and clear the painting phase as well as auto restore the
460 class PaintingPhase {
462 PaintingPhase(GraphicsLayer* layer)
464 , m_originalPhase(layer->paintingPhase()) {}
468 m_layer->setPaintingPhase(m_originalPhase);
471 void set(GraphicsLayerPaintingPhase phase)
473 m_layer->setPaintingPhase(phase);
476 void clear(GraphicsLayerPaintingPhase phase)
478 m_layer->setPaintingPhase(
479 (GraphicsLayerPaintingPhase) (m_originalPhase & ~phase));
482 GraphicsLayer* m_layer;
483 GraphicsLayerPaintingPhase m_originalPhase;
486 void GraphicsLayerAndroid::updateScrollingLayers()
488 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
489 RenderLayer* layer = renderLayerFromClient(m_client);
490 if (!layer || !m_haveContents)
492 bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable();
493 bool layerNeedsOverflow = layer->hasOverflowScroll();
494 bool iframeNeedsOverflow = layer->isRootLayer() &&
495 layer->renderer()->frame()->ownerRenderer() &&
496 layer->renderer()->frame()->view()->hasOverflowScroll();
498 if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) {
499 // Already has overflow layers.
502 if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) {
503 // Does not need overflow layers.
506 if (layerNeedsOverflow || iframeNeedsOverflow) {
507 ASSERT(!hasOverflowScroll);
508 if (layerNeedsOverflow) {
509 ASSERT(!m_foregroundLayer && !m_foregroundClipLayer);
510 m_foregroundLayer = new ScrollableLayerAndroid(layer);
511 m_foregroundClipLayer = new LayerAndroid(layer);
512 m_foregroundClipLayer->setMasksToBounds(true);
513 m_foregroundClipLayer->addChild(m_foregroundLayer);
514 m_contentLayer->addChild(m_foregroundClipLayer);
515 m_contentLayer->setHasOverflowChildren(true);
517 ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable());
518 // No need to copy the children as they will be removed and synced.
519 m_contentLayer->removeChildren();
520 // Replace the content layer with a scrollable layer.
521 LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer);
522 m_contentLayer->unref();
523 m_contentLayer = layer;
525 // The content layer has changed so the parent needs to sync
527 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
530 // Need to rebuild our children based on the new structure.
531 m_needsSyncChildren = true;
533 ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow);
534 ASSERT(m_contentLayer);
535 // Remove the foreground layers.
536 if (m_foregroundLayer) {
537 m_foregroundLayer->unref();
538 m_foregroundLayer = 0;
539 m_foregroundClipLayer->unref();
540 m_foregroundClipLayer = 0;
542 // No need to copy over children.
543 m_contentLayer->removeChildren();
544 LayerAndroid* layer = new LayerAndroid(*m_contentLayer);
545 m_contentLayer->unref();
546 m_contentLayer = layer;
548 // The content layer has changed so the parent needs to sync
550 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
552 // Children are all re-parented.
553 m_needsSyncChildren = true;
558 bool GraphicsLayerAndroid::repaint()
560 LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
561 this, gPaused, m_needsRepaint, m_haveContents);
563 if (!gPaused && m_haveContents && m_needsRepaint && !m_image) {
564 // with SkPicture, we request the entire layer's content.
565 IntRect layerBounds(0, 0, m_size.width(), m_size.height());
567 RenderLayer* layer = renderLayerFromClient(m_client);
570 if (m_foregroundLayer) {
571 PaintingPhase phase(this);
572 // Paint the background into a separate context.
573 phase.set(GraphicsLayerPaintBackground);
574 if (!paintContext(m_contentLayer->recordContext(), layerBounds))
576 m_contentLayer->checkTextPresence();
578 // Construct the foreground layer and draw.
579 RenderBox* box = layer->renderBox();
580 int outline = box->view()->maximalOutlineSize();
581 IntRect contentsRect(0, 0,
582 box->borderLeft() + box->borderRight() + layer->scrollWidth(),
583 box->borderTop() + box->borderBottom() + layer->scrollHeight());
584 contentsRect.inflate(outline);
585 // Update the foreground layer size.
586 m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height());
587 // Paint everything else into the main recording canvas.
588 phase.clear(GraphicsLayerPaintBackground);
591 IntSize scroll = layer->scrolledContentOffset();
592 layer->scrollToOffset(0, 0);
593 // At this point, it doesn't matter if painting failed.
594 (void) paintContext(m_foregroundLayer->recordContext(), contentsRect);
595 m_foregroundLayer->checkTextPresence();
596 layer->scrollToOffset(scroll.width(), scroll.height());
598 // Construct the clip layer for masking the contents.
599 IntRect clip = layer->renderer()->absoluteBoundingBoxRect();
600 // absoluteBoundingBoxRect does not include the outline so we need
601 // to offset the position.
602 int x = box->borderLeft() + outline;
603 int y = box->borderTop() + outline;
604 int width = clip.width() - box->borderLeft() - box->borderRight();
605 int height = clip.height() - box->borderTop() - box->borderBottom();
606 m_foregroundClipLayer->setPosition(x, y);
607 m_foregroundClipLayer->setSize(width, height);
609 // Need to offset the foreground layer by the clip layer in order
610 // for the contents to be in the correct position.
611 m_foregroundLayer->setPosition(-x, -y);
612 // Set the scrollable bounds of the layer.
613 m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height());
615 // Invalidate the entire layer for now, as webkit will only send the
616 // setNeedsDisplayInRect() for the visible (clipped) scrollable area,
617 // offsetting the invals by the scroll position would not be enough.
618 // TODO: have webkit send us invals even for non visible area
620 region.setRect(0, 0, contentsRect.width(), contentsRect.height());
621 m_foregroundLayer->markAsDirty(region);
622 m_foregroundLayer->needsRepaint();
624 // If there is no contents clip, we can draw everything into one
626 if (!paintContext(m_contentLayer->recordContext(), layerBounds))
628 m_contentLayer->checkTextPresence();
629 // Check for a scrollable iframe and report the scrolling
630 // limits based on the view size.
631 if (m_contentLayer->contentIsScrollable()) {
632 FrameView* view = layer->renderer()->frame()->view();
633 static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits(
634 m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight());
638 LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
639 this, m_size.width(), m_size.height(),
640 m_contentLayer->getPosition().fX,
641 m_contentLayer->getPosition().fY,
642 m_contentLayer->getSize().width(),
643 m_contentLayer->getSize().height());
645 m_contentLayer->markAsDirty(m_dirtyRegion);
646 m_dirtyRegion.setEmpty();
647 m_contentLayer->needsRepaint();
648 m_needsRepaint = false;
652 if (m_needsRepaint && m_image && m_newImage) {
653 // We need to tell the GL thread that we will need to repaint the
654 // texture. Only do so if we effectively have a new image!
655 m_contentLayer->markAsDirty(m_dirtyRegion);
656 m_dirtyRegion.setEmpty();
657 m_contentLayer->needsRepaint();
659 m_needsRepaint = false;
665 bool GraphicsLayerAndroid::paintContext(SkPicture* context,
668 SkAutoPictureRecord arp(context, rect.width(), rect.height());
669 SkCanvas* canvas = arp.getRecordingCanvas();
674 PlatformGraphicsContext platformContext(canvas);
675 GraphicsContext graphicsContext(&platformContext);
677 paintGraphicsLayerContents(graphicsContext, rect);
681 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
683 // rect is in the render object coordinates
685 if (!m_image && !drawsContent()) {
686 LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
687 this, rect.x(), rect.y(), rect.width(), rect.height());
692 region.setRect(rect.x(), rect.y(),
693 rect.x() + rect.width(),
694 rect.y() + rect.height());
695 m_dirtyRegion.op(region, SkRegion::kUnion_Op);
697 m_needsRepaint = true;
701 void GraphicsLayerAndroid::pauseDisplay(bool state)
705 gPausedDelay = WTF::currentTime() + 1;
708 bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
709 const IntSize& boxSize,
710 const Animation* anim,
711 const String& keyframesName,
714 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
717 bool createdAnimations = false;
718 if (valueList.property() == AnimatedPropertyWebkitTransform) {
719 createdAnimations = createTransformAnimationsFromKeyframes(valueList,
725 createdAnimations = createAnimationFromKeyframes(valueList,
730 if (createdAnimations)
732 return createdAnimations;
735 bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList,
736 const Animation* animation, const String& keyframesName, double beginTime)
738 bool isKeyframe = valueList.size() > 2;
739 TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
740 isKeyframe, keyframesName.latin1().data(), beginTime);
742 switch (valueList.property()) {
743 case AnimatedPropertyInvalid: break;
744 case AnimatedPropertyWebkitTransform: break;
745 case AnimatedPropertyBackgroundColor: break;
746 case AnimatedPropertyOpacity: {
747 MLOG("ANIMATEDPROPERTYOPACITY");
749 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity);
750 for (unsigned int i = 0; i < valueList.size(); i++) {
751 FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i);
752 PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
753 FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(),
754 originalValue->value(),
756 operationsList->insert(value);
759 RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation,
762 if (keyframesName.isEmpty())
763 anim->setName(propertyIdToString(valueList.property()));
765 anim->setName(keyframesName);
767 m_contentLayer->addAnimation(anim.release());
775 void GraphicsLayerAndroid::needsNotifyClient()
777 m_needsNotifyClient = true;
781 bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList,
782 const Animation* animation,
783 const String& keyframesName,
785 const IntSize& boxSize)
787 ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
788 TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
789 keyframesName.latin1().data(), beginTime);
791 KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform);
792 for (unsigned int i = 0; i < valueList.size(); i++) {
793 TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i);
794 PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
795 TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(),
796 originalValue->value(),
798 operationsList->insert(value);
801 RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation,
805 if (keyframesName.isEmpty())
806 anim->setName(propertyIdToString(valueList.property()));
808 anim->setName(keyframesName);
811 m_contentLayer->addAnimation(anim.release());
817 void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
819 TLOG("NRO removeAnimationsForProperty(%d)", anID);
820 m_contentLayer->removeAnimationsForProperty(anID);
824 void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
826 TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data());
827 m_contentLayer->removeAnimationsForKeyframes(keyframesName);
831 void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
833 TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data());
836 void GraphicsLayerAndroid::suspendAnimations(double time)
838 TLOG("NRO suspendAnimations(%.2f)", time);
841 void GraphicsLayerAndroid::resumeAnimations()
843 TLOG("NRO resumeAnimations()");
846 void GraphicsLayerAndroid::setContentsToImage(Image* image)
848 TLOG("(%x) setContentsToImage", this, image);
849 if (image && image != m_image) {
855 SkBitmapRef* bitmap = image->nativeImageForCurrentFrame();
856 m_contentLayer->setContentsImage(bitmap);
858 m_haveContents = true;
861 if (!image && m_image) {
862 m_contentLayer->setContentsImage(0);
871 void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer)
873 // Only fullscreen video on Android, so media doesn't get it's own layer.
874 // We might still have other layers though.
875 if (m_contentLayer != mediaLayer && mediaLayer) {
877 // TODO add a copy method to LayerAndroid to sync everything
878 // copy data from the original content layer to the new one
879 mediaLayer->setPosition(m_contentLayer->getPosition().fX,
880 m_contentLayer->getPosition().fY);
881 mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight());
882 mediaLayer->setDrawTransform(*m_contentLayer->drawTransform());
885 m_contentLayer->unref();
886 m_contentLayer = mediaLayer;
888 // If the parent exists then notify it to re-sync it's children
890 GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
891 parent->m_needsSyncChildren = true;
893 m_needsSyncChildren = true;
900 PlatformLayer* GraphicsLayerAndroid::platformLayer() const
902 LOG("platformLayer");
903 return m_contentLayer;
907 void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color)
911 void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth)
916 void GraphicsLayerAndroid::setZPosition(float position)
918 if (position == m_zPosition)
920 LOG("(%x) setZPosition: %.2f", this, position);
921 GraphicsLayer::setZPosition(position);
925 void GraphicsLayerAndroid::askForSync()
931 m_client->notifySyncRequired(this);
934 void GraphicsLayerAndroid::syncChildren()
936 if (m_needsSyncChildren) {
937 m_contentLayer->removeChildren();
938 LayerAndroid* layer = m_contentLayer;
939 if (m_foregroundClipLayer) {
940 m_contentLayer->addChild(m_foregroundClipLayer);
941 // Use the scrollable content layer as the parent of the children so
942 // that they move with the content.
943 layer = m_foregroundLayer;
944 layer->removeChildren();
946 for (unsigned int i = 0; i < m_children.size(); i++)
947 layer->addChild(m_children[i]->platformLayer());
948 m_needsSyncChildren = false;
952 void GraphicsLayerAndroid::syncMask()
954 if (m_needsSyncMask) {
956 LayerAndroid* mask = m_maskLayer->platformLayer();
957 m_contentLayer->setMaskLayer(mask);
959 m_contentLayer->setMaskLayer(0);
961 m_contentLayer->setMasksToBounds(m_masksToBounds);
962 m_needsSyncMask = false;
966 void GraphicsLayerAndroid::syncCompositingState()
968 for (unsigned int i = 0; i < m_children.size(); i++)
969 m_children[i]->syncCompositingState();
971 updateScrollingLayers();
972 updateFixedPosition();
976 if (!gPaused || WTF::currentTime() >= gPausedDelay)
980 void GraphicsLayerAndroid::notifyClientAnimationStarted()
982 for (unsigned int i = 0; i < m_children.size(); i++)
983 static_cast<GraphicsLayerAndroid*>(m_children[i])->notifyClientAnimationStarted();
985 if (m_needsNotifyClient) {
987 client()->notifyAnimationStarted(this, WTF::currentTime());
988 m_needsNotifyClient = false;
992 } // namespace WebCore
994 #endif // USE(ACCELERATED_COMPOSITING)