OSDN Git Service

Fix incorrect position when using CSS shadows, and use left/top over right/bottom...
[android-x86/external-webkit.git] / WebCore / platform / graphics / android / GraphicsLayerAndroid.cpp
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 "FloatRect.h"
25 #include "GraphicsContext.h"
26 #include "Image.h"
27 #include "Length.h"
28 #include "SkLayer.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 "SkCanvas.h"
36 #include "TransformationMatrix.h"
37 #include "TranslateTransformOperation.h"
38
39 #include <cutils/log.h>
40 #include <wtf/CurrentTime.h>
41 #include <wtf/text/CString.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;
64 inline int GraphicsLayerAndroid::instancesCount()
65 {
66     return gDebugGraphicsLayerAndroidInstances;
67 }
68
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
85 GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation()
86 {
87     return CompositingCoordinatesBottomUp;
88 }
89
90 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
91 {
92     return new GraphicsLayerAndroid(client);
93 }
94
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
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
133 GraphicsLayerAndroid::~GraphicsLayerAndroid()
134 {
135     m_contentLayer->unref();
136     gDebugGraphicsLayerAndroidInstances--;
137 }
138
139 void GraphicsLayerAndroid::setName(const String& name)
140 {
141     GraphicsLayer::setName(name);
142 }
143
144 NativeLayer GraphicsLayerAndroid::nativeLayer() const
145 {
146     LOG("(%x) nativeLayer", this);
147     return 0;
148 }
149
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
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
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
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
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
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
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
215 void GraphicsLayerAndroid::needsSyncChildren()
216 {
217     m_needsSyncChildren = true;
218     askForSync();
219 }
220
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         // We need to get the passed CSS properties for the element
233         SkLength left, top, right, bottom;
234         left = convertLength(view->style()->left());
235         top = convertLength(view->style()->top());
236         right = convertLength(view->style()->right());
237         bottom = convertLength(view->style()->bottom());
238
239         // We also need to get the margin...
240         SkLength marginLeft, marginTop, marginRight, marginBottom;
241         marginLeft = convertLength(view->style()->marginLeft());
242         marginTop = convertLength(view->style()->marginTop());
243         marginRight = convertLength(view->style()->marginRight());
244         marginBottom = convertLength(view->style()->marginBottom());
245
246         // The layer can be bigger than the element we want to draw;
247         // not only that, the layout rect of the element might also be
248         // different from the visible rect of that element (i.e. the element
249         // has a CSS shadow property -- the shadow is "outside" the element).
250         // We thus need to:
251         // 1/ get the size of the element (w,h), using the layoutOverflow rect
252         // 2/ pass the current offset of the painting relative to the layer
253         int w = view->rightLayoutOverflow() - view->leftLayoutOverflow();
254         int h = view->bottomLayoutOverflow() - view->topLayoutOverflow();
255         int paintingOffsetX = - offsetFromRenderer().width();
256         int paintingOffsetY = - offsetFromRenderer().height();
257
258         SkRect viewRect;
259         viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h);
260
261         m_contentLayer->setFixedPosition(left, top, right, bottom,
262                                          marginLeft, marginTop,
263                                          marginRight, marginBottom,
264                                          viewRect);
265     }
266 }
267
268 void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
269 {
270     m_currentPosition = point;
271     m_needsDisplay = true;
272 #ifdef LAYER_DEBUG_2
273     LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
274         this, point.x(), point.y(), m_currentPosition.x(), m_currentPosition.y(),
275         m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height());
276 #endif
277     updateFixedPosition();
278     askForSync();
279 }
280
281 void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point)
282 {
283     GraphicsLayer::setAnchorPoint(point);
284     m_contentLayer->setAnchorPoint(point.x(), point.y());
285     askForSync();
286 }
287
288 void GraphicsLayerAndroid::setSize(const FloatSize& size)
289 {
290     if ((size.width() != m_size.width())
291           || (size.height() != m_size.height())) {
292         MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height());
293         GraphicsLayer::setSize(size);
294         m_contentLayer->setSize(size.width(), size.height());
295         updateFixedPosition();
296         askForSync();
297     }
298 }
299
300 void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t)
301 {
302     TransformationMatrix::DecomposedType tDecomp;
303     t.decompose(tDecomp);
304     LOG("(%x) setTransform, translate (%.2f, %.2f), mpos(%.2f,%.2f)",
305         this, tDecomp.translateX, tDecomp.translateY,
306         m_position.x(), m_position.y());
307
308     if ((m_currentTranslateX != tDecomp.translateX)
309           || (m_currentTranslateY != tDecomp.translateY)) {
310         m_currentTranslateX = tDecomp.translateX;
311         m_currentTranslateY = tDecomp.translateY;
312         m_needsDisplay = true;
313         askForSync();
314     }
315 }
316
317 void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t)
318 {
319     if (t == m_childrenTransform)
320        return;
321     LOG("(%x) setChildrenTransform", this);
322
323     GraphicsLayer::setChildrenTransform(t);
324     for (unsigned int i = 0; i < m_children.size(); i++) {
325         GraphicsLayer* layer = m_children[i];
326         layer->setTransform(t);
327         if (layer->children().size())
328             layer->setChildrenTransform(t);
329     }
330     askForSync();
331 }
332
333 void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer)
334 {
335     if (layer == m_maskLayer)
336       return;
337
338     GraphicsLayer::setMaskLayer(layer);
339     m_needsSyncMask = true;
340     askForSync();
341 }
342
343 void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds)
344 {
345     GraphicsLayer::setMasksToBounds(masksToBounds);
346     m_needsSyncMask = true;
347     askForSync();
348 }
349
350 void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
351 {
352     GraphicsLayer::setDrawsContent(drawsContent);
353
354     if (m_drawsContent) {
355         m_haveContents = true;
356         setNeedsDisplay();
357     }
358     askForSync();
359 }
360
361 void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
362 {
363     LOG("(%x) setBackgroundColor", this);
364     GraphicsLayer::setBackgroundColor(color);
365     SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue());
366     m_contentLayer->setBackgroundColor(c);
367     m_haveContents = true;
368     askForSync();
369 }
370
371 void GraphicsLayerAndroid::clearBackgroundColor()
372 {
373     LOG("(%x) clearBackgroundColor", this);
374     GraphicsLayer::clearBackgroundColor();
375     askForSync();
376 }
377
378 void GraphicsLayerAndroid::setContentsOpaque(bool opaque)
379 {
380     LOG("(%x) setContentsOpaque (%d)", this, opaque);
381     GraphicsLayer::setContentsOpaque(opaque);
382     m_haveContents = true;
383     askForSync();
384 }
385
386 void GraphicsLayerAndroid::setOpacity(float opacity)
387 {
388     LOG("(%x) setOpacity: %.2f", this, opacity);
389     float clampedOpacity = max(0.0f, min(opacity, 1.0f));
390
391     if (clampedOpacity == m_opacity)
392         return;
393
394     MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
395         opacity, clampedOpacity, m_opacity);
396     GraphicsLayer::setOpacity(clampedOpacity);
397     m_contentLayer->setOpacity(clampedOpacity);
398     askForSync();
399 }
400
401 bool GraphicsLayerAndroid::repaintAll()
402 {
403      LOG("(%x) repaintAll", this);
404      bool ret = false;
405      for (unsigned int i = 0; i < m_children.size(); i++) {
406          GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
407          if (layer && layer->repaintAll())
408              ret = true;
409      }
410      int nbRects = m_invalidatedRects.size();
411
412      for (int i = 0; !gPaused && i < nbRects; i++) {
413          FloatRect rect = m_invalidatedRects[i];
414          if (repaint(rect))
415              ret = true;
416      }
417      if (!gPaused) {
418          m_needsRepaint = false;
419          m_invalidatedRects.clear();
420      }
421      return ret;
422 }
423
424 void GraphicsLayerAndroid::setNeedsDisplay()
425 {
426     LOG("(%x) setNeedsDisplay()", this);
427     FloatRect rect(0, 0, m_size.width(), m_size.height());
428     setNeedsDisplayInRect(rect);
429 }
430
431 void GraphicsLayerAndroid::setFrame(Frame* f)
432 {
433     m_frame = f;
434 }
435
436 void GraphicsLayerAndroid::sendImmediateRepaint()
437 {
438     LOG("(%x) sendImmediateRepaint()", this);
439     GraphicsLayerAndroid* rootGraphicsLayer = this;
440
441     while (rootGraphicsLayer->parent())
442         rootGraphicsLayer = static_cast<GraphicsLayerAndroid*>(rootGraphicsLayer->parent());
443
444     if (rootGraphicsLayer->m_frame
445         && rootGraphicsLayer->m_frame->view()) {
446         LayerAndroid* rootLayer = new LayerAndroid(true);
447         LayerAndroid* copyLayer = new LayerAndroid(*m_contentLayer);
448         rootLayer->addChild(copyLayer);
449         copyLayer->unref();
450         TLOG("(%x) sendImmediateRepaint, copy the layer, (%.2f,%.2f => %.2f,%.2f)",
451             this, m_contentLayer->getSize().width(), m_contentLayer->getSize().height(),
452             copyLayer->getSize().width(), copyLayer->getSize().height());
453         PlatformBridge::setUIRootLayer(m_frame->view(), rootLayer);
454         PlatformBridge::immediateRepaint(m_frame->view());
455     }
456 }
457
458 bool GraphicsLayerAndroid::repaint(const FloatRect& rect)
459 {
460     LOG("(%x) repaint(%.2f,%.2f,%.2f,%.2f), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
461         this, rect.x(), rect.y(), rect.width(), rect.height(),
462         gPaused, m_needsRepaint, m_haveContents);
463
464     if (!gPaused && m_haveContents && m_needsRepaint && !m_haveImage) {
465         SkAutoPictureRecord arp(m_contentLayer->recordContext(), m_size.width(), m_size.height());
466         SkCanvas* recordingCanvas = arp.getRecordingCanvas();
467
468         if (!recordingCanvas)
469             return false;
470
471         if ((rect.width() > 0.5) && (rect.height() > 0.5)) {
472             IntRect r((int)rect.x(), (int)rect.y(),
473                   (int)rect.width(), (int)rect.height());
474
475             PlatformGraphicsContext pgc(recordingCanvas, 0);
476             GraphicsContext gc(&pgc);
477
478             // with SkPicture, we request the entire layer's content.
479             r.setX(0);
480             r.setY(0);
481             r.setWidth(m_contentLayer->getWidth());
482             r.setHeight(m_contentLayer->getHeight());
483             paintGraphicsLayerContents(gc, r);
484
485             TLOG("(%x) repaint(%.2f,%.2f,%.2f,%.2f) on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
486                 this, rect.x(), rect.y(), rect.width(),
487                 rect.height(), m_size.width(), m_size.height(),
488                 m_contentLayer->getPosition().fX,
489                 m_contentLayer->getPosition().fY,
490                 m_contentLayer->getSize().width(),
491                 m_contentLayer->getSize().height());
492         }
493         return true;
494     }
495     return false;
496 }
497
498 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
499 {
500     for (unsigned int i = 0; i < m_children.size(); i++) {
501         GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
502         if (layer) {
503             FloatRect childrenRect(m_position.x() + m_translateX + rect.x(),
504                                    m_position.y() + m_translateY + rect.y(),
505                                    rect.width(), rect.height());
506             layer->setNeedsDisplayInRect(childrenRect);
507         }
508     }
509     if (!m_haveImage && !drawsContent()) {
510         LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
511             this, rect.x(), rect.y(), rect.width(), rect.height());
512         return;
513     }
514
515     const size_t maxDirtyRects = 8;
516     for (size_t i = 0; i < m_invalidatedRects.size(); ++i) {
517         if (m_invalidatedRects[i].contains(rect))
518             return;
519     }
520
521 #ifdef LAYER_DEBUG
522     LOG("(%x) setNeedsDisplayInRect(%d) - (%.2f, %.2f, %.2f, %.2f)", this,
523         m_needsRepaint, rect.x(), rect.y(), rect.width(), rect.height());
524 #endif
525
526     if (m_invalidatedRects.size() < maxDirtyRects)
527         m_invalidatedRects.append(rect);
528     else
529         m_invalidatedRects[0].unite(rect);
530
531     m_needsRepaint = true;
532     askForSync();
533 }
534
535 void GraphicsLayerAndroid::pauseDisplay(bool state)
536 {
537     gPaused = state;
538     if (gPaused)
539         gPausedDelay = WTF::currentTime() + 1;
540 }
541
542 bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
543                                         const IntSize& boxSize,
544                                         const Animation* anim,
545                                         const String& keyframesName,
546                                         double beginTime)
547 {
548     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() != 2)
549     return false;
550
551     bool createdAnimations = false;
552     if (valueList.property() == AnimatedPropertyWebkitTransform) {
553         createdAnimations = createTransformAnimationsFromKeyframes(valueList,
554                                                                    anim,
555                                                                    keyframesName,
556                                                                    beginTime,
557                                                                    boxSize);
558     } else {
559         createdAnimations = createAnimationFromKeyframes(valueList,
560                                                          anim,
561                                                          keyframesName,
562                                                          beginTime);
563     }
564     askForSync();
565     return createdAnimations;
566 }
567
568 bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList,
569      const Animation* animation, const String& keyframesName, double beginTime)
570 {
571     bool isKeyframe = valueList.size() > 2;
572     TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
573         isKeyframe, keyframesName.latin1().data(), beginTime);
574     // TODO: handles keyframe animations correctly
575
576     switch (valueList.property()) {
577     case AnimatedPropertyInvalid: break;
578     case AnimatedPropertyWebkitTransform: break;
579     case AnimatedPropertyBackgroundColor: break;
580     case AnimatedPropertyOpacity: {
581         MLOG("ANIMATEDPROPERTYOPACITY");
582         const FloatAnimationValue* startVal =
583             static_cast<const FloatAnimationValue*>(valueList.at(0));
584         const FloatAnimationValue* endVal =
585             static_cast<const FloatAnimationValue*>(valueList.at(1));
586         RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(startVal->value(),
587                                                                                endVal->value(),
588                                                                                animation,
589                                                                                beginTime);
590         if (keyframesName.isEmpty())
591             anim->setName(propertyIdToString(valueList.property()));
592         else
593             anim->setName(keyframesName);
594
595         m_contentLayer->addAnimation(anim.release());
596         needsNotifyClient();
597         return true;
598     } break;
599     }
600     return false;
601 }
602
603 void GraphicsLayerAndroid::needsNotifyClient()
604 {
605     m_needsNotifyClient = true;
606     askForSync();
607 }
608
609 bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList,
610                                                                   const Animation* animation,
611                                                                   const String& keyframesName,
612                                                                   double beginTime,
613                                                                   const IntSize& boxSize)
614 {
615     ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
616     TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
617         keyframesName.latin1().data(), beginTime);
618
619     TransformOperationList functionList;
620     bool listsMatch, hasBigRotation;
621     fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation);
622
623     // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation.
624     // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation
625     // if that's not true as well.
626
627     bool isMatrixAnimation = !listsMatch;
628     size_t numAnimations = isMatrixAnimation ? 1 : functionList.size();
629     bool isKeyframe = valueList.size() > 2;
630
631     float fromTranslateX = 0;
632     float fromTranslateY = 0;
633     float fromTranslateZ = 0;
634     float toTranslateX   = 0;
635     float toTranslateY   = 0;
636     float toTranslateZ   = 0;
637     float fromAngle      = 0;
638     float toAngle        = 0;
639     float fromScaleX     = 1;
640     float fromScaleY     = 1;
641     float fromScaleZ     = 1;
642     float toScaleX       = 1;
643     float toScaleY       = 1;
644     float toScaleZ       = 1;
645
646     bool doTranslation = false;
647     bool doRotation = false;
648     bool doScaling = false;
649
650     TLOG("(%x) animateTransform, valueList(%d) functionList(%d) duration(%.2f)", this,
651         valueList.size(), functionList.size(), animation->duration());
652
653     // FIXME: add support for the translate 3d operations (when
654     // we'll have an OpenGL backend)
655
656     for (unsigned int i = 0; i < valueList.size(); i++) {
657         const TransformOperations* operation = ((TransformAnimationValue*)valueList.at(i))->value();
658         Vector<RefPtr<TransformOperation> > ops = operation->operations();
659         TLOG("(%x) animateTransform, dealing with the %d operation, with %d ops", this, i, ops.size());
660         for (unsigned int j = 0; j < ops.size(); j++) {
661             TransformOperation* op = ops[j].get();
662             TLOG("(%x) animateTransform, dealing with the %d:%d operation, current op: %d (translate is %d, rotate %d, scale %d)",
663                 this, i, j, op->getOperationType(), TransformOperation::TRANSLATE, TransformOperation::ROTATE, TransformOperation::SCALE);
664             if ((op->getOperationType() == TransformOperation::TRANSLATE) ||
665                 (op->getOperationType() == TransformOperation::TRANSLATE_3D)) {
666                 TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
667                 IntSize bounds(m_size.width(), m_size.height());
668                 float x = translateOperation->x(bounds);
669                 float y = translateOperation->y(bounds);
670                 float z = translateOperation->z(bounds);
671                 if (!i) {
672                     fromTranslateX = x;
673                     fromTranslateY = y;
674                     fromTranslateZ = z;
675                 } else {
676                     toTranslateX = x;
677                     toTranslateY = y;
678                     toTranslateZ = z;
679                 }
680                 TLOG("(%x) animateTransform, the %d operation is a translation(%.2f,%.2f,%.2f)",
681                     this, j, x, y, z);
682                 doTranslation = true;
683             } else if (op->getOperationType() == TransformOperation::TRANSLATE_X) {
684                 TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
685                 IntSize bounds(m_size.width(), m_size.height());
686                 float x = translateOperation->x(bounds);
687                 if (!i)
688                     fromTranslateX = x;
689                 else
690                     toTranslateX = x;
691                 TLOG("(%x) animateTransform, the %d operation is a translation_x(%.2f)",
692                     this, j, x);
693                 doTranslation = true;
694             } else if (op->getOperationType() == TransformOperation::TRANSLATE_Y) {
695                 TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
696                 IntSize bounds(m_size.width(), m_size.height());
697                 float y = translateOperation->y(bounds);
698                 if (!i)
699                     fromTranslateY = y;
700                 else
701                     toTranslateY = y;
702                 TLOG("(%x) animateTransform, the %d operation is a translation_y(%.2f)",
703                     this, j, y);
704                 doTranslation = true;
705             } else if (op->getOperationType() == TransformOperation::TRANSLATE_Z) {
706                 TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
707                 IntSize bounds(m_size.width(), m_size.height());
708                 float z = translateOperation->z(bounds);
709                 if (!i)
710                     fromTranslateZ = z;
711                 else
712                     toTranslateZ = z;
713                 TLOG("(%x) animateTransform, the %d operation is a translation_z(%.2f)",
714                     this, j, z);
715                 doTranslation = true;
716             } else if ((op->getOperationType() == TransformOperation::ROTATE)
717                           || (op->getOperationType() == TransformOperation::ROTATE_X)
718                           || (op->getOperationType() == TransformOperation::ROTATE_Y)) {
719                 LOG("(%x) animateTransform, the %d operation is a rotation", this, j);
720                 RotateTransformOperation* rotateOperation = (RotateTransformOperation*) op;
721                 float angle = rotateOperation->angle();
722                 TLOG("(%x) animateTransform, the %d operation is a rotation (%d), of angle %.2f",
723                     this, j, op->getOperationType(), angle);
724
725                 if (!i)
726                     fromAngle = angle;
727                 else
728                     toAngle = angle;
729                 doRotation = true;
730             } else if (op->getOperationType() == TransformOperation::SCALE_X) {
731                 ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
732                 if (!i)
733                     fromScaleX = scaleOperation->x();
734                 else
735                     toScaleX = scaleOperation->x();
736                 doScaling = true;
737             } else if (op->getOperationType() == TransformOperation::SCALE_Y) {
738                 ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
739                 if (!i)
740                     fromScaleY = scaleOperation->y();
741                 else
742                     toScaleY = scaleOperation->y();
743                 doScaling = true;
744             } else if (op->getOperationType() == TransformOperation::SCALE_Z) {
745                 ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
746                 if (!i)
747                     fromScaleZ = scaleOperation->z();
748                 else
749                     toScaleZ = scaleOperation->z();
750                 doScaling = true;
751             } else if (op->getOperationType() == TransformOperation::SCALE) {
752                 ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
753                 if (!i) {
754                     fromScaleX = scaleOperation->x();
755                     fromScaleY = scaleOperation->y();
756                     fromScaleZ = scaleOperation->z();
757                 } else {
758                     toScaleX = scaleOperation->x();
759                     toScaleY = scaleOperation->y();
760                     toScaleZ = scaleOperation->z();
761                 }
762                 doScaling = true;
763             } else {
764                 TLOG("(%x) animateTransform, the %d operation is not a rotation (%d)",
765                     this, j, op->getOperationType());
766             }
767         }
768     }
769
770     RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation, beginTime);
771
772     if (keyframesName.isEmpty())
773         anim->setName(propertyIdToString(valueList.property()));
774     else
775         anim->setName(keyframesName);
776
777     anim->setOriginalPosition(m_position);
778
779     if (doTranslation)
780         anim->setTranslation(fromTranslateX, fromTranslateY, fromTranslateZ,
781                          toTranslateX, toTranslateY, toTranslateZ);
782     if (doRotation)
783         anim->setRotation(fromAngle, toAngle);
784     if (doScaling)
785         anim->setScale(fromScaleX, fromScaleY, fromScaleZ,
786                        toScaleX, toScaleY, toScaleZ);
787     m_contentLayer->addAnimation(anim.release());
788
789     needsNotifyClient();
790     return true;
791 }
792
793 void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
794 {
795     TLOG("NRO removeAnimationsForProperty(%d)", anID);
796     m_contentLayer->removeAnimation(propertyIdToString(anID));
797     askForSync();
798 }
799
800 void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
801 {
802     TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data());
803     m_contentLayer->removeAnimation(keyframesName);
804     askForSync();
805 }
806
807 void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
808 {
809     TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data());
810 }
811
812 void GraphicsLayerAndroid::suspendAnimations(double time)
813 {
814     TLOG("NRO suspendAnimations(%.2f)", time);
815 }
816
817 void GraphicsLayerAndroid::resumeAnimations()
818 {
819     TLOG("NRO resumeAnimations()");
820 }
821
822 void GraphicsLayerAndroid::setContentsToImage(Image* image)
823 {
824     TLOG("(%x) setContentsToImage", this, image);
825     if (image) {
826         m_haveContents = true;
827         m_haveImage = true;
828         m_contentLayer->setContentsImage(image->nativeImageForCurrentFrame());
829         setNeedsDisplay();
830         askForSync();
831     }
832 }
833
834 PlatformLayer* GraphicsLayerAndroid::platformLayer() const
835 {
836     LOG("platformLayer");
837     return (PlatformLayer*) m_contentLayer;
838 }
839
840 #ifndef NDEBUG
841 void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color)
842 {
843 }
844
845 void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth)
846 {
847 }
848 #endif
849
850 void GraphicsLayerAndroid::setZPosition(float position)
851 {
852     LOG("(%x) setZPosition: %.2f", this, position);
853     GraphicsLayer::setZPosition(position);
854     askForSync();
855 }
856
857 void GraphicsLayerAndroid::askForSync()
858 {
859     if (m_client)
860         m_client->notifySyncRequired(this);
861 }
862
863 void GraphicsLayerAndroid::syncChildren()
864 {
865     if (m_needsSyncChildren) {
866         m_contentLayer->removeChildren();
867         for (unsigned int i = 0; i < m_children.size(); i++) {
868             m_contentLayer->addChild(
869                 (static_cast<GraphicsLayerAndroid*>(m_children[i]))->contentLayer());
870         }
871         m_needsSyncChildren = false;
872     }
873 }
874
875 void GraphicsLayerAndroid::syncMask()
876 {
877     if (m_needsSyncMask) {
878         if (m_maskLayer) {
879             GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_maskLayer);
880             LayerAndroid* mask = reinterpret_cast<LayerAndroid*>(layer->platformLayer());
881             m_contentLayer->setMaskLayer(mask);
882         } else
883             m_contentLayer->setMaskLayer(0);
884
885         m_contentLayer->setMasksToBounds(m_masksToBounds);
886         m_needsSyncMask = false;
887     }
888 }
889
890 void GraphicsLayerAndroid::syncPositionState()
891 {
892      if (m_needsDisplay) {
893          m_translateX = m_currentTranslateX;
894          m_translateY = m_currentTranslateY;
895          m_position = m_currentPosition;
896          m_contentLayer->setTranslation(m_currentTranslateX, m_currentTranslateY);
897          m_contentLayer->setPosition(m_currentPosition.x(), m_currentPosition.y());
898          m_needsDisplay = false;
899      }
900 }
901
902 void GraphicsLayerAndroid::syncCompositingState()
903 {
904     for (unsigned int i = 0; i < m_children.size(); i++) {
905         GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
906         layer->syncCompositingState();
907     }
908
909     syncChildren();
910     syncMask();
911     syncPositionState();
912
913     if (!gPaused || WTF::currentTime() >= gPausedDelay)
914         repaintAll();
915 }
916
917 void GraphicsLayerAndroid::notifyClientAnimationStarted()
918 {
919     for (unsigned int i = 0; i < m_children.size(); i++) {
920         GraphicsLayerAndroid* layer = static_cast<GraphicsLayerAndroid*>(m_children[i]);
921         layer->notifyClientAnimationStarted();
922     }
923
924     if (m_needsNotifyClient) {
925         if (client())
926             client()->notifyAnimationStarted(this, WTF::currentTime());
927         m_needsNotifyClient = false;
928     }
929 }
930
931 } // namespace WebCore
932
933 #endif // USE(ACCELERATED_COMPOSITING)