• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 #include "config.h"
18 #include "GraphicsLayerAndroid.h"
19 
20 #if USE(ACCELERATED_COMPOSITING)
21 
22 #include "AndroidAnimation.h"
23 #include "Animation.h"
24 #include "CString.h"
25 #include "FloatRect.h"
26 #include "GraphicsContext.h"
27 #include "Image.h"
28 #include "Length.h"
29 #include "SkLayer.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 "SkCanvas.h"
37 #include "TransformationMatrix.h"
38 #include "TranslateTransformOperation.h"
39 
40 #include <cutils/log.h>
41 #include <wtf/CurrentTime.h>
42 
43 #undef LOG
44 #define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
45 #define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
46 #define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
47 
48 #undef LOG
49 #define LOG(...)
50 #undef MLOG
51 #define MLOG(...)
52 #undef TLOG
53 #define TLOG(...)
54 #undef LAYER_DEBUG
55 
56 using namespace std;
57 
58 static bool gPaused;
59 static double gPausedDelay;
60 
61 namespace WebCore {
62 
63 static int gDebugGraphicsLayerAndroidInstances = 0;
instancesCount()64 inline int GraphicsLayerAndroid::instancesCount()
65 {
66     return gDebugGraphicsLayerAndroidInstances;
67 }
68 
propertyIdToString(AnimatedPropertyID property)69 static String propertyIdToString(AnimatedPropertyID property)
70 {
71     switch (property) {
72     case AnimatedPropertyWebkitTransform:
73         return "transform";
74     case AnimatedPropertyOpacity:
75         return "opacity";
76     case AnimatedPropertyBackgroundColor:
77         return "backgroundColor";
78     case AnimatedPropertyInvalid:
79         ASSERT_NOT_REACHED();
80     }
81     ASSERT_NOT_REACHED();
82     return "";
83 }
84 
compositingCoordinatesOrientation()85 GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation()
86 {
87     return CompositingCoordinatesBottomUp;
88 }
89 
create(GraphicsLayerClient * client)90 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
91 {
92     return new GraphicsLayerAndroid(client);
93 }
94 
convertLength(Length l)95 SkLength convertLength(Length l) {
96   SkLength length;
97   length.type = SkLength::Undefined;
98   length.value = 0;
99   if (l.type() == WebCore::Percent) {
100     length.type = SkLength::Percent;
101     length.value = l.percent();
102   } if (l.type() == WebCore::Fixed) {
103     length.type = SkLength::Fixed;
104     length.value = l.value();
105   }
106   return length;
107 }
108 
GraphicsLayerAndroid(GraphicsLayerClient * client)109 GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
110     GraphicsLayer(client),
111     m_needsSyncChildren(false),
112     m_needsSyncMask(false),
113     m_needsRepaint(false),
114     m_needsDisplay(false),
115     m_needsNotifyClient(false),
116     m_haveContents(false),
117     m_haveImage(false),
118     m_translateX(0),
119     m_translateY(0),
120     m_currentTranslateX(0),
121     m_currentTranslateY(0),
122     m_currentPosition(0, 0)
123 {
124     m_contentLayer = new LayerAndroid(true);
125     if (m_client) {
126         RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_client);
127         RenderLayer* renderLayer = backing->owningLayer();
128         m_contentLayer->setIsRootLayer(renderLayer->isRootLayer());
129     }
130     gDebugGraphicsLayerAndroidInstances++;
131 }
132 
~GraphicsLayerAndroid()133 GraphicsLayerAndroid::~GraphicsLayerAndroid()
134 {
135     m_contentLayer->unref();
136     gDebugGraphicsLayerAndroidInstances--;
137 }
138 
setName(const String & name)139 void GraphicsLayerAndroid::setName(const String& name)
140 {
141     GraphicsLayer::setName(name);
142 }
143 
nativeLayer() const144 NativeLayer GraphicsLayerAndroid::nativeLayer() const
145 {
146     LOG("(%x) nativeLayer", this);
147     return 0;
148 }
149 
setChildren(const Vector<GraphicsLayer * > & children)150 bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children)
151 {
152     bool childrenChanged = GraphicsLayer::setChildren(children);
153     if (childrenChanged) {
154         m_needsSyncChildren = true;
155         askForSync();
156     }
157 
158     return childrenChanged;
159 }
160 
addChild(GraphicsLayer * childLayer)161 void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer)
162 {
163 #ifndef NDEBUG
164     const char* n = (static_cast<GraphicsLayerAndroid*>(childLayer))->m_name.latin1().data();
165     LOG("(%x) addChild: %x (%s)", this, childLayer, n);
166 #endif
167     GraphicsLayer::addChild(childLayer);
168     m_needsSyncChildren = true;
169     askForSync();
170 }
171 
addChildAtIndex(GraphicsLayer * childLayer,int index)172 void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index)
173 {
174     LOG("(%x) addChild %x AtIndex %d", this, childLayer, index);
175     GraphicsLayer::addChildAtIndex(childLayer, index);
176     m_needsSyncChildren = true;
177     askForSync();
178 }
179 
addChildBelow(GraphicsLayer * childLayer,GraphicsLayer * sibling)180 void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
181 {
182     LOG("(%x) addChild %x Below %x", this, childLayer, sibling);
183     GraphicsLayer::addChildBelow(childLayer, sibling);
184     m_needsSyncChildren = true;
185     askForSync();
186 }
187 
addChildAbove(GraphicsLayer * childLayer,GraphicsLayer * sibling)188 void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
189 {
190     LOG("(%x) addChild %x Above %x", this, childLayer, sibling);
191     GraphicsLayer::addChildAbove(childLayer, sibling);
192     m_needsSyncChildren = true;
193     askForSync();
194 }
195 
replaceChild(GraphicsLayer * oldChild,GraphicsLayer * newChild)196 bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
197 {
198     LOG("(%x) replaceChild %x by %x", this, oldChild, newChild);
199     bool ret = GraphicsLayer::replaceChild(oldChild, newChild);
200     m_needsSyncChildren = true;
201     askForSync();
202     return ret;
203 }
204 
removeFromParent()205 void GraphicsLayerAndroid::removeFromParent()
206 {
207     LOG("(%x) removeFromParent()", this);
208     if (m_parent)
209         static_cast<GraphicsLayerAndroid*>(m_parent)->needsSyncChildren();
210     GraphicsLayer::removeFromParent();
211     m_needsSyncChildren = true;
212     askForSync();
213 }
214 
needsSyncChildren()215 void GraphicsLayerAndroid::needsSyncChildren()
216 {
217     m_needsSyncChildren = true;
218     askForSync();
219 }
220 
updateFixedPosition()221 void GraphicsLayerAndroid::updateFixedPosition()
222 {
223     if (!m_client)
224         return;
225 
226     RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_client);
227     RenderLayer* renderLayer = backing->owningLayer();
228     RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
229 
230     // If we are a fixed position layer, just set it
231     if (view->isPositioned() && view->style()->position() == FixedPosition) {
232         SkLength left, top, right, bottom;
233         left = convertLength(view->style()->left());
234         top = convertLength(view->style()->top());
235         right = convertLength(view->style()->right());
236         bottom = convertLength(view->style()->bottom());
237         // We need to pass the size of the element to compute the final fixed
238         // position -- we can't use the layer's size as it could possibly differs.
239         // We also have to use the visible overflow and not just the size,
240         // as some child elements could be overflowing.
241         int w = view->rightVisibleOverflow() - view->leftVisibleOverflow();
242         int h = view->bottomVisibleOverflow() - view->topVisibleOverflow();
243 
244         SkLength marginLeft, marginTop, marginRight, marginBottom;
245         marginLeft = convertLength(view->style()->marginLeft());
246         marginTop = convertLength(view->style()->marginTop());
247         marginRight = convertLength(view->style()->marginRight());
248         marginBottom = convertLength(view->style()->marginBottom());
249 
250         m_contentLayer->setFixedPosition(left, top, right, bottom,
251                                          marginLeft, marginTop,
252                                          marginRight, marginBottom,
253                                          offsetFromRenderer().width(),
254                                          offsetFromRenderer().height(),
255                                          w, h);
256     }
257 }
258 
setPosition(const FloatPoint & point)259 void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
260 {
261     m_currentPosition = point;
262     m_needsDisplay = true;
263 #ifdef LAYER_DEBUG_2
264     LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
265         this, point.x(), point.y(), m_currentPosition.x(), m_currentPosition.y(),
266         m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height());
267 #endif
268     updateFixedPosition();
269     askForSync();
270 }
271 
setAnchorPoint(const FloatPoint3D & point)272 void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point)
273 {
274     GraphicsLayer::setAnchorPoint(point);
275     m_contentLayer->setAnchorPoint(point.x(), point.y());
276     askForSync();
277 }
278 
setSize(const FloatSize & size)279 void GraphicsLayerAndroid::setSize(const FloatSize& size)
280 {
281     if ((size.width() != m_size.width())
282           || (size.height() != m_size.height())) {
283         MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height());
284         GraphicsLayer::setSize(size);
285         m_contentLayer->setSize(size.width(), size.height());
286         askForSync();
287     }
288 }
289 
setTransform(const TransformationMatrix & t)290 void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t)
291 {
292     TransformationMatrix::DecomposedType tDecomp;
293     t.decompose(tDecomp);
294     LOG("(%x) setTransform, translate (%.2f, %.2f), mpos(%.2f,%.2f)",
295         this, tDecomp.translateX, tDecomp.translateY,
296         m_position.x(), m_position.y());
297 
298     if ((m_currentTranslateX != tDecomp.translateX)
299           || (m_currentTranslateY != tDecomp.translateY)) {
300         m_currentTranslateX = tDecomp.translateX;
301         m_currentTranslateY = tDecomp.translateY;
302         m_needsDisplay = true;
303         askForSync();
304     }
305 }
306 
setChildrenTransform(const TransformationMatrix & t)307 void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t)
308 {
309     if (t == m_childrenTransform)
310        return;
311     LOG("(%x) setChildrenTransform", this);
312 
313     GraphicsLayer::setChildrenTransform(t);
314     for (unsigned int i = 0; i < m_children.size(); i++) {
315         GraphicsLayer* layer = m_children[i];
316         layer->setTransform(t);
317         if (layer->children().size())
318             layer->setChildrenTransform(t);
319     }
320     askForSync();
321 }
322 
setMaskLayer(GraphicsLayer * layer)323 void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer)
324 {
325     if (layer == m_maskLayer)
326       return;
327 
328     GraphicsLayer::setMaskLayer(layer);
329     m_needsSyncMask = true;
330     askForSync();
331 }
332 
setMasksToBounds(bool masksToBounds)333 void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds)
334 {
335     GraphicsLayer::setMasksToBounds(masksToBounds);
336     m_needsSyncMask = true;
337     askForSync();
338 }
339 
setDrawsContent(bool drawsContent)340 void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
341 {
342     GraphicsLayer::setDrawsContent(drawsContent);
343 
344     if (m_drawsContent) {
345         m_haveContents = true;
346         setNeedsDisplay();
347     }
348     askForSync();
349 }
350 
setBackgroundColor(const Color & color)351 void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
352 {
353     LOG("(%x) setBackgroundColor", this);
354     GraphicsLayer::setBackgroundColor(color);
355     SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue());
356     m_contentLayer->setBackgroundColor(c);
357     m_haveContents = true;
358     askForSync();
359 }
360 
clearBackgroundColor()361 void GraphicsLayerAndroid::clearBackgroundColor()
362 {
363     LOG("(%x) clearBackgroundColor", this);
364     GraphicsLayer::clearBackgroundColor();
365     askForSync();
366 }
367 
setContentsOpaque(bool opaque)368 void GraphicsLayerAndroid::setContentsOpaque(bool opaque)
369 {
370     LOG("(%x) setContentsOpaque (%d)", this, opaque);
371     GraphicsLayer::setContentsOpaque(opaque);
372     m_haveContents = true;
373     askForSync();
374 }
375 
setOpacity(float opacity)376 void GraphicsLayerAndroid::setOpacity(float opacity)
377 {
378     LOG("(%x) setOpacity: %.2f", this, opacity);
379     float clampedOpacity = max(0.0f, min(opacity, 1.0f));
380 
381     if (clampedOpacity == m_opacity)
382         return;
383 
384     MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
385         opacity, clampedOpacity, m_opacity);
386     GraphicsLayer::setOpacity(clampedOpacity);
387     m_contentLayer->setOpacity(clampedOpacity);
388     askForSync();
389 }
390 
repaintAll()391 bool GraphicsLayerAndroid::repaintAll()
392 {
393      LOG("(%x) repaintAll", this);
394      bool ret = false;
395      for (unsigned int i = 0; i < m_children.size(); i++) {
396          GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
397          if (layer && layer->repaintAll())
398              ret = true;
399      }
400      int nbRects = m_invalidatedRects.size();
401 
402      for (int i = 0; !gPaused && i < nbRects; i++) {
403          FloatRect rect = m_invalidatedRects[i];
404          if (repaint(rect))
405              ret = true;
406      }
407      if (!gPaused) {
408          m_needsRepaint = false;
409          m_invalidatedRects.clear();
410      }
411      return ret;
412 }
413 
setNeedsDisplay()414 void GraphicsLayerAndroid::setNeedsDisplay()
415 {
416     LOG("(%x) setNeedsDisplay()", this);
417     FloatRect rect(0, 0, m_size.width(), m_size.height());
418     setNeedsDisplayInRect(rect);
419 }
420 
setFrame(Frame * f)421 void GraphicsLayerAndroid::setFrame(Frame* f)
422 {
423     m_frame = f;
424 }
425 
sendImmediateRepaint()426 void GraphicsLayerAndroid::sendImmediateRepaint()
427 {
428     LOG("(%x) sendImmediateRepaint()", this);
429     GraphicsLayerAndroid* rootGraphicsLayer = this;
430 
431     while (rootGraphicsLayer->parent())
432         rootGraphicsLayer = static_cast<GraphicsLayerAndroid*>(rootGraphicsLayer->parent());
433 
434     if (rootGraphicsLayer->m_frame
435         && rootGraphicsLayer->m_frame->view()) {
436         LayerAndroid* rootLayer = new LayerAndroid(true);
437         LayerAndroid* copyLayer = new LayerAndroid(*m_contentLayer);
438         rootLayer->addChild(copyLayer);
439         copyLayer->unref();
440         TLOG("(%x) sendImmediateRepaint, copy the layer, (%.2f,%.2f => %.2f,%.2f)",
441             this, m_contentLayer->getSize().width(), m_contentLayer->getSize().height(),
442             copyLayer->getSize().width(), copyLayer->getSize().height());
443         PlatformBridge::setUIRootLayer(m_frame->view(), rootLayer);
444         PlatformBridge::immediateRepaint(m_frame->view());
445     }
446 }
447 
repaint(const FloatRect & rect)448 bool GraphicsLayerAndroid::repaint(const FloatRect& rect)
449 {
450     LOG("(%x) repaint(%.2f,%.2f,%.2f,%.2f), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
451         this, rect.x(), rect.y(), rect.width(), rect.height(),
452         gPaused, m_needsRepaint, m_haveContents);
453 
454     if (!gPaused && m_haveContents && m_needsRepaint) {
455         SkAutoPictureRecord arp(m_contentLayer->recordContext(), m_size.width(), m_size.height());
456         SkCanvas* recordingCanvas = arp.getRecordingCanvas();
457 
458         if (!recordingCanvas)
459             return false;
460 
461         if ((rect.width() > 0.5) && (rect.height() > 0.5)) {
462             IntRect r((int)rect.x(), (int)rect.y(),
463                   (int)rect.width(), (int)rect.height());
464 
465             PlatformGraphicsContext pgc(recordingCanvas, 0);
466             GraphicsContext gc(&pgc);
467 
468             // with SkPicture, we request the entire layer's content.
469             r.setX(0);
470             r.setY(0);
471             r.setWidth(m_contentLayer->getWidth());
472             r.setHeight(m_contentLayer->getHeight());
473             paintGraphicsLayerContents(gc, r);
474 
475             TLOG("(%x) repaint(%.2f,%.2f,%.2f,%.2f) on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
476                 this, rect.x(), rect.y(), rect.width(),
477                 rect.height(), m_size.width(), m_size.height(),
478                 m_contentLayer->getPosition().fX,
479                 m_contentLayer->getPosition().fY,
480                 m_contentLayer->getSize().width(),
481                 m_contentLayer->getSize().height());
482         }
483         return true;
484     }
485     return false;
486 }
487 
setNeedsDisplayInRect(const FloatRect & rect)488 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
489 {
490     for (unsigned int i = 0; i < m_children.size(); i++) {
491         GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
492         if (layer) {
493             FloatRect childrenRect(m_position.x() + m_translateX + rect.x(),
494                                    m_position.y() + m_translateY + rect.y(),
495                                    rect.width(), rect.height());
496             layer->setNeedsDisplayInRect(childrenRect);
497         }
498     }
499     if (!m_haveImage && !drawsContent()) {
500         LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
501             this, rect.x(), rect.y(), rect.width(), rect.height());
502         return;
503     }
504 
505     const size_t maxDirtyRects = 8;
506     for (size_t i = 0; i < m_invalidatedRects.size(); ++i) {
507         if (m_invalidatedRects[i].contains(rect))
508             return;
509     }
510 
511 #ifdef LAYER_DEBUG
512     LOG("(%x) setNeedsDisplayInRect(%d) - (%.2f, %.2f, %.2f, %.2f)", this,
513         m_needsRepaint, rect.x(), rect.y(), rect.width(), rect.height());
514 #endif
515 
516     if (m_invalidatedRects.size() < maxDirtyRects)
517         m_invalidatedRects.append(rect);
518     else
519         m_invalidatedRects[0].unite(rect);
520 
521     m_needsRepaint = true;
522     askForSync();
523 }
524 
pauseDisplay(bool state)525 void GraphicsLayerAndroid::pauseDisplay(bool state)
526 {
527     gPaused = state;
528     if (gPaused)
529         gPausedDelay = WTF::currentTime() + 1;
530 }
531 
addAnimation(const KeyframeValueList & valueList,const IntSize & boxSize,const Animation * anim,const String & keyframesName,double beginTime)532 bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
533                                         const IntSize& boxSize,
534                                         const Animation* anim,
535                                         const String& keyframesName,
536                                         double beginTime)
537 {
538     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() != 2)
539     return false;
540 
541     bool createdAnimations = false;
542     if (valueList.property() == AnimatedPropertyWebkitTransform) {
543         createdAnimations = createTransformAnimationsFromKeyframes(valueList,
544                                                                    anim,
545                                                                    keyframesName,
546                                                                    beginTime,
547                                                                    boxSize);
548     } else {
549         createdAnimations = createAnimationFromKeyframes(valueList,
550                                                          anim,
551                                                          keyframesName,
552                                                          beginTime);
553     }
554     askForSync();
555     return createdAnimations;
556 }
557 
createAnimationFromKeyframes(const KeyframeValueList & valueList,const Animation * animation,const String & keyframesName,double beginTime)558 bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList,
559      const Animation* animation, const String& keyframesName, double beginTime)
560 {
561     bool isKeyframe = valueList.size() > 2;
562     TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
563         isKeyframe, keyframesName.latin1().data(), beginTime);
564     // TODO: handles keyframe animations correctly
565 
566     switch (valueList.property()) {
567     case AnimatedPropertyInvalid: break;
568     case AnimatedPropertyWebkitTransform: break;
569     case AnimatedPropertyBackgroundColor: break;
570     case AnimatedPropertyOpacity: {
571         MLOG("ANIMATEDPROPERTYOPACITY");
572         const FloatAnimationValue* startVal =
573             static_cast<const FloatAnimationValue*>(valueList.at(0));
574         const FloatAnimationValue* endVal =
575             static_cast<const FloatAnimationValue*>(valueList.at(1));
576         RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(startVal->value(),
577                                                                                endVal->value(),
578                                                                                animation,
579                                                                                beginTime);
580         if (keyframesName.isEmpty())
581             anim->setName(propertyIdToString(valueList.property()));
582         else
583             anim->setName(keyframesName);
584 
585         m_contentLayer->addAnimation(anim.release());
586         needsNotifyClient();
587         return true;
588     } break;
589     }
590     return false;
591 }
592 
needsNotifyClient()593 void GraphicsLayerAndroid::needsNotifyClient()
594 {
595     m_needsNotifyClient = true;
596     askForSync();
597 }
598 
createTransformAnimationsFromKeyframes(const KeyframeValueList & valueList,const Animation * animation,const String & keyframesName,double beginTime,const IntSize & boxSize)599 bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList,
600                                                                   const Animation* animation,
601                                                                   const String& keyframesName,
602                                                                   double beginTime,
603                                                                   const IntSize& boxSize)
604 {
605     ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
606     TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
607         keyframesName.latin1().data(), beginTime);
608 
609     TransformOperationList functionList;
610     bool listsMatch, hasBigRotation;
611     fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation);
612 
613     // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation.
614     // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation
615     // if that's not true as well.
616 
617     bool isMatrixAnimation = !listsMatch;
618     size_t numAnimations = isMatrixAnimation ? 1 : functionList.size();
619     bool isKeyframe = valueList.size() > 2;
620 
621     float fromTranslateX = 0;
622     float fromTranslateY = 0;
623     float fromTranslateZ = 0;
624     float toTranslateX   = 0;
625     float toTranslateY   = 0;
626     float toTranslateZ   = 0;
627     float fromAngle      = 0;
628     float toAngle        = 0;
629     float fromScaleX     = 1;
630     float fromScaleY     = 1;
631     float fromScaleZ     = 1;
632     float toScaleX       = 1;
633     float toScaleY       = 1;
634     float toScaleZ       = 1;
635 
636     bool doTranslation = false;
637     bool doRotation = false;
638     bool doScaling = false;
639 
640     TLOG("(%x) animateTransform, valueList(%d) functionList(%d) duration(%.2f)", this,
641         valueList.size(), functionList.size(), animation->duration());
642 
643     // FIXME: add support for the translate 3d operations (when
644     // we'll have an OpenGL backend)
645 
646     for (unsigned int i = 0; i < valueList.size(); i++) {
647         const TransformOperations* operation = ((TransformAnimationValue*)valueList.at(i))->value();
648         Vector<RefPtr<TransformOperation> > ops = operation->operations();
649         TLOG("(%x) animateTransform, dealing with the %d operation, with %d ops", this, i, ops.size());
650         for (unsigned int j = 0; j < ops.size(); j++) {
651             TransformOperation* op = ops[j].get();
652             TLOG("(%x) animateTransform, dealing with the %d:%d operation, current op: %d (translate is %d, rotate %d, scale %d)",
653                 this, i, j, op->getOperationType(), TransformOperation::TRANSLATE, TransformOperation::ROTATE, TransformOperation::SCALE);
654             if ((op->getOperationType() == TransformOperation::TRANSLATE) ||
655                 (op->getOperationType() == TransformOperation::TRANSLATE_3D)) {
656                 TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
657                 IntSize bounds(m_size.width(), m_size.height());
658                 float x = translateOperation->x(bounds);
659                 float y = translateOperation->y(bounds);
660                 float z = translateOperation->z(bounds);
661                 if (!i) {
662                     fromTranslateX = x;
663                     fromTranslateY = y;
664                     fromTranslateZ = z;
665                 } else {
666                     toTranslateX = x;
667                     toTranslateY = y;
668                     toTranslateZ = z;
669                 }
670                 TLOG("(%x) animateTransform, the %d operation is a translation(%.2f,%.2f,%.2f)",
671                     this, j, x, y, z);
672                 doTranslation = true;
673             } else if (op->getOperationType() == TransformOperation::TRANSLATE_X) {
674                 TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
675                 IntSize bounds(m_size.width(), m_size.height());
676                 float x = translateOperation->x(bounds);
677                 if (!i)
678                     fromTranslateX = x;
679                 else
680                     toTranslateX = x;
681                 TLOG("(%x) animateTransform, the %d operation is a translation_x(%.2f)",
682                     this, j, x);
683                 doTranslation = true;
684             } else if (op->getOperationType() == TransformOperation::TRANSLATE_Y) {
685                 TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
686                 IntSize bounds(m_size.width(), m_size.height());
687                 float y = translateOperation->y(bounds);
688                 if (!i)
689                     fromTranslateY = y;
690                 else
691                     toTranslateY = y;
692                 TLOG("(%x) animateTransform, the %d operation is a translation_y(%.2f)",
693                     this, j, y);
694                 doTranslation = true;
695             } else if (op->getOperationType() == TransformOperation::TRANSLATE_Z) {
696                 TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
697                 IntSize bounds(m_size.width(), m_size.height());
698                 float z = translateOperation->z(bounds);
699                 if (!i)
700                     fromTranslateZ = z;
701                 else
702                     toTranslateZ = z;
703                 TLOG("(%x) animateTransform, the %d operation is a translation_z(%.2f)",
704                     this, j, z);
705                 doTranslation = true;
706             } else if ((op->getOperationType() == TransformOperation::ROTATE)
707                           || (op->getOperationType() == TransformOperation::ROTATE_X)
708                           || (op->getOperationType() == TransformOperation::ROTATE_Y)) {
709                 LOG("(%x) animateTransform, the %d operation is a rotation", this, j);
710                 RotateTransformOperation* rotateOperation = (RotateTransformOperation*) op;
711                 float angle = rotateOperation->angle();
712                 TLOG("(%x) animateTransform, the %d operation is a rotation (%d), of angle %.2f",
713                     this, j, op->getOperationType(), angle);
714 
715                 if (!i)
716                     fromAngle = angle;
717                 else
718                     toAngle = angle;
719                 doRotation = true;
720             } else if (op->getOperationType() == TransformOperation::SCALE_X) {
721                 ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
722                 if (!i)
723                     fromScaleX = scaleOperation->x();
724                 else
725                     toScaleX = scaleOperation->x();
726                 doScaling = true;
727             } else if (op->getOperationType() == TransformOperation::SCALE_Y) {
728                 ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
729                 if (!i)
730                     fromScaleY = scaleOperation->y();
731                 else
732                     toScaleY = scaleOperation->y();
733                 doScaling = true;
734             } else if (op->getOperationType() == TransformOperation::SCALE_Z) {
735                 ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
736                 if (!i)
737                     fromScaleZ = scaleOperation->z();
738                 else
739                     toScaleZ = scaleOperation->z();
740                 doScaling = true;
741             } else if (op->getOperationType() == TransformOperation::SCALE) {
742                 ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
743                 if (!i) {
744                     fromScaleX = scaleOperation->x();
745                     fromScaleY = scaleOperation->y();
746                     fromScaleZ = scaleOperation->z();
747                 } else {
748                     toScaleX = scaleOperation->x();
749                     toScaleY = scaleOperation->y();
750                     toScaleZ = scaleOperation->z();
751                 }
752                 doScaling = true;
753             } else {
754                 TLOG("(%x) animateTransform, the %d operation is not a rotation (%d)",
755                     this, j, op->getOperationType());
756             }
757         }
758     }
759 
760     RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation, beginTime);
761 
762     if (keyframesName.isEmpty())
763         anim->setName(propertyIdToString(valueList.property()));
764     else
765         anim->setName(keyframesName);
766 
767     anim->setOriginalPosition(m_position);
768 
769     if (doTranslation)
770         anim->setTranslation(fromTranslateX, fromTranslateY, fromTranslateZ,
771                          toTranslateX, toTranslateY, toTranslateZ);
772     if (doRotation)
773         anim->setRotation(fromAngle, toAngle);
774     if (doScaling)
775         anim->setScale(fromScaleX, fromScaleY, fromScaleZ,
776                        toScaleX, toScaleY, toScaleZ);
777     m_contentLayer->addAnimation(anim.release());
778 
779     needsNotifyClient();
780     return true;
781 }
782 
removeAnimationsForProperty(AnimatedPropertyID anID)783 void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
784 {
785     TLOG("NRO removeAnimationsForProperty(%d)", anID);
786     m_contentLayer->removeAnimation(propertyIdToString(anID));
787     askForSync();
788 }
789 
removeAnimationsForKeyframes(const String & keyframesName)790 void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
791 {
792     TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data());
793     m_contentLayer->removeAnimation(keyframesName);
794     askForSync();
795 }
796 
pauseAnimation(const String & keyframesName)797 void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
798 {
799     TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data());
800 }
801 
suspendAnimations(double time)802 void GraphicsLayerAndroid::suspendAnimations(double time)
803 {
804     TLOG("NRO suspendAnimations(%.2f)", time);
805 }
806 
resumeAnimations()807 void GraphicsLayerAndroid::resumeAnimations()
808 {
809     TLOG("NRO resumeAnimations()");
810 }
811 
setContentsToImage(Image * image)812 void GraphicsLayerAndroid::setContentsToImage(Image* image)
813 {
814     TLOG("(%x) setContentsToImage", this, image);
815     if (image) {
816         m_haveContents = true;
817         if (!m_haveImage) {
818             m_haveImage = true;
819             setNeedsDisplay();
820             askForSync();
821         }
822     }
823 }
824 
platformLayer() const825 PlatformLayer* GraphicsLayerAndroid::platformLayer() const
826 {
827     LOG("platformLayer");
828     return (PlatformLayer*) m_contentLayer;
829 }
830 
831 #ifndef NDEBUG
setDebugBackgroundColor(const Color & color)832 void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color)
833 {
834 }
835 
setDebugBorder(const Color & color,float borderWidth)836 void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth)
837 {
838 }
839 #endif
840 
setZPosition(float position)841 void GraphicsLayerAndroid::setZPosition(float position)
842 {
843     LOG("(%x) setZPosition: %.2f", this, position);
844     GraphicsLayer::setZPosition(position);
845     askForSync();
846 }
847 
askForSync()848 void GraphicsLayerAndroid::askForSync()
849 {
850     if (m_client)
851         m_client->notifySyncRequired(this);
852 }
853 
syncChildren()854 void GraphicsLayerAndroid::syncChildren()
855 {
856     if (m_needsSyncChildren) {
857         m_contentLayer->removeChildren();
858         for (unsigned int i = 0; i < m_children.size(); i++) {
859             m_contentLayer->addChild(
860                 (static_cast<GraphicsLayerAndroid*>(m_children[i]))->contentLayer());
861         }
862         m_needsSyncChildren = false;
863     }
864 }
865 
syncMask()866 void GraphicsLayerAndroid::syncMask()
867 {
868     if (m_needsSyncMask) {
869         if (m_maskLayer) {
870             GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_maskLayer);
871             LayerAndroid* mask = reinterpret_cast<LayerAndroid*>(layer->platformLayer());
872             m_contentLayer->setMaskLayer(mask);
873         } else
874             m_contentLayer->setMaskLayer(0);
875 
876         m_contentLayer->setMasksToBounds(m_masksToBounds);
877         m_needsSyncMask = false;
878     }
879 }
880 
syncPositionState()881 void GraphicsLayerAndroid::syncPositionState()
882 {
883      if (m_needsDisplay) {
884          m_translateX = m_currentTranslateX;
885          m_translateY = m_currentTranslateY;
886          m_position = m_currentPosition;
887          m_contentLayer->setTranslation(m_currentTranslateX, m_currentTranslateY);
888          m_contentLayer->setPosition(m_currentPosition.x(), m_currentPosition.y());
889          m_needsDisplay = false;
890      }
891 }
892 
syncCompositingState()893 void GraphicsLayerAndroid::syncCompositingState()
894 {
895     for (unsigned int i = 0; i < m_children.size(); i++) {
896         GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
897         layer->syncCompositingState();
898     }
899 
900     syncChildren();
901     syncMask();
902     syncPositionState();
903 
904     if (!gPaused || WTF::currentTime() >= gPausedDelay)
905         repaintAll();
906 }
907 
notifyClientAnimationStarted()908 void GraphicsLayerAndroid::notifyClientAnimationStarted()
909 {
910     for (unsigned int i = 0; i < m_children.size(); i++) {
911         GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
912         layer->notifyClientAnimationStarted();
913     }
914 
915     if (m_needsNotifyClient) {
916         if (client())
917             client()->notifyAnimationStarted(this, WTF::currentTime());
918         m_needsNotifyClient = false;
919     }
920 }
921 
922 } // namespace WebCore
923 
924 #endif // USE(ACCELERATED_COMPOSITING)
925