OSDN Git Service

am b245689d: (-s ours) am b39b82ea: am e61ae1cb: DO NOT MERGE: Partially revert chang...
[android-x86/external-webkit.git] / Source / 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 "MediaLayer.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 "ScrollableLayerAndroid.h"
36 #include "SkCanvas.h"
37 #include "SkLayer.h"
38 #include "TransformationMatrix.h"
39 #include "TranslateTransformOperation.h"
40
41 #include <cutils/log.h>
42 #include <wtf/CurrentTime.h>
43 #include <wtf/text/CString.h>
44
45 #undef LOG
46 #define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
47 #define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
48 #define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
49
50 #undef LOG
51 #define LOG(...)
52 #undef MLOG
53 #define MLOG(...)
54 #undef TLOG
55 #define TLOG(...)
56 #undef LAYER_DEBUG
57
58 using namespace std;
59
60 static bool gPaused;
61 static double gPausedDelay;
62
63 namespace WebCore {
64
65 static int gDebugGraphicsLayerAndroidInstances = 0;
66 inline int GraphicsLayerAndroid::instancesCount()
67 {
68     return gDebugGraphicsLayerAndroidInstances;
69 }
70
71 static String propertyIdToString(AnimatedPropertyID property)
72 {
73     switch (property) {
74     case AnimatedPropertyWebkitTransform:
75         return "transform";
76     case AnimatedPropertyOpacity:
77         return "opacity";
78     case AnimatedPropertyBackgroundColor:
79         return "backgroundColor";
80     case AnimatedPropertyInvalid:
81         ASSERT_NOT_REACHED();
82     }
83     ASSERT_NOT_REACHED();
84     return "";
85 }
86
87 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
88 {
89     return new GraphicsLayerAndroid(client);
90 }
91
92 SkLength convertLength(Length len)
93 {
94     SkLength length;
95     length.type = SkLength::Undefined;
96     length.value = 0;
97     if (len.type() == WebCore::Percent) {
98         length.type = SkLength::Percent;
99         length.value = len.percent();
100     }
101     if (len.type() == WebCore::Fixed) {
102         length.type = SkLength::Fixed;
103         length.value = len.value();
104     }
105     return length;
106 }
107
108 static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client)
109 {
110     if (client)
111         return static_cast<RenderLayerBacking*>(client)->owningLayer();
112     return 0;
113 }
114
115 GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
116     GraphicsLayer(client),
117     m_needsSyncChildren(false),
118     m_needsSyncMask(false),
119     m_needsRepaint(false),
120     m_needsNotifyClient(false),
121     m_haveContents(false),
122     m_haveImage(false),
123     m_newImage(false),
124     m_imageRef(0),
125     m_foregroundLayer(0),
126     m_foregroundClipLayer(0)
127 {
128     RenderLayer* renderLayer = renderLayerFromClient(m_client);
129     m_contentLayer = new LayerAndroid(renderLayer);
130     gDebugGraphicsLayerAndroidInstances++;
131 }
132
133 GraphicsLayerAndroid::~GraphicsLayerAndroid()
134 {
135     m_contentLayer->unref();
136     SkSafeUnref(m_foregroundLayer);
137     SkSafeUnref(m_foregroundClipLayer);
138     gDebugGraphicsLayerAndroidInstances--;
139 }
140
141 void GraphicsLayerAndroid::setName(const String& name)
142 {
143     GraphicsLayer::setName(name);
144 }
145
146 NativeLayer GraphicsLayerAndroid::nativeLayer() const
147 {
148     LOG("(%x) nativeLayer", this);
149     return 0;
150 }
151
152 bool GraphicsLayerAndroid::setChildren(const Vector<GraphicsLayer*>& children)
153 {
154     bool childrenChanged = GraphicsLayer::setChildren(children);
155     if (childrenChanged) {
156         m_needsSyncChildren = true;
157         askForSync();
158     }
159
160     return childrenChanged;
161 }
162
163 void GraphicsLayerAndroid::addChild(GraphicsLayer* childLayer)
164 {
165 #ifndef NDEBUG
166     const String& name = childLayer->name();
167     LOG("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data());
168 #endif
169     GraphicsLayer::addChild(childLayer);
170     m_needsSyncChildren = true;
171     askForSync();
172 }
173
174 void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index)
175 {
176     LOG("(%x) addChild %x AtIndex %d", this, childLayer, index);
177     GraphicsLayer::addChildAtIndex(childLayer, index);
178     m_needsSyncChildren = true;
179     askForSync();
180 }
181
182 void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
183 {
184     LOG("(%x) addChild %x Below %x", this, childLayer, sibling);
185     GraphicsLayer::addChildBelow(childLayer, sibling);
186     m_needsSyncChildren = true;
187     askForSync();
188 }
189
190 void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
191 {
192     LOG("(%x) addChild %x Above %x", this, childLayer, sibling);
193     GraphicsLayer::addChildAbove(childLayer, sibling);
194     m_needsSyncChildren = true;
195     askForSync();
196 }
197
198 bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
199 {
200     LOG("(%x) replaceChild %x by %x", this, oldChild, newChild);
201     bool ret = GraphicsLayer::replaceChild(oldChild, newChild);
202     if (ret) {
203         m_needsSyncChildren = true;
204         askForSync();
205     }
206     return ret;
207 }
208
209 void GraphicsLayerAndroid::removeFromParent()
210 {
211     LOG("(%x) removeFromParent()", this);
212     GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
213     GraphicsLayer::removeFromParent();
214     // Update the parent's children.
215     if (parent) {
216         parent->m_needsSyncChildren = true;
217         askForSync();
218     }
219 }
220
221 void GraphicsLayerAndroid::updateFixedPosition()
222 {
223     if (!m_client)
224         return;
225
226     RenderLayer* renderLayer = renderLayerFromClient(m_client);
227     RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
228
229     // We will need the Iframe flag in the LayerAndroid tree for fixed position
230     if (view && view->isRenderIFrame())
231         m_contentLayer->setIsIframe(true);
232     // If we are a fixed position layer, just set it
233     if (view->isPositioned() && view->style()->position() == FixedPosition) {
234         // We need to get the passed CSS properties for the element
235         SkLength left, top, right, bottom;
236         left = convertLength(view->style()->left());
237         top = convertLength(view->style()->top());
238         right = convertLength(view->style()->right());
239         bottom = convertLength(view->style()->bottom());
240
241         // We also need to get the margin...
242         SkLength marginLeft, marginTop, marginRight, marginBottom;
243         marginLeft = convertLength(view->style()->marginLeft());
244         marginTop = convertLength(view->style()->marginTop());
245         marginRight = convertLength(view->style()->marginRight());
246         marginBottom = convertLength(view->style()->marginBottom());
247
248         // The layer can be bigger than the element we want to draw;
249         // not only that, the layout rect of the element might also be
250         // different from the visible rect of that element (i.e. the element
251         // has a CSS shadow property -- the shadow is "outside" the element).
252         // We thus need to:
253         // 1/ get the size of the element (w,h), using the layoutOverflow rect
254         // 2/ pass the current offset of the painting relative to the layer
255         int w = view->rightLayoutOverflow() - view->leftLayoutOverflow();
256         int h = view->bottomLayoutOverflow() - view->topLayoutOverflow();
257         int paintingOffsetX = - offsetFromRenderer().width();
258         int paintingOffsetY = - offsetFromRenderer().height();
259
260         SkRect viewRect;
261         viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h);
262         IntPoint renderLayerPos(renderLayer->x(), renderLayer->y());
263         m_contentLayer->setFixedPosition(left, top, right, bottom,
264                                          marginLeft, marginTop,
265                                          marginRight, marginBottom,
266                                          renderLayerPos,
267                                          viewRect);
268     }
269 }
270
271 void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
272 {
273     if (point == m_position)
274         return;
275
276     GraphicsLayer::setPosition(point);
277
278 #ifdef LAYER_DEBUG_2
279     LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
280         this, point.x(), point.y(), m_position.x(), m_position.y(),
281         m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height());
282 #endif
283     m_contentLayer->setPosition(point.x(), point.y());
284     askForSync();
285 }
286
287 void GraphicsLayerAndroid::setPreserves3D(bool preserves3D)
288 {
289     if (preserves3D == m_preserves3D)
290         return;
291
292     GraphicsLayer::setPreserves3D(preserves3D);
293     m_contentLayer->setPreserves3D(preserves3D);
294     askForSync();
295 }
296
297 void GraphicsLayerAndroid::setAnchorPoint(const FloatPoint3D& point)
298 {
299     if (point == m_anchorPoint)
300         return;
301     GraphicsLayer::setAnchorPoint(point);
302     m_contentLayer->setAnchorPoint(point.x(), point.y());
303     m_contentLayer->setAnchorPointZ(point.z());
304     askForSync();
305 }
306
307 void GraphicsLayerAndroid::setSize(const FloatSize& size)
308 {
309     if (size == m_size)
310         return;
311     MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height());
312     GraphicsLayer::setSize(size);
313
314     // If it is a media layer the size may have changed as a result of the media
315     // element (e.g. plugin) gaining focus. Therefore, we must sync the size of
316     // the focus' outline so that our UI thread can draw accordingly.
317     if (m_contentLayer->isMedia() && m_client) {
318         RenderLayer* layer = renderLayerFromClient(m_client);
319         RenderBox* box = layer->renderBox();
320         int outline = box->view()->maximalOutlineSize();
321         static_cast<MediaLayer*>(m_contentLayer)->setOutlineSize(outline);
322         LOG("Media Outline: %d %p %p %p", outline, m_client, layer, box);
323         LOG("Media Size: %g,%g", size.width(), size.height());
324     }
325
326     m_contentLayer->setSize(size.width(), size.height());
327     askForSync();
328 }
329
330 void GraphicsLayerAndroid::setBackfaceVisibility(bool b)
331 {
332     GraphicsLayer::setBackfaceVisibility(b);
333     m_contentLayer->setBackfaceVisibility(b);
334     askForSync();
335 }
336
337 void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t)
338 {
339     if (t == m_transform)
340         return;
341
342     GraphicsLayer::setTransform(t);
343     m_contentLayer->setTransform(t);
344     askForSync();
345 }
346
347 void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t)
348 {
349     if (t == m_childrenTransform)
350        return;
351     LOG("(%x) setChildrenTransform", this);
352
353     GraphicsLayer::setChildrenTransform(t);
354     m_contentLayer->setChildrenTransform(t);
355     for (unsigned int i = 0; i < m_children.size(); i++) {
356         GraphicsLayer* layer = m_children[i];
357         layer->setTransform(t);
358         if (layer->children().size())
359             layer->setChildrenTransform(t);
360     }
361     askForSync();
362 }
363
364 void GraphicsLayerAndroid::setMaskLayer(GraphicsLayer* layer)
365 {
366     if (layer == m_maskLayer)
367         return;
368
369     GraphicsLayer::setMaskLayer(layer);
370     m_needsSyncMask = true;
371     askForSync();
372 }
373
374 void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds)
375 {
376     if (masksToBounds == m_masksToBounds)
377         return;
378     GraphicsLayer::setMasksToBounds(masksToBounds);
379     m_needsSyncMask = true;
380     askForSync();
381 }
382
383 void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
384 {
385     if (drawsContent == m_drawsContent)
386         return;
387     GraphicsLayer::setDrawsContent(drawsContent);
388     if (m_drawsContent) {
389         m_haveContents = true;
390         setNeedsDisplay();
391     }
392     askForSync();
393 }
394
395 void GraphicsLayerAndroid::setBackgroundColor(const Color& color)
396 {
397     if (color == m_backgroundColor)
398         return;
399     LOG("(%x) setBackgroundColor", this);
400     GraphicsLayer::setBackgroundColor(color);
401     SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue());
402     m_contentLayer->setBackgroundColor(c);
403     m_haveContents = true;
404     askForSync();
405 }
406
407 void GraphicsLayerAndroid::clearBackgroundColor()
408 {
409     LOG("(%x) clearBackgroundColor", this);
410     GraphicsLayer::clearBackgroundColor();
411     askForSync();
412 }
413
414 void GraphicsLayerAndroid::setContentsOpaque(bool opaque)
415 {
416     if (opaque == m_contentsOpaque)
417         return;
418     LOG("(%x) setContentsOpaque (%d)", this, opaque);
419     GraphicsLayer::setContentsOpaque(opaque);
420     m_haveContents = true;
421     askForSync();
422 }
423
424 void GraphicsLayerAndroid::setOpacity(float opacity)
425 {
426     LOG("(%x) setOpacity: %.2f", this, opacity);
427     float clampedOpacity = max(0.0f, min(opacity, 1.0f));
428
429     if (clampedOpacity == m_opacity)
430         return;
431
432     MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
433         opacity, clampedOpacity, m_opacity);
434     GraphicsLayer::setOpacity(clampedOpacity);
435     m_contentLayer->setOpacity(clampedOpacity);
436     askForSync();
437 }
438
439 void GraphicsLayerAndroid::setNeedsDisplay()
440 {
441     LOG("(%x) setNeedsDisplay()", this);
442     FloatRect rect(0, 0, m_size.width(), m_size.height());
443     setNeedsDisplayInRect(rect);
444 }
445
446 // Helper to set and clear the painting phase as well as auto restore the
447 // original phase.
448 class PaintingPhase {
449 public:
450     PaintingPhase(GraphicsLayer* layer)
451         : m_layer(layer)
452         , m_originalPhase(layer->paintingPhase()) {}
453
454     ~PaintingPhase()
455     {
456         m_layer->setPaintingPhase(m_originalPhase);
457     }
458
459     void set(GraphicsLayerPaintingPhase phase)
460     {
461         m_layer->setPaintingPhase(phase);
462     }
463
464     void clear(GraphicsLayerPaintingPhase phase)
465     {
466         m_layer->setPaintingPhase(
467                 (GraphicsLayerPaintingPhase) (m_originalPhase & ~phase));
468     }
469 private:
470     GraphicsLayer* m_layer;
471     GraphicsLayerPaintingPhase m_originalPhase;
472 };
473
474 void GraphicsLayerAndroid::updateScrollingLayers()
475 {
476 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
477     RenderLayer* layer = renderLayerFromClient(m_client);
478     if (!layer || !m_haveContents)
479         return;
480     bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable();
481     bool layerNeedsOverflow = layer->hasOverflowScroll();
482     bool iframeNeedsOverflow = layer->isRootLayer() &&
483         layer->renderer()->frame()->ownerRenderer() &&
484         layer->renderer()->frame()->view()->hasOverflowScroll();
485
486     if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) {
487         // Already has overflow layers.
488         return;
489     }
490     if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) {
491         // Does not need overflow layers.
492         return;
493     }
494     if (layerNeedsOverflow || iframeNeedsOverflow) {
495         ASSERT(!hasOverflowScroll);
496         if (layerNeedsOverflow) {
497             ASSERT(!m_foregroundLayer && !m_foregroundClipLayer);
498             m_foregroundLayer = new ScrollableLayerAndroid(layer);
499             m_foregroundClipLayer = new LayerAndroid(layer);
500             m_foregroundClipLayer->setMasksToBounds(true);
501             m_foregroundClipLayer->addChild(m_foregroundLayer);
502             m_contentLayer->addChild(m_foregroundClipLayer);
503         } else {
504             ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable());
505             // No need to copy the children as they will be removed and synced.
506             m_contentLayer->removeChildren();
507             // Replace the content layer with a scrollable layer.
508             LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer);
509             m_contentLayer->unref();
510             m_contentLayer = layer;
511             if (m_parent) {
512                 // The content layer has changed so the parent needs to sync
513                 // children.
514                 static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
515             }
516         }
517         // Need to rebuild our children based on the new structure.
518         m_needsSyncChildren = true;
519     } else {
520         ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow);
521         ASSERT(m_contentLayer);
522         // Remove the foreground layers.
523         if (m_foregroundLayer) {
524             m_foregroundLayer->unref();
525             m_foregroundLayer = 0;
526             m_foregroundClipLayer->unref();
527             m_foregroundClipLayer = 0;
528         }
529         // No need to copy over children.
530         m_contentLayer->removeChildren();
531         LayerAndroid* layer = new LayerAndroid(*m_contentLayer);
532         m_contentLayer->unref();
533         m_contentLayer = layer;
534         if (m_parent) {
535             // The content layer has changed so the parent needs to sync
536             // children.
537             static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
538         }
539         // Children are all re-parented.
540         m_needsSyncChildren = true;
541     }
542 #endif
543 }
544
545 bool GraphicsLayerAndroid::repaint()
546 {
547     LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
548         this, gPaused, m_needsRepaint, m_haveContents);
549
550     if (!gPaused && m_haveContents && m_needsRepaint && !m_haveImage) {
551         // with SkPicture, we request the entire layer's content.
552         IntRect layerBounds(0, 0, m_size.width(), m_size.height());
553
554         RenderLayer* layer = renderLayerFromClient(m_client);
555         if (m_foregroundLayer) {
556             PaintingPhase phase(this);
557             // Paint the background into a separate context.
558             phase.set(GraphicsLayerPaintBackground);
559             if (!paintContext(m_contentLayer->recordContext(), layerBounds))
560                 return false;
561
562             // Construct the foreground layer and draw.
563             RenderBox* box = layer->renderBox();
564             int outline = box->view()->maximalOutlineSize();
565             IntRect contentsRect(0, 0,
566                                  box->borderLeft() + box->borderRight() + layer->scrollWidth(),
567                                  box->borderTop() + box->borderBottom() + layer->scrollHeight());
568             contentsRect.inflate(outline);
569             // Update the foreground layer size.
570             m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height());
571             // Paint everything else into the main recording canvas.
572             phase.clear(GraphicsLayerPaintBackground);
573
574             // Paint at 0,0.
575             IntSize scroll = layer->scrolledContentOffset();
576             layer->scrollToOffset(0, 0, true, false);
577             // At this point, it doesn't matter if painting failed.
578             (void) paintContext(m_foregroundLayer->recordContext(), contentsRect);
579             layer->scrollToOffset(scroll.width(), scroll.height(), true, false);
580
581             // Construct the clip layer for masking the contents.
582             IntRect clip = layer->renderer()->absoluteBoundingBoxRect();
583             // absoluteBoundingBoxRect does not include the outline so we need
584             // to offset the position.
585             int x = box->borderLeft() + outline;
586             int y = box->borderTop() + outline;
587             int width = clip.width() - box->borderLeft() - box->borderRight();
588             int height = clip.height() - box->borderTop() - box->borderBottom();
589             m_foregroundClipLayer->setPosition(x, y);
590             m_foregroundClipLayer->setSize(width, height);
591
592             // Need to offset the foreground layer by the clip layer in order
593             // for the contents to be in the correct position.
594             m_foregroundLayer->setPosition(-x, -y);
595             // Set the scrollable bounds of the layer.
596             m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height());
597             m_foregroundLayer->needsRepaint();
598         } else {
599             // If there is no contents clip, we can draw everything into one
600             // picture.
601             if (!paintContext(m_contentLayer->recordContext(), layerBounds))
602                 return false;
603             // Check for a scrollable iframe and report the scrolling
604             // limits based on the view size.
605             if (m_contentLayer->contentIsScrollable()) {
606                 FrameView* view = layer->renderer()->frame()->view();
607                 static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits(
608                     m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight());
609             }
610         }
611
612         LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
613             this, m_size.width(), m_size.height(),
614             m_contentLayer->getPosition().fX,
615             m_contentLayer->getPosition().fY,
616             m_contentLayer->getSize().width(),
617             m_contentLayer->getSize().height());
618
619         m_contentLayer->needsRepaint();
620         m_needsRepaint = false;
621         m_invalidatedRects.clear();
622
623         return true;
624     }
625     if (m_needsRepaint && m_haveImage && m_newImage) {
626         // We need to tell the GL thread that we will need to repaint the
627         // texture. Only do so if we effectively have a new image!
628         m_contentLayer->needsRepaint();
629         m_newImage = false;
630         m_needsRepaint = false;
631         return true;
632     }
633     return false;
634 }
635
636 bool GraphicsLayerAndroid::paintContext(SkPicture* context,
637                                         const IntRect& rect)
638 {
639     SkAutoPictureRecord arp(context, rect.width(), rect.height());
640     SkCanvas* canvas = arp.getRecordingCanvas();
641
642     if (!canvas)
643         return false;
644
645     PlatformGraphicsContext platformContext(canvas, 0);
646     GraphicsContext graphicsContext(&platformContext);
647
648     paintGraphicsLayerContents(graphicsContext, rect);
649     return true;
650 }
651
652 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
653 {
654     for (unsigned int i = 0; i < m_children.size(); i++) {
655         GraphicsLayer* layer = m_children[i];
656         if (layer) {
657            FloatRect childrenRect = m_transform.mapRect(rect);
658            layer->setNeedsDisplayInRect(childrenRect);
659         }
660     }
661
662     if (!m_haveImage && !drawsContent()) {
663         LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
664             this, rect.x(), rect.y(), rect.width(), rect.height());
665         return;
666     }
667
668     bool addInval = true;
669     const size_t maxDirtyRects = 8;
670     for (size_t i = 0; i < m_invalidatedRects.size(); ++i) {
671         if (m_invalidatedRects[i].contains(rect)) {
672             addInval = false;
673             break;
674         }
675     }
676
677 #ifdef LAYER_DEBUG
678     LOG("(%x) layer %d setNeedsDisplayInRect(%d) - (%.2f, %.2f, %.2f, %.2f)", this,
679         m_contentLayer->uniqueId(), m_needsRepaint, rect.x(), rect.y(), rect.width(), rect.height());
680 #endif
681
682     if (addInval) {
683         if (m_invalidatedRects.size() < maxDirtyRects)
684             m_invalidatedRects.append(rect);
685         else
686             m_invalidatedRects[0].unite(rect);
687     }
688
689     m_needsRepaint = true;
690     askForSync();
691 }
692
693 void GraphicsLayerAndroid::pauseDisplay(bool state)
694 {
695     gPaused = state;
696     if (gPaused)
697         gPausedDelay = WTF::currentTime() + 1;
698 }
699
700 bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
701                                         const IntSize& boxSize,
702                                         const Animation* anim,
703                                         const String& keyframesName,
704                                         double beginTime)
705 {
706     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
707         return false;
708
709     bool createdAnimations = false;
710     if (valueList.property() == AnimatedPropertyWebkitTransform) {
711         createdAnimations = createTransformAnimationsFromKeyframes(valueList,
712                                                                    anim,
713                                                                    keyframesName,
714                                                                    beginTime,
715                                                                    boxSize);
716     } else {
717         createdAnimations = createAnimationFromKeyframes(valueList,
718                                                          anim,
719                                                          keyframesName,
720                                                          beginTime);
721     }
722     if (createdAnimations)
723         askForSync();
724     return createdAnimations;
725 }
726
727 bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList,
728      const Animation* animation, const String& keyframesName, double beginTime)
729 {
730     bool isKeyframe = valueList.size() > 2;
731     TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
732         isKeyframe, keyframesName.latin1().data(), beginTime);
733
734     switch (valueList.property()) {
735     case AnimatedPropertyInvalid: break;
736     case AnimatedPropertyWebkitTransform: break;
737     case AnimatedPropertyBackgroundColor: break;
738     case AnimatedPropertyOpacity: {
739         MLOG("ANIMATEDPROPERTYOPACITY");
740
741         KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity);
742         for (unsigned int i = 0; i < valueList.size(); i++) {
743             FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i);
744             PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
745             FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(),
746                                                                  originalValue->value(),
747                                                                  timingFunction);
748             operationsList->insert(value);
749         }
750
751         RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation,
752                                                                                operationsList,
753                                                                                beginTime);
754         if (keyframesName.isEmpty())
755             anim->setName(propertyIdToString(valueList.property()));
756         else
757             anim->setName(keyframesName);
758
759         m_contentLayer->addAnimation(anim.release());
760         needsNotifyClient();
761         return true;
762     } break;
763     }
764     return false;
765 }
766
767 void GraphicsLayerAndroid::needsNotifyClient()
768 {
769     m_needsNotifyClient = true;
770     askForSync();
771 }
772
773 bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList,
774                                                                   const Animation* animation,
775                                                                   const String& keyframesName,
776                                                                   double beginTime,
777                                                                   const IntSize& boxSize)
778 {
779     ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
780     TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
781         keyframesName.latin1().data(), beginTime);
782
783     KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform);
784     for (unsigned int i = 0; i < valueList.size(); i++) {
785         TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i);
786         PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
787         TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(),
788                                                                      originalValue->value(),
789                                                                      timingFunction);
790         operationsList->insert(value);
791     }
792
793     RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation,
794                                                                                operationsList,
795                                                                                beginTime);
796
797     if (keyframesName.isEmpty())
798         anim->setName(propertyIdToString(valueList.property()));
799     else
800         anim->setName(keyframesName);
801
802
803     m_contentLayer->addAnimation(anim.release());
804
805     needsNotifyClient();
806     return true;
807 }
808
809 void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
810 {
811     TLOG("NRO removeAnimationsForProperty(%d)", anID);
812     m_contentLayer->removeAnimationsForProperty(anID);
813     askForSync();
814 }
815
816 void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
817 {
818     TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data());
819     m_contentLayer->removeAnimationsForKeyframes(keyframesName);
820     askForSync();
821 }
822
823 void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
824 {
825     TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data());
826 }
827
828 void GraphicsLayerAndroid::suspendAnimations(double time)
829 {
830     TLOG("NRO suspendAnimations(%.2f)", time);
831 }
832
833 void GraphicsLayerAndroid::resumeAnimations()
834 {
835     TLOG("NRO resumeAnimations()");
836 }
837
838 void GraphicsLayerAndroid::setContentsToImage(Image* image)
839 {
840     TLOG("(%x) setContentsToImage", this, image);
841     if (image) {
842         m_haveContents = true;
843         m_haveImage = true;
844         // Only pass the new image if it's a different one
845         if (image->nativeImageForCurrentFrame() != m_imageRef) {
846             m_newImage = true;
847             m_contentLayer->setContentsImage(image->nativeImageForCurrentFrame());
848             // remember the passed image.
849             m_imageRef = image->nativeImageForCurrentFrame();
850             setNeedsDisplay();
851             askForSync();
852         }
853     }
854 }
855
856 void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer)
857 {
858     // Only fullscreen video on Android, so media doesn't get it's own layer.
859     // We might still have other layers though.
860     if (m_contentLayer != mediaLayer && mediaLayer) {
861
862         // TODO add a copy method to LayerAndroid to sync everything
863         // copy data from the original content layer to the new one
864         mediaLayer->setPosition(m_contentLayer->getPosition().fX,
865                                 m_contentLayer->getPosition().fY);
866         mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight());
867         mediaLayer->setDrawTransform(m_contentLayer->drawTransform());
868
869         mediaLayer->ref();
870         m_contentLayer->unref();
871         m_contentLayer = mediaLayer;
872
873         // If the parent exists then notify it to re-sync it's children
874         if (m_parent) {
875             GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
876             parent->m_needsSyncChildren = true;
877         }
878         m_needsSyncChildren = true;
879
880         setNeedsDisplay();
881         askForSync();
882     }
883 }
884
885 PlatformLayer* GraphicsLayerAndroid::platformLayer() const
886 {
887     LOG("platformLayer");
888     return m_contentLayer;
889 }
890
891 #ifndef NDEBUG
892 void GraphicsLayerAndroid::setDebugBackgroundColor(const Color& color)
893 {
894 }
895
896 void GraphicsLayerAndroid::setDebugBorder(const Color& color, float borderWidth)
897 {
898 }
899 #endif
900
901 void GraphicsLayerAndroid::setZPosition(float position)
902 {
903     if (position == m_zPosition)
904         return;
905     LOG("(%x) setZPosition: %.2f", this, position);
906     GraphicsLayer::setZPosition(position);
907     askForSync();
908 }
909
910 void GraphicsLayerAndroid::askForSync()
911 {
912     if (!m_client)
913         return;
914
915     if (m_client)
916         m_client->notifySyncRequired(this);
917 }
918
919 void GraphicsLayerAndroid::syncChildren()
920 {
921     if (m_needsSyncChildren) {
922         m_contentLayer->removeChildren();
923         LayerAndroid* layer = m_contentLayer;
924         if (m_foregroundClipLayer) {
925             m_contentLayer->addChild(m_foregroundClipLayer);
926             // Use the scrollable content layer as the parent of the children so
927             // that they move with the content.
928             layer = m_foregroundLayer;
929             layer->removeChildren();
930         }
931         for (unsigned int i = 0; i < m_children.size(); i++)
932             layer->addChild(m_children[i]->platformLayer());
933         m_needsSyncChildren = false;
934     }
935 }
936
937 void GraphicsLayerAndroid::syncMask()
938 {
939     if (m_needsSyncMask) {
940         if (m_maskLayer) {
941             LayerAndroid* mask = m_maskLayer->platformLayer();
942             m_contentLayer->setMaskLayer(mask);
943         } else
944             m_contentLayer->setMaskLayer(0);
945
946         m_contentLayer->setMasksToBounds(m_masksToBounds);
947         m_needsSyncMask = false;
948     }
949 }
950
951 void GraphicsLayerAndroid::syncCompositingState()
952 {
953     for (unsigned int i = 0; i < m_children.size(); i++)
954         m_children[i]->syncCompositingState();
955
956     updateScrollingLayers();
957     updateFixedPosition();
958     syncChildren();
959     syncMask();
960
961     if (!gPaused || WTF::currentTime() >= gPausedDelay)
962         repaint();
963 }
964
965 void GraphicsLayerAndroid::notifyClientAnimationStarted()
966 {
967     for (unsigned int i = 0; i < m_children.size(); i++)
968         static_cast<GraphicsLayerAndroid*>(m_children[i])->notifyClientAnimationStarted();
969
970     if (m_needsNotifyClient) {
971         if (client())
972             client()->notifyAnimationStarted(this, WTF::currentTime());
973         m_needsNotifyClient = false;
974     }
975 }
976
977 } // namespace WebCore
978
979 #endif // USE(ACCELERATED_COMPOSITING)