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

Layer rendering issue fix + optimization

This commit is contained in:
Martin Tůma 2021-04-14 22:03:06 +02:00
parent f97f33f111
commit ce6f03de73
4 changed files with 131 additions and 45 deletions

View File

@ -47,6 +47,8 @@ static QPointF centroid(const QPainterPath &polygon)
void RasterTile::processPoints(QList<TextItem*> &textItems)
{
const Style &s = style();
QList<const Style::TextRender*> labels(s.pointLabels(_zoom));
QList<const Style::Symbol*> symbols(s.symbols(_zoom));
for (int i = 0; i < _points.size(); i++) {
const MapData::Point &point = _points.at(i);
@ -55,19 +57,19 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
const Style::Symbol *si = 0;
if (label) {
for (int i = 0; i < s.pointLabels().size(); i++) {
const Style::TextRender &ri = s.pointLabels().at(i);
if (ri.rule().match(_zoom, point.tags)) {
ti = &ri;
for (int i = 0; i < labels.size(); i++) {
const Style::TextRender *ri = labels.at(i);
if (ri->rule().match(point.tags)) {
ti = ri;
break;
}
}
}
for (int i = 0; i < s.symbols().size(); i++) {
const Style::Symbol &ri = s.symbols().at(i);
if (ri.rule().match(_zoom, point.tags)) {
si = &ri;
for (int i = 0; i < symbols.size(); i++) {
const Style::Symbol *ri = symbols.at(i);
if (ri->rule().match(point.tags)) {
si = ri;
break;
}
}
@ -89,32 +91,33 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
}
}
void RasterTile::processPolygonNames(const QRect &tileRect,
void RasterTile::processAreaNames(const QRect &tileRect,
QList<TextItem*> &textItems)
{
const Style &s = style();
QList<const Style::TextRender*> instructions(s.areaLabels(_zoom));
QSet<QString> set;
for (int i = 0; i < s.pointLabels().size(); i++) {
const Style::TextRender &ri = s.pointLabels().at(i);
for (int i = 0; i < instructions.size(); i++) {
const Style::TextRender *ri = instructions.at(i);
for (int j = 0; j < _paths.size(); j++) {
const MapData::Path &path = _paths.at(j);
if (path.label.isEmpty())
if (!path.closed || path.label.isEmpty())
continue;
if (!path.path.elementCount())
continue;
if (set.contains(path.label))
continue;
if (!ri.rule().match(_zoom, path.closed, path.tags))
if (!ri->rule().match(path.closed, path.tags))
continue;
QPointF pos = path.labelPos.isNull()
? centroid(path.path) : ll2xy(path.labelPos);
TextPointItem *item = new TextPointItem(pos.toPoint(), &path.label,
&ri.font(), 0, &ri.fillColor(), 0, false);
&ri->font(), 0, &ri->fillColor(), 0, false);
if (item->isValid() && tileRect.contains(item->boundingRect().toRect())
&& !item->collides(textItems)) {
textItems.append(item);
@ -129,9 +132,10 @@ void RasterTile::processStreetNames(const QRect &tileRect,
QList<TextItem*> &textItems)
{
const Style &s = style();
QList<const Style::TextRender*> instructions(s.pathLabels(_zoom));
for (int i = 0; i < s.pathLabels().size(); i++) {
const Style::TextRender &ri = s.pathLabels().at(i);
for (int i = 0; i < instructions.size(); i++) {
const Style::TextRender *ri = instructions.at(i);
for (int j = 0; j < _paths.size(); j++) {
MapData::Path &path = _paths[j];
@ -140,12 +144,12 @@ void RasterTile::processStreetNames(const QRect &tileRect,
continue;
if (!path.path.elementCount())
continue;
if (!ri.rule().match(_zoom, path.closed, path.tags))
if (!ri->rule().match(path.closed, path.tags))
continue;
TextPathItem *item = new TextPathItem(path.path,
&path.label, tileRect, &ri.font(), &ri.fillColor(),
&ri.strokeColor());
&path.label, tileRect, &ri->font(), &ri->fillColor(),
&ri->strokeColor());
if (item->isValid() && !item->collides(textItems))
textItems.append(item);
else
@ -208,19 +212,35 @@ QVector<RasterTile::PathInstruction> RasterTile::pathInstructions()
void RasterTile::drawPaths(QPainter *painter)
{
QVector<PathInstruction> instructions(pathInstructions());
const Style::PathRender *lri = 0;
QPixmap layer(_pixmap.size());
layer.fill(Qt::transparent);
QPainter lp(&layer);
lp.setRenderHint(QPainter::Antialiasing);
lp.translate(-_xy.x(), -_xy.y());
lp.setCompositionMode(QPainter::CompositionMode_Source);
for (int i = 0; i < instructions.size(); i++) {
PathInstruction &is = instructions[i];
const Style::PathRender *ri = is.render();
painter->setPen(ri->pen(_zoom));
painter->setBrush(ri->brush());
if (lri && ri != lri) {
painter->drawPixmap(_xy, layer);
layer.fill(Qt::transparent);
}
lri = ri;
if (!is.path()->path.elementCount())
is.path()->path = painterPath(is.path()->poly);
painter->drawPath(is.path()->path);
lp.setPen(ri->pen(_zoom));
lp.setBrush(ri->brush());
lp.drawPath(is.path()->path);
}
painter->drawPixmap(_xy, layer);
}
void RasterTile::render()
@ -239,13 +259,13 @@ void RasterTile::render()
drawPaths(&painter);
processPoints(textItems);
processPolygonNames(tileRect, textItems);
processAreaNames(tileRect, textItems);
processStreetNames(tileRect, textItems);
drawTextItems(&painter, textItems);
//painter.setPen(Qt::red);
//painter.setBrush(Qt::NoBrush);
//painter.drawRect(QRect(_xy, _img.size()));
//painter.drawRect(QRect(_xy, _pixmap.size()));
qDeleteAll(textItems);
}

View File

@ -72,7 +72,7 @@ private:
QPointF ll2xy(const Coordinates &c) const
{return _transform.proj2img(_proj.ll2xy(c));}
void processPoints(QList<TextItem*> &textItems);
void processPolygonNames(const QRect &tileRect, QList<TextItem*> &textItems);
void processAreaNames(const QRect &tileRect, QList<TextItem*> &textItems);
void processStreetNames(const QRect &tileRect, QList<TextItem*> &textItems);
QPainterPath painterPath(const Polygon &polygon) const;
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);

View File

@ -35,15 +35,19 @@ static QImage image(const QString &path, int width, int height)
return QImage(path);
}
bool Style::Rule::match(int zoom, bool closed,
const QVector<MapData::Tag> &tags) const
bool Style::Rule::match(const QVector<MapData::Tag> &tags) const
{
for (int i = 0; i < _filters.size(); i++)
if (!_filters.at(i).match(tags))
return false;
return true;
}
bool Style::Rule::match(bool closed, const QVector<MapData::Tag> &tags) const
{
Closed cl = closed ? YesClosed : NoClosed;
if (_type && WayType != _type)
return false;
if (!_zooms.contains(zoom))
return false;
if (_closed && cl != _closed)
return false;
@ -54,12 +58,17 @@ bool Style::Rule::match(int zoom, bool closed,
return true;
}
bool Style::Rule::match(int zoom, const QVector<MapData::Tag> &tags) const
bool Style::Rule::match(int zoom, bool closed,
const QVector<MapData::Tag> &tags) const
{
if (_type && NodeType != _type)
Closed cl = closed ? YesClosed : NoClosed;
if (_type && WayType != _type)
return false;
if (!_zooms.contains(zoom))
return false;
if (_closed && cl != _closed)
return false;
for (int i = 0; i < _filters.size(); i++)
if (!_filters.at(i).match(tags))
@ -136,7 +145,7 @@ void Style::line(QXmlStreamReader &reader, const Rule &rule)
}
void Style::text(QXmlStreamReader &reader, const Rule &rule,
QList<TextRender> &list)
QList<QList<TextRender>*> &lists)
{
TextRender ri(rule);
const QXmlStreamAttributes &attr = reader.attributes();
@ -165,7 +174,8 @@ void Style::text(QXmlStreamReader &reader, const Rule &rule,
ri._font.setBold(bold);
ri._font.setItalic(italic);
list.append(ri);
for (int i = 0; i < lists.size(); i++)
lists[i]->append(ri);
reader.skipCurrentElement();
}
@ -233,10 +243,18 @@ void Style::rule(QXmlStreamReader &reader, const QString &dir,
area(reader, dir, r);
else if (reader.name() == QLatin1String("line"))
line(reader, r);
else if (reader.name() == QLatin1String("pathText"))
text(reader, r, _pathLabels);
else if (reader.name() == QLatin1String("caption"))
text(reader, r, _pointLabels);
else if (reader.name() == QLatin1String("pathText")) {
QList<QList<TextRender>*> list;
list.append(&_pathLabels);
text(reader, 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);
}
else if (reader.name() == QLatin1String("symbol"))
symbol(reader, dir, r);
else
@ -327,6 +345,50 @@ void Style::match(int zoom, bool closed, const QVector<MapData::Tag> &tags,
ri->append(&_paths.at(i));
}
QList<const Style::TextRender*> Style::pathLabels(int zoom) const
{
QList<const Style::TextRender*> list;
for (int i = 0; i < _pathLabels.size(); i++)
if (_pathLabels.at(i).rule().zooms().contains(zoom))
list.append(&_pathLabels.at(i));
return list;
}
QList<const Style::TextRender*> Style::pointLabels(int zoom) const
{
QList<const Style::TextRender*> list;
for (int i = 0; i < _pointLabels.size(); i++)
if (_pointLabels.at(i).rule().zooms().contains(zoom))
list.append(&_pointLabels.at(i));
return list;
}
QList<const Style::TextRender*> Style::areaLabels(int zoom) const
{
QList<const Style::TextRender*> list;
for (int i = 0; i < _areaLabels.size(); i++)
if (_areaLabels.at(i).rule().zooms().contains(zoom))
list.append(&_areaLabels.at(i));
return list;
}
QList<const Style::Symbol*> Style::symbols(int zoom) const
{
QList<const Style::Symbol*> list;
for (int i = 0; i < _symbols.size(); i++)
if (_symbols.at(i).rule().zooms().contains(zoom))
list.append(&_symbols.at(i));
return list;
}
QPen Style::PathRender::pen(int zoom) const
{
qreal width = (zoom >= 12)

View File

@ -29,9 +29,12 @@ public:
public:
Rule() : _type(AnyType), _closed(AnyClosed), _zooms(0, 127) {}
bool match(const QVector<MapData::Tag> &tags) const;
bool match(bool closed, const QVector<MapData::Tag> &tags) const;
bool match(int zoom, bool closed,
const QVector<MapData::Tag> &tags) const;
bool match(int zoom, const QVector<MapData::Tag> &tags) const;
const Range &zooms() const {return _zooms;}
private:
enum Type {
@ -214,13 +217,14 @@ public:
void match(int zoom, bool closed, const QVector<MapData::Tag> &tags,
QVector<const PathRender *> *ri) const;
const QList<TextRender> &pathLabels() const {return _pathLabels;}
const QList<TextRender> &pointLabels() const {return _pointLabels;}
const QList<Symbol> &symbols() const {return _symbols;}
QList<const TextRender*> pathLabels(int zoom) const;
QList<const TextRender*> pointLabels(int zoom) const;
QList<const TextRender*> areaLabels(int zoom) const;
QList<const Symbol*> symbols(int zoom) const;
private:
QList<PathRender> _paths;
QList<TextRender> _pathLabels, _pointLabels;
QList<TextRender> _pathLabels, _pointLabels, _areaLabels;
QList<Symbol> _symbols;
bool loadXml(const QString &path);
@ -233,7 +237,7 @@ private:
void area(QXmlStreamReader &reader, const QString &dir, const Rule &rule);
void line(QXmlStreamReader &reader, const Rule &rule);
void text(QXmlStreamReader &reader, const Rule &rule,
QList<TextRender> &list);
QList<QList<TextRender> *> &lists);
void symbol(QXmlStreamReader &reader, const QString &dir, const Rule &rule);
};