src/declarative/util/qdeclarativepixmapcache.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
equal deleted inserted replaced
36:ef0373b55136 37:758a864f9613
    68 #define CACHE_EXPIRE_TIME 30
    68 #define CACHE_EXPIRE_TIME 30
    69 #define CACHE_REMOVAL_FRACTION 4
    69 #define CACHE_REMOVAL_FRACTION 4
    70 
    70 
    71 QT_BEGIN_NAMESPACE
    71 QT_BEGIN_NAMESPACE
    72 
    72 
       
    73 // The cache limit describes the maximum "junk" in the cache.
       
    74 // These are the same defaults as QPixmapCache
       
    75 #if defined(Q_OS_SYMBIAN)
       
    76 static int cache_limit = 1024 * 1024; // 1048 KB cache limit for symbian
       
    77 #elif defined(Q_WS_QWS) || defined(Q_WS_WINCE)
       
    78 static int cache_limit = 2048 * 1024; // 2048 KB cache limit for embedded
       
    79 #else
       
    80 static int cache_limit = 10240 * 1024; // 10 MB cache limit for desktop
       
    81 #endif
       
    82 
    73 class QDeclarativePixmapReader;
    83 class QDeclarativePixmapReader;
    74 class QDeclarativePixmapData;
    84 class QDeclarativePixmapData;
    75 class QDeclarativePixmapReply : public QObject
    85 class QDeclarativePixmapReply : public QObject
    76 {
    86 {
    77     Q_OBJECT
    87     Q_OBJECT
   143     void run();
   153     void run();
   144 
   154 
   145 private:
   155 private:
   146     friend class QDeclarativePixmapReaderThreadObject;
   156     friend class QDeclarativePixmapReaderThreadObject;
   147     void processJobs();
   157     void processJobs();
   148     void processJob(QDeclarativePixmapReply *);
   158     void processJob(QDeclarativePixmapReply *, const QUrl &, const QSize &);
   149     void networkRequestDone(QNetworkReply *);
   159     void networkRequestDone(QNetworkReply *);
   150 
   160 
   151     QList<QDeclarativePixmapReply*> jobs;
   161     QList<QDeclarativePixmapReply*> jobs;
   152     QList<QDeclarativePixmapReply*> cancelled;
   162     QList<QDeclarativePixmapReply*> cancelled;
   153     QDeclarativeEngine *engine;
   163     QDeclarativeEngine *engine;
   422 
   432 
   423         if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) {
   433         if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) {
   424             QDeclarativePixmapReply *runningJob = jobs.takeLast();
   434             QDeclarativePixmapReply *runningJob = jobs.takeLast();
   425             runningJob->loading = true;
   435             runningJob->loading = true;
   426 
   436 
       
   437             QUrl url = runningJob->data->url;
       
   438             QSize requestSize = runningJob->data->requestSize;
   427             locker.unlock();
   439             locker.unlock();
   428             processJob(runningJob);
   440             processJob(runningJob, url, requestSize);
   429             locker.relock();
   441             locker.relock();
   430         }
   442         }
   431     }
   443     }
   432 }
   444 }
   433 
   445 
   434 void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob)
   446 void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob, const QUrl &url, 
   435 {
   447                                           const QSize &requestSize)
   436     QUrl url = runningJob->data->url;
   448 {
   437 
       
   438     // fetch
   449     // fetch
   439     if (url.scheme() == QLatin1String("image")) {
   450     if (url.scheme() == QLatin1String("image")) {
   440         // Use QmlImageProvider
   451         // Use QmlImageProvider
   441         QSize readSize;
   452         QSize readSize;
   442         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
   453         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
   443         QImage image = ep->getImageFromProvider(url, &readSize, runningJob->data->requestSize);
   454         QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
   444 
   455 
   445         QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
   456         QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
   446         QString errorStr;
   457         QString errorStr;
   447         if (image.isNull()) {
   458         if (image.isNull()) {
   448             errorCode = QDeclarativePixmapReply::Loading;
   459             errorCode = QDeclarativePixmapReply::Loading;
   460             QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
   471             QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError;
   461             QString errorStr;
   472             QString errorStr;
   462             QFile f(lf);
   473             QFile f(lf);
   463             QSize readSize;
   474             QSize readSize;
   464             if (f.open(QIODevice::ReadOnly)) {
   475             if (f.open(QIODevice::ReadOnly)) {
   465                 if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->data->requestSize))
   476                 if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize))
   466                     errorCode = QDeclarativePixmapReply::Loading;
   477                     errorCode = QDeclarativePixmapReply::Loading;
   467             } else {
   478             } else {
   468                 errorStr = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString());
   479                 errorStr = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString());
   469                 errorCode = QDeclarativePixmapReply::Loading;
   480                 errorCode = QDeclarativePixmapReply::Loading;
   470             }
   481             }
   513 void QDeclarativePixmapReader::cancel(QDeclarativePixmapReply *reply)
   524 void QDeclarativePixmapReader::cancel(QDeclarativePixmapReply *reply)
   514 {
   525 {
   515     mutex.lock();
   526     mutex.lock();
   516     if (reply->loading) {
   527     if (reply->loading) {
   517         cancelled.append(reply);
   528         cancelled.append(reply);
       
   529         reply->data = 0;
   518         // XXX 
   530         // XXX 
   519         if (threadObject) threadObject->processJobs();
   531         if (threadObject) threadObject->processJobs();
   520     } else {
   532     } else {
   521         jobs.removeAll(reply);
   533         jobs.removeAll(reply);
   522         delete reply;
   534         delete reply;
   578 
   590 
   579 public:
   591 public:
   580     QHash<QDeclarativePixmapKey, QDeclarativePixmapData *> m_cache;
   592     QHash<QDeclarativePixmapKey, QDeclarativePixmapData *> m_cache;
   581 
   593 
   582 private:
   594 private:
       
   595     void shrinkCache(int remove);
       
   596 
   583     QDeclarativePixmapData *m_unreferencedPixmaps;
   597     QDeclarativePixmapData *m_unreferencedPixmaps;
   584     QDeclarativePixmapData *m_lastUnreferencedPixmap;
   598     QDeclarativePixmapData *m_lastUnreferencedPixmap;
   585 
   599 
   586     int m_unreferencedCost;
   600     int m_unreferencedCost;
   587     int m_timerId;
   601     int m_timerId;
   611     if (!m_lastUnreferencedPixmap)
   625     if (!m_lastUnreferencedPixmap)
   612         m_lastUnreferencedPixmap = data;
   626         m_lastUnreferencedPixmap = data;
   613 
   627 
   614     m_unreferencedCost += data->cost();
   628     m_unreferencedCost += data->cost();
   615 
   629 
   616     if (m_timerId == -1)
   630     shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit
       
   631 
       
   632     if (m_timerId == -1 && m_unreferencedPixmaps) 
   617         m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000);
   633         m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000);
   618 }
   634 }
   619 
   635 
   620 void QDeclarativePixmapStore::referencePixmap(QDeclarativePixmapData *data)
   636 void QDeclarativePixmapStore::referencePixmap(QDeclarativePixmapData *data)
   621 {
   637 {
   634     data->prevUnreferenced = 0;
   650     data->prevUnreferenced = 0;
   635 
   651 
   636     m_unreferencedCost -= data->cost();
   652     m_unreferencedCost -= data->cost();
   637 }
   653 }
   638 
   654 
   639 void QDeclarativePixmapStore::timerEvent(QTimerEvent *)
   655 void QDeclarativePixmapStore::shrinkCache(int remove)
   640 {
   656 {
   641     int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION;
   657     while ((remove > 0 || m_unreferencedCost > cache_limit) && m_lastUnreferencedPixmap) {
   642 
       
   643     while (removalCost > 0 && m_lastUnreferencedPixmap) {
       
   644         QDeclarativePixmapData *data = m_lastUnreferencedPixmap;
   658         QDeclarativePixmapData *data = m_lastUnreferencedPixmap;
   645         Q_ASSERT(data->nextUnreferenced == 0);
   659         Q_ASSERT(data->nextUnreferenced == 0);
   646 
   660 
   647         *data->prevUnreferencedPtr = 0;
   661         *data->prevUnreferencedPtr = 0;
   648         m_lastUnreferencedPixmap = data->prevUnreferenced;
   662         m_lastUnreferencedPixmap = data->prevUnreferenced;
   649         data->prevUnreferencedPtr = 0;
   663         data->prevUnreferencedPtr = 0;
   650         data->prevUnreferenced = 0;
   664         data->prevUnreferenced = 0;
   651 
   665 
   652         removalCost -= data->cost();
   666         remove -= data->cost();
       
   667         m_unreferencedCost -= data->cost();
   653         data->removeFromCache();
   668         data->removeFromCache();
   654         delete data;
   669         delete data;
   655     }
   670     }
       
   671 }
       
   672 
       
   673 void QDeclarativePixmapStore::timerEvent(QTimerEvent *)
       
   674 {
       
   675     int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION;
       
   676 
       
   677     shrinkCache(removalCost);
   656 
   678 
   657     if (m_unreferencedPixmaps == 0) {
   679     if (m_unreferencedPixmaps == 0) {
   658         killTimer(m_timerId);
   680         killTimer(m_timerId);
   659         m_timerId = -1;
   681         m_timerId = -1;
   660     }
   682     }
   700     }
   722     }
   701 }
   723 }
   702 
   724 
   703 int QDeclarativePixmapData::cost() const
   725 int QDeclarativePixmapData::cost() const
   704 {
   726 {
   705     return pixmap.width() * pixmap.height() * pixmap.depth();
   727     return (pixmap.width() * pixmap.height() * pixmap.depth()) / 8;
   706 }
   728 }
   707 
   729 
   708 void QDeclarativePixmapData::addref()
   730 void QDeclarativePixmapData::addref()
   709 {
   731 {
   710     ++refCount;
   732     ++refCount;
   717     Q_ASSERT(refCount > 0);
   739     Q_ASSERT(refCount > 0);
   718     --refCount;
   740     --refCount;
   719 
   741 
   720     if (refCount == 0) {
   742     if (refCount == 0) {
   721         if (reply) {
   743         if (reply) {
   722             reply->data = 0;
       
   723             reply->reader->cancel(reply);
   744             reply->reader->cancel(reply);
   724             reply = 0;
   745             reply = 0;
   725         }
   746         }
   726 
   747 
   727         if (pixmapStatus == QDeclarativePixmap::Ready) {
   748         if (pixmapStatus == QDeclarativePixmap::Ready) {