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