| Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/gui/image/qpixmapcache.cpp |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /**************************************************************************** | - | ||||||||||||
| 2 | ** | - | ||||||||||||
| 3 | ** Copyright (C) 2015 The Qt Company Ltd. | - | ||||||||||||
| 4 | ** Contact: http://www.qt.io/licensing/ | - | ||||||||||||
| 5 | ** | - | ||||||||||||
| 6 | ** This file is part of the QtGui module of the Qt Toolkit. | - | ||||||||||||
| 7 | ** | - | ||||||||||||
| 8 | ** $QT_BEGIN_LICENSE:LGPL21$ | - | ||||||||||||
| 9 | ** Commercial License Usage | - | ||||||||||||
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||
| 11 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||
| 12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||
| 14 | ** and conditions see http://www.qt.io/terms-conditions. For further | - | ||||||||||||
| 15 | ** information use the contact form at http://www.qt.io/contact-us. | - | ||||||||||||
| 16 | ** | - | ||||||||||||
| 17 | ** GNU Lesser General Public License Usage | - | ||||||||||||
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||
| 19 | ** General Public License version 2.1 or version 3 as published by the Free | - | ||||||||||||
| 20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and | - | ||||||||||||
| 21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the | - | ||||||||||||
| 22 | ** following information to ensure the GNU Lesser General Public License | - | ||||||||||||
| 23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and | - | ||||||||||||
| 24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | - | ||||||||||||
| 25 | ** | - | ||||||||||||
| 26 | ** As a special exception, The Qt Company gives you certain additional | - | ||||||||||||
| 27 | ** rights. These rights are described in The Qt Company LGPL Exception | - | ||||||||||||
| 28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | - | ||||||||||||
| 29 | ** | - | ||||||||||||
| 30 | ** $QT_END_LICENSE$ | - | ||||||||||||
| 31 | ** | - | ||||||||||||
| 32 | ****************************************************************************/ | - | ||||||||||||
| 33 | - | |||||||||||||
| 34 | #define Q_TEST_QPIXMAPCACHE | - | ||||||||||||
| 35 | #include "qpixmapcache.h" | - | ||||||||||||
| 36 | #include "qobject.h" | - | ||||||||||||
| 37 | #include "qdebug.h" | - | ||||||||||||
| 38 | #include "qpixmapcache_p.h" | - | ||||||||||||
| 39 | - | |||||||||||||
| 40 | QT_BEGIN_NAMESPACE | - | ||||||||||||
| 41 | - | |||||||||||||
| 42 | /*! | - | ||||||||||||
| 43 | \class QPixmapCache | - | ||||||||||||
| 44 | \inmodule QtGui | - | ||||||||||||
| 45 | - | |||||||||||||
| 46 | \brief The QPixmapCache class provides an application-wide cache for pixmaps. | - | ||||||||||||
| 47 | - | |||||||||||||
| 48 | This class is a tool for optimized drawing with QPixmap. You can | - | ||||||||||||
| 49 | use it to store temporary pixmaps that are expensive to generate | - | ||||||||||||
| 50 | without using more storage space than cacheLimit(). Use insert() | - | ||||||||||||
| 51 | to insert pixmaps, find() to find them, and clear() to empty the | - | ||||||||||||
| 52 | cache. | - | ||||||||||||
| 53 | - | |||||||||||||
| 54 | QPixmapCache contains no member data, only static functions to | - | ||||||||||||
| 55 | access the global pixmap cache. It creates an internal QCache | - | ||||||||||||
| 56 | object for caching the pixmaps. | - | ||||||||||||
| 57 | - | |||||||||||||
| 58 | The cache associates a pixmap with a user-provided string as a key, | - | ||||||||||||
| 59 | or with a QPixmapCache::Key that the cache generates. | - | ||||||||||||
| 60 | Using QPixmapCache::Key for keys is faster than using strings. The string API is | - | ||||||||||||
| 61 | very convenient for complex keys but the QPixmapCache::Key API will be very | - | ||||||||||||
| 62 | efficient and convenient for a one-to-one object-to-pixmap mapping - in | - | ||||||||||||
| 63 | this case, you can store the keys as members of an object. | - | ||||||||||||
| 64 | - | |||||||||||||
| 65 | If two pixmaps are inserted into the cache using equal keys then the | - | ||||||||||||
| 66 | last pixmap will replace the first pixmap in the cache. This follows the | - | ||||||||||||
| 67 | behavior of the QHash and QCache classes. | - | ||||||||||||
| 68 | - | |||||||||||||
| 69 | The cache becomes full when the total size of all pixmaps in the | - | ||||||||||||
| 70 | cache exceeds cacheLimit(). The initial cache limit is 10240 KB (10 MB); | - | ||||||||||||
| 71 | you can change this by calling setCacheLimit() with the required value. | - | ||||||||||||
| 72 | A pixmap takes roughly (\e{width} * \e{height} * \e{depth})/8 bytes of | - | ||||||||||||
| 73 | memory. | - | ||||||||||||
| 74 | - | |||||||||||||
| 75 | The \e{Qt Quarterly} article | - | ||||||||||||
| 76 | \l{http://doc.qt.io/archives/qq/qq12-qpixmapcache.html}{Optimizing | - | ||||||||||||
| 77 | with QPixmapCache} explains how to use QPixmapCache to speed up | - | ||||||||||||
| 78 | applications by caching the results of painting. | - | ||||||||||||
| 79 | - | |||||||||||||
| 80 | \sa QCache, QPixmap | - | ||||||||||||
| 81 | */ | - | ||||||||||||
| 82 | - | |||||||||||||
| 83 | static int cache_limit = 10240; // 10 MB cache limit | - | ||||||||||||
| 84 | - | |||||||||||||
| 85 | /*! | - | ||||||||||||
| 86 | \class QPixmapCache::Key | - | ||||||||||||
| 87 | \brief The QPixmapCache::Key class can be used for efficient access | - | ||||||||||||
| 88 | to the QPixmapCache. | - | ||||||||||||
| 89 | \inmodule QtGui | - | ||||||||||||
| 90 | \since 4.6 | - | ||||||||||||
| 91 | - | |||||||||||||
| 92 | Use QPixmapCache::insert() to receive an instance of Key generated | - | ||||||||||||
| 93 | by the pixmap cache. You can store the key in your own objects for | - | ||||||||||||
| 94 | a very efficient one-to-one object-to-pixmap mapping. | - | ||||||||||||
| 95 | */ | - | ||||||||||||
| 96 | - | |||||||||||||
| 97 | /*! | - | ||||||||||||
| 98 | Constructs an empty Key object. | - | ||||||||||||
| 99 | */ | - | ||||||||||||
| 100 | QPixmapCache::Key::Key() : d(0) | - | ||||||||||||
| 101 | { | - | ||||||||||||
| 102 | } never executed: end of block | 0 | ||||||||||||
| 103 | - | |||||||||||||
| 104 | /*! | - | ||||||||||||
| 105 | \internal | - | ||||||||||||
| 106 | Constructs a copy of \a other. | - | ||||||||||||
| 107 | */ | - | ||||||||||||
| 108 | QPixmapCache::Key::Key(const Key &other) | - | ||||||||||||
| 109 | { | - | ||||||||||||
| 110 | if (other.d)
| 0 | ||||||||||||
| 111 | ++(other.d->ref); never executed: ++(other.d->ref); | 0 | ||||||||||||
| 112 | d = other.d; | - | ||||||||||||
| 113 | } never executed: end of block | 0 | ||||||||||||
| 114 | - | |||||||||||||
| 115 | /*! | - | ||||||||||||
| 116 | Destroys the key. | - | ||||||||||||
| 117 | */ | - | ||||||||||||
| 118 | QPixmapCache::Key::~Key() | - | ||||||||||||
| 119 | { | - | ||||||||||||
| 120 | if (d && --(d->ref) == 0)
| 0 | ||||||||||||
| 121 | delete d; never executed: delete d; | 0 | ||||||||||||
| 122 | } never executed: end of block | 0 | ||||||||||||
| 123 | - | |||||||||||||
| 124 | /*! | - | ||||||||||||
| 125 | \internal | - | ||||||||||||
| 126 | - | |||||||||||||
| 127 | Returns \c true if this key is the same as the given \a key; otherwise returns | - | ||||||||||||
| 128 | false. | - | ||||||||||||
| 129 | */ | - | ||||||||||||
| 130 | bool QPixmapCache::Key::operator ==(const Key &key) const | - | ||||||||||||
| 131 | { | - | ||||||||||||
| 132 | return (d == key.d); never executed: return (d == key.d); | 0 | ||||||||||||
| 133 | } | - | ||||||||||||
| 134 | - | |||||||||||||
| 135 | /*! | - | ||||||||||||
| 136 | \fn bool QPixmapCache::Key::operator !=(const Key &key) const | - | ||||||||||||
| 137 | \internal | - | ||||||||||||
| 138 | */ | - | ||||||||||||
| 139 | - | |||||||||||||
| 140 | /*! | - | ||||||||||||
| 141 | \fn QPixmapCache::Key::Key(Key &&) | - | ||||||||||||
| 142 | \internal | - | ||||||||||||
| 143 | \since 5.6 | - | ||||||||||||
| 144 | */ | - | ||||||||||||
| 145 | - | |||||||||||||
| 146 | /*! | - | ||||||||||||
| 147 | \fn QPixmapCache::Key &QPixmapCache::Key::operator=(Key &&) | - | ||||||||||||
| 148 | \internal | - | ||||||||||||
| 149 | \since 5.6 | - | ||||||||||||
| 150 | */ | - | ||||||||||||
| 151 | - | |||||||||||||
| 152 | /*! | - | ||||||||||||
| 153 | \fn void QPixmapCache::Key::swap(Key &) | - | ||||||||||||
| 154 | \internal | - | ||||||||||||
| 155 | \since 5.6 | - | ||||||||||||
| 156 | */ | - | ||||||||||||
| 157 | - | |||||||||||||
| 158 | /*! | - | ||||||||||||
| 159 | \internal | - | ||||||||||||
| 160 | */ | - | ||||||||||||
| 161 | QPixmapCache::Key &QPixmapCache::Key::operator =(const Key &other) | - | ||||||||||||
| 162 | { | - | ||||||||||||
| 163 | if (d != other.d) {
| 0 | ||||||||||||
| 164 | if (other.d)
| 0 | ||||||||||||
| 165 | ++(other.d->ref); never executed: ++(other.d->ref); | 0 | ||||||||||||
| 166 | if (d && --(d->ref) == 0)
| 0 | ||||||||||||
| 167 | delete d; never executed: delete d; | 0 | ||||||||||||
| 168 | d = other.d; | - | ||||||||||||
| 169 | } never executed: end of block | 0 | ||||||||||||
| 170 | return *this; never executed: return *this; | 0 | ||||||||||||
| 171 | } | - | ||||||||||||
| 172 | - | |||||||||||||
| 173 | class QPMCache : public QObject, public QCache<QPixmapCache::Key, QPixmapCacheEntry> | - | ||||||||||||
| 174 | { | - | ||||||||||||
| 175 | Q_OBJECT | - | ||||||||||||
| 176 | public: | - | ||||||||||||
| 177 | QPMCache(); | - | ||||||||||||
| 178 | ~QPMCache(); | - | ||||||||||||
| 179 | - | |||||||||||||
| 180 | void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE; | - | ||||||||||||
| 181 | bool insert(const QString& key, const QPixmap &pixmap, int cost); | - | ||||||||||||
| 182 | QPixmapCache::Key insert(const QPixmap &pixmap, int cost); | - | ||||||||||||
| 183 | bool replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost); | - | ||||||||||||
| 184 | bool remove(const QString &key); | - | ||||||||||||
| 185 | bool remove(const QPixmapCache::Key &key); | - | ||||||||||||
| 186 | - | |||||||||||||
| 187 | void resizeKeyArray(int size); | - | ||||||||||||
| 188 | QPixmapCache::Key createKey(); | - | ||||||||||||
| 189 | void releaseKey(const QPixmapCache::Key &key); | - | ||||||||||||
| 190 | void clear(); | - | ||||||||||||
| 191 | - | |||||||||||||
| 192 | QPixmap *object(const QString &key) const; | - | ||||||||||||
| 193 | QPixmap *object(const QPixmapCache::Key &key) const; | - | ||||||||||||
| 194 | - | |||||||||||||
| 195 | static inline QPixmapCache::KeyData *get(const QPixmapCache::Key &key) | - | ||||||||||||
| 196 | {return key.d;} never executed: return key.d; | 0 | ||||||||||||
| 197 | - | |||||||||||||
| 198 | static QPixmapCache::KeyData* getKeyData(QPixmapCache::Key *key); | - | ||||||||||||
| 199 | - | |||||||||||||
| 200 | bool flushDetachedPixmaps(bool nt); | - | ||||||||||||
| 201 | - | |||||||||||||
| 202 | private: | - | ||||||||||||
| 203 | enum { soon_time = 10000, flush_time = 30000 }; | - | ||||||||||||
| 204 | int *keyArray; | - | ||||||||||||
| 205 | int theid; | - | ||||||||||||
| 206 | int ps; | - | ||||||||||||
| 207 | int keyArraySize; | - | ||||||||||||
| 208 | int freeKey; | - | ||||||||||||
| 209 | QHash<QString, QPixmapCache::Key> cacheKeys; | - | ||||||||||||
| 210 | bool t; | - | ||||||||||||
| 211 | }; | - | ||||||||||||
| 212 | - | |||||||||||||
| 213 | QT_BEGIN_INCLUDE_NAMESPACE | - | ||||||||||||
| 214 | #include "qpixmapcache.moc" | - | ||||||||||||
| 215 | QT_END_INCLUDE_NAMESPACE | - | ||||||||||||
| 216 | - | |||||||||||||
| 217 | uint qHash(const QPixmapCache::Key &k) | - | ||||||||||||
| 218 | { | - | ||||||||||||
| 219 | return qHash(QPMCache::get(k)->key); never executed: return qHash(QPMCache::get(k)->key); | 0 | ||||||||||||
| 220 | } | - | ||||||||||||
| 221 | - | |||||||||||||
| 222 | QPMCache::QPMCache() | - | ||||||||||||
| 223 | : QObject(0), | - | ||||||||||||
| 224 | QCache<QPixmapCache::Key, QPixmapCacheEntry>(cache_limit * 1024), | - | ||||||||||||
| 225 | keyArray(0), theid(0), ps(0), keyArraySize(0), freeKey(0), t(false) | - | ||||||||||||
| 226 | { | - | ||||||||||||
| 227 | } never executed: end of block | 0 | ||||||||||||
| 228 | QPMCache::~QPMCache() | - | ||||||||||||
| 229 | { | - | ||||||||||||
| 230 | clear(); | - | ||||||||||||
| 231 | free(keyArray); | - | ||||||||||||
| 232 | } never executed: end of block | 0 | ||||||||||||
| 233 | - | |||||||||||||
| 234 | /* | - | ||||||||||||
| 235 | This is supposed to cut the cache size down by about 25% in a | - | ||||||||||||
| 236 | minute once the application becomes idle, to let any inserted pixmap | - | ||||||||||||
| 237 | remain in the cache for some time before it becomes a candidate for | - | ||||||||||||
| 238 | cleaning-up, and to not cut down the size of the cache while the | - | ||||||||||||
| 239 | cache is in active use. | - | ||||||||||||
| 240 | - | |||||||||||||
| 241 | When the last detached pixmap has been deleted from the cache, kill the | - | ||||||||||||
| 242 | timer so Qt won't keep the CPU from going into sleep mode. Currently | - | ||||||||||||
| 243 | the timer is not restarted when the pixmap becomes unused, but it does | - | ||||||||||||
| 244 | restart once something else is added (i.e. the cache space is actually needed). | - | ||||||||||||
| 245 | - | |||||||||||||
| 246 | Returns \c true if any were removed. | - | ||||||||||||
| 247 | */ | - | ||||||||||||
| 248 | bool QPMCache::flushDetachedPixmaps(bool nt) | - | ||||||||||||
| 249 | { | - | ||||||||||||
| 250 | int mc = maxCost(); | - | ||||||||||||
| 251 | setMaxCost(nt ? totalCost() * 3 / 4 : totalCost() -1); | - | ||||||||||||
| 252 | setMaxCost(mc); | - | ||||||||||||
| 253 | ps = totalCost(); | - | ||||||||||||
| 254 | - | |||||||||||||
| 255 | bool any = false; | - | ||||||||||||
| 256 | QHash<QString, QPixmapCache::Key>::iterator it = cacheKeys.begin(); | - | ||||||||||||
| 257 | while (it != cacheKeys.end()) {
| 0 | ||||||||||||
| 258 | if (!contains(it.value())) {
| 0 | ||||||||||||
| 259 | releaseKey(it.value()); | - | ||||||||||||
| 260 | it = cacheKeys.erase(it); | - | ||||||||||||
| 261 | any = true; | - | ||||||||||||
| 262 | } else { never executed: end of block | 0 | ||||||||||||
| 263 | ++it; | - | ||||||||||||
| 264 | } never executed: end of block | 0 | ||||||||||||
| 265 | } | - | ||||||||||||
| 266 | - | |||||||||||||
| 267 | return any; never executed: return any; | 0 | ||||||||||||
| 268 | } | - | ||||||||||||
| 269 | - | |||||||||||||
| 270 | void QPMCache::timerEvent(QTimerEvent *) | - | ||||||||||||
| 271 | { | - | ||||||||||||
| 272 | bool nt = totalCost() == ps; | - | ||||||||||||
| 273 | if (!flushDetachedPixmaps(nt)) {
| 0 | ||||||||||||
| 274 | killTimer(theid); | - | ||||||||||||
| 275 | theid = 0; | - | ||||||||||||
| 276 | } else if (nt != t) { never executed: end of block
| 0 | ||||||||||||
| 277 | killTimer(theid); | - | ||||||||||||
| 278 | theid = startTimer(nt ? soon_time : flush_time); | - | ||||||||||||
| 279 | t = nt; | - | ||||||||||||
| 280 | } never executed: end of block | 0 | ||||||||||||
| 281 | } never executed: end of block | 0 | ||||||||||||
| 282 | - | |||||||||||||
| 283 | - | |||||||||||||
| 284 | QPixmap *QPMCache::object(const QString &key) const | - | ||||||||||||
| 285 | { | - | ||||||||||||
| 286 | QPixmapCache::Key cacheKey = cacheKeys.value(key); | - | ||||||||||||
| 287 | if (!cacheKey.d || !cacheKey.d->isValid) {
| 0 | ||||||||||||
| 288 | const_cast<QPMCache *>(this)->cacheKeys.remove(key); | - | ||||||||||||
| 289 | return 0; never executed: return 0; | 0 | ||||||||||||
| 290 | } | - | ||||||||||||
| 291 | QPixmap *ptr = QCache<QPixmapCache::Key, QPixmapCacheEntry>::object(cacheKey); | - | ||||||||||||
| 292 | //We didn't find the pixmap in the cache, the key is not valid anymore | - | ||||||||||||
| 293 | if (!ptr) {
| 0 | ||||||||||||
| 294 | const_cast<QPMCache *>(this)->cacheKeys.remove(key); | - | ||||||||||||
| 295 | } never executed: end of block | 0 | ||||||||||||
| 296 | return ptr; never executed: return ptr; | 0 | ||||||||||||
| 297 | } | - | ||||||||||||
| 298 | - | |||||||||||||
| 299 | QPixmap *QPMCache::object(const QPixmapCache::Key &key) const | - | ||||||||||||
| 300 | { | - | ||||||||||||
| 301 | Q_ASSERT(key.d->isValid); | - | ||||||||||||
| 302 | QPixmap *ptr = QCache<QPixmapCache::Key, QPixmapCacheEntry>::object(key); | - | ||||||||||||
| 303 | //We didn't find the pixmap in the cache, the key is not valid anymore | - | ||||||||||||
| 304 | if (!ptr)
| 0 | ||||||||||||
| 305 | const_cast<QPMCache *>(this)->releaseKey(key); never executed: const_cast<QPMCache *>(this)->releaseKey(key); | 0 | ||||||||||||
| 306 | return ptr; never executed: return ptr; | 0 | ||||||||||||
| 307 | } | - | ||||||||||||
| 308 | - | |||||||||||||
| 309 | bool QPMCache::insert(const QString& key, const QPixmap &pixmap, int cost) | - | ||||||||||||
| 310 | { | - | ||||||||||||
| 311 | QPixmapCache::Key cacheKey; | - | ||||||||||||
| 312 | QPixmapCache::Key oldCacheKey = cacheKeys.value(key); | - | ||||||||||||
| 313 | //If for the same key we add already a pixmap we should delete it | - | ||||||||||||
| 314 | if (oldCacheKey.d) {
| 0 | ||||||||||||
| 315 | QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(oldCacheKey); | - | ||||||||||||
| 316 | cacheKeys.remove(key); | - | ||||||||||||
| 317 | } never executed: end of block | 0 | ||||||||||||
| 318 | - | |||||||||||||
| 319 | //we create a new key the old one has been removed | - | ||||||||||||
| 320 | cacheKey = createKey(); | - | ||||||||||||
| 321 | - | |||||||||||||
| 322 | bool success = QCache<QPixmapCache::Key, QPixmapCacheEntry>::insert(cacheKey, new QPixmapCacheEntry(cacheKey, pixmap), cost); | - | ||||||||||||
| 323 | if (success) {
| 0 | ||||||||||||
| 324 | cacheKeys.insert(key, cacheKey); | - | ||||||||||||
| 325 | if (!theid) {
| 0 | ||||||||||||
| 326 | theid = startTimer(flush_time); | - | ||||||||||||
| 327 | t = false; | - | ||||||||||||
| 328 | } never executed: end of block | 0 | ||||||||||||
| 329 | } else { never executed: end of block | 0 | ||||||||||||
| 330 | //Insertion failed we released the new allocated key | - | ||||||||||||
| 331 | releaseKey(cacheKey); | - | ||||||||||||
| 332 | } never executed: end of block | 0 | ||||||||||||
| 333 | return success; never executed: return success; | 0 | ||||||||||||
| 334 | } | - | ||||||||||||
| 335 | - | |||||||||||||
| 336 | QPixmapCache::Key QPMCache::insert(const QPixmap &pixmap, int cost) | - | ||||||||||||
| 337 | { | - | ||||||||||||
| 338 | QPixmapCache::Key cacheKey = createKey(); | - | ||||||||||||
| 339 | bool success = QCache<QPixmapCache::Key, QPixmapCacheEntry>::insert(cacheKey, new QPixmapCacheEntry(cacheKey, pixmap), cost); | - | ||||||||||||
| 340 | if (success) {
| 0 | ||||||||||||
| 341 | if (!theid) {
| 0 | ||||||||||||
| 342 | theid = startTimer(flush_time); | - | ||||||||||||
| 343 | t = false; | - | ||||||||||||
| 344 | } never executed: end of block | 0 | ||||||||||||
| 345 | } else { never executed: end of block | 0 | ||||||||||||
| 346 | //Insertion failed we released the key and return an invalid one | - | ||||||||||||
| 347 | releaseKey(cacheKey); | - | ||||||||||||
| 348 | } never executed: end of block | 0 | ||||||||||||
| 349 | return cacheKey; never executed: return cacheKey; | 0 | ||||||||||||
| 350 | } | - | ||||||||||||
| 351 | - | |||||||||||||
| 352 | bool QPMCache::replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost) | - | ||||||||||||
| 353 | { | - | ||||||||||||
| 354 | Q_ASSERT(key.d->isValid); | - | ||||||||||||
| 355 | //If for the same key we had already an entry so we should delete the pixmap and use the new one | - | ||||||||||||
| 356 | QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(key); | - | ||||||||||||
| 357 | - | |||||||||||||
| 358 | QPixmapCache::Key cacheKey = createKey(); | - | ||||||||||||
| 359 | - | |||||||||||||
| 360 | bool success = QCache<QPixmapCache::Key, QPixmapCacheEntry>::insert(cacheKey, new QPixmapCacheEntry(cacheKey, pixmap), cost); | - | ||||||||||||
| 361 | if (success) {
| 0 | ||||||||||||
| 362 | if(!theid) {
| 0 | ||||||||||||
| 363 | theid = startTimer(flush_time); | - | ||||||||||||
| 364 | t = false; | - | ||||||||||||
| 365 | } never executed: end of block | 0 | ||||||||||||
| 366 | const_cast<QPixmapCache::Key&>(key) = cacheKey; | - | ||||||||||||
| 367 | } else { never executed: end of block | 0 | ||||||||||||
| 368 | //Insertion failed we released the key | - | ||||||||||||
| 369 | releaseKey(cacheKey); | - | ||||||||||||
| 370 | } never executed: end of block | 0 | ||||||||||||
| 371 | return success; never executed: return success; | 0 | ||||||||||||
| 372 | } | - | ||||||||||||
| 373 | - | |||||||||||||
| 374 | bool QPMCache::remove(const QString &key) | - | ||||||||||||
| 375 | { | - | ||||||||||||
| 376 | QPixmapCache::Key cacheKey = cacheKeys.value(key); | - | ||||||||||||
| 377 | //The key was not in the cache | - | ||||||||||||
| 378 | if (!cacheKey.d)
| 0 | ||||||||||||
| 379 | return false; never executed: return false; | 0 | ||||||||||||
| 380 | cacheKeys.remove(key); | - | ||||||||||||
| 381 | return QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(cacheKey); never executed: return QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(cacheKey); | 0 | ||||||||||||
| 382 | } | - | ||||||||||||
| 383 | - | |||||||||||||
| 384 | bool QPMCache::remove(const QPixmapCache::Key &key) | - | ||||||||||||
| 385 | { | - | ||||||||||||
| 386 | return QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(key); never executed: return QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(key); | 0 | ||||||||||||
| 387 | } | - | ||||||||||||
| 388 | - | |||||||||||||
| 389 | void QPMCache::resizeKeyArray(int size) | - | ||||||||||||
| 390 | { | - | ||||||||||||
| 391 | if (size <= keyArraySize || size == 0)
| 0 | ||||||||||||
| 392 | return; never executed: return; | 0 | ||||||||||||
| 393 | keyArray = q_check_ptr(reinterpret_cast<int *>(realloc(keyArray, | - | ||||||||||||
| 394 | size * sizeof(int)))); | - | ||||||||||||
| 395 | for (int i = keyArraySize; i != size; ++i)
| 0 | ||||||||||||
| 396 | keyArray[i] = i + 1; never executed: keyArray[i] = i + 1; | 0 | ||||||||||||
| 397 | keyArraySize = size; | - | ||||||||||||
| 398 | } never executed: end of block | 0 | ||||||||||||
| 399 | - | |||||||||||||
| 400 | QPixmapCache::Key QPMCache::createKey() | - | ||||||||||||
| 401 | { | - | ||||||||||||
| 402 | if (freeKey == keyArraySize)
| 0 | ||||||||||||
| 403 | resizeKeyArray(keyArraySize ? keyArraySize << 1 : 2); never executed: resizeKeyArray(keyArraySize ? keyArraySize << 1 : 2); | 0 | ||||||||||||
| 404 | int id = freeKey; | - | ||||||||||||
| 405 | freeKey = keyArray[id]; | - | ||||||||||||
| 406 | QPixmapCache::Key key; | - | ||||||||||||
| 407 | QPixmapCache::KeyData *d = QPMCache::getKeyData(&key); | - | ||||||||||||
| 408 | d->key = ++id; | - | ||||||||||||
| 409 | return key; never executed: return key; | 0 | ||||||||||||
| 410 | } | - | ||||||||||||
| 411 | - | |||||||||||||
| 412 | void QPMCache::releaseKey(const QPixmapCache::Key &key) | - | ||||||||||||
| 413 | { | - | ||||||||||||
| 414 | if (key.d->key > keyArraySize || key.d->key <= 0)
| 0 | ||||||||||||
| 415 | return; never executed: return; | 0 | ||||||||||||
| 416 | key.d->key--; | - | ||||||||||||
| 417 | keyArray[key.d->key] = freeKey; | - | ||||||||||||
| 418 | freeKey = key.d->key; | - | ||||||||||||
| 419 | key.d->isValid = false; | - | ||||||||||||
| 420 | key.d->key = 0; | - | ||||||||||||
| 421 | } never executed: end of block | 0 | ||||||||||||
| 422 | - | |||||||||||||
| 423 | void QPMCache::clear() | - | ||||||||||||
| 424 | { | - | ||||||||||||
| 425 | free(keyArray); | - | ||||||||||||
| 426 | keyArray = 0; | - | ||||||||||||
| 427 | freeKey = 0; | - | ||||||||||||
| 428 | keyArraySize = 0; | - | ||||||||||||
| 429 | //Mark all keys as invalid | - | ||||||||||||
| 430 | QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QPixmapCacheEntry>::keys(); | - | ||||||||||||
| 431 | for (int i = 0; i < keys.size(); ++i)
| 0 | ||||||||||||
| 432 | keys.at(i).d->isValid = false; never executed: keys.at(i).d->isValid = false; | 0 | ||||||||||||
| 433 | QCache<QPixmapCache::Key, QPixmapCacheEntry>::clear(); | - | ||||||||||||
| 434 | } never executed: end of block | 0 | ||||||||||||
| 435 | - | |||||||||||||
| 436 | QPixmapCache::KeyData* QPMCache::getKeyData(QPixmapCache::Key *key) | - | ||||||||||||
| 437 | { | - | ||||||||||||
| 438 | if (!key->d)
| 0 | ||||||||||||
| 439 | key->d = new QPixmapCache::KeyData; never executed: key->d = new QPixmapCache::KeyData; | 0 | ||||||||||||
| 440 | return key->d; never executed: return key->d; | 0 | ||||||||||||
| 441 | } | - | ||||||||||||
| 442 | - | |||||||||||||
| 443 | Q_GLOBAL_STATIC(QPMCache, pm_cache) never executed: end of blocknever executed: guard.store(QtGlobalStatic::Destroyed);never executed: return &holder.value;
| 0 | ||||||||||||
| 444 | - | |||||||||||||
| 445 | int Q_AUTOTEST_EXPORT q_QPixmapCache_keyHashSize() | - | ||||||||||||
| 446 | { | - | ||||||||||||
| 447 | return pm_cache()->size(); never executed: return pm_cache()->size(); | 0 | ||||||||||||
| 448 | } | - | ||||||||||||
| 449 | - | |||||||||||||
| 450 | QPixmapCacheEntry::~QPixmapCacheEntry() | - | ||||||||||||
| 451 | { | - | ||||||||||||
| 452 | pm_cache()->releaseKey(key); | - | ||||||||||||
| 453 | } never executed: end of block | 0 | ||||||||||||
| 454 | - | |||||||||||||
| 455 | /*! | - | ||||||||||||
| 456 | \obsolete | - | ||||||||||||
| 457 | \overload | - | ||||||||||||
| 458 | - | |||||||||||||
| 459 | Returns the pixmap associated with the \a key in the cache, or | - | ||||||||||||
| 460 | null if there is no such pixmap. | - | ||||||||||||
| 461 | - | |||||||||||||
| 462 | \warning If valid, you should copy the pixmap immediately (this is | - | ||||||||||||
| 463 | fast). Subsequent insertions into the cache could cause the | - | ||||||||||||
| 464 | pointer to become invalid. For this reason, we recommend you use | - | ||||||||||||
| 465 | bool find(const QString&, QPixmap*) instead. | - | ||||||||||||
| 466 | - | |||||||||||||
| 467 | Example: | - | ||||||||||||
| 468 | \snippet code/src_gui_image_qpixmapcache.cpp 0 | - | ||||||||||||
| 469 | */ | - | ||||||||||||
| 470 | - | |||||||||||||
| 471 | QPixmap *QPixmapCache::find(const QString &key) | - | ||||||||||||
| 472 | { | - | ||||||||||||
| 473 | return pm_cache()->object(key); never executed: return pm_cache()->object(key); | 0 | ||||||||||||
| 474 | } | - | ||||||||||||
| 475 | - | |||||||||||||
| 476 | - | |||||||||||||
| 477 | /*! | - | ||||||||||||
| 478 | \obsolete | - | ||||||||||||
| 479 | - | |||||||||||||
| 480 | Use bool find(const QString&, QPixmap*) instead. | - | ||||||||||||
| 481 | */ | - | ||||||||||||
| 482 | - | |||||||||||||
| 483 | bool QPixmapCache::find(const QString &key, QPixmap& pixmap) | - | ||||||||||||
| 484 | { | - | ||||||||||||
| 485 | return find(key, &pixmap); never executed: return find(key, &pixmap); | 0 | ||||||||||||
| 486 | } | - | ||||||||||||
| 487 | - | |||||||||||||
| 488 | /*! | - | ||||||||||||
| 489 | Looks for a cached pixmap associated with the given \a key in the cache. | - | ||||||||||||
| 490 | If the pixmap is found, the function sets \a pixmap to that pixmap and | - | ||||||||||||
| 491 | returns \c true; otherwise it leaves \a pixmap alone and returns \c false. | - | ||||||||||||
| 492 | - | |||||||||||||
| 493 | \since 4.6 | - | ||||||||||||
| 494 | - | |||||||||||||
| 495 | Example: | - | ||||||||||||
| 496 | \snippet code/src_gui_image_qpixmapcache.cpp 1 | - | ||||||||||||
| 497 | */ | - | ||||||||||||
| 498 | - | |||||||||||||
| 499 | bool QPixmapCache::find(const QString &key, QPixmap* pixmap) | - | ||||||||||||
| 500 | { | - | ||||||||||||
| 501 | QPixmap *ptr = pm_cache()->object(key); | - | ||||||||||||
| 502 | if (ptr && pixmap)
| 0 | ||||||||||||
| 503 | *pixmap = *ptr; never executed: *pixmap = *ptr; | 0 | ||||||||||||
| 504 | return ptr != 0; never executed: return ptr != 0; | 0 | ||||||||||||
| 505 | } | - | ||||||||||||
| 506 | - | |||||||||||||
| 507 | /*! | - | ||||||||||||
| 508 | Looks for a cached pixmap associated with the given \a key in the cache. | - | ||||||||||||
| 509 | If the pixmap is found, the function sets \a pixmap to that pixmap and | - | ||||||||||||
| 510 | returns \c true; otherwise it leaves \a pixmap alone and returns \c false. If | - | ||||||||||||
| 511 | the pixmap is not found, it means that the \a key is no longer valid, | - | ||||||||||||
| 512 | so it will be released for the next insertion. | - | ||||||||||||
| 513 | - | |||||||||||||
| 514 | \since 4.6 | - | ||||||||||||
| 515 | */ | - | ||||||||||||
| 516 | bool QPixmapCache::find(const Key &key, QPixmap* pixmap) | - | ||||||||||||
| 517 | { | - | ||||||||||||
| 518 | //The key is not valid anymore, a flush happened before probably | - | ||||||||||||
| 519 | if (!key.d || !key.d->isValid)
| 0 | ||||||||||||
| 520 | return false; never executed: return false; | 0 | ||||||||||||
| 521 | QPixmap *ptr = pm_cache()->object(key); | - | ||||||||||||
| 522 | if (ptr && pixmap)
| 0 | ||||||||||||
| 523 | *pixmap = *ptr; never executed: *pixmap = *ptr; | 0 | ||||||||||||
| 524 | return ptr != 0; never executed: return ptr != 0; | 0 | ||||||||||||
| 525 | } | - | ||||||||||||
| 526 | - | |||||||||||||
| 527 | /*! | - | ||||||||||||
| 528 | Inserts a copy of the pixmap \a pixmap associated with the \a key into | - | ||||||||||||
| 529 | the cache. | - | ||||||||||||
| 530 | - | |||||||||||||
| 531 | All pixmaps inserted by the Qt library have a key starting with | - | ||||||||||||
| 532 | "$qt", so your own pixmap keys should never begin "$qt". | - | ||||||||||||
| 533 | - | |||||||||||||
| 534 | When a pixmap is inserted and the cache is about to exceed its | - | ||||||||||||
| 535 | limit, it removes pixmaps until there is enough room for the | - | ||||||||||||
| 536 | pixmap to be inserted. | - | ||||||||||||
| 537 | - | |||||||||||||
| 538 | The oldest pixmaps (least recently accessed in the cache) are | - | ||||||||||||
| 539 | deleted when more space is needed. | - | ||||||||||||
| 540 | - | |||||||||||||
| 541 | The function returns \c true if the object was inserted into the | - | ||||||||||||
| 542 | cache; otherwise it returns \c false. | - | ||||||||||||
| 543 | - | |||||||||||||
| 544 | \sa setCacheLimit() | - | ||||||||||||
| 545 | */ | - | ||||||||||||
| 546 | - | |||||||||||||
| 547 | bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap) | - | ||||||||||||
| 548 | { | - | ||||||||||||
| 549 | return pm_cache()->insert(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); never executed: return pm_cache()->insert(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); | 0 | ||||||||||||
| 550 | } | - | ||||||||||||
| 551 | - | |||||||||||||
| 552 | /*! | - | ||||||||||||
| 553 | Inserts a copy of the given \a pixmap into the cache and returns a key | - | ||||||||||||
| 554 | that can be used to retrieve it. | - | ||||||||||||
| 555 | - | |||||||||||||
| 556 | When a pixmap is inserted and the cache is about to exceed its | - | ||||||||||||
| 557 | limit, it removes pixmaps until there is enough room for the | - | ||||||||||||
| 558 | pixmap to be inserted. | - | ||||||||||||
| 559 | - | |||||||||||||
| 560 | The oldest pixmaps (least recently accessed in the cache) are | - | ||||||||||||
| 561 | deleted when more space is needed. | - | ||||||||||||
| 562 | - | |||||||||||||
| 563 | \sa setCacheLimit(), replace() | - | ||||||||||||
| 564 | - | |||||||||||||
| 565 | \since 4.6 | - | ||||||||||||
| 566 | */ | - | ||||||||||||
| 567 | QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap) | - | ||||||||||||
| 568 | { | - | ||||||||||||
| 569 | return pm_cache()->insert(pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); never executed: return pm_cache()->insert(pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); | 0 | ||||||||||||
| 570 | } | - | ||||||||||||
| 571 | - | |||||||||||||
| 572 | /*! | - | ||||||||||||
| 573 | Replaces the pixmap associated with the given \a key with the \a pixmap | - | ||||||||||||
| 574 | specified. Returns \c true if the \a pixmap has been correctly inserted into | - | ||||||||||||
| 575 | the cache; otherwise returns \c false. | - | ||||||||||||
| 576 | - | |||||||||||||
| 577 | \sa setCacheLimit(), insert() | - | ||||||||||||
| 578 | - | |||||||||||||
| 579 | \since 4.6 | - | ||||||||||||
| 580 | */ | - | ||||||||||||
| 581 | bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap) | - | ||||||||||||
| 582 | { | - | ||||||||||||
| 583 | //The key is not valid anymore, a flush happened before probably | - | ||||||||||||
| 584 | if (!key.d || !key.d->isValid)
| 0 | ||||||||||||
| 585 | return false; never executed: return false; | 0 | ||||||||||||
| 586 | return pm_cache()->replace(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); never executed: return pm_cache()->replace(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); | 0 | ||||||||||||
| 587 | } | - | ||||||||||||
| 588 | - | |||||||||||||
| 589 | /*! | - | ||||||||||||
| 590 | Returns the cache limit (in kilobytes). | - | ||||||||||||
| 591 | - | |||||||||||||
| 592 | The default cache limit is 10240 KB. | - | ||||||||||||
| 593 | - | |||||||||||||
| 594 | \sa setCacheLimit() | - | ||||||||||||
| 595 | */ | - | ||||||||||||
| 596 | - | |||||||||||||
| 597 | int QPixmapCache::cacheLimit() | - | ||||||||||||
| 598 | { | - | ||||||||||||
| 599 | return cache_limit; never executed: return cache_limit; | 0 | ||||||||||||
| 600 | } | - | ||||||||||||
| 601 | - | |||||||||||||
| 602 | /*! | - | ||||||||||||
| 603 | Sets the cache limit to \a n kilobytes. | - | ||||||||||||
| 604 | - | |||||||||||||
| 605 | The default setting is 10240 KB. | - | ||||||||||||
| 606 | - | |||||||||||||
| 607 | \sa cacheLimit() | - | ||||||||||||
| 608 | */ | - | ||||||||||||
| 609 | - | |||||||||||||
| 610 | void QPixmapCache::setCacheLimit(int n) | - | ||||||||||||
| 611 | { | - | ||||||||||||
| 612 | cache_limit = n; | - | ||||||||||||
| 613 | pm_cache()->setMaxCost(1024 * cache_limit); | - | ||||||||||||
| 614 | } never executed: end of block | 0 | ||||||||||||
| 615 | - | |||||||||||||
| 616 | /*! | - | ||||||||||||
| 617 | Removes the pixmap associated with \a key from the cache. | - | ||||||||||||
| 618 | */ | - | ||||||||||||
| 619 | void QPixmapCache::remove(const QString &key) | - | ||||||||||||
| 620 | { | - | ||||||||||||
| 621 | pm_cache()->remove(key); | - | ||||||||||||
| 622 | } never executed: end of block | 0 | ||||||||||||
| 623 | - | |||||||||||||
| 624 | /*! | - | ||||||||||||
| 625 | Removes the pixmap associated with \a key from the cache and releases | - | ||||||||||||
| 626 | the key for a future insertion. | - | ||||||||||||
| 627 | - | |||||||||||||
| 628 | \since 4.6 | - | ||||||||||||
| 629 | */ | - | ||||||||||||
| 630 | void QPixmapCache::remove(const Key &key) | - | ||||||||||||
| 631 | { | - | ||||||||||||
| 632 | //The key is not valid anymore, a flush happened before probably | - | ||||||||||||
| 633 | if (!key.d || !key.d->isValid)
| 0 | ||||||||||||
| 634 | return; never executed: return; | 0 | ||||||||||||
| 635 | pm_cache()->remove(key); | - | ||||||||||||
| 636 | } never executed: end of block | 0 | ||||||||||||
| 637 | - | |||||||||||||
| 638 | /*! | - | ||||||||||||
| 639 | Removes all pixmaps from the cache. | - | ||||||||||||
| 640 | */ | - | ||||||||||||
| 641 | - | |||||||||||||
| 642 | void QPixmapCache::clear() | - | ||||||||||||
| 643 | { | - | ||||||||||||
| 644 | QT_TRY { | - | ||||||||||||
| 645 | if (pm_cache.exists())
| 0 | ||||||||||||
| 646 | pm_cache->clear(); never executed: pm_cache->clear(); | 0 | ||||||||||||
| 647 | } QT_CATCH(const std::bad_alloc &) { never executed: end of blockdead code: { } | - | ||||||||||||
| 648 | // if we ran out of memory during pm_cache(), it's no leak, dead code: { } | - | ||||||||||||
| 649 | // so just ignore it. dead code: { } | - | ||||||||||||
| 650 | } dead code: { } | - | ||||||||||||
| 651 | } | - | ||||||||||||
| 652 | - | |||||||||||||
| 653 | void QPixmapCache::flushDetachedPixmaps() | - | ||||||||||||
| 654 | { | - | ||||||||||||
| 655 | pm_cache()->flushDetachedPixmaps(true); | - | ||||||||||||
| 656 | } never executed: end of block | 0 | ||||||||||||
| 657 | - | |||||||||||||
| 658 | int QPixmapCache::totalUsed() | - | ||||||||||||
| 659 | { | - | ||||||||||||
| 660 | return (pm_cache()->totalCost()+1023) / 1024; never executed: return (pm_cache()->totalCost()+1023) / 1024; | 0 | ||||||||||||
| 661 | } | - | ||||||||||||
| 662 | - | |||||||||||||
| 663 | /*! | - | ||||||||||||
| 664 | \fn QPixmapCache::KeyData::KeyData() | - | ||||||||||||
| 665 | - | |||||||||||||
| 666 | \internal | - | ||||||||||||
| 667 | */ | - | ||||||||||||
| 668 | /*! | - | ||||||||||||
| 669 | \fn QPixmapCache::KeyData::KeyData(const KeyData &other) | - | ||||||||||||
| 670 | \internal | - | ||||||||||||
| 671 | */ | - | ||||||||||||
| 672 | /*! | - | ||||||||||||
| 673 | \fn QPixmapCache::KeyData::~KeyData() | - | ||||||||||||
| 674 | - | |||||||||||||
| 675 | \internal | - | ||||||||||||
| 676 | */ | - | ||||||||||||
| 677 | QT_END_NAMESPACE | - | ||||||||||||
| Source code | Switch to Preprocessed file |