OSDN Git Service

Merge WebKit at r71558: Initial merge by git.
[android-x86/external-webkit.git] / WebCore / platform / graphics / qt / GraphicsLayerQt.cpp
index aa7ed2f..49387a2 100644 (file)
 #include <QtGui/qgraphicseffect.h>
 #include <QtGui/qgraphicsitem.h>
 #include <QtGui/qgraphicsscene.h>
+#include <QtGui/qgraphicsview.h>
 #include <QtGui/qgraphicswidget.h>
 #include <QtGui/qpainter.h>
 #include <QtGui/qpixmap.h>
 #include <QtGui/qpixmapcache.h>
 #include <QtGui/qstyleoption.h>
 
+#if ENABLE(TILED_BACKING_STORE)
+#include "TiledBackingStore.h"
+#include "TiledBackingStoreClient.h"
+
+// The minimum width/height for tiling. We use the same value as the Windows implementation.
+#define GRAPHICS_LAYER_TILING_THRESHOLD 2000
+#endif
+
 
 #define QT_DEBUG_RECACHE 0
 #define QT_DEBUG_CACHEDUMP 0
@@ -112,7 +121,11 @@ public:
 };
 #endif // QT_NO_GRAPHICSEFFECT
 
-class GraphicsLayerQtImpl : public QGraphicsObject {
+class GraphicsLayerQtImpl : public QGraphicsObject
+#if ENABLE(TILED_BACKING_STORE)
+, public virtual TiledBackingStoreClient
+#endif
+{
     Q_OBJECT
 
 public:
@@ -182,6 +195,16 @@ public:
     // ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP)
     void flushChanges(bool recursive = true, bool forceTransformUpdate = false);
 
+#if ENABLE(TILED_BACKING_STORE)
+    // reimplementations from TiledBackingStoreClient
+    virtual void tiledBackingStorePaintBegin();
+    virtual void tiledBackingStorePaint(GraphicsContext*, const IntRect&);
+    virtual void tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea);
+    virtual IntRect tiledBackingStoreContentsRect();
+    virtual IntRect tiledBackingStoreVisibleRect();
+    virtual Color tiledBackingStoreBackgroundColor() const;
+#endif
+
 public slots:
     // We need to notify the client (ie. the layer compositor) when the animation actually starts.
     void notifyAnimationStarted();
@@ -232,6 +255,10 @@ public:
 
     int m_changeMask;
 
+#if ENABLE(TILED_BACKING_STORE)
+    TiledBackingStore* m_tiledBackingStore;
+#endif
+
     QSizeF m_size;
     struct {
         QPixmapCache::Key key;
@@ -303,6 +330,9 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer)
     , m_opacityAnimationRunning(false)
     , m_blockNotifySyncRequired(false)
     , m_changeMask(NoChanges)
+#if ENABLE(TILED_BACKING_STORE)
+    , m_tiledBackingStore(0)
+#endif
 #if ENABLE(3D_CANVAS)
     , m_gc3D(0)
 #endif
@@ -330,7 +360,9 @@ GraphicsLayerQtImpl::~GraphicsLayerQtImpl()
             item->setParentItem(0);
         }
     }
-
+#if ENABLE(TILED_BACKING_STORE)
+    delete m_tiledBackingStore;
+#endif
 #ifndef QT_NO_ANIMATION
     // We do, however, own the animations.
     QList<QWeakPointer<QAbstractAnimation> >::iterator it;
@@ -352,6 +384,27 @@ QPixmap GraphicsLayerQtImpl::recache(const QRegion& regionToUpdate)
     if (!m_layer->drawsContent() || m_size.isEmpty() || !m_size.isValid())
         return QPixmap();
 
+#if ENABLE(TILED_BACKING_STORE)
+    const bool requiresTiling = (m_state.drawsContent && m_currentContent.contentType == HTMLContentType) && (m_size.width() > GRAPHICS_LAYER_TILING_THRESHOLD || m_size.height() > GRAPHICS_LAYER_TILING_THRESHOLD);
+    if (requiresTiling && !m_tiledBackingStore) {
+        m_tiledBackingStore = new TiledBackingStore(this);
+        m_tiledBackingStore->setTileCreationDelay(0);
+        setFlag(ItemUsesExtendedStyleOption, true);
+    } else if (!requiresTiling && m_tiledBackingStore) {
+        delete m_tiledBackingStore;
+        m_tiledBackingStore = 0;
+        setFlag(ItemUsesExtendedStyleOption, false);
+    }
+
+    if (m_tiledBackingStore) {
+        m_tiledBackingStore->adjustVisibleRect();
+        const QVector<QRect> rects = regionToUpdate.rects();
+        for (int i = 0; i < rects.size(); ++i)
+           m_tiledBackingStore->invalidate(rects[i]);
+        return QPixmap();
+    }
+#endif
+
     QPixmap pixmap;
     QRegion region = regionToUpdate;
     if (QPixmapCache::find(m_backingStore.key, &pixmap)) {
@@ -562,8 +615,15 @@ QRectF GraphicsLayerQtImpl::boundingRect() const
 
 void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
 {
+#if ENABLE(TILED_BACKING_STORE)
+    // FIXME: There's currently no Qt API to know if a new region of an item is exposed outside of the paint event.
+    // Suggested for Qt: http://bugreports.qt.nokia.com/browse/QTBUG-14877.
+    if (m_tiledBackingStore)
+        m_tiledBackingStore->adjustVisibleRect();
+#endif
+
     if (m_currentContent.backgroundColor.isValid())
-        painter->fillRect(option->rect, QColor(m_currentContent.backgroundColor));
+        painter->fillRect(option->exposedRect, QColor(m_currentContent.backgroundColor));
 
     switch (m_currentContent.contentType) {
     case HTMLContentType:
@@ -828,6 +888,56 @@ afterLayerChanges:
     }
 }
 
+#if ENABLE(TILED_BACKING_STORE)
+/* \reimp (TiledBackingStoreClient.h)
+*/
+void GraphicsLayerQtImpl::tiledBackingStorePaintBegin()
+{
+}
+
+/* \reimp (TiledBackingStoreClient.h)
+*/
+void GraphicsLayerQtImpl::tiledBackingStorePaint(GraphicsContext* gc,  const IntRect& rect)
+{
+    m_layer->paintGraphicsLayerContents(*gc, rect);
+}
+
+/* \reimp (TiledBackingStoreClient.h)
+*/
+void GraphicsLayerQtImpl::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea)
+{
+    for (int i = 0; i < paintedArea.size(); ++i)
+        update(QRectF(paintedArea[i]));
+}
+
+/* \reimp (TiledBackingStoreClient.h)
+*/
+IntRect GraphicsLayerQtImpl::tiledBackingStoreContentsRect()
+{
+    return m_layer->contentsRect();
+}
+
+/* \reimp (TiledBackingStoreClient.h)
+*/
+Color GraphicsLayerQtImpl::tiledBackingStoreBackgroundColor() const
+{
+    if (m_currentContent.contentType == PixmapContentType && !m_currentContent.pixmap.hasAlphaChannel())
+        return Color(0, 0, 0);
+    // We return a transparent color so that the tiles initialize with alpha.
+    return Color(0, 0, 0, 0);
+}
+
+IntRect GraphicsLayerQtImpl::tiledBackingStoreVisibleRect()
+{
+    const QGraphicsView* view = scene()->views().isEmpty() ? 0 : scene()->views().first();
+    if (!view)
+        return mapFromScene(scene()->sceneRect()).boundingRect().toAlignedRect();
+
+    // All we get is the viewport's visible region. We have to map it to the scene and then to item coordinates.
+    return mapFromScene(view->mapToScene(view->viewport()->visibleRegion().boundingRect()).boundingRect()).boundingRect().toAlignedRect();
+}
+#endif
+
 void GraphicsLayerQtImpl::notifyAnimationStarted()
 {
     // WebCore notifies javascript when the animation starts. Here we're letting it know.