1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-01-31 17:15:14 +01:00

Fix/improve Mapsforge tiles rendering

This commit is contained in:
Martin Tůma 2023-04-05 19:28:17 +02:00
parent 981bd33680
commit 6cd122f59b
8 changed files with 162 additions and 165 deletions

View File

@ -3,6 +3,7 @@
#include <QFile> #include <QFile>
#include <QDataStream> #include <QDataStream>
#include <QColor> #include <QColor>
#include "common/hash.h"
#include "map/osm.h" #include "map/osm.h"
#include "subfile.h" #include "subfile.h"
#include "mapdata.h" #include "mapdata.h"
@ -14,7 +15,7 @@ using namespace Mapsforge;
#define MD(val) ((val) / 1e6) #define MD(val) ((val) / 1e6)
#define OFFSET_MASK 0x7FFFFFFFFFL #define OFFSET_MASK 0x7FFFFFFFFFL
static uint pointType(const QVector<MapData::Tag> &tags) static quint8 pointType(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);
@ -37,20 +38,19 @@ static uint pointType(const QVector<MapData::Tag> &tags)
static void setPointId(MapData::Point &p) static void setPointId(MapData::Point &p)
{ {
uint hash = (uint)qHash(QPair<double,double>((uint)qHash( HASH_T hash = qHash(QPair<double, double>(p.coordinates.lon(),
QPair<double, double>(p.coordinates.lon(), p.coordinates.lat())), p.coordinates.lat()));
(uint)qHash(p.label))); quint8 type = pointType(p.tags);
uint type = pointType(p.tags);
p.id = ((quint64)type)<<32 | hash; p.id = ((quint64)type)<<56 | (quint64)hash;
} }
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) QSet<MapData::Path> *dst)
{ {
for (int i = 0; i < src->size(); i++) for (int i = 0; i < src->size(); i++)
if (rect.intersects(src->at(i).poly.boundingRect())) if (rect.intersects(src->at(i).poly.boundingRect()))
dst->append(src->at(i)); dst->insert(src->at(i));
} }
static void copyPoints(const RectC &rect, const QList<MapData::Point> *src, static void copyPoints(const RectC &rect, const QList<MapData::Point> *src,
@ -194,7 +194,7 @@ static bool readDoubleDelta(SubFile &subfile, const Coordinates &c,
return true; return true;
} }
static bool readPolygon(SubFile &subfile, const Coordinates &c, static bool readPolygonPath(SubFile &subfile, const Coordinates &c,
bool doubleDelta, Polygon &polygon) bool doubleDelta, Polygon &polygon)
{ {
quint32 blocks, nodes; quint32 blocks, nodes;
@ -202,7 +202,7 @@ static bool readPolygon(SubFile &subfile, const Coordinates &c,
if (!subfile.readVUInt32(blocks)) if (!subfile.readVUInt32(blocks))
return false; return false;
polygon.reserve(blocks); polygon.reserve(polygon.size() + blocks);
for (quint32 i = 0; i < blocks; i++) { for (quint32 i = 0; i < blocks; i++) {
if (!subfile.readVUInt32(nodes) || !nodes) if (!subfile.readVUInt32(nodes) || !nodes)
return false; return false;
@ -494,7 +494,7 @@ void MapData::clearTiles()
bool MapData::pathCb(VectorTile *tile, void *context) bool MapData::pathCb(VectorTile *tile, void *context)
{ {
PathCTX *ctx = (PathCTX*)context; PathCTX *ctx = (PathCTX*)context;
ctx->data->paths(tile, ctx->rect, ctx->zoom, ctx->list); ctx->data->paths(tile, ctx->rect, ctx->zoom, ctx->set);
return true; return true;
} }
@ -545,10 +545,10 @@ void MapData::points(const VectorTile *tile, const RectC &rect, int zoom,
copyPoints(rect, cached, list); copyPoints(rect, cached, list);
} }
void MapData::paths(const RectC &rect, int zoom, QList<Path> *list) void MapData::paths(const RectC &rect, int zoom, QSet<Path> *set)
{ {
int l(level(zoom)); int l(level(zoom));
PathCTX ctx(this, rect, zoom, list); PathCTX ctx(this, rect, zoom, set);
double min[2], max[2]; double min[2], max[2];
min[0] = rect.left(); min[0] = rect.left();
@ -560,7 +560,7 @@ void MapData::paths(const RectC &rect, int zoom, QList<Path> *list)
} }
void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom, void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom,
QList<Path> *list) QSet<Path> *set)
{ {
Key key(tile, zoom); Key key(tile, zoom);
QList<Path> *cached = _pathCache.object(key); QList<Path> *cached = _pathCache.object(key);
@ -568,12 +568,12 @@ void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom,
if (!cached) { if (!cached) {
QList<Path> *p = new QList<Path>(); QList<Path> *p = new QList<Path>();
if (readPaths(tile, zoom, p)) { if (readPaths(tile, zoom, p)) {
copyPaths(rect, p, list); copyPaths(rect, p, set);
_pathCache.insert(key, p); _pathCache.insert(key, p);
} else } else
delete p; delete p;
} else } else
copyPaths(rect, cached, list); copyPaths(rect, cached, set);
} }
bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list) bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
@ -604,7 +604,7 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
return false; return false;
for (unsigned i = 0; i < paths[zoom - info.min]; i++) { for (unsigned i = 0; i < paths[zoom - info.min]; i++) {
Path p; Path p(subfile.offset() + subfile.pos());
qint32 lon = 0, lat = 0; qint32 lon = 0, lat = 0;
if (!(subfile.readVUInt32(unused) && subfile.readUInt16(bitmap) if (!(subfile.readVUInt32(unused) && subfile.readUInt16(bitmap)
@ -646,15 +646,15 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
Q_ASSERT(blocks); Q_ASSERT(blocks);
for (unsigned j = 0; j < blocks; j++) { for (unsigned j = 0; j < blocks; j++) {
if (!readPolygon(subfile, tile->pos, flags & 0x04, p.poly)) if (!readPolygonPath(subfile, tile->pos, flags & 0x04, p.poly))
return false; return false;
p.closed = isClosed(p.poly);
if (flags & 0x10)
p.labelPos = Coordinates(p.poly.first().first().lon() + MD(lon),
p.poly.first().first().lat() + MD(lat));
list->append(p);
} }
p.closed = isClosed(p.poly);
if (flags & 0x10)
p.labelPos = Coordinates(p.poly.first().first().lon() + MD(lon),
p.poly.first().first().lat() + MD(lat));
list->append(p);
} }
return true; return true;
@ -720,6 +720,7 @@ bool MapData::readPoints(const VectorTile *tile, int zoom, QList<Point> *list)
} }
setPointId(p); setPointId(p);
list->append(p); list->append(p);
} }
@ -735,15 +736,14 @@ QDebug operator<<(QDebug dbg, const Mapsforge::MapData::Tag &tag)
QDebug operator<<(QDebug dbg, const MapData::Path &path) QDebug operator<<(QDebug dbg, const MapData::Path &path)
{ {
dbg.nospace() << "Path(" << path.poly.boundingRect() << ", " << path.label dbg.nospace() << "Path(" << path.poly.boundingRect() << ", "
<< ", " << path.tags << ")"; << path.tags << ")";
return dbg.space(); return dbg.space();
} }
QDebug operator<<(QDebug dbg, const MapData::Point &point) QDebug operator<<(QDebug dbg, const MapData::Point &point)
{ {
dbg.nospace() << "Point(" << point.coordinates << "," << point.label dbg.nospace() << "Point(" << point.coordinates << ", " << point.tags << ")";
<< ", " << point.tags << ")";
return dbg.space(); return dbg.space();
} }
#endif // QT_NO_DEBUG #endif // QT_NO_DEBUG

View File

@ -44,29 +44,29 @@ public:
struct Point { struct Point {
Point(const Coordinates &c) : coordinates(c) {} Point(const Coordinates &c) : coordinates(c) {}
quint64 id;
Coordinates coordinates; Coordinates coordinates;
QVector<Tag> tags; QVector<Tag> tags;
int layer; int layer;
quint64 id;
QString label;
bool operator<(const Point &other) const bool operator<(const Point &other) const
{return id > other.id;} {return id > other.id;}
}; };
struct Path { struct Path {
Path(quint64 id) : id(id) {}
quint64 id;
Polygon poly; Polygon poly;
QVector<Tag> tags; QVector<Tag> tags;
Coordinates labelPos; Coordinates labelPos;
int layer; int layer;
bool closed; bool closed;
QString label;
QPainterPath path;
bool operator<(const Path &other) const bool operator<(const Path &other) const
{return layer < other.layer;} {return layer < other.layer;}
bool operator==(const Path &other) const
{return (id == other.id);}
}; };
RectC bounds() const; RectC bounds() const;
@ -75,7 +75,7 @@ public:
int tileSize() const {return _tileSize;} int tileSize() const {return _tileSize;}
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> *list); void paths(const RectC &rect, int zoom, QSet<Path> *set);
void load(); void load();
void clear(); void clear();
@ -101,13 +101,13 @@ private:
}; };
struct PathCTX { struct PathCTX {
PathCTX(MapData *data, const RectC &rect, int zoom, QList<Path> *list) PathCTX(MapData *data, const RectC &rect, int zoom, QSet<Path> *set)
: data(data), rect(rect), zoom(zoom), list(list) {} : data(data), rect(rect), zoom(zoom), set(set) {}
MapData *data; MapData *data;
const RectC &rect; const RectC &rect;
int zoom; int zoom;
QList<Path> *list; QSet<Path> *set;
}; };
struct PointCTX { struct PointCTX {
@ -140,7 +140,7 @@ private:
int level(int zoom) const; int level(int zoom) const;
void paths(const VectorTile *tile, const RectC &rect, int zoom, void paths(const VectorTile *tile, const RectC &rect, int zoom,
QList<Path> *list); QSet<Path> *set);
void points(const VectorTile *tile, const RectC &rect, int zoom, void points(const VectorTile *tile, const RectC &rect, int zoom,
QList<Point> *list); QList<Point> *list);
bool readPaths(const VectorTile *tile, int zoom, QList<Path> *list); bool readPaths(const VectorTile *tile, int zoom, QList<Path> *list);
@ -175,6 +175,11 @@ inline HASH_T qHash(const MapData::Tag &tag)
return ::qHash(tag.key) ^ ::qHash(tag.value); return ::qHash(tag.key) ^ ::qHash(tag.value);
} }
inline HASH_T qHash(const MapData::Path &path)
{
return ::qHash(path.id);
}
} }
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG

View File

@ -3,7 +3,6 @@
#include "common/programpaths.h" #include "common/programpaths.h"
#include "map/mapsforgemap.h" #include "map/mapsforgemap.h"
#include "map/textpathitem.h" #include "map/textpathitem.h"
#include "map/textpointitem.h"
#include "rastertile.h" #include "rastertile.h"
using namespace Mapsforge; using namespace Mapsforge;
@ -44,34 +43,19 @@ static QPointF centroid(const QPainterPath &polygon)
return QPointF(cx * factor, cy * factor); return QPointF(cx * factor, cy * factor);
} }
static QString *pointLabel(const Style::TextRender *ri, MapData::Point &point) static const QByteArray *label(const QByteArray &key,
const QVector<MapData::Tag> &tags, bool *limit = 0)
{ {
for (int i = 0; i < point.tags.size(); i++) { for (int i = 0; i < tags.size(); i++) {
if (point.tags.at(i).key == ri->key()) { const MapData::Tag &tag = tags.at(i);
if (point.tags.at(i).value.isEmpty())
if (tag.key == key) {
if (tag.value.isEmpty())
return 0; return 0;
else { else {
point.label = point.tags.at(i).value;
return &point.label;
}
}
}
return 0;
}
static QString *pathLabel(const Style::TextRender *ri, MapData::Path &path,
bool *limit = 0)
{
for (int i = 0; i < path.tags.size(); i++) {
if (path.tags.at(i).key == ri->key()) {
if (path.tags.at(i).value.isEmpty())
return 0;
else {
path.label = path.tags.at(i).value;
if (limit) if (limit)
*limit = (path.tags.at(i).key == "ref"); *limit = (tag.key == "ref");
return &path.label; return &tag.value;
} }
} }
} }
@ -94,14 +78,14 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
for (int i = 0; i < _points.size(); i++) { for (int i = 0; i < _points.size(); i++) {
MapData::Point &point = _points[i]; MapData::Point &point = _points[i];
QString *label = 0; const QByteArray *l = 0;
const Style::TextRender *ti = 0; const Style::TextRender *ti = 0;
const Style::Symbol *si = 0; const Style::Symbol *si = 0;
for (int j = 0; j < labels.size(); j++) { for (int j = 0; j < labels.size(); j++) {
const Style::TextRender *ri = labels.at(j); const Style::TextRender *ri = labels.at(j);
if (ri->rule().match(point.tags)) { if (ri->rule().match(point.tags)) {
if ((label = pointLabel(ri, point))) { if ((l = label(ri->key(), point.tags))) {
ti = ri; ti = ri;
break; break;
} }
@ -124,9 +108,8 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
const QColor *color = ti ? &ti->fillColor() : 0; const QColor *color = ti ? &ti->fillColor() : 0;
const QColor *hColor = ti ? haloColor(ti) : 0; const QColor *hColor = ti ? haloColor(ti) : 0;
TextPointItem *item = new TextPointItem( PointItem *item = new PointItem(ll2xy(point.coordinates).toPoint(),
ll2xy(point.coordinates).toPoint(), label, font, img, color, l ? new QString(*l) : 0, font, img, color, hColor);
hColor, 0);
if (item->isValid() && !item->collides(textItems)) if (item->isValid() && !item->collides(textItems))
textItems.append(item); textItems.append(item);
else else
@ -134,34 +117,36 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
} }
} }
void RasterTile::processAreaLabels(QList<TextItem*> &textItems) void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
QVector<RenderPath> &renderPaths)
{ {
const Style &s = style(_ratio); const Style &s = style(_ratio);
QList<const Style::TextRender*> labels(s.areaLabels(_zoom)); QList<const Style::TextRender*> labels(s.areaLabels(_zoom));
QList<const Style::Symbol*> symbols(s.areaSymbols(_zoom)); QList<const Style::Symbol*> symbols(s.areaSymbols(_zoom));
for (int i = 0; i < _paths.size(); i++) { for (int i = 0; i < renderPaths.size(); i++) {
MapData::Path &path = _paths[i]; RenderPath &path = renderPaths[i];
QString *label = 0;
const Style::TextRender *ti = 0; const Style::TextRender *ti = 0;
const Style::Symbol *si = 0; const Style::Symbol *si = 0;
if (!path.closed) if (!path.path->closed)
continue; continue;
for (int j = 0; j < labels.size(); j++) { for (int j = 0; j < labels.size(); j++) {
const Style::TextRender *ri = labels.at(j); const Style::TextRender *ri = labels.at(j);
if (ri->rule().match(path.closed, path.tags)) { if (ri->rule().match(path.path->closed, path.path->tags)) {
if ((label = pathLabel(ri, path))) { const QByteArray *l;
if ((l = label(ri->key(), path.path->tags))) {
path.label = *l;
ti = ri; ti = ri;
break;
} }
break;
} }
} }
for (int j = 0; j < symbols.size(); j++) { for (int j = 0; j < symbols.size(); j++) {
const Style::Symbol *ri = symbols.at(j); const Style::Symbol *ri = symbols.at(j);
if (ri->rule().match(path.tags)) { if (ri->rule().match(path.path->tags)) {
si = ri; si = ri;
break; break;
} }
@ -170,18 +155,15 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems)
if (!ti && !si) if (!ti && !si)
continue; continue;
if (!path.path.elementCount())
path.path = painterPath(path.poly, false);
const QImage *img = si ? &si->img() : 0; const QImage *img = si ? &si->img() : 0;
const QFont *font = ti ? &ti->font() : 0; const QFont *font = ti ? &ti->font() : 0;
const QColor *color = ti ? &ti->fillColor() : 0; const QColor *color = ti ? &ti->fillColor() : 0;
const QColor *hColor = ti ? haloColor(ti) : 0; const QColor *hColor = ti ? haloColor(ti) : 0;
QPointF pos = path.labelPos.isNull() QPointF pos = path.path->labelPos.isNull()
? centroid(path.path) : ll2xy(path.labelPos); ? centroid(path.pp) : ll2xy(path.path->labelPos);
TextPointItem *item = new TextPointItem(pos.toPoint(), label, font, img, TextPointItem *item = new TextPointItem(pos.toPoint(), &path.label,
color, hColor, 0); font, img, color, hColor, 0);
if (item->isValid() && _rect.contains(item->boundingRect().toRect()) if (item->isValid() && _rect.contains(item->boundingRect().toRect())
&& !item->collides(textItems)) && !item->collides(textItems))
textItems.append(item); textItems.append(item);
@ -190,38 +172,40 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems)
} }
} }
void RasterTile::processLineLabels(QList<TextItem*> &textItems) void RasterTile::processLineLabels(QList<TextItem*> &textItems,
QVector<RenderPath> &renderPaths)
{ {
const Style &s = style(_ratio); const Style &s = style(_ratio);
QList<const Style::TextRender*> instructions(s.pathLabels(_zoom)); QList<const Style::TextRender*> instructions(s.pathLabels(_zoom));
QSet<QString> set; QSet<QByteArray> set;
bool limit;
for (int i = 0; i < instructions.size(); i++) { for (int i = 0; i < instructions.size(); i++) {
const Style::TextRender *ri = instructions.at(i); const Style::TextRender *ri = instructions.at(i);
for (int j = 0; j < _paths.size(); j++) { for (int i = 0; i < renderPaths.size(); i++) {
MapData::Path &path = _paths[j]; RenderPath &path = renderPaths[i];
QString *label = 0; const QByteArray *l = label(ri->key(), path.path->tags,
bool limit = false; &limit);
if (!path.path.elementCount()) if (!l)
continue; continue;
if (!ri->rule().match(path.closed, path.tags)) if (!ri->rule().match(path.path->closed, path.path->tags))
continue; continue;
if (!(label = pathLabel(ri, path, &limit))) if (limit && set.contains(*l))
continue;
if (limit && set.contains(path.label))
continue; continue;
TextPathItem *item = new TextPathItem(path.path, label, _rect, path.label = *l;
TextPathItem *item = new TextPathItem(path.pp, &path.label, _rect,
&ri->font(), &ri->fillColor(), haloColor(ri)); &ri->font(), &ri->fillColor(), haloColor(ri));
if (item->isValid() && !item->collides(textItems)) { if (item->isValid() && !item->collides(textItems)) {
textItems.append(item); textItems.append(item);
if (limit) if (limit)
set.insert(path.label); set.insert(*l);
} else } else
delete item; delete item;
} }
} }
} }
@ -262,28 +246,35 @@ QPainterPath RasterTile::painterPath(const Polygon &polygon, bool curve) const
return path; return path;
} }
QVector<RasterTile::PathInstruction> RasterTile::pathInstructions() QVector<RasterTile::PathInstruction> RasterTile::pathInstructions(
QVector<RenderPath> &renderPaths)
{ {
QCache<Key, QVector<const Style::PathRender *> > cache(8192); QCache<Key, QList<const Style::PathRender *> > cache(8192);
QVector<PathInstruction> instructions; QVector<PathInstruction> instructions;
const Style &s = style(_ratio); const Style &s = style(_ratio);
QVector<const Style::PathRender*> *ri; QList<const Style::PathRender*> *ri;
int i = 0;
for (int i = 0 ; i < _paths.size(); i++) {
MapData::Path &path = _paths[i];
for (QSet<MapData::Path>::const_iterator it = _paths.cbegin();
it != _paths.cend(); ++it) {
const MapData::Path &path = *it;
RenderPath &rp = renderPaths[i];
Key key(_zoom, path.closed, path.tags); Key key(_zoom, path.closed, path.tags);
QVector<const Style::PathRender*> *cached = cache.object(key);
if (!cached) { rp.path = &path;
ri = new QVector<const Style::PathRender*>(s.paths(_zoom,
if (!(ri = cache.object(key))) {
ri = new QList<const Style::PathRender*>(s.paths(_zoom,
path.closed, path.tags)); path.closed, path.tags));
for (int j = 0; j < ri->size(); j++) for (int j = 0; j < ri->size(); j++)
instructions.append(PathInstruction(ri->at(j), &path)); instructions.append(PathInstruction(ri->at(j), &rp));
cache.insert(key, ri); cache.insert(key, ri);
} else { } else {
for (int j = 0; j < cached->size(); j++) for (int j = 0; j < ri->size(); j++)
instructions.append(PathInstruction(cached->at(j), &path)); instructions.append(PathInstruction(ri->at(j), &rp));
} }
i++;
} }
std::sort(instructions.begin(), instructions.end()); std::sort(instructions.begin(), instructions.end());
@ -291,47 +282,22 @@ QVector<RasterTile::PathInstruction> RasterTile::pathInstructions()
return instructions; return instructions;
} }
void RasterTile::drawPaths(QPainter *painter) void RasterTile::drawPaths(QPainter *painter, QVector<RenderPath> &renderPaths)
{ {
QVector<PathInstruction> instructions(pathInstructions()); QVector<PathInstruction> instructions(pathInstructions(renderPaths));
const Style::PathRender *lri = 0;
QPixmap layer(_pixmap.size());
layer.setDevicePixelRatio(_ratio);
layer.fill(Qt::transparent);
QPainter lp(&layer);
lp.setRenderHint(QPainter::Antialiasing);
lp.translate(-_rect.x(), -_rect.y());
lp.setCompositionMode(QPainter::CompositionMode_Source);
for (int i = 0; i < instructions.size(); i++) { for (int i = 0; i < instructions.size(); i++) {
PathInstruction &is = instructions[i]; const PathInstruction &is = instructions.at(i);
const Style::PathRender *ri = is.render(); const Style::PathRender *ri = is.render();
RenderPath *path = is.path();
if (lri && lri != ri) { if (!path->pp.elementCount())
painter->drawPixmap(_rect.topLeft(), layer); path->pp = painterPath(path->path->poly, ri->curve());
lp.fillRect(QRect(_rect.topLeft(), _pixmap.size()), Qt::transparent);
}
if (!is.path()->path.elementCount()) painter->setPen(ri->pen(_zoom));
is.path()->path = painterPath(is.path()->poly, ri->curve()); painter->setBrush(ri->brush());
painter->drawPath(path->pp);
if (ri->area()) {
lp.setPen(ri->pen(_zoom));
lp.setBrush(ri->brush());
lp.drawPath(is.path()->path);
lri = ri;
} else {
painter->setPen(ri->pen(_zoom));
painter->setBrush(ri->brush());
painter->drawPath(is.path()->path);
lri = 0;
}
} }
if (lri)
painter->drawPixmap(_rect.topLeft(), layer);
} }
void RasterTile::render() void RasterTile::render()
@ -339,6 +305,7 @@ void RasterTile::render()
std::sort(_points.begin(), _points.end()); std::sort(_points.begin(), _points.end());
QList<TextItem*> textItems; QList<TextItem*> textItems;
QVector<RenderPath> renderPaths(_paths.size());
_pixmap.setDevicePixelRatio(_ratio); _pixmap.setDevicePixelRatio(_ratio);
_pixmap.fill(Qt::transparent); _pixmap.fill(Qt::transparent);
@ -347,11 +314,11 @@ void RasterTile::render()
painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::Antialiasing);
painter.translate(-_rect.x(), -_rect.y()); painter.translate(-_rect.x(), -_rect.y());
drawPaths(&painter); drawPaths(&painter, renderPaths);
processPointLabels(textItems); processPointLabels(textItems);
processAreaLabels(textItems); processAreaLabels(textItems, renderPaths);
processLineLabels(textItems); processLineLabels(textItems, renderPaths);
drawTextItems(&painter, textItems); drawTextItems(&painter, textItems);
//painter.setPen(Qt::red); //painter.setPen(Qt::red);

View File

@ -4,6 +4,7 @@
#include <QPixmap> #include <QPixmap>
#include "map/projection.h" #include "map/projection.h"
#include "map/transform.h" #include "map/transform.h"
#include "map/textpointitem.h"
#include "style.h" #include "style.h"
#include "mapdata.h" #include "mapdata.h"
@ -16,7 +17,7 @@ class RasterTile
{ {
public: public:
RasterTile(const Projection &proj, const Transform &transform, int zoom, RasterTile(const Projection &proj, const Transform &transform, int zoom,
const QRect &rect, qreal ratio, const QList<MapData::Path> &paths, const QRect &rect, qreal ratio, const QSet<MapData::Path> &paths,
const QList<MapData::Point> &points) : _proj(proj), _transform(transform), const QList<MapData::Point> &points) : _proj(proj), _transform(transform),
_zoom(zoom), _rect(rect), _ratio(ratio), _zoom(zoom), _rect(rect), _ratio(ratio),
_pixmap(rect.width() * ratio, rect.height() * ratio), _paths(paths), _pixmap(rect.width() * ratio, rect.height() * ratio), _paths(paths),
@ -30,27 +31,35 @@ public:
void render(); void render();
private: private:
struct RenderPath {
RenderPath() : path(0) {}
QPainterPath pp;
QString label;
const MapData::Path *path;
};
class PathInstruction class PathInstruction
{ {
public: public:
PathInstruction() : _render(0), _path(0) {} PathInstruction() : _render(0), _path(0) {}
PathInstruction(const Style::PathRender *render, MapData::Path *path) PathInstruction(const Style::PathRender *render, RenderPath *path)
: _render(render), _path(path) {} : _render(render), _path(path) {}
bool operator<(const PathInstruction &other) const bool operator<(const PathInstruction &other) const
{ {
if (_path->layer == other._path->layer) if (_path->path->layer == other._path->path->layer)
return _render->zOrder() < other._render->zOrder(); return _render->zOrder() < other._render->zOrder();
else else
return (_path->layer < other._path->layer); return (_path->path->layer < other._path->path->layer);
} }
const Style::PathRender *render() const {return _render;} const Style::PathRender *render() const {return _render;}
MapData::Path *path() {return _path;} RenderPath *path() const {return _path;}
private: private:
const Style::PathRender *_render; const Style::PathRender *_render;
MapData::Path *_path; RenderPath *_path;
}; };
struct Key { struct Key {
@ -67,18 +76,32 @@ private:
const QVector<MapData::Tag> &tags; const QVector<MapData::Tag> &tags;
}; };
friend HASH_T qHash(const RasterTile::Key &key); class PointItem : public TextPointItem
friend HASH_T qHash(const RasterTile::PathInstruction &pi); {
public:
PointItem(const QPoint &point, QString *text, const QFont *font,
const QImage *img, const QColor *color, const QColor *haloColor)
: TextPointItem(point, text, font, img, color, haloColor, 0),
_label(text) {}
~PointItem() {delete _label;}
QVector<PathInstruction> pathInstructions(); private:
QString *_label;
};
friend HASH_T qHash(const RasterTile::Key &key);
QVector<PathInstruction> pathInstructions(QVector<RenderPath> &renderPaths);
QPointF ll2xy(const Coordinates &c) const QPointF ll2xy(const Coordinates &c) const
{return _transform.proj2img(_proj.ll2xy(c));} {return _transform.proj2img(_proj.ll2xy(c));}
void processPointLabels(QList<TextItem*> &textItems); void processPointLabels(QList<TextItem*> &textItems);
void processAreaLabels(QList<TextItem*> &textItems); void processAreaLabels(QList<TextItem*> &textItems,
void processLineLabels(QList<TextItem*> &textItems); QVector<RenderPath> &renderPaths);
void processLineLabels(QList<TextItem*> &textItems,
QVector<RenderPath> &renderPaths);
QPainterPath painterPath(const Polygon &polygon, bool curve) const; QPainterPath painterPath(const Polygon &polygon, bool curve) const;
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems); void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
void drawPaths(QPainter *painter); void drawPaths(QPainter *painter, QVector<RenderPath> &renderPaths);
Projection _proj; Projection _proj;
Transform _transform; Transform _transform;
@ -86,8 +109,9 @@ private:
QRect _rect; QRect _rect;
qreal _ratio; qreal _ratio;
QPixmap _pixmap; QPixmap _pixmap;
QList<MapData::Path> _paths; QSet<MapData::Path> _paths;
QList<MapData::Point> _points; QList<MapData::Point> _points;
bool _valid; bool _valid;
}; };

View File

@ -432,10 +432,10 @@ Style::Style(const QString &path, qreal ratio)
loadXml(":/mapsforge/default.xml", ratio); loadXml(":/mapsforge/default.xml", ratio);
} }
QVector<const Style::PathRender *> Style::paths(int zoom, bool closed, QList<const Style::PathRender *> Style::paths(int zoom, bool closed,
const QVector<MapData::Tag> &tags) const const QVector<MapData::Tag> &tags) const
{ {
QVector<const PathRender*> ri; QList<const PathRender*> ri;
for (int i = 0; i < _paths.size(); i++) for (int i = 0; i < _paths.size(); i++)
if (_paths.at(i).rule().match(zoom, closed, tags)) if (_paths.at(i).rule().match(zoom, closed, tags))

View File

@ -221,7 +221,7 @@ public:
Style(const QString &path, qreal ratio); Style(const QString &path, qreal ratio);
QVector<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;
QList<const TextRender*> pathLabels(int zoom) const; QList<const TextRender*> pathLabels(int zoom) const;
QList<const TextRender*> pointLabels(int zoom) const; QList<const TextRender*> pointLabels(int zoom) const;

View File

@ -14,6 +14,7 @@ public:
: _file(file), _offset(offset), _size(size), _pos(-1), : _file(file), _offset(offset), _size(size), _pos(-1),
_blockNum(-1), _blockPos(-1) {} _blockNum(-1), _blockPos(-1) {}
quint64 offset() const {return _offset;}
quint64 pos() const {return _pos;} quint64 pos() const {return _pos;}
bool seek(quint64 pos); bool seek(quint64 pos);

View File

@ -175,7 +175,7 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
if (QPixmapCache::find(key(_zoom, ttl), &pm)) if (QPixmapCache::find(key(_zoom, ttl), &pm))
painter->drawPixmap(ttl, pm); painter->drawPixmap(ttl, pm);
else { else {
QList<MapData::Path> paths; QSet<MapData::Path> paths;
QList<MapData::Point> points; QList<MapData::Point> points;
/* Add a "sub-pixel" margin to assure the tile areas do not /* Add a "sub-pixel" margin to assure the tile areas do not