src/declarative/util/qdeclarativepixmapcache.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
--- a/src/declarative/util/qdeclarativepixmapcache.cpp	Fri Sep 17 08:34:18 2010 +0300
+++ b/src/declarative/util/qdeclarativepixmapcache.cpp	Mon Oct 04 01:19:32 2010 +0300
@@ -70,6 +70,16 @@
 
 QT_BEGIN_NAMESPACE
 
+// The cache limit describes the maximum "junk" in the cache.
+// These are the same defaults as QPixmapCache
+#if defined(Q_OS_SYMBIAN)
+static int cache_limit = 1024 * 1024; // 1048 KB cache limit for symbian
+#elif defined(Q_WS_QWS) || defined(Q_WS_WINCE)
+static int cache_limit = 2048 * 1024; // 2048 KB cache limit for embedded
+#else
+static int cache_limit = 10240 * 1024; // 10 MB cache limit for desktop
+#endif
+
 class QDeclarativePixmapReader;
 class QDeclarativePixmapData;
 class QDeclarativePixmapReply : public QObject
@@ -145,7 +155,7 @@
 private:
     friend class QDeclarativePixmapReaderThreadObject;
     void processJobs();
-    void processJob(QDeclarativePixmapReply *);
+    void processJob(QDeclarativePixmapReply *, const QUrl &, const QSize &);
     void networkRequestDone(QNetworkReply *);
 
     QList<QDeclarativePixmapReply*> jobs;
@@ -424,23 +434,24 @@
             QDeclarativePixmapReply *runningJob = jobs.takeLast();
             runningJob->loading = true;
 
+            QUrl url = runningJob->data->url;
+            QSize requestSize = runningJob->data->requestSize;
             locker.unlock();
-            processJob(runningJob);
+            processJob(runningJob, url, requestSize);
             locker.relock();
         }
     }
 }
 
-void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob)
+void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob, const QUrl &url, 
+                                          const QSize &requestSize)
 {
-    QUrl url = runningJob->data->url;
-
     // fetch
     if (url.scheme() == QLatin1String("image")) {
         // Use QmlImageProvider
         QSize readSize;
         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-        QImage image = ep->getImageFromProvider(url, &readSize, runningJob->data->requestSize);
+        QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
 
         QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
         QString errorStr;
@@ -462,7 +473,7 @@
             QFile f(lf);
             QSize readSize;
             if (f.open(QIODevice::ReadOnly)) {
-                if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->data->requestSize))
+                if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize))
                     errorCode = QDeclarativePixmapReply::Loading;
             } else {
                 errorStr = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString());
@@ -515,6 +526,7 @@
     mutex.lock();
     if (reply->loading) {
         cancelled.append(reply);
+        reply->data = 0;
         // XXX 
         if (threadObject) threadObject->processJobs();
     } else {
@@ -580,6 +592,8 @@
     QHash<QDeclarativePixmapKey, QDeclarativePixmapData *> m_cache;
 
 private:
+    void shrinkCache(int remove);
+
     QDeclarativePixmapData *m_unreferencedPixmaps;
     QDeclarativePixmapData *m_lastUnreferencedPixmap;
 
@@ -613,7 +627,9 @@
 
     m_unreferencedCost += data->cost();
 
-    if (m_timerId == -1)
+    shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit
+
+    if (m_timerId == -1 && m_unreferencedPixmaps) 
         m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000);
 }
 
@@ -636,11 +652,9 @@
     m_unreferencedCost -= data->cost();
 }
 
-void QDeclarativePixmapStore::timerEvent(QTimerEvent *)
+void QDeclarativePixmapStore::shrinkCache(int remove)
 {
-    int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION;
-
-    while (removalCost > 0 && m_lastUnreferencedPixmap) {
+    while ((remove > 0 || m_unreferencedCost > cache_limit) && m_lastUnreferencedPixmap) {
         QDeclarativePixmapData *data = m_lastUnreferencedPixmap;
         Q_ASSERT(data->nextUnreferenced == 0);
 
@@ -649,10 +663,18 @@
         data->prevUnreferencedPtr = 0;
         data->prevUnreferenced = 0;
 
-        removalCost -= data->cost();
+        remove -= data->cost();
+        m_unreferencedCost -= data->cost();
         data->removeFromCache();
         delete data;
     }
+}
+
+void QDeclarativePixmapStore::timerEvent(QTimerEvent *)
+{
+    int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION;
+
+    shrinkCache(removalCost);
 
     if (m_unreferencedPixmaps == 0) {
         killTimer(m_timerId);
@@ -702,7 +724,7 @@
 
 int QDeclarativePixmapData::cost() const
 {
-    return pixmap.width() * pixmap.height() * pixmap.depth();
+    return (pixmap.width() * pixmap.height() * pixmap.depth()) / 8;
 }
 
 void QDeclarativePixmapData::addref()
@@ -719,7 +741,6 @@
 
     if (refCount == 0) {
         if (reply) {
-            reply->data = 0;
             reply->reader->cancel(reply);
             reply = 0;
         }