diff --git a/src/map/mapsforge/mapdata.cpp b/src/map/mapsforge/mapdata.cpp index bc90e795..6be62e12 100644 --- a/src/map/mapsforge/mapdata.cpp +++ b/src/map/mapsforge/mapdata.cpp @@ -15,6 +15,11 @@ using namespace Mapsforge; #define MD(val) ((val) / 1e6) #define OFFSET_MASK 0x7FFFFFFFFFL +#define KEY_NAME "name" +#define KEY_HOUSE "addr:housenumber" +#define KEY_REF "ref" +#define KEY_ELE "ele" + static void copyPaths(const RectC &rect, const QList *src, QList *dst) { @@ -43,65 +48,6 @@ static bool isClosed(const Polygon &poly) return (distance(poly.first().first(), poly.first().last()) < 0.000000001); } -static bool readTags(SubFile &subfile, int count, - const QVector &tags, QVector &list) -{ - QVector ids(count); - - list.resize(count); - - for (int i = 0; i < count; i++) { - if (!subfile.readVUInt32(ids[i])) - return false; - if (ids[i] >= (quint32)tags.size()) - return false; - } - - for (int i = 0; i < count; i++) { - const MapData::Tag &tag = tags.at(ids.at(i)); - - if (tag.value.length() == 2 && tag.value.at(0) == '%') { - QByteArray value; - - if (tag.value.at(1) == 'b') { - quint8 b; - if (!subfile.readByte(b)) - return false; - value.setNum(b); - } else if (tag.value.at(1) == 'i') { - qint32 u; - if (!subfile.readInt32(u)) - return false; - - if (tag.key.contains(":colour")) - value = QColor((quint32)u).name().toLatin1(); - else - value.setNum(u); - } else if (tag.value.at(1) == 'f') { - quint32 u; - if (!subfile.readUInt32(u)) - return false; - float *f = (float *)&u; - value.setNum(*f); - } else if (tag.value.at(1) == 'h') { - quint16 s; - if (!subfile.readUInt16(s)) - return false; - value.setNum(s); - } else if (tag.value.at(1) == 's') { - if (!subfile.readString(value)) - return false; - } else - value = tag.value; - - list[i] = MapData::Tag(tag.key, value); - } else - list[i] = tag; - } - - return true; -} - static bool readSingleDelta(SubFile &subfile, const Coordinates &c, int count, QVector &nodes) { @@ -204,6 +150,64 @@ static bool readOffset(QDataStream &stream, quint64 &offset) return (stream.status() == QDataStream::Ok); } +bool MapData::readTags(SubFile &subfile, int count, + const QVector &tags, QVector &list) +{ + QVector ids(count); + + list.resize(count); + + for (int i = 0; i < count; i++) { + if (!subfile.readVUInt32(ids[i])) + return false; + if (ids[i] >= (quint32)tags.size()) + return false; + } + + for (int i = 0; i < count; i++) { + const TagSource &tag = tags.at(ids.at(i)); + + if (tag.value.length() == 2 && tag.value.at(0) == '%') { + QByteArray value; + + if (tag.value.at(1) == 'b') { + quint8 b; + if (!subfile.readByte(b)) + return false; + value.setNum(b); + } else if (tag.value.at(1) == 'i') { + qint32 u; + if (!subfile.readInt32(u)) + return false; + if (tag.key.contains(":colour")) + value = QColor((quint32)u).name().toLatin1(); + else + value.setNum(u); + } else if (tag.value.at(1) == 'f') { + quint32 u; + if (!subfile.readUInt32(u)) + return false; + float *f = (float *)&u; + value.setNum(*f); + } else if (tag.value.at(1) == 'h') { + quint16 s; + if (!subfile.readUInt16(s)) + return false; + value.setNum(s); + } else if (tag.value.at(1) == 's') { + if (!subfile.readString(value)) + return false; + } else + value = tag.value; + + list[i] = MapData::Tag(tag.id, value); + } else + list[i] = MapData::Tag(tag.id, tag.value); + } + + return true; +} + bool MapData::readSubFiles() { QDataStream stream(&_file); @@ -273,34 +277,43 @@ bool MapData::readZoomInfo(SubFile &hdr) return true; } -bool MapData::readTagInfo(SubFile &hdr) +bool MapData::readTagInfo(SubFile &hdr, QVector &tags) { - quint16 tags; - QByteArray tag; + quint16 size; + QByteArray str; - if (!hdr.readUInt16(tags)) + if (!hdr.readUInt16(size)) return false; - _pointTags.resize(tags); - for (quint16 i = 0; i < tags; i++) { - if (!hdr.readString(tag)) - return false; - _pointTags[i] = tag; - } + tags.resize(size); - if (!hdr.readUInt16(tags)) - return false; - _pathTags.resize(tags); - for (quint16 i = 0; i < tags; i++) { - if (!hdr.readString(tag)) + for (quint16 i = 0; i < size; i++) { + TagSource &tag = tags[i]; + if (!hdr.readString(str)) return false; - _pathTags[i] = tag; + tag = str; + unsigned key = _keys.value(tag.key); + if (key) + tag.id = key; + else { + tag.id = _keys.size() + 1; + _keys.insert(tag.key, tag.id); + } } return true; } -bool MapData::readMapInfo(SubFile &hdr, QByteArray &projection, - bool &debugMap) +bool MapData::readTagInfo(SubFile &hdr) +{ + _keys.insert(KEY_NAME, ID_NAME); + _keys.insert(KEY_HOUSE, ID_HOUSE); + _keys.insert(KEY_REF, ID_REF); + _keys.insert(KEY_ELE, ID_ELE); + + return (readTagInfo(hdr, _pointTags) && readTagInfo(hdr, _pathTags)); +} + +bool MapData::readMapInfo(SubFile &hdr, QByteArray &projection, bool &debugMap) { quint64 fileSize, date; quint32 version; @@ -592,17 +605,17 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList *list) if (!subfile.readString(name)) return false; name = name.split('\r').first(); - p.tags.append(Tag("name", name)); + p.tags.append(Tag(ID_NAME, name)); } if (flags & 0x40) { if (!subfile.readString(houseNumber)) return false; - p.tags.append(Tag("addr:housenumber", houseNumber)); + p.tags.append(Tag(ID_HOUSE, houseNumber)); } if (flags & 0x20) { if (!subfile.readString(reference)) return false; - p.tags.append(Tag("ref", reference)); + p.tags.append(Tag(ID_REF, reference)); } if (flags & 0x10) { if (!(subfile.readVInt32(lat) && subfile.readVInt32(lon))) @@ -675,18 +688,18 @@ bool MapData::readPoints(const VectorTile *tile, int zoom, QList *list) if (!subfile.readString(name)) return false; name = name.split('\r').first(); - p.tags.append(Tag("name", name)); + p.tags.append(Tag(ID_NAME, name)); } if (flags & 0x40) { if (!subfile.readString(houseNumber)) return false; - p.tags.append(Tag("addr:housenumber", houseNumber)); + p.tags.append(Tag(ID_HOUSE, houseNumber)); } if (flags & 0x20) { qint32 elevation; if (!subfile.readVInt32(elevation)) return false; - p.tags.append(Tag("ele", QByteArray::number(elevation))); + p.tags.append(Tag(ID_ELE, QByteArray::number(elevation))); } list->append(p); diff --git a/src/map/mapsforge/mapdata.h b/src/map/mapsforge/mapdata.h index d1ab62ea..064fb10a 100644 --- a/src/map/mapsforge/mapdata.h +++ b/src/map/mapsforge/mapdata.h @@ -9,6 +9,10 @@ #include "common/range.h" #include "common/polygon.h" +#define ID_NAME 1 +#define ID_HOUSE 2 +#define ID_REF 3 +#define ID_ELE 4 namespace Mapsforge { @@ -22,21 +26,12 @@ public: struct Tag { Tag() {} - Tag(const QByteArray &key, const QByteArray &value) - : key(key), value(value) {} - Tag(const QByteArray &str) - { - QList l(str.split('=')); - if (l.size() == 2) { - key = l.at(0); - value = l.at(1); - } - } + Tag(unsigned key, const QByteArray &value) : key(key), value(value) {} bool operator==(const Tag &other) const {return (key == other.key && value == other.value);} - QByteArray key; + unsigned key; QByteArray value; }; @@ -75,6 +70,7 @@ public: void points(const RectC &rect, int zoom, QList *list); void paths(const RectC &rect, int zoom, QList *set); + unsigned tagId(const QByteArray &name) const {return _keys.value(name);} void load(); void clear(); @@ -128,10 +124,27 @@ private: int zoom; }; + struct TagSource { + TagSource() {} + TagSource(const QByteArray &str) + { + QList l(str.split('=')); + if (l.size() == 2) { + key = l.at(0); + value = l.at(1); + } + } + + QByteArray key; + QByteArray value; + unsigned id; + }; + typedef RTree TileTree; bool readZoomInfo(SubFile &hdr); bool readTagInfo(SubFile &hdr); + bool readTagInfo(SubFile &hdr, QVector &tags); bool readMapInfo(SubFile &hdr, QByteArray &projection, bool &debugMap); bool readHeader(); bool readSubFiles(); @@ -145,6 +158,8 @@ private: bool readPaths(const VectorTile *tile, int zoom, QList *list); bool readPoints(const VectorTile *tile, int zoom, QList *list); + static bool readTags(SubFile &subfile, int count, + const QVector &tags, QVector &list); static bool pathCb(VectorTile *tile, void *context); static bool pointCb(VectorTile *tile, void *context); @@ -153,9 +168,10 @@ private: QFile _file; RectC _bounds; quint16 _tileSize; - QVector _pointTags, _pathTags; QVector _subFiles; + QVector _pointTags, _pathTags; QList _tiles; + QHash _keys; QCache > _pathCache; QCache > _pointCache; diff --git a/src/map/mapsforge/rastertile.cpp b/src/map/mapsforge/rastertile.cpp index 9c64ac74..d68bae72 100644 --- a/src/map/mapsforge/rastertile.cpp +++ b/src/map/mapsforge/rastertile.cpp @@ -5,12 +5,6 @@ using namespace Mapsforge; -static const Style& style(qreal ratio) -{ - static Style s(ProgramPaths::renderthemeFile(), ratio); - return s; -} - static qreal area(const QPainterPath &polygon) { qreal area = 0; @@ -41,8 +35,7 @@ static QPointF centroid(const QPainterPath &polygon) return QPointF(cx * factor, cy * factor); } -static const QByteArray *label(const QByteArray &key, - const QVector &tags) +static const QByteArray *label(unsigned key, const QVector &tags) { for (int i = 0; i < tags.size(); i++) { const MapData::Tag &tag = tags.at(i); @@ -61,9 +54,8 @@ static const QColor *haloColor(const Style::TextRender *ti) void RasterTile::processPointLabels(QList &textItems) { - const Style &s = style(_ratio); - QList labels(s.pointLabels(_zoom)); - QList symbols(s.pointSymbols(_zoom)); + QList labels(_style->pointLabels(_zoom)); + QList symbols(_style->pointSymbols(_zoom)); QList points; for (int i = 0; i < _points.size(); i++) { @@ -115,9 +107,8 @@ void RasterTile::processPointLabels(QList &textItems) void RasterTile::processAreaLabels(QList &textItems, QVector &paths) { - const Style &s = style(_ratio); - QList labels(s.areaLabels(_zoom)); - QList symbols(s.areaSymbols(_zoom)); + QList labels(_style->areaLabels(_zoom)); + QList symbols(_style->areaSymbols(_zoom)); for (int i = 0; i < paths.size(); i++) { PainterPath &path = paths[i]; @@ -168,8 +159,7 @@ void RasterTile::processAreaLabels(QList &textItems, void RasterTile::processLineLabels(QList &textItems, QVector &paths) { - const Style &s = style(_ratio); - QList instructions(s.pathLabels(_zoom)); + QList instructions(_style->pathLabels(_zoom)); QSet set; for (int i = 0; i < instructions.size(); i++) { @@ -183,9 +173,7 @@ void RasterTile::processLineLabels(QList &textItems, continue; if (!ri->rule().match(path.path->closed, path.path->tags)) continue; - bool limit = (ri->key() == "ref" || ri->key() == "ele" - || ri->key() == "ref_hike" || ri->key() == "ref_cycle" - || ri->key() == "ref_mtb"); + bool limit = (ri->key() == ID_ELE || ri->key() == ID_REF); if (limit && set.contains(*lbl)) continue; @@ -242,7 +230,6 @@ void RasterTile::pathInstructions(QVector &paths, QVector &instructions) { QCache > cache(8192); - const Style &s = style(_ratio); QList *ri; for (int i = 0; i < _paths.size(); i++) { @@ -253,8 +240,8 @@ void RasterTile::pathInstructions(QVector &paths, rp.path = &path; if (!(ri = cache.object(key))) { - ri = new QList(s.paths(_zoom, path.closed, - path.tags)); + ri = new QList(_style->paths(_zoom, + path.closed, path.tags)); for (int j = 0; j < ri->size(); j++) instructions.append(RenderInstruction(ri->at(j), &rp)); cache.insert(key, ri); @@ -269,7 +256,6 @@ void RasterTile::circleInstructions( QVector &instructions) { QCache > cache(8192); - const Style &s = style(_ratio); QList *ri; for (int i = 0; i < _points.size(); i++) { @@ -277,7 +263,8 @@ void RasterTile::circleInstructions( PointKey key(_zoom, point.tags); if (!(ri = cache.object(key))) { - ri = new QList(s.circles(_zoom, point.tags)); + ri = new QList(_style->circles(_zoom, + point.tags)); for (int j = 0; j < ri->size(); j++) instructions.append(RenderInstruction(ri->at(j), &point)); cache.insert(key, ri); diff --git a/src/map/mapsforge/rastertile.h b/src/map/mapsforge/rastertile.h index d7fb65b1..d5f41646 100644 --- a/src/map/mapsforge/rastertile.h +++ b/src/map/mapsforge/rastertile.h @@ -14,12 +14,12 @@ namespace Mapsforge { class RasterTile { public: - RasterTile(const Projection &proj, const Transform &transform, int zoom, - const QRect &rect, qreal ratio, const QList &paths, - const QList &points) : _proj(proj), _transform(transform), - _zoom(zoom), _rect(rect), _ratio(ratio), - _pixmap(rect.width() * ratio, rect.height() * ratio), _paths(paths), - _points(points), _valid(false) {} + RasterTile(const Projection &proj, const Transform &transform, + const Style *style, int zoom, const QRect &rect, qreal ratio, + const QList &paths, const QList &points) + : _proj(proj), _transform(transform), _style(style), + _zoom(zoom), _rect(rect), _ratio(ratio), _pixmap(rect.width() * ratio, + rect.height() * ratio), _paths(paths), _points(points), _valid(false) {} int zoom() const {return _zoom;} QPoint xy() const {return _rect.topLeft();} @@ -159,8 +159,10 @@ private: void drawTextItems(QPainter *painter, const QList &textItems); void drawPaths(QPainter *painter, QVector &paths); + Projection _proj; Transform _transform; + const Style *_style; int _zoom; QRect _rect; qreal _ratio; diff --git a/src/map/mapsforge/style.cpp b/src/map/mapsforge/style.cpp index 79de8424..25903dfe 100644 --- a/src/map/mapsforge/style.cpp +++ b/src/map/mapsforge/style.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "common/programpaths.h" #include "style.h" using namespace Mapsforge; @@ -37,6 +38,48 @@ static QImage image(const QString &path, int width, int height, qreal ratio) return QImage(path); } +static QList keyList(const MapData &data, const QList &in) +{ + QList out; + + for (int i = 0; i < in.size(); i++) { + if (in.at(i) == "*") + out.append(0); + else { + unsigned key = data.tagId(in.at(i)); + if (key) + out.append(key); + } + } + + return out; +} + +static QList valList(const QList &in) +{ + QList out; + + for (int i = 0; i < in.size(); i++) { + if (in.at(i) == "*") + out.append(QByteArray()); + else + out.append(in.at(i)); + } + + return out; +} + +Style::Rule::Filter::Filter(const MapData &data, const QList &keys, + const QList &vals) : _neg(false) +{ + _keys = keyList(data, keys); + + QList vc(vals); + if (vc.removeAll("~")) + _neg = true; + _vals = valList(vc); +} + bool Style::Rule::match(const QVector &tags) const { for (int i = 0; i < _filters.size(); i++) @@ -237,7 +280,7 @@ void Style::circle(QXmlStreamReader &reader, const Rule &rule) reader.skipCurrentElement(); } -void Style::text(QXmlStreamReader &reader, const Rule &rule, +void Style::text(QXmlStreamReader &reader, const MapData &data, const Rule &rule, QList*> &lists) { TextRender ri(rule); @@ -249,7 +292,7 @@ void Style::text(QXmlStreamReader &reader, const Rule &rule, bool ok; if (attr.hasAttribute("k")) - ri._key = attr.value("k").toLatin1(); + ri._key = data.tagId(attr.value("k").toLatin1()); if (attr.hasAttribute("fill")) ri._fillColor = QColor(attr.value("fill").toString()); if (attr.hasAttribute("stroke")) @@ -357,8 +400,9 @@ void Style::symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio, reader.skipCurrentElement(); } -void Style::rule(QXmlStreamReader &reader, const QString &dir, qreal ratio, - const QSet &cats, const Rule &parent) +void Style::rule(QXmlStreamReader &reader, const QString &dir, + const MapData &data, qreal ratio, const QSet &cats, + const Rule &parent) { Rule r(parent); const QXmlStreamAttributes &attr = reader.attributes(); @@ -399,11 +443,11 @@ void Style::rule(QXmlStreamReader &reader, const QString &dir, qreal ratio, QList keys(attr.value("k").toLatin1().split('|')); QList vals(attr.value("v").toLatin1().split('|')); - r.addFilter(Rule::Filter(keys, vals)); + r.addFilter(Rule::Filter(data, keys, vals)); while (reader.readNextStartElement()) { if (reader.name() == QLatin1String("rule")) - rule(reader, dir, ratio, cats, r); + rule(reader, dir, data, ratio, cats, r); else if (reader.name() == QLatin1String("area")) area(reader, dir, ratio, r); else if (reader.name() == QLatin1String("line")) @@ -413,14 +457,14 @@ void Style::rule(QXmlStreamReader &reader, const QString &dir, qreal ratio, else if (reader.name() == QLatin1String("pathText")) { QList*> list; list.append(&_pathLabels); - text(reader, r, list); + text(reader, data, r, list); } else if (reader.name() == QLatin1String("caption")) { QList*> list; if (r._type == Rule::WayType || r._type == Rule::AnyType) list.append(&_areaLabels); if (r._type == Rule::NodeType || r._type == Rule::AnyType) list.append(&_pointLabels); - text(reader, r, list); + text(reader, data, r, list); } else if (reader.name() == QLatin1String("symbol")) symbol(reader, dir, ratio, r); @@ -462,14 +506,14 @@ void Style::stylemenu(QXmlStreamReader &reader, QSet &cats) } void Style::rendertheme(QXmlStreamReader &reader, const QString &dir, - qreal ratio) + const MapData &data, qreal ratio) { Rule r; QSet cats; while (reader.readNextStartElement()) { if (reader.name() == QLatin1String("rule")) - rule(reader, dir, ratio, cats, r); + rule(reader, dir, data, ratio, cats, r); else if (reader.name() == QLatin1String("stylemenu")) stylemenu(reader, cats); else @@ -477,7 +521,7 @@ void Style::rendertheme(QXmlStreamReader &reader, const QString &dir, } } -bool Style::loadXml(const QString &path, qreal ratio) +bool Style::loadXml(const QString &path, const MapData &data, qreal ratio) { QFile file(path); if (!file.open(QFile::ReadOnly)) @@ -487,7 +531,7 @@ bool Style::loadXml(const QString &path, qreal ratio) if (reader.readNextStartElement()) { if (reader.name() == QLatin1String("rendertheme")) - rendertheme(reader, fi.absolutePath(), ratio); + rendertheme(reader, fi.absolutePath(), data, ratio); else reader.raiseError("Not a Mapsforge style file"); } @@ -499,10 +543,22 @@ bool Style::loadXml(const QString &path, qreal ratio) return !reader.error(); } -Style::Style(const QString &path, qreal ratio) +void Style::load(const MapData &data, qreal ratio) { - if (!QFileInfo::exists(path) || !loadXml(path, ratio)) - loadXml(":/mapsforge/default.xml", ratio); + QString path(ProgramPaths::renderthemeFile()); + + if (!QFileInfo::exists(path) || !loadXml(path, data, ratio)) + loadXml(":/mapsforge/default.xml", data, ratio); +} + +void Style::clear() +{ + _paths.clear(); + _circles.clear(); + _pathLabels.clear(); + _pointLabels.clear(); + _areaLabels.clear(); + _symbols.clear(); } QList Style::paths(int zoom, bool closed, diff --git a/src/map/mapsforge/style.h b/src/map/mapsforge/style.h index 09a54143..2ad07259 100644 --- a/src/map/mapsforge/style.h +++ b/src/map/mapsforge/style.h @@ -53,16 +53,8 @@ public: class Filter { public: Filter() : _neg(false) {} - Filter(const QList &keys, const QList &vals) - : _neg(false) - { - _keys = list(keys); - - QList vc(vals); - if (vc.removeAll("~")) - _neg = true; - _vals = list(vc); - } + Filter(const MapData &data, const QList &keys, + const QList &vals); bool match(const QVector &tags) const { @@ -76,30 +68,15 @@ public: bool isTautology() const { - return (!_neg && _keys.contains(QByteArray()) - && _vals.contains(QByteArray())); + return (!_neg && _keys.contains(0u) && _vals.contains(QByteArray())); } private: - static QList list(const QList &in) - { - QList out; - - for (int i = 0; i < in.size(); i++) { - if (in.at(i) == "*") - out.append(QByteArray()); - else - out.append(in.at(i)); - } - - return out; - } - bool keyMatches(const QVector &tags) const { for (int i = 0; i < _keys.size(); i++) for (int j = 0; j < tags.size(); j++) - if (wcmp(_keys.at(i), tags.at(j).key)) + if (!_keys.at(i) || _keys.at(i) == tags.at(j).key) return true; return false; @@ -115,7 +92,7 @@ public: return false; } - QList _keys; + QList _keys; QList _vals; bool _neg; }; @@ -218,7 +195,7 @@ public: const QColor &fillColor() const {return _fillColor;} const QColor &strokeColor() const {return _strokeColor;} qreal strokeWidth() const {return _strokeWidth;} - const QByteArray &key() const {return _key;} + unsigned key() const {return _key;} int priority() const {return _priority;} private: @@ -228,7 +205,7 @@ public: QColor _fillColor, _strokeColor; qreal _strokeWidth; QFont _font; - QByteArray _key; + unsigned _key; }; class Symbol : public Render @@ -246,7 +223,8 @@ public: QImage _img; }; - Style(const QString &path, qreal ratio); + void load(const MapData &data, qreal ratio); + void clear(); QList paths(int zoom, bool closed, const QVector &tags) const; @@ -264,18 +242,19 @@ private: QList _pathLabels, _pointLabels, _areaLabels; QList _symbols; - bool loadXml(const QString &path, qreal ratio); - void rendertheme(QXmlStreamReader &reader, const QString &dir, qreal ratio); + bool loadXml(const QString &path, const MapData &data, qreal ratio); + void rendertheme(QXmlStreamReader &reader, const QString &dir, + const MapData &data, qreal ratio); void layer(QXmlStreamReader &reader, QSet &cats); void stylemenu(QXmlStreamReader &reader, QSet &cats); void cat(QXmlStreamReader &reader, QSet &cats); - void rule(QXmlStreamReader &reader, const QString &dir, qreal ratio, - const QSet &cats, const Rule &parent); + void rule(QXmlStreamReader &reader, const QString &dir, const MapData &data, + qreal ratio, const QSet &cats, const Rule &parent); void area(QXmlStreamReader &reader, const QString &dir, qreal ratio, const Rule &rule); void line(QXmlStreamReader &reader, const Rule &rule); void circle(QXmlStreamReader &reader, const Rule &rule); - void text(QXmlStreamReader &reader, const Rule &rule, + void text(QXmlStreamReader &reader, const MapData &data, const Rule &rule, QList *> &lists); void symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio, const Rule &rule); diff --git a/src/map/mapsforgemap.cpp b/src/map/mapsforgemap.cpp index ca9a5e55..a517184e 100644 --- a/src/map/mapsforgemap.cpp +++ b/src/map/mapsforgemap.cpp @@ -24,11 +24,15 @@ MapsforgeMap::MapsforgeMap(const QString &fileName, QObject *parent) void MapsforgeMap::load() { _data.load(); + _style.load(_data, _tileRatio); } void MapsforgeMap::unload() { + cancelJobs(true); + _data.clear(); + _style.clear(); } int MapsforgeMap::zoomFit(const QSize &size, const RectC &rect) @@ -54,7 +58,7 @@ int MapsforgeMap::zoomFit(const QSize &size, const RectC &rect) int MapsforgeMap::zoomIn() { - cancelJobs(); + cancelJobs(false); _zoom = qMin(_zoom + 1, _data.zooms().max()); updateTransform(); @@ -63,7 +67,7 @@ int MapsforgeMap::zoomIn() int MapsforgeMap::zoomOut() { - cancelJobs(); + cancelJobs(false); _zoom = qMax(_zoom - 1, _data.zooms().min()); updateTransform(); @@ -148,10 +152,10 @@ void MapsforgeMap::jobFinished(MapsforgeMapJob *job) emit tilesLoaded(); } -void MapsforgeMap::cancelJobs() +void MapsforgeMap::cancelJobs(bool wait) { for (int i = 0; i < _jobs.size(); i++) - _jobs.at(i)->cancel(); + _jobs.at(i)->cancel(wait); } void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags) @@ -198,7 +202,7 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags) _data.points(pointRectD.toRectC(_projection, 20), _zoom, &points); - tiles.append(RasterTile(_projection, _transform, _zoom, + tiles.append(RasterTile(_projection, _transform, &_style, _zoom, QRect(ttl, QSize(_data.tileSize(), _data.tileSize())), _tileRatio, paths, points)); } diff --git a/src/map/mapsforgemap.h b/src/map/mapsforgemap.h index 55cac8dd..ba29f6f7 100644 --- a/src/map/mapsforgemap.h +++ b/src/map/mapsforgemap.h @@ -24,7 +24,12 @@ public: _future = QtConcurrent::map(_tiles, &Mapsforge::RasterTile::render); _watcher.setFuture(_future); } - void cancel() {_future.cancel();} + void cancel(bool wait) + { + _future.cancel(); + if (wait) + _future.waitForFinished(); + } const QList &tiles() const {return _tiles;} signals: @@ -82,9 +87,10 @@ private: bool isRunning(int zoom, const QPoint &xy) const; void runJob(MapsforgeMapJob *job); void removeJob(MapsforgeMapJob *job); - void cancelJobs(); + void cancelJobs(bool wait); Mapsforge::MapData _data; + Mapsforge::Style _style; int _zoom; Projection _projection;