From 9afeaf672a2c7270ea70c8ba9d7b6c3130bcc029 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Martin=20T=C5=AFma?= Date: Sat, 10 Jun 2023 08:11:18 +0200 Subject: [PATCH] Properly match symbols to captions --- src/map/mapsforge/rastertile.cpp | 118 +++++++++++++++++++++++---------------- src/map/mapsforge/rastertile.h | 26 ++++++++- src/map/mapsforge/style.cpp | 4 ++ src/map/mapsforge/style.h | 9 ++- src/map/textpathitem.cpp | 1 + src/map/textpointitem.cpp | 1 + 6 files changed, 105 insertions(+), 54 deletions(-) diff --git a/src/map/mapsforge/rastertile.cpp b/src/map/mapsforge/rastertile.cpp index 0e2f70eb..4c4ac682 100644 --- a/src/map/mapsforge/rastertile.cpp +++ b/src/map/mapsforge/rastertile.cpp @@ -106,40 +106,43 @@ void RasterTile::processPointLabels(const QList &points, { QList labels(_style->pointLabels(_zoom)); QList symbols(_style->pointSymbols(_zoom)); - QList painterPoints; + QList items; for (int i = 0; i < points.size(); i++) { const MapData::Point &point = points.at(i); - const QByteArray *lbl = 0; const Style::TextRender *ti = 0; const Style::Symbol *si = 0; + const QByteArray *lbl = 0; + + for (int j = 0; j < symbols.size(); j++) { + const Style::Symbol *ri = symbols.at(j); + + if (ri->rule().match(point.tags)) + if (!si || si->priority() < ri->priority()) + si = ri; + } for (int j = 0; j < labels.size(); j++) { const Style::TextRender *ri = labels.at(j); if (ri->rule().match(point.tags)) { if ((lbl = label(ri->key(), point.tags))) { + if (si && si->id() != ri->symbolId()) + continue; + ti = ri; break; } } } - for (int j = 0; j < symbols.size(); j++) { - const Style::Symbol *ri = symbols.at(j); - if (ri->rule().match(point.tags)) { - si = ri; - break; - } - } - if (ti || si) - painterPoints.append(PainterPoint(&point, lbl, si, ti)); + items.append(PointText(&point, lbl, si, ti)); } - std::sort(painterPoints.begin(), painterPoints.end()); + std::sort(items.begin(), items.end()); - for (int i = 0; i < painterPoints.size(); i++) { - const PainterPoint &p = painterPoints.at(i); + for (int i = 0; i < items.size(); i++) { + const PointText &p = items.at(i); const QImage *img = p.si ? &p.si->img() : 0; const QFont *font = p.ti ? &p.ti->font() : 0; const QColor *color = p.ti ? &p.ti->fillColor() : 0; @@ -159,6 +162,7 @@ void RasterTile::processAreaLabels(const QVector &paths, { QList labels(_style->areaLabels(_zoom)); QList symbols(_style->areaSymbols(_zoom)); + QList items; for (int i = 0; i < paths.size(); i++) { const PainterPath &path = paths.at(i); @@ -169,34 +173,43 @@ void RasterTile::processAreaLabels(const QVector &paths, if (!path.path->closed) continue; + for (int j = 0; j < symbols.size(); j++) { + const Style::Symbol *ri = symbols.at(j); + + if (ri->rule().match(path.path->closed, path.path->tags)) + if (!si || si->priority() < ri->priority()) + si = ri; + } + for (int j = 0; j < labels.size(); j++) { const Style::TextRender *ri = labels.at(j); if (ri->rule().match(path.path->closed, path.path->tags)) { - if ((lbl = label(ri->key(), path.path->tags))) + if ((lbl = label(ri->key(), path.path->tags))) { + if (si && si->id() != ri->symbolId()) + continue; + ti = ri; - break; + break; + } } } - for (int j = 0; j < symbols.size(); j++) { - const Style::Symbol *ri = symbols.at(j); - if (ri->rule().match(path.path->tags)) { - si = ri; - break; - } - } + if (ti || si) + items.append(PathText(&path, lbl, si, ti)); + } - if (!ti && !si) - continue; + std::sort(items.begin(), items.end()); - const QImage *img = si ? &si->img() : 0; - const QFont *font = ti ? &ti->font() : 0; - const QColor *color = ti ? &ti->fillColor() : 0; - const QColor *hColor = ti ? haloColor(ti) : 0; - QPointF pos = path.path->labelPos.isNull() - ? centroid(path.pp) : ll2xy(path.path->labelPos); + for (int i = 0; i < items.size(); i++) { + const PathText &p = items.at(i); + const QImage *img = p.si ? &p.si->img() : 0; + const QFont *font = p.ti ? &p.ti->font() : 0; + const QColor *color = p.ti ? &p.ti->fillColor() : 0; + const QColor *hColor = p.ti ? haloColor(p.ti) : 0; + QPointF pos = p.p->path->labelPos.isNull() + ? centroid(p.p->pp) : ll2xy(p.p->path->labelPos); - PointItem *item = new PointItem(pos.toPoint(), lbl, font, img, color, + PointItem *item = new PointItem(pos.toPoint(), p.lbl, font, img, color, hColor); if (item->isValid() && _rect.contains(item->boundingRect().toRect()) && !item->collides(textItems)) @@ -211,6 +224,7 @@ void RasterTile::processLineLabels(const QVector &paths, { QList labels(_style->pathLabels(_zoom)); QList symbols(_style->lineSymbols(_zoom)); + QList items; QSet set; for (int i = 0; i < paths.size(); i++) { @@ -218,7 +232,6 @@ void RasterTile::processLineLabels(const QVector &paths, const Style::TextRender *ti = 0; const Style::Symbol *si = 0; const QByteArray *lbl = 0; - bool limit = false; if (path.path->closed) continue; @@ -234,37 +247,44 @@ void RasterTile::processLineLabels(const QVector &paths, for (int j = 0; j < symbols.size(); j++) { const Style::Symbol *ri = symbols.at(j); - if (ri->rule().match(path.path->tags)) { + if (ri->rule().match(path.path->closed, path.path->tags)) { si = ri; break; } } - if (!ti && !si) - continue; - if (ti) { - limit = (ti->key() == ID_ELE || ti->key() == ID_REF); - if (limit && set.contains(*lbl)) + if (ti || si) + items.append(PathText(&path, lbl, si, ti)); + } + + std::sort(items.begin(), items.end()); + + for (int i = 0; i < items.size(); i++) { + const PathText &p = items.at(i); + const QImage *img = p.si ? &p.si->img() : 0; + const QFont *font = p.ti ? &p.ti->font() : 0; + const QColor *color = p.ti ? &p.ti->fillColor() : 0; + const QColor *hColor = p.ti ? haloColor(p.ti) : 0; + bool rotate = p.si ? p.si->rotate() : false; + bool limit = false; + + if (p.ti) { + limit = (p.ti->key() == ID_ELE || p.ti->key() == ID_REF); + if (limit && set.contains(*p.lbl)) continue; } - const QImage *img = si ? &si->img() : 0; - const QFont *font = ti ? &ti->font() : 0; - const QColor *color = ti ? &ti->fillColor() : 0; - const QColor *hColor = ti ? haloColor(ti) : 0; - bool rotate = si ? si->rotate() : false; - - PathItem *item = new PathItem(path.pp, lbl, img, _rect, font, color, + PathItem *item = new PathItem(p.p->pp, p.lbl, img, _rect, font, color, hColor, rotate); if (item->isValid() && !item->collides(textItems)) { textItems.append(item); if (limit) - set.insert(*lbl); + set.insert(*p.lbl); } else { delete item; - if (img && lbl) { - PathItem *item = new PathItem(path.pp, 0, img, _rect, 0, 0, 0, + if (img && p.lbl) { + PathItem *item = new PathItem(p.p->pp, 0, img, _rect, 0, 0, 0, rotate); if (item->isValid() && !item->collides(textItems)) textItems.append(item); diff --git a/src/map/mapsforge/rastertile.h b/src/map/mapsforge/rastertile.h index 8c7cc665..1f912418 100644 --- a/src/map/mapsforge/rastertile.h +++ b/src/map/mapsforge/rastertile.h @@ -35,15 +35,15 @@ private: const MapData::Path *path; }; - struct PainterPoint { - PainterPoint(const MapData::Point *p, const QByteArray *lbl, + struct PointText { + PointText(const MapData::Point *p, const QByteArray *lbl, const Style::Symbol *si, const Style::TextRender *ti) : p(p), lbl(lbl), ti(ti), si(si) { Q_ASSERT(si || ti); } - bool operator<(const PainterPoint &other) const + bool operator<(const PointText &other) const { if (priority() == other.priority()) return p->id < other.p->id; @@ -58,6 +58,26 @@ private: const Style::Symbol *si; }; + struct PathText { + PathText(const PainterPath *p, const QByteArray *lbl, + const Style::Symbol *si, const Style::TextRender *ti) + : p(p), lbl(lbl), ti(ti), si(si) + { + Q_ASSERT(si || ti); + } + + bool operator<(const PathText &other) const + { + return (priority() > other.priority()); + } + int priority() const {return si ? si->priority() : ti->priority();} + + const PainterPath *p; + const QByteArray *lbl; + const Style::TextRender *ti; + const Style::Symbol *si; + }; + class RenderInstruction { public: diff --git a/src/map/mapsforge/style.cpp b/src/map/mapsforge/style.cpp index 68418c3e..e60a6cb2 100644 --- a/src/map/mapsforge/style.cpp +++ b/src/map/mapsforge/style.cpp @@ -421,6 +421,8 @@ void Style::text(QXmlStreamReader &reader, const MapData &data, const Rule &rule return; } } + if (attr.hasAttribute("symbol-id")) + ri._symbolId = attr.value("symbol-id").toString(); ri._font.setFamily(fontFamily); ri._font.setPixelSize(fontSize); @@ -482,6 +484,8 @@ void Style::symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio, if (attr.value("rotate").toString() == "false") ri._rotate = false; } + if (attr.hasAttribute("id")) + ri._id = attr.value("id").toString(); ri._img = image(file, width, height, percent, ratio); diff --git a/src/map/mapsforge/style.h b/src/map/mapsforge/style.h index a732f9d7..82aa71b8 100644 --- a/src/map/mapsforge/style.h +++ b/src/map/mapsforge/style.h @@ -192,6 +192,7 @@ public: : Render(rule), _priority(0), _fillColor(Qt::black), _strokeColor(Qt::black), _strokeWidth(0) {} + const QString &symbolId() const {return _symbolId;} const QFont &font() const {return _font;} const QColor &fillColor() const {return _fillColor;} const QColor &strokeColor() const {return _strokeColor;} @@ -202,6 +203,7 @@ public: private: friend class Style; + QString _symbolId; int _priority; QColor _fillColor, _strokeColor; qreal _strokeWidth; @@ -212,15 +214,18 @@ public: class Symbol : public Render { public: - Symbol(const Rule &rule) : Render(rule), _priority(0), _rotate(true) {} + Symbol(const Rule &rule) + : Render(rule), _priority(0), _rotate(true) {} + const QString &id() const {return _id;} const QImage &img() const {return _img;} - int priority() const {return _priority;} bool rotate() const {return _rotate;} + int priority() const {return _priority;} private: friend class Style; + QString _id; int _priority; bool _rotate; QImage _img; diff --git a/src/map/textpathitem.cpp b/src/map/textpathitem.cpp index 8c4783e1..a811d450 100644 --- a/src/map/textpathitem.cpp +++ b/src/map/textpathitem.cpp @@ -382,5 +382,6 @@ void TextPathItem::paint(QPainter *painter) const //painter->setBrush(Qt::NoBrush); //painter->setPen(Qt::red); + //painter->setRenderHint(QPainter::Antialiasing, false); //painter->drawPath(_shape); } diff --git a/src/map/textpointitem.cpp b/src/map/textpointitem.cpp index 3a896896..42099f2c 100644 --- a/src/map/textpointitem.cpp +++ b/src/map/textpointitem.cpp @@ -109,6 +109,7 @@ void TextPointItem::paint(QPainter *painter) const } //painter->setPen(Qt::red); + //painter.setBrush(Qt::NoBrush); //painter->setRenderHint(QPainter::Antialiasing, false); //painter->drawRect(_rect); } -- 2.11.4.GIT