1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-28 13:41:16 +01:00

QPixmap is not thread safe, do the parallel computations on QImage

This commit is contained in:
Martin Tůma 2018-11-10 10:40:00 +01:00
parent 409ce889cd
commit c1a217847f
2 changed files with 47 additions and 32 deletions

View File

@ -15,25 +15,34 @@
#include "mbtilesmap.h" #include "mbtilesmap.h"
struct MBTile class MBTile
{ {
public: public:
MBTile() {} MBTile(int zoom, const QPoint &xy, const QByteArray &data,
MBTile(const QPoint &xy) : xy(xy) {} const QString &key) : _zoom(zoom), _xy(xy), _data(data), _key(key) {}
QPixmap pixmap; const QPoint &xy() const {return _xy;}
QByteArray data; const QString &key() const {return _key;}
QString key; QPixmap pixmap() const {return QPixmap::fromImage(_image);}
int zoom;
QPoint xy; void load() {
QByteArray z(QString::number(_zoom).toLatin1());
_image.loadFromData(_data, z);
}
private:
int _zoom;
QPoint _xy;
QByteArray _data;
QString _key;
QImage _image;
}; };
#define META_TYPE(type) static_cast<QMetaType::Type>(type) #define META_TYPE(type) static_cast<QMetaType::Type>(type)
static void render(MBTile *tile) static void render(MBTile &tile)
{ {
tile->pixmap.loadFromData(tile->data, QString::number(tile->zoom) tile.load();
.toLatin1());
} }
static double index2mercator(int index, int zoom) static double index2mercator(int index, int zoom)
@ -249,43 +258,48 @@ void MBTilesMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
int width = ceil(s.width() / tileSize()); int width = ceil(s.width() / tileSize());
int height = ceil(s.height() / tileSize()); int height = ceil(s.height() / tileSize());
QList<MBTile*> jobs;
QVector<MBTile> tiles; QList<MBTile> tiles;
tiles.reserve(width * height);
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) { for (int j = 0; j < height; j++) {
QPixmap pm;
QPoint t(tile.x() + i, tile.y() + j); QPoint t(tile.x() + i, tile.y() + j);
QString key = _fileName + "-" + QString::number(_zoom) + "_" QString key = _fileName + "-" + QString::number(_zoom) + "_"
+ QString::number(t.x()) + "_" + QString::number(t.y()); + QString::number(t.x()) + "_" + QString::number(t.y());
tiles.append(MBTile(t)); if (QPixmapCache::find(key, pm)) {
MBTile &mt = tiles.last(); QPointF tp(qMax(tl.x(), b.left()) + (t.x() - tile.x())
if (!QPixmapCache::find(key, &(mt.pixmap))) { * tileSize(), qMax(tl.y(), b.top()) + (t.y() - tile.y())
mt.data = tileData(_zoom, t); * tileSize());
mt.key = key; drawTile(painter, pm, tp);
mt.zoom = _zoom; } else
jobs.append(&mt); tiles.append(MBTile(_zoom, t, tileData(_zoom, t), key));
}
} }
} }
QFuture<void> future = QtConcurrent::map(jobs, render); QFuture<void> future = QtConcurrent::map(tiles, render);
future.waitForFinished(); future.waitForFinished();
for (int i = 0; i < tiles.size(); i++) { for (int i = 0; i < tiles.size(); i++) {
MBTile &mt = tiles[i]; const MBTile &mt = tiles.at(i);
if (!mt.pixmap.isNull() && !mt.data.isNull()) QPixmap pm(mt.pixmap());
QPixmapCache::insert(mt.key, mt.pixmap); if (!pm.isNull())
QPixmapCache::insert(mt.key(), pm);
QPointF tp(qMax(tl.x(), b.left()) + (mt.xy.x() - tile.x()) * tileSize(), QPointF tp(qMax(tl.x(), b.left()) + (mt.xy().x() - tile.x()) * tileSize(),
qMax(tl.y(), b.top()) + (mt.xy.y() - tile.y()) * tileSize()); qMax(tl.y(), b.top()) + (mt.xy().y() - tile.y()) * tileSize());
if (!mt.pixmap.isNull()) { drawTile(painter, pm, tp);
#ifdef ENABLE_HIDPI
mt.pixmap.setDevicePixelRatio(imageRatio());
#endif // ENABLE_HIDPI
painter->drawPixmap(tp, mt.pixmap);
} }
}
void MBTilesMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp)
{
if (!pixmap.isNull()) {
#ifdef ENABLE_HIDPI
pixmap.setDevicePixelRatio(imageRatio());
#endif // ENABLE_HIDPI
painter->drawPixmap(tp, pixmap);
} }
} }

View File

@ -40,6 +40,7 @@ private:
qreal coordinatesRatio() const; qreal coordinatesRatio() const;
qreal imageRatio() const; qreal imageRatio() const;
QByteArray tileData(int zoom, const QPoint &tile) const; QByteArray tileData(int zoom, const QPoint &tile) const;
void drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp);
QSqlDatabase _db; QSqlDatabase _db;