diff --git a/src/libtiled/imagecache.cpp b/src/libtiled/imagecache.cpp index e6afa35b5a..6b24e2b298 100644 --- a/src/libtiled/imagecache.cpp +++ b/src/libtiled/imagecache.cpp @@ -29,6 +29,7 @@ #include "imagecache.h" #include +#include namespace Tiled { @@ -53,36 +54,62 @@ uint qHash(const TilesheetParameters &key, uint seed) Q_DECL_NOTHROW return h; } +LoadedImage::LoadedImage(const QString &fileName) + : image(fileName) + , lastModified(QFileInfo(fileName).lastModified()) +{} -QHash ImageCache::sLoadedImages; -QHash ImageCache::sLoadedPixmaps; -QHash> ImageCache::sCutTiles; +LoadedPixmap::LoadedPixmap(const LoadedImage &cachedImage) + : pixmap(QPixmap::fromImage(cachedImage)) + , lastModified(cachedImage.lastModified) +{} -QImage ImageCache::loadImage(const QString &fileName) + +QHash ImageCache::sLoadedImages; +QHash ImageCache::sLoadedPixmaps; +QHash ImageCache::sCutTiles; + +LoadedImage ImageCache::loadImage(const QString &fileName) { auto it = sLoadedImages.find(fileName); - if (it == sLoadedImages.end()) - it = sLoadedImages.insert(fileName, QImage(fileName)); + + bool found = it != sLoadedImages.end(); + bool old = found && it.value().lastModified < QFileInfo(fileName).lastModified(); + + if (old) + remove(fileName); + if (old || !found) + it = sLoadedImages.insert(fileName, LoadedImage(fileName)); + return it.value(); } QPixmap ImageCache::loadPixmap(const QString &fileName) { auto it = sLoadedPixmaps.find(fileName); - if (it == sLoadedPixmaps.end()) - it = sLoadedPixmaps.insert(fileName, QPixmap::fromImage(loadImage(fileName))); + + bool found = it != sLoadedPixmaps.end(); + bool old = found && it.value().lastModified < QFileInfo(fileName).lastModified(); + + if (old) + remove(fileName); + if (old || !found) + it = sLoadedPixmaps.insert(fileName, LoadedPixmap(loadImage(fileName))); + return it.value(); } -static QVector cutTilesImpl(const TilesheetParameters &p) +static CutTiles cutTilesImpl(const TilesheetParameters &p) { Q_ASSERT(p.tileWidth > 0 && p.tileHeight > 0); - const QImage image(ImageCache::loadImage(p.fileName)); + const LoadedImage loadedImage = ImageCache::loadImage(p.fileName); + const QImage &image = loadedImage.image; const int stopWidth = image.width() - p.tileWidth; const int stopHeight = image.height() - p.tileHeight; - QVector tiles; + CutTiles result; + result.lastModified = loadedImage.lastModified; for (int y = p.margin; y <= stopHeight; y += p.tileHeight + p.spacing) { for (int x = p.margin; x <= stopWidth; x += p.tileWidth + p.spacing) { @@ -94,18 +121,25 @@ static QVector cutTilesImpl(const TilesheetParameters &p) tilePixmap.setMask(QBitmap::fromImage(mask)); } - tiles.append(tilePixmap); + result.tiles.append(tilePixmap); } } - return tiles; + return result; } QVector ImageCache::cutTiles(const TilesheetParameters ¶meters) { auto it = sCutTiles.find(parameters); - if (it == sCutTiles.end()) + + bool found = it != sCutTiles.end(); + bool old = found && it.value().lastModified < QFileInfo(parameters.fileName).lastModified(); + + if (old) + remove(parameters.fileName); + if (old || !found) it = sCutTiles.insert(parameters, cutTilesImpl(parameters)); + return it.value(); } @@ -115,7 +149,7 @@ void ImageCache::remove(const QString &fileName) sLoadedPixmaps.remove(fileName); // Also remove any previously cut tiles - QMutableHashIterator> it(sCutTiles); + QMutableHashIterator it(sCutTiles); while (it.hasNext()) { if (it.next().key().fileName == fileName) it.remove(); diff --git a/src/libtiled/imagecache.h b/src/libtiled/imagecache.h index 77b4a14363..a2309a2f0b 100644 --- a/src/libtiled/imagecache.h +++ b/src/libtiled/imagecache.h @@ -32,6 +32,7 @@ #include "tiled_global.h" #include +#include #include #include #include @@ -53,18 +54,47 @@ struct TILEDSHARED_EXPORT TilesheetParameters uint TILEDSHARED_EXPORT qHash(const TilesheetParameters &key, uint seed = 0) Q_DECL_NOTHROW; +struct LoadedImage +{ + explicit LoadedImage(const QString &fileName); + + operator const QImage &() const { return image; } + + QImage image; + QDateTime lastModified; +}; + +struct LoadedPixmap +{ + explicit LoadedPixmap(const LoadedImage &cachedImage); + + operator const QPixmap &() const { return pixmap; } + + QPixmap pixmap; + QDateTime lastModified; +}; + +struct CutTiles +{ + operator const QVector &() const { return tiles; } + + QVector tiles; + QDateTime lastModified; +}; + class TILEDSHARED_EXPORT ImageCache { public: - static QImage loadImage(const QString &fileName); + static LoadedImage loadImage(const QString &fileName); static QPixmap loadPixmap(const QString &fileName); static QVector cutTiles(const TilesheetParameters ¶meters); static void remove(const QString &fileName); - static QHash sLoadedImages; - static QHash sLoadedPixmaps; - static QHash> sCutTiles; +private: + static QHash sLoadedImages; + static QHash sLoadedPixmaps; + static QHash sCutTiles; }; } // namespace Tiled diff --git a/src/libtiled/tileset.cpp b/src/libtiled/tileset.cpp index 966f858abb..ad7363151d 100644 --- a/src/libtiled/tileset.cpp +++ b/src/libtiled/tileset.cpp @@ -293,7 +293,7 @@ bool Tileset::loadImage() p.margin = mMargin; p.transparentColor = mImageReference.transparentColor; - auto image = ImageCache::loadImage(p.fileName); + QImage image = ImageCache::loadImage(p.fileName); if (image.isNull()) { mImageReference.status = LoadingError; return false;