1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-01-19 12:12:08 +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 MD(val) ((val) / 1e6)
#define OFFSET_MASK 0x7FFFFFFFFFL #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, static void copyPaths(const RectC &rect, const QList<MapData::Path> *src,
QList<MapData::Path> *dst) QList<MapData::Path> *dst)
{ {
@ -43,65 +48,6 @@ static bool isClosed(const Polygon &poly)
return (distance(poly.first().first(), poly.first().last()) < 0.000000001); 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, static bool readSingleDelta(SubFile &subfile, const Coordinates &c,
int count, QVector<Coordinates> &nodes) int count, QVector<Coordinates> &nodes)
{ {
@ -204,6 +150,64 @@ static bool readOffset(QDataStream &stream, quint64 &offset)
return (stream.status() == QDataStream::Ok); 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() bool MapData::readSubFiles()
{ {
QDataStream stream(&_file); QDataStream stream(&_file);
@ -273,34 +277,43 @@ bool MapData::readZoomInfo(SubFile &hdr)
return true; return true;
} }
bool MapData::readTagInfo(SubFile &hdr) bool MapData::readTagInfo(SubFile &hdr, QVector<TagSource> &tags)
{ {
quint16 tags; quint16 size;
QByteArray tag; QByteArray str;
if (!hdr.readUInt16(tags)) if (!hdr.readUInt16(size))
return false; return false;
_pointTags.resize(tags); tags.resize(size);
for (quint16 i = 0; i < tags; i++) {
if (!hdr.readString(tag))
return false;
_pointTags[i] = tag;
}
if (!hdr.readUInt16(tags)) for (quint16 i = 0; i < size; i++) {
return false; TagSource &tag = tags[i];
_pathTags.resize(tags); if (!hdr.readString(str))
for (quint16 i = 0; i < tags; i++) {
if (!hdr.readString(tag))
return false; 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; return true;
} }
bool MapData::readMapInfo(SubFile &hdr, QByteArray &projection, bool MapData::readTagInfo(SubFile &hdr)
bool &debugMap) {
_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; quint64 fileSize, date;
quint32 version; quint32 version;
@ -592,17 +605,17 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
if (!subfile.readString(name)) if (!subfile.readString(name))
return false; return false;
name = name.split('\r').first(); name = name.split('\r').first();
p.tags.append(Tag("name", name)); p.tags.append(Tag(ID_NAME, name));
} }
if (flags & 0x40) { if (flags & 0x40) {
if (!subfile.readString(houseNumber)) if (!subfile.readString(houseNumber))
return false; return false;
p.tags.append(Tag("addr:housenumber", houseNumber)); p.tags.append(Tag(ID_HOUSE, houseNumber));
} }
if (flags & 0x20) { if (flags & 0x20) {
if (!subfile.readString(reference)) if (!subfile.readString(reference))
return false; return false;
p.tags.append(Tag("ref", reference)); p.tags.append(Tag(ID_REF, reference));
} }
if (flags & 0x10) { if (flags & 0x10) {
if (!(subfile.readVInt32(lat) && subfile.readVInt32(lon))) 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)) if (!subfile.readString(name))
return false; return false;
name = name.split('\r').first(); name = name.split('\r').first();
p.tags.append(Tag("name", name)); p.tags.append(Tag(ID_NAME, name));
} }
if (flags & 0x40) { if (flags & 0x40) {
if (!subfile.readString(houseNumber)) if (!subfile.readString(houseNumber))
return false; return false;
p.tags.append(Tag("addr:housenumber", houseNumber)); p.tags.append(Tag(ID_HOUSE, houseNumber));
} }
if (flags & 0x20) { if (flags & 0x20) {
qint32 elevation; qint32 elevation;
if (!subfile.readVInt32(elevation)) if (!subfile.readVInt32(elevation))
return false; return false;
p.tags.append(Tag("ele", QByteArray::number(elevation))); p.tags.append(Tag(ID_ELE, QByteArray::number(elevation)));
} }
list->append(p); list->append(p);

View File

@ -9,6 +9,10 @@
#include "common/range.h" #include "common/range.h"
#include "common/polygon.h" #include "common/polygon.h"
#define ID_NAME 1
#define ID_HOUSE 2
#define ID_REF 3
#define ID_ELE 4
namespace Mapsforge { namespace Mapsforge {
@ -22,21 +26,12 @@ public:
struct Tag { struct Tag {
Tag() {} Tag() {}
Tag(const QByteArray &key, const QByteArray &value) Tag(unsigned key, const QByteArray &value) : key(key), value(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);
}
}
bool operator==(const Tag &other) const bool operator==(const Tag &other) const
{return (key == other.key && value == other.value);} {return (key == other.key && value == other.value);}
QByteArray key; unsigned key;
QByteArray value; QByteArray value;
}; };
@ -75,6 +70,7 @@ public:
void points(const RectC &rect, int zoom, QList<Point> *list); void points(const RectC &rect, int zoom, QList<Point> *list);
void paths(const RectC &rect, int zoom, QList<Path> *set); void paths(const RectC &rect, int zoom, QList<Path> *set);
unsigned tagId(const QByteArray &name) const {return _keys.value(name);}
void load(); void load();
void clear(); void clear();
@ -128,10 +124,27 @@ private:
int zoom; 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; typedef RTree<VectorTile *, double, 2> TileTree;
bool readZoomInfo(SubFile &hdr); bool readZoomInfo(SubFile &hdr);
bool readTagInfo(SubFile &hdr); bool readTagInfo(SubFile &hdr);
bool readTagInfo(SubFile &hdr, QVector<TagSource> &tags);
bool readMapInfo(SubFile &hdr, QByteArray &projection, bool &debugMap); bool readMapInfo(SubFile &hdr, QByteArray &projection, bool &debugMap);
bool readHeader(); bool readHeader();
bool readSubFiles(); bool readSubFiles();
@ -145,6 +158,8 @@ private:
bool readPaths(const VectorTile *tile, int zoom, QList<Path> *list); bool readPaths(const VectorTile *tile, int zoom, QList<Path> *list);
bool readPoints(const VectorTile *tile, int zoom, QList<Point> *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 pathCb(VectorTile *tile, void *context);
static bool pointCb(VectorTile *tile, void *context); static bool pointCb(VectorTile *tile, void *context);
@ -153,9 +168,10 @@ private:
QFile _file; QFile _file;
RectC _bounds; RectC _bounds;
quint16 _tileSize; quint16 _tileSize;
QVector<Tag> _pointTags, _pathTags;
QVector<SubFileInfo> _subFiles; QVector<SubFileInfo> _subFiles;
QVector<TagSource> _pointTags, _pathTags;
QList<TileTree*> _tiles; QList<TileTree*> _tiles;
QHash<QByteArray, unsigned> _keys;
QCache<Key, QList<Path> > _pathCache; QCache<Key, QList<Path> > _pathCache;
QCache<Key, QList<Point> > _pointCache; QCache<Key, QList<Point> > _pointCache;

View File

@ -5,12 +5,6 @@
using namespace Mapsforge; using namespace Mapsforge;
static const Style& style(qreal ratio)
{
static Style s(ProgramPaths::renderthemeFile(), ratio);
return s;
}
static qreal area(const QPainterPath &polygon) static qreal area(const QPainterPath &polygon)
{ {
qreal area = 0; qreal area = 0;
@ -41,8 +35,7 @@ static QPointF centroid(const QPainterPath &polygon)
return QPointF(cx * factor, cy * factor); return QPointF(cx * factor, cy * factor);
} }
static const QByteArray *label(const QByteArray &key, static const QByteArray *label(unsigned key, const QVector<MapData::Tag> &tags)
const QVector<MapData::Tag> &tags)
{ {
for (int i = 0; i < tags.size(); i++) { for (int i = 0; i < tags.size(); i++) {
const MapData::Tag &tag = tags.at(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) void RasterTile::processPointLabels(QList<TextItem*> &textItems)
{ {
const Style &s = style(_ratio); QList<const Style::TextRender*> labels(_style->pointLabels(_zoom));
QList<const Style::TextRender*> labels(s.pointLabels(_zoom)); QList<const Style::Symbol*> symbols(_style->pointSymbols(_zoom));
QList<const Style::Symbol*> symbols(s.pointSymbols(_zoom));
QList<PainterPoint> points; QList<PainterPoint> points;
for (int i = 0; i < _points.size(); i++) { for (int i = 0; i < _points.size(); i++) {
@ -115,9 +107,8 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
void RasterTile::processAreaLabels(QList<TextItem*> &textItems, void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
QVector<PainterPath> &paths) QVector<PainterPath> &paths)
{ {
const Style &s = style(_ratio); QList<const Style::TextRender*> labels(_style->areaLabels(_zoom));
QList<const Style::TextRender*> labels(s.areaLabels(_zoom)); QList<const Style::Symbol*> symbols(_style->areaSymbols(_zoom));
QList<const Style::Symbol*> symbols(s.areaSymbols(_zoom));
for (int i = 0; i < paths.size(); i++) { for (int i = 0; i < paths.size(); i++) {
PainterPath &path = paths[i]; PainterPath &path = paths[i];
@ -168,8 +159,7 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
void RasterTile::processLineLabels(QList<TextItem*> &textItems, void RasterTile::processLineLabels(QList<TextItem*> &textItems,
QVector<PainterPath> &paths) QVector<PainterPath> &paths)
{ {
const Style &s = style(_ratio); QList<const Style::TextRender*> instructions(_style->pathLabels(_zoom));
QList<const Style::TextRender*> instructions(s.pathLabels(_zoom));
QSet<QByteArray> set; QSet<QByteArray> set;
for (int i = 0; i < instructions.size(); i++) { for (int i = 0; i < instructions.size(); i++) {
@ -183,9 +173,7 @@ void RasterTile::processLineLabels(QList<TextItem*> &textItems,
continue; continue;
if (!ri->rule().match(path.path->closed, path.path->tags)) if (!ri->rule().match(path.path->closed, path.path->tags))
continue; continue;
bool limit = (ri->key() == "ref" || ri->key() == "ele" bool limit = (ri->key() == ID_ELE || ri->key() == ID_REF);
|| ri->key() == "ref_hike" || ri->key() == "ref_cycle"
|| ri->key() == "ref_mtb");
if (limit && set.contains(*lbl)) if (limit && set.contains(*lbl))
continue; continue;
@ -242,7 +230,6 @@ void RasterTile::pathInstructions(QVector<PainterPath> &paths,
QVector<RasterTile::RenderInstruction> &instructions) QVector<RasterTile::RenderInstruction> &instructions)
{ {
QCache<PathKey, QList<const Style::PathRender *> > cache(8192); QCache<PathKey, QList<const Style::PathRender *> > cache(8192);
const Style &s = style(_ratio);
QList<const Style::PathRender*> *ri; QList<const Style::PathRender*> *ri;
for (int i = 0; i < _paths.size(); i++) { for (int i = 0; i < _paths.size(); i++) {
@ -253,8 +240,8 @@ void RasterTile::pathInstructions(QVector<PainterPath> &paths,
rp.path = &path; rp.path = &path;
if (!(ri = cache.object(key))) { if (!(ri = cache.object(key))) {
ri = new QList<const Style::PathRender*>(s.paths(_zoom, path.closed, ri = new QList<const Style::PathRender*>(_style->paths(_zoom,
path.tags)); path.closed, path.tags));
for (int j = 0; j < ri->size(); j++) for (int j = 0; j < ri->size(); j++)
instructions.append(RenderInstruction(ri->at(j), &rp)); instructions.append(RenderInstruction(ri->at(j), &rp));
cache.insert(key, ri); cache.insert(key, ri);
@ -269,7 +256,6 @@ void RasterTile::circleInstructions(
QVector<RasterTile::RenderInstruction> &instructions) QVector<RasterTile::RenderInstruction> &instructions)
{ {
QCache<PointKey, QList<const Style::CircleRender *> > cache(8192); QCache<PointKey, QList<const Style::CircleRender *> > cache(8192);
const Style &s = style(_ratio);
QList<const Style::CircleRender*> *ri; QList<const Style::CircleRender*> *ri;
for (int i = 0; i < _points.size(); i++) { for (int i = 0; i < _points.size(); i++) {
@ -277,7 +263,8 @@ void RasterTile::circleInstructions(
PointKey key(_zoom, point.tags); PointKey key(_zoom, point.tags);
if (!(ri = cache.object(key))) { 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++) for (int j = 0; j < ri->size(); j++)
instructions.append(RenderInstruction(ri->at(j), &point)); instructions.append(RenderInstruction(ri->at(j), &point));
cache.insert(key, ri); cache.insert(key, ri);

View File

@ -14,12 +14,12 @@ namespace Mapsforge {
class RasterTile class RasterTile
{ {
public: public:
RasterTile(const Projection &proj, const Transform &transform, int zoom, RasterTile(const Projection &proj, const Transform &transform,
const QRect &rect, qreal ratio, const QList<MapData::Path> &paths, const Style *style, int zoom, const QRect &rect, qreal ratio,
const QList<MapData::Point> &points) : _proj(proj), _transform(transform), const QList<MapData::Path> &paths, const QList<MapData::Point> &points)
_zoom(zoom), _rect(rect), _ratio(ratio), : _proj(proj), _transform(transform), _style(style),
_pixmap(rect.width() * ratio, rect.height() * ratio), _paths(paths), _zoom(zoom), _rect(rect), _ratio(ratio), _pixmap(rect.width() * ratio,
_points(points), _valid(false) {} rect.height() * ratio), _paths(paths), _points(points), _valid(false) {}
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
QPoint xy() const {return _rect.topLeft();} QPoint xy() const {return _rect.topLeft();}
@ -159,8 +159,10 @@ private:
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems); void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
void drawPaths(QPainter *painter, QVector<PainterPath> &paths); void drawPaths(QPainter *painter, QVector<PainterPath> &paths);
Projection _proj; Projection _proj;
Transform _transform; Transform _transform;
const Style *_style;
int _zoom; int _zoom;
QRect _rect; QRect _rect;
qreal _ratio; qreal _ratio;

View File

@ -3,6 +3,7 @@
#include <QUrl> #include <QUrl>
#include <QFileInfo> #include <QFileInfo>
#include <QImageReader> #include <QImageReader>
#include "common/programpaths.h"
#include "style.h" #include "style.h"
using namespace Mapsforge; using namespace Mapsforge;
@ -37,6 +38,48 @@ static QImage image(const QString &path, int width, int height, qreal ratio)
return QImage(path); 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 bool Style::Rule::match(const QVector<MapData::Tag> &tags) const
{ {
for (int i = 0; i < _filters.size(); i++) for (int i = 0; i < _filters.size(); i++)
@ -237,7 +280,7 @@ void Style::circle(QXmlStreamReader &reader, const Rule &rule)
reader.skipCurrentElement(); 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) QList<QList<TextRender>*> &lists)
{ {
TextRender ri(rule); TextRender ri(rule);
@ -249,7 +292,7 @@ void Style::text(QXmlStreamReader &reader, const Rule &rule,
bool ok; bool ok;
if (attr.hasAttribute("k")) if (attr.hasAttribute("k"))
ri._key = attr.value("k").toLatin1(); ri._key = data.tagId(attr.value("k").toLatin1());
if (attr.hasAttribute("fill")) if (attr.hasAttribute("fill"))
ri._fillColor = QColor(attr.value("fill").toString()); ri._fillColor = QColor(attr.value("fill").toString());
if (attr.hasAttribute("stroke")) if (attr.hasAttribute("stroke"))
@ -357,8 +400,9 @@ void Style::symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
reader.skipCurrentElement(); reader.skipCurrentElement();
} }
void Style::rule(QXmlStreamReader &reader, const QString &dir, qreal ratio, void Style::rule(QXmlStreamReader &reader, const QString &dir,
const QSet<QString> &cats, const Rule &parent) const MapData &data, qreal ratio, const QSet<QString> &cats,
const Rule &parent)
{ {
Rule r(parent); Rule r(parent);
const QXmlStreamAttributes &attr = reader.attributes(); 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> keys(attr.value("k").toLatin1().split('|'));
QList<QByteArray> vals(attr.value("v").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()) { while (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("rule")) if (reader.name() == QLatin1String("rule"))
rule(reader, dir, ratio, cats, r); rule(reader, dir, data, ratio, cats, r);
else if (reader.name() == QLatin1String("area")) else if (reader.name() == QLatin1String("area"))
area(reader, dir, ratio, r); area(reader, dir, ratio, r);
else if (reader.name() == QLatin1String("line")) 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")) { else if (reader.name() == QLatin1String("pathText")) {
QList<QList<TextRender>*> list; QList<QList<TextRender>*> list;
list.append(&_pathLabels); list.append(&_pathLabels);
text(reader, r, list); text(reader, data, r, list);
} else if (reader.name() == QLatin1String("caption")) { } else if (reader.name() == QLatin1String("caption")) {
QList<QList<TextRender>*> list; QList<QList<TextRender>*> list;
if (r._type == Rule::WayType || r._type == Rule::AnyType) if (r._type == Rule::WayType || r._type == Rule::AnyType)
list.append(&_areaLabels); list.append(&_areaLabels);
if (r._type == Rule::NodeType || r._type == Rule::AnyType) if (r._type == Rule::NodeType || r._type == Rule::AnyType)
list.append(&_pointLabels); list.append(&_pointLabels);
text(reader, r, list); text(reader, data, r, list);
} }
else if (reader.name() == QLatin1String("symbol")) else if (reader.name() == QLatin1String("symbol"))
symbol(reader, dir, ratio, r); 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, void Style::rendertheme(QXmlStreamReader &reader, const QString &dir,
qreal ratio) const MapData &data, qreal ratio)
{ {
Rule r; Rule r;
QSet<QString> cats; QSet<QString> cats;
while (reader.readNextStartElement()) { while (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("rule")) if (reader.name() == QLatin1String("rule"))
rule(reader, dir, ratio, cats, r); rule(reader, dir, data, ratio, cats, r);
else if (reader.name() == QLatin1String("stylemenu")) else if (reader.name() == QLatin1String("stylemenu"))
stylemenu(reader, cats); stylemenu(reader, cats);
else 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); QFile file(path);
if (!file.open(QFile::ReadOnly)) if (!file.open(QFile::ReadOnly))
@ -487,7 +531,7 @@ bool Style::loadXml(const QString &path, qreal ratio)
if (reader.readNextStartElement()) { if (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("rendertheme")) if (reader.name() == QLatin1String("rendertheme"))
rendertheme(reader, fi.absolutePath(), ratio); rendertheme(reader, fi.absolutePath(), data, ratio);
else else
reader.raiseError("Not a Mapsforge style file"); reader.raiseError("Not a Mapsforge style file");
} }
@ -499,10 +543,22 @@ bool Style::loadXml(const QString &path, qreal ratio)
return !reader.error(); 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)) QString path(ProgramPaths::renderthemeFile());
loadXml(":/mapsforge/default.xml", ratio);
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, QList<const Style::PathRender *> Style::paths(int zoom, bool closed,

View File

@ -53,16 +53,8 @@ public:
class Filter { class Filter {
public: public:
Filter() : _neg(false) {} Filter() : _neg(false) {}
Filter(const QList<QByteArray> &keys, const QList<QByteArray> &vals) Filter(const MapData &data, const QList<QByteArray> &keys,
: _neg(false) const QList<QByteArray> &vals);
{
_keys = list(keys);
QList<QByteArray> vc(vals);
if (vc.removeAll("~"))
_neg = true;
_vals = list(vc);
}
bool match(const QVector<MapData::Tag> &tags) const bool match(const QVector<MapData::Tag> &tags) const
{ {
@ -76,30 +68,15 @@ public:
bool isTautology() const bool isTautology() const
{ {
return (!_neg && _keys.contains(QByteArray()) return (!_neg && _keys.contains(0u) && _vals.contains(QByteArray()));
&& _vals.contains(QByteArray()));
} }
private: 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 bool keyMatches(const QVector<MapData::Tag> &tags) const
{ {
for (int i = 0; i < _keys.size(); i++) for (int i = 0; i < _keys.size(); i++)
for (int j = 0; j < tags.size(); j++) 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 true;
return false; return false;
@ -115,7 +92,7 @@ public:
return false; return false;
} }
QList<QByteArray> _keys; QList<unsigned> _keys;
QList<QByteArray> _vals; QList<QByteArray> _vals;
bool _neg; bool _neg;
}; };
@ -218,7 +195,7 @@ public:
const QColor &fillColor() const {return _fillColor;} const QColor &fillColor() const {return _fillColor;}
const QColor &strokeColor() const {return _strokeColor;} const QColor &strokeColor() const {return _strokeColor;}
qreal strokeWidth() const {return _strokeWidth;} qreal strokeWidth() const {return _strokeWidth;}
const QByteArray &key() const {return _key;} unsigned key() const {return _key;}
int priority() const {return _priority;} int priority() const {return _priority;}
private: private:
@ -228,7 +205,7 @@ public:
QColor _fillColor, _strokeColor; QColor _fillColor, _strokeColor;
qreal _strokeWidth; qreal _strokeWidth;
QFont _font; QFont _font;
QByteArray _key; unsigned _key;
}; };
class Symbol : public Render class Symbol : public Render
@ -246,7 +223,8 @@ public:
QImage _img; 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, QList<const PathRender *> paths(int zoom, bool closed,
const QVector<MapData::Tag> &tags) const; const QVector<MapData::Tag> &tags) const;
@ -264,18 +242,19 @@ private:
QList<TextRender> _pathLabels, _pointLabels, _areaLabels; QList<TextRender> _pathLabels, _pointLabels, _areaLabels;
QList<Symbol> _symbols; QList<Symbol> _symbols;
bool loadXml(const QString &path, qreal ratio); bool loadXml(const QString &path, const MapData &data, qreal ratio);
void rendertheme(QXmlStreamReader &reader, const QString &dir, qreal ratio); void rendertheme(QXmlStreamReader &reader, const QString &dir,
const MapData &data, qreal ratio);
void layer(QXmlStreamReader &reader, QSet<QString> &cats); void layer(QXmlStreamReader &reader, QSet<QString> &cats);
void stylemenu(QXmlStreamReader &reader, QSet<QString> &cats); void stylemenu(QXmlStreamReader &reader, QSet<QString> &cats);
void cat(QXmlStreamReader &reader, QSet<QString> &cats); void cat(QXmlStreamReader &reader, QSet<QString> &cats);
void rule(QXmlStreamReader &reader, const QString &dir, qreal ratio, void rule(QXmlStreamReader &reader, const QString &dir, const MapData &data,
const QSet<QString> &cats, const Rule &parent); qreal ratio, const QSet<QString> &cats, const Rule &parent);
void area(QXmlStreamReader &reader, const QString &dir, qreal ratio, void area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
const Rule &rule); const Rule &rule);
void line(QXmlStreamReader &reader, const Rule &rule); void line(QXmlStreamReader &reader, const Rule &rule);
void circle(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); QList<QList<TextRender> *> &lists);
void symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio, void symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
const Rule &rule); const Rule &rule);

View File

@ -24,11 +24,15 @@ MapsforgeMap::MapsforgeMap(const QString &fileName, QObject *parent)
void MapsforgeMap::load() void MapsforgeMap::load()
{ {
_data.load(); _data.load();
_style.load(_data, _tileRatio);
} }
void MapsforgeMap::unload() void MapsforgeMap::unload()
{ {
cancelJobs(true);
_data.clear(); _data.clear();
_style.clear();
} }
int MapsforgeMap::zoomFit(const QSize &size, const RectC &rect) 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() int MapsforgeMap::zoomIn()
{ {
cancelJobs(); cancelJobs(false);
_zoom = qMin(_zoom + 1, _data.zooms().max()); _zoom = qMin(_zoom + 1, _data.zooms().max());
updateTransform(); updateTransform();
@ -63,7 +67,7 @@ int MapsforgeMap::zoomIn()
int MapsforgeMap::zoomOut() int MapsforgeMap::zoomOut()
{ {
cancelJobs(); cancelJobs(false);
_zoom = qMax(_zoom - 1, _data.zooms().min()); _zoom = qMax(_zoom - 1, _data.zooms().min());
updateTransform(); updateTransform();
@ -148,10 +152,10 @@ void MapsforgeMap::jobFinished(MapsforgeMapJob *job)
emit tilesLoaded(); emit tilesLoaded();
} }
void MapsforgeMap::cancelJobs() void MapsforgeMap::cancelJobs(bool wait)
{ {
for (int i = 0; i < _jobs.size(); i++) 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) 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, _data.points(pointRectD.toRectC(_projection, 20), _zoom,
&points); &points);
tiles.append(RasterTile(_projection, _transform, _zoom, tiles.append(RasterTile(_projection, _transform, &_style, _zoom,
QRect(ttl, QSize(_data.tileSize(), _data.tileSize())), QRect(ttl, QSize(_data.tileSize(), _data.tileSize())),
_tileRatio, paths, points)); _tileRatio, paths, points));
} }

View File

@ -24,7 +24,12 @@ public:
_future = QtConcurrent::map(_tiles, &Mapsforge::RasterTile::render); _future = QtConcurrent::map(_tiles, &Mapsforge::RasterTile::render);
_watcher.setFuture(_future); _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;} const QList<Mapsforge::RasterTile> &tiles() const {return _tiles;}
signals: signals:
@ -82,9 +87,10 @@ private:
bool isRunning(int zoom, const QPoint &xy) const; bool isRunning(int zoom, const QPoint &xy) const;
void runJob(MapsforgeMapJob *job); void runJob(MapsforgeMapJob *job);
void removeJob(MapsforgeMapJob *job); void removeJob(MapsforgeMapJob *job);
void cancelJobs(); void cancelJobs(bool wait);
Mapsforge::MapData _data; Mapsforge::MapData _data;
Mapsforge::Style _style;
int _zoom; int _zoom;
Projection _projection; Projection _projection;