diff --git a/src/map/mapsource.cpp b/src/map/mapsource.cpp index 8fbad6d4..8695128b 100644 --- a/src/map/mapsource.cpp +++ b/src/map/mapsource.cpp @@ -9,7 +9,7 @@ MapSource::Config::Config() : type(OSM), zooms(OSM::ZOOMS), bounds(OSM::BOUNDS), - format("image/png"), rest(false), tileRatio(1.0) {} + format("image/png"), rest(false), tileRatio(1.0), scalable(false) {} static CoordinateSystem coordinateSystem(QXmlStreamReader &reader) @@ -178,6 +178,10 @@ void MapSource::map(QXmlStreamReader &reader, Config &config) #else // ENABLE_HIDPI reader.raiseError("HiDPI maps not supported"); #endif // ENABLE_HIDPI + } else if (reader.name() == "scalable") { + QString val = reader.readElementText().trimmed(); + if (val == "true" || val == "1") + config.scalable = true; } else reader.skipCurrentElement(); } @@ -250,10 +254,12 @@ Map *MapSource::loadMap(const QString &path, QString &errorString) config.dimensions, config.authorization)); case TMS: return new OnlineMap(config.name, config.url, config.zooms, - config.bounds, config.tileRatio, config.authorization, true); + config.bounds, config.tileRatio, config.authorization, + config.scalable, true); case OSM: return new OnlineMap(config.name, config.url, config.zooms, - config.bounds, config.tileRatio, config.authorization, false); + config.bounds, config.tileRatio, config.authorization, + config.scalable, false); default: return 0; } diff --git a/src/map/mapsource.h b/src/map/mapsource.h index 61ff618f..99520f33 100644 --- a/src/map/mapsource.h +++ b/src/map/mapsource.h @@ -40,6 +40,7 @@ private: QList dimensions; Authorization authorization; qreal tileRatio; + bool scalable; Config(); }; diff --git a/src/map/mbtilesmap.cpp b/src/map/mbtilesmap.cpp index 7384eda1..55ad1ea7 100644 --- a/src/map/mbtilesmap.cpp +++ b/src/map/mbtilesmap.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #include #else // QT_VERSION < 5 @@ -18,8 +20,9 @@ class MBTile { public: - MBTile(int zoom, const QPoint &xy, const QByteArray &data, - const QString &key) : _zoom(zoom), _xy(xy), _data(data), _key(key) {} + MBTile(int zoom, int scaledSize, const QPoint &xy, const QByteArray &data, + const QString &key) : _zoom(zoom), _scaledSize(scaledSize), _xy(xy), + _data(data), _key(key) {} const QPoint &xy() const {return _xy;} const QString &key() const {return _key;} @@ -27,11 +30,17 @@ public: void load() { QByteArray z(QString::number(_zoom).toLatin1()); - _image.loadFromData(_data, z); + + QBuffer buffer(&_data); + QImageReader reader(&buffer, z); + if (_scaledSize) + reader.setScaledSize(QSize(_scaledSize, _scaledSize)); + reader.read(&_image); } private: int _zoom; + int _scaledSize; QPoint _xy; QByteArray _data; QString _key; @@ -52,7 +61,7 @@ static double index2mercator(int index, int zoom) MBTilesMap::MBTilesMap(const QString &fileName, QObject *parent) : Map(parent), _fileName(fileName), _deviceRatio(1.0), _tileRatio(1.0), - _valid(false) + _scalable(false), _scaledSize(0), _valid(false) { _db = QSqlDatabase::addDatabase("QSQLITE", fileName); _db.setDatabaseName(fileName); @@ -118,12 +127,26 @@ MBTilesMap::MBTilesMap(const QString &fileName, QObject *parent) QString sql = QString("SELECT tile_data FROM tiles LIMIT 1"); QSqlQuery query(sql, _db); query.first(); - QImage tile = QImage::fromData(query.value(0).toByteArray()); - if (tile.isNull() || tile.size().width() != tile.size().height()) { + + QByteArray data = query.value(0).toByteArray(); + QBuffer buffer(&data); + QImageReader reader(&buffer); + QSize tileSize(reader.size()); + + if (tileSize.isNull() || tileSize.width() != tileSize.height()) { _errorString = "Unsupported/invalid tile images"; return; } - _tileSize = tile.size().width(); + _tileSize = tileSize.width(); + } + + { + QSqlQuery query("SELECT value FROM metadata WHERE name = 'format'", _db); + if (query.first()) { + if (query.value(0).toString() == "pbf") + _scalable = true; + } else + qWarning("%s: missing map name", qPrintable(_fileName)); } { @@ -210,6 +233,16 @@ int MBTilesMap::zoomOut() return _zoom; } +void MBTilesMap::setDevicePixelRatio(qreal ratio) +{ + _deviceRatio = ratio; + + if (_scalable) { + _scaledSize = _tileSize * ratio; + _tileRatio = ratio; + } +} + qreal MBTilesMap::coordinatesRatio() const { return _deviceRatio > 1.0 ? _deviceRatio / _tileRatio : 1.0; @@ -273,8 +306,10 @@ void MBTilesMap::draw(QPainter *painter, const QRectF &rect, Flags flags) * tileSize(), qMax(tl.y(), b.top()) + (t.y() - tile.y()) * tileSize()); drawTile(painter, pm, tp); - } else - tiles.append(MBTile(_zoom, t, tileData(_zoom, t), key)); + } else { + tiles.append(MBTile(_zoom, _scaledSize, t, tileData(_zoom, t), + key)); + } } } diff --git a/src/map/mbtilesmap.h b/src/map/mbtilesmap.h index 450c966b..f8eefc96 100644 --- a/src/map/mbtilesmap.h +++ b/src/map/mbtilesmap.h @@ -29,7 +29,7 @@ public: void load(); void unload(); - void setDevicePixelRatio(qreal ratio) {_deviceRatio = ratio;} + void setDevicePixelRatio(qreal ratio); bool isValid() const {return _valid;} QString errorString() const {return _errorString;} @@ -50,6 +50,8 @@ private: int _zoom; int _tileSize; qreal _deviceRatio, _tileRatio; + bool _scalable; + int _scaledSize; bool _valid; QString _errorString; diff --git a/src/map/onlinemap.cpp b/src/map/onlinemap.cpp index 77b92059..759b1cf3 100644 --- a/src/map/onlinemap.cpp +++ b/src/map/onlinemap.cpp @@ -12,10 +12,11 @@ OnlineMap::OnlineMap(const QString &name, const QString &url, const Range &zooms, const RectC &bounds, qreal tileRatio, - const Authorization &authorization, bool invertY, QObject *parent) + const Authorization &authorization, bool scalable, bool invertY, + QObject *parent) : Map(parent), _name(name), _zooms(zooms), _bounds(bounds), _zoom(_zooms.max()), _deviceRatio(1.0), _tileRatio(tileRatio), - _invertY(invertY) + _scalable(scalable), _scaledSize(0), _invertY(invertY) { _tileLoader = new TileLoader(QDir(ProgramPaths::tilesDir()).filePath(_name), this); @@ -70,6 +71,16 @@ int OnlineMap::zoomOut() return _zoom; } +void OnlineMap::setDevicePixelRatio(qreal ratio) +{ + _deviceRatio = ratio; + + if (_scalable) { + _scaledSize = TILE_SIZE * ratio; + _tileRatio = ratio; + } +} + qreal OnlineMap::coordinatesRatio() const { return _deviceRatio > 1.0 ? _deviceRatio / _tileRatio : 1.0; @@ -103,7 +114,7 @@ void OnlineMap::draw(QPainter *painter, const QRectF &rect, Flags flags) for (int i = 0; i < width; i++) for (int j = 0; j < height; j++) tiles.append(Tile(QPoint(tile.x() + i, _invertY ? (1<<_zoom) - - (tile.y() + j) - 1 : tile.y() + j), _zoom)); + - (tile.y() + j) - 1 : tile.y() + j), _zoom, _scaledSize)); if (flags & Map::Block) _tileLoader->loadTilesSync(tiles); diff --git a/src/map/onlinemap.h b/src/map/onlinemap.h index 146e3638..4ac0b6d7 100644 --- a/src/map/onlinemap.h +++ b/src/map/onlinemap.h @@ -13,7 +13,7 @@ class OnlineMap : public Map public: OnlineMap(const QString &name, const QString &url, const Range &zooms, const RectC &bounds, qreal tileRatio, const Authorization &authorization, - bool invertY, QObject *parent = 0); + bool scalable, bool invertY, QObject *parent = 0); QString name() const {return _name;} @@ -31,7 +31,7 @@ public: void draw(QPainter *painter, const QRectF &rect, Flags flags); - void setDevicePixelRatio(qreal ratio) {_deviceRatio = ratio;} + void setDevicePixelRatio(qreal ratio); void clearCache() {_tileLoader->clearCache();} private: @@ -46,6 +46,8 @@ private: RectC _bounds; int _zoom; qreal _deviceRatio, _tileRatio; + bool _scalable; + int _scaledSize; bool _invertY; }; diff --git a/src/map/tile.h b/src/map/tile.h index a90651c5..bbbec272 100644 --- a/src/map/tile.h +++ b/src/map/tile.h @@ -11,17 +11,20 @@ class Tile { public: Tile() {} - Tile(const QPoint &xy, const QVariant &zoom, const RectD &bbox = RectD()) - {_xy = xy; _zoom = zoom; _bbox = bbox;} + Tile(const QPoint &xy, const QVariant &zoom, int scaledSize = 0, + const RectD &bbox = RectD()) : _xy(xy), _zoom(zoom), + _scaledSize(scaledSize), _bbox(bbox) {} const QVariant &zoom() const {return _zoom;} const QPoint &xy() const {return _xy;} const RectD &bbox() const {return _bbox;} + int scaledSize() const {return _scaledSize;} QPixmap& pixmap() {return _pixmap;} private: - QVariant _zoom; QPoint _xy; + QVariant _zoom; + int _scaledSize; RectD _bbox; QPixmap _pixmap; }; diff --git a/src/map/tileloader.cpp b/src/map/tileloader.cpp index 75c69b70..ec727080 100644 --- a/src/map/tileloader.cpp +++ b/src/map/tileloader.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #include #else // QT_VERSION < 5 @@ -24,7 +25,10 @@ public: void load() { QByteArray z(_tile->zoom().toString().toLatin1()); - _image.load(_file, z); + QImageReader reader(_file, z); + if (_tile->scaledSize()) + reader.setScaledSize(QSize(_tile->scaledSize(), _tile->scaledSize())); + reader.read(&_image); } const QString &file() const {return _file;} diff --git a/src/map/wmsmap.cpp b/src/map/wmsmap.cpp index 73bf2b87..979d7974 100644 --- a/src/map/wmsmap.cpp +++ b/src/map/wmsmap.cpp @@ -206,7 +206,7 @@ void WMSMap::draw(QPainter *painter, const QRectF &rect, Flags flags) ? RectD(PointD(tbr.y(), tbr.x()), PointD(ttl.y(), ttl.x())) : RectD(ttl, tbr); - tiles.append(Tile(QPoint(i, j), _zoom, bbox)); + tiles.append(Tile(QPoint(i, j), _zoom, 0, bbox)); } }