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