1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-01-19 04:02:09 +01:00

Use integers as tag keys in Mapsforge maps

This commit is contained in:
Martin Tůma 2023-04-22 17:28:32 +02:00
parent dacaeca71a
commit ce4f0472c0
8 changed files with 246 additions and 183 deletions

View File

@ -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<MapData::Path> *src,
QList<MapData::Path> *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<MapData::Tag> &tags, QVector<MapData::Tag> &list)
{
QVector<quint32> 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<Coordinates> &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<TagSource> &tags, QVector<Tag> &list)
{
QVector<quint32> 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<TagSource> &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<Path> *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<Point> *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);

View File

@ -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<QByteArray> 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<Point> *list);
void paths(const RectC &rect, int zoom, QList<Path> *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<QByteArray> l(str.split('='));
if (l.size() == 2) {
key = l.at(0);
value = l.at(1);
}
}
QByteArray key;
QByteArray value;
unsigned id;
};
typedef RTree<VectorTile *, double, 2> TileTree;
bool readZoomInfo(SubFile &hdr);
bool readTagInfo(SubFile &hdr);
bool readTagInfo(SubFile &hdr, QVector<TagSource> &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<Path> *list);
bool readPoints(const VectorTile *tile, int zoom, QList<Point> *list);
static bool readTags(SubFile &subfile, int count,
const QVector<TagSource> &tags, QVector<Tag> &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<Tag> _pointTags, _pathTags;
QVector<SubFileInfo> _subFiles;
QVector<TagSource> _pointTags, _pathTags;
QList<TileTree*> _tiles;
QHash<QByteArray, unsigned> _keys;
QCache<Key, QList<Path> > _pathCache;
QCache<Key, QList<Point> > _pointCache;

View File

@ -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<MapData::Tag> &tags)
static const QByteArray *label(unsigned key, const QVector<MapData::Tag> &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<TextItem*> &textItems)
{
const Style &s = style(_ratio);
QList<const Style::TextRender*> labels(s.pointLabels(_zoom));
QList<const Style::Symbol*> symbols(s.pointSymbols(_zoom));
QList<const Style::TextRender*> labels(_style->pointLabels(_zoom));
QList<const Style::Symbol*> symbols(_style->pointSymbols(_zoom));
QList<PainterPoint> points;
for (int i = 0; i < _points.size(); i++) {
@ -115,9 +107,8 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
QVector<PainterPath> &paths)
{
const Style &s = style(_ratio);
QList<const Style::TextRender*> labels(s.areaLabels(_zoom));
QList<const Style::Symbol*> symbols(s.areaSymbols(_zoom));
QList<const Style::TextRender*> labels(_style->areaLabels(_zoom));
QList<const Style::Symbol*> symbols(_style->areaSymbols(_zoom));
for (int i = 0; i < paths.size(); i++) {
PainterPath &path = paths[i];
@ -168,8 +159,7 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
void RasterTile::processLineLabels(QList<TextItem*> &textItems,
QVector<PainterPath> &paths)
{
const Style &s = style(_ratio);
QList<const Style::TextRender*> instructions(s.pathLabels(_zoom));
QList<const Style::TextRender*> instructions(_style->pathLabels(_zoom));
QSet<QByteArray> set;
for (int i = 0; i < instructions.size(); i++) {
@ -183,9 +173,7 @@ void RasterTile::processLineLabels(QList<TextItem*> &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<PainterPath> &paths,
QVector<RasterTile::RenderInstruction> &instructions)
{
QCache<PathKey, QList<const Style::PathRender *> > cache(8192);
const Style &s = style(_ratio);
QList<const Style::PathRender*> *ri;
for (int i = 0; i < _paths.size(); i++) {
@ -253,8 +240,8 @@ void RasterTile::pathInstructions(QVector<PainterPath> &paths,
rp.path = &path;
if (!(ri = cache.object(key))) {
ri = new QList<const Style::PathRender*>(s.paths(_zoom, path.closed,
path.tags));
ri = new QList<const Style::PathRender*>(_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<RasterTile::RenderInstruction> &instructions)
{
QCache<PointKey, QList<const Style::CircleRender *> > cache(8192);
const Style &s = style(_ratio);
QList<const Style::CircleRender*> *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<const Style::CircleRender*>(s.circles(_zoom, point.tags));
ri = new QList<const Style::CircleRender*>(_style->circles(_zoom,
point.tags));
for (int j = 0; j < ri->size(); j++)
instructions.append(RenderInstruction(ri->at(j), &point));
cache.insert(key, ri);

View File

@ -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<MapData::Path> &paths,
const QList<MapData::Point> &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<MapData::Path> &paths, const QList<MapData::Point> &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<TextItem*> &textItems);
void drawPaths(QPainter *painter, QVector<PainterPath> &paths);
Projection _proj;
Transform _transform;
const Style *_style;
int _zoom;
QRect _rect;
qreal _ratio;

View File

@ -3,6 +3,7 @@
#include <QUrl>
#include <QFileInfo>
#include <QImageReader>
#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<unsigned> keyList(const MapData &data, const QList<QByteArray> &in)
{
QList<unsigned> 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<QByteArray> valList(const QList<QByteArray> &in)
{
QList<QByteArray> 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<QByteArray> &keys,
const QList<QByteArray> &vals) : _neg(false)
{
_keys = keyList(data, keys);
QList<QByteArray> vc(vals);
if (vc.removeAll("~"))
_neg = true;
_vals = valList(vc);
}
bool Style::Rule::match(const QVector<MapData::Tag> &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<QList<TextRender>*> &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<QString> &cats, const Rule &parent)
void Style::rule(QXmlStreamReader &reader, const QString &dir,
const MapData &data, qreal ratio, const QSet<QString> &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<QByteArray> keys(attr.value("k").toLatin1().split('|'));
QList<QByteArray> 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<QList<TextRender>*> list;
list.append(&_pathLabels);
text(reader, r, list);
text(reader, data, r, list);
} else if (reader.name() == QLatin1String("caption")) {
QList<QList<TextRender>*> 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<QString> &cats)
}
void Style::rendertheme(QXmlStreamReader &reader, const QString &dir,
qreal ratio)
const MapData &data, qreal ratio)
{
Rule r;
QSet<QString> 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<const Style::PathRender *> Style::paths(int zoom, bool closed,

View File

@ -53,16 +53,8 @@ public:
class Filter {
public:
Filter() : _neg(false) {}
Filter(const QList<QByteArray> &keys, const QList<QByteArray> &vals)
: _neg(false)
{
_keys = list(keys);
QList<QByteArray> vc(vals);
if (vc.removeAll("~"))
_neg = true;
_vals = list(vc);
}
Filter(const MapData &data, const QList<QByteArray> &keys,
const QList<QByteArray> &vals);
bool match(const QVector<MapData::Tag> &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<QByteArray> list(const QList<QByteArray> &in)
{
QList<QByteArray> 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<MapData::Tag> &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<QByteArray> _keys;
QList<unsigned> _keys;
QList<QByteArray> _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<const PathRender *> paths(int zoom, bool closed,
const QVector<MapData::Tag> &tags) const;
@ -264,18 +242,19 @@ private:
QList<TextRender> _pathLabels, _pointLabels, _areaLabels;
QList<Symbol> _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<QString> &cats);
void stylemenu(QXmlStreamReader &reader, QSet<QString> &cats);
void cat(QXmlStreamReader &reader, QSet<QString> &cats);
void rule(QXmlStreamReader &reader, const QString &dir, qreal ratio,
const QSet<QString> &cats, const Rule &parent);
void rule(QXmlStreamReader &reader, const QString &dir, const MapData &data,
qreal ratio, const QSet<QString> &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<QList<TextRender> *> &lists);
void symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
const Rule &rule);

View File

@ -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));
}

View File

@ -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<Mapsforge::RasterTile> &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;