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