2021-04-10 15:27:40 +02:00
|
|
|
#include <QFile>
|
|
|
|
#include <QXmlStreamReader>
|
|
|
|
#include <QUrl>
|
|
|
|
#include <QFileInfo>
|
|
|
|
#include <QImageReader>
|
|
|
|
#include "style.h"
|
|
|
|
|
|
|
|
using namespace Mapsforge;
|
|
|
|
|
|
|
|
static QString resourcePath(const QString &src, const QString &dir)
|
|
|
|
{
|
|
|
|
QUrl url(src);
|
|
|
|
if (url.scheme().isEmpty())
|
|
|
|
return src;
|
|
|
|
else
|
|
|
|
return dir + "/" + url.toLocalFile();
|
|
|
|
}
|
|
|
|
|
2021-04-18 18:10:23 +02:00
|
|
|
static QImage image(const QString &path, int width, int height, qreal ratio)
|
2021-04-10 15:27:40 +02:00
|
|
|
{
|
|
|
|
QImageReader ir(path, "svg");
|
|
|
|
|
|
|
|
if (ir.canRead()) {
|
|
|
|
if (!height && !width) {
|
|
|
|
height = 20;
|
|
|
|
width = 20;
|
|
|
|
} else if (!width) {
|
|
|
|
width = ir.size().height() / (ir.size().height() / (double)height);
|
|
|
|
} else if (!height)
|
|
|
|
height = ir.size().width() / (ir.size().width() / (double)width);
|
|
|
|
|
2021-04-18 18:10:23 +02:00
|
|
|
ir.setScaledSize(QSize(width * ratio, height * ratio));
|
|
|
|
QImage img(ir.read());
|
|
|
|
img.setDevicePixelRatio(ratio);
|
|
|
|
return img;
|
2021-04-10 15:27:40 +02:00
|
|
|
} else
|
|
|
|
return QImage(path);
|
|
|
|
}
|
|
|
|
|
2021-04-14 22:03:06 +02:00
|
|
|
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
|
2021-04-10 15:27:40 +02:00
|
|
|
{
|
|
|
|
Closed cl = closed ? YesClosed : NoClosed;
|
|
|
|
|
|
|
|
if (_closed && cl != _closed)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (int i = 0; i < _filters.size(); i++)
|
|
|
|
if (!_filters.at(i).match(tags))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-04-14 22:03:06 +02:00
|
|
|
bool Style::Rule::match(int zoom, bool closed,
|
|
|
|
const QVector<MapData::Tag> &tags) const
|
2021-04-10 15:27:40 +02:00
|
|
|
{
|
2021-04-14 22:03:06 +02:00
|
|
|
Closed cl = closed ? YesClosed : NoClosed;
|
|
|
|
|
|
|
|
if (_type && WayType != _type)
|
2021-04-10 15:27:40 +02:00
|
|
|
return false;
|
|
|
|
if (!_zooms.contains(zoom))
|
|
|
|
return false;
|
2021-04-14 22:03:06 +02:00
|
|
|
if (_closed && cl != _closed)
|
|
|
|
return false;
|
2021-04-10 15:27:40 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < _filters.size(); i++)
|
|
|
|
if (!_filters.at(i).match(tags))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-04-18 18:10:23 +02:00
|
|
|
void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
|
|
|
const Rule &rule)
|
2021-04-10 15:27:40 +02:00
|
|
|
{
|
|
|
|
PathRender ri(rule, _paths.size());
|
|
|
|
const QXmlStreamAttributes &attr = reader.attributes();
|
|
|
|
QString file;
|
|
|
|
int height = 0, width = 0;
|
2021-07-13 19:43:29 +02:00
|
|
|
bool ok;
|
2021-04-10 15:27:40 +02:00
|
|
|
|
2021-04-17 00:43:00 +02:00
|
|
|
ri._area = true;
|
2021-04-10 15:27:40 +02:00
|
|
|
if (attr.hasAttribute("fill"))
|
|
|
|
ri._fillColor = QColor(attr.value("fill").toString());
|
|
|
|
if (attr.hasAttribute("stroke"))
|
|
|
|
ri._strokeColor = QColor(attr.value("stroke").toString());
|
2021-07-13 19:43:29 +02:00
|
|
|
if (attr.hasAttribute("stroke-width")) {
|
|
|
|
ri._strokeWidth = attr.value("stroke-width").toFloat(&ok);
|
|
|
|
if (!ok || ri._strokeWidth < 0) {
|
|
|
|
reader.raiseError("invalid stroke-width value");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-04-10 15:27:40 +02:00
|
|
|
if (attr.hasAttribute("src"))
|
|
|
|
file = resourcePath(attr.value("src").toString(), dir);
|
2021-07-13 19:43:29 +02:00
|
|
|
if (attr.hasAttribute("symbol-height")) {
|
|
|
|
height = attr.value("symbol-height").toInt(&ok);
|
|
|
|
if (!ok || height < 0) {
|
|
|
|
reader.raiseError("invalid symbol-height value");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attr.hasAttribute("symbol-width")) {
|
|
|
|
width = attr.value("symbol-width").toInt(&ok);
|
|
|
|
if (!ok || width < 0) {
|
|
|
|
reader.raiseError("invalid symbol-width value");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-04-10 15:27:40 +02:00
|
|
|
|
|
|
|
if (!file.isNull())
|
2021-04-18 18:10:23 +02:00
|
|
|
ri._fillImage = image(file, width, height, ratio);
|
2021-04-10 15:27:40 +02:00
|
|
|
|
|
|
|
_paths.append(ri);
|
|
|
|
|
|
|
|
reader.skipCurrentElement();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Style::line(QXmlStreamReader &reader, const Rule &rule)
|
|
|
|
{
|
|
|
|
PathRender ri(rule, _paths.size());
|
|
|
|
const QXmlStreamAttributes &attr = reader.attributes();
|
2021-07-13 19:43:29 +02:00
|
|
|
bool ok;
|
2021-04-10 15:27:40 +02:00
|
|
|
|
|
|
|
if (attr.hasAttribute("stroke"))
|
|
|
|
ri._strokeColor = QColor(attr.value("stroke").toString());
|
2021-07-13 19:43:29 +02:00
|
|
|
if (attr.hasAttribute("stroke-width")) {
|
|
|
|
ri._strokeWidth = attr.value("stroke-width").toFloat(&ok);
|
|
|
|
if (!ok || ri._strokeWidth < 0) {
|
|
|
|
reader.raiseError("invalid stroke-width value");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-04-10 15:27:40 +02:00
|
|
|
if (attr.hasAttribute("stroke-dasharray")) {
|
|
|
|
QStringList l(attr.value("stroke-dasharray").toString().split(','));
|
|
|
|
ri._strokeDasharray.resize(l.size());
|
|
|
|
for (int i = 0; i < l.size(); i++)
|
|
|
|
ri._strokeDasharray[i] = l.at(i).toDouble();
|
|
|
|
}
|
|
|
|
if (attr.hasAttribute("stroke-linecap")) {
|
|
|
|
QString cap(attr.value("stroke-linecap").toString());
|
|
|
|
if (cap == "butt")
|
|
|
|
ri._strokeCap = Qt::FlatCap;
|
|
|
|
else if (cap == "round")
|
|
|
|
ri._strokeCap = Qt::RoundCap;
|
|
|
|
else if (cap == "square")
|
|
|
|
ri._strokeCap = Qt::SquareCap;
|
|
|
|
}
|
|
|
|
if (attr.hasAttribute("stroke-linejoin")) {
|
|
|
|
QString join(attr.value("stroke-linejoin").toString());
|
|
|
|
if (join == "miter")
|
|
|
|
ri._strokeJoin = Qt::MiterJoin;
|
|
|
|
else if (join == "round")
|
|
|
|
ri._strokeJoin = Qt::RoundJoin;
|
|
|
|
else if (join == "bevel")
|
|
|
|
ri._strokeJoin = Qt::BevelJoin;
|
|
|
|
}
|
|
|
|
|
|
|
|
_paths.append(ri);
|
|
|
|
|
|
|
|
reader.skipCurrentElement();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Style::text(QXmlStreamReader &reader, const Rule &rule,
|
2021-04-14 22:03:06 +02:00
|
|
|
QList<QList<TextRender>*> &lists)
|
2021-04-10 15:27:40 +02:00
|
|
|
{
|
|
|
|
TextRender ri(rule);
|
|
|
|
const QXmlStreamAttributes &attr = reader.attributes();
|
|
|
|
int fontSize = 9;
|
|
|
|
bool bold = false, italic = false;
|
2021-05-27 22:06:14 +02:00
|
|
|
QString fontFamily("Helvetica");
|
2021-07-13 17:31:37 +02:00
|
|
|
bool ok;
|
2021-04-10 15:27:40 +02:00
|
|
|
|
2021-04-15 23:11:47 +02:00
|
|
|
if (attr.hasAttribute("k"))
|
|
|
|
ri._key = attr.value("k").toLatin1();
|
2021-04-10 15:27:40 +02:00
|
|
|
if (attr.hasAttribute("fill"))
|
|
|
|
ri._fillColor = QColor(attr.value("fill").toString());
|
|
|
|
if (attr.hasAttribute("stroke"))
|
|
|
|
ri._strokeColor = QColor(attr.value("stroke").toString());
|
2021-07-13 17:31:37 +02:00
|
|
|
if (attr.hasAttribute("stroke-width")) {
|
|
|
|
ri._strokeWidth = attr.value("stroke-width").toFloat(&ok);
|
|
|
|
if (!ok || ri._strokeWidth < 0) {
|
2021-07-13 19:43:29 +02:00
|
|
|
reader.raiseError("invalid stroke-width value");
|
2021-07-13 17:31:37 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attr.hasAttribute("font-size")) {
|
|
|
|
fontSize = attr.value("font-size").toFloat(&ok);
|
|
|
|
if (!ok || fontSize < 0) {
|
2021-07-13 19:43:29 +02:00
|
|
|
reader.raiseError("invalid font-size value");
|
2021-07-13 17:31:37 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-04-10 15:27:40 +02:00
|
|
|
if (attr.hasAttribute("font-style")) {
|
|
|
|
QString style(attr.value("font-style").toString());
|
|
|
|
if (style == "bold")
|
|
|
|
bold = true;
|
|
|
|
else if (style == "italic")
|
|
|
|
italic = true;
|
|
|
|
else if (style == "bold_italic") {
|
|
|
|
bold = true;
|
|
|
|
italic = true;
|
|
|
|
}
|
|
|
|
}
|
2021-05-27 22:06:14 +02:00
|
|
|
if (attr.hasAttribute("font-family")) {
|
|
|
|
QString family(attr.value("font-family").toString());
|
|
|
|
if (family == "monospace")
|
|
|
|
fontFamily = "Courier New";
|
|
|
|
else if (family == "serif")
|
|
|
|
fontFamily = "Times New Roman";
|
|
|
|
}
|
|
|
|
|
|
|
|
ri._font.setFamily(fontFamily);
|
2021-04-10 15:27:40 +02:00
|
|
|
ri._font.setPixelSize(fontSize);
|
|
|
|
ri._font.setBold(bold);
|
|
|
|
ri._font.setItalic(italic);
|
|
|
|
|
2021-07-13 17:31:37 +02:00
|
|
|
if (fontSize)
|
|
|
|
for (int i = 0; i < lists.size(); i++)
|
|
|
|
lists[i]->append(ri);
|
2021-04-10 15:27:40 +02:00
|
|
|
|
|
|
|
reader.skipCurrentElement();
|
|
|
|
}
|
|
|
|
|
2021-04-18 18:10:23 +02:00
|
|
|
void Style::symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
2021-04-10 15:27:40 +02:00
|
|
|
const Rule &rule)
|
|
|
|
{
|
|
|
|
Symbol ri(rule);
|
|
|
|
const QXmlStreamAttributes &attr = reader.attributes();
|
|
|
|
QString file;
|
|
|
|
int height = 0, width = 0;
|
2021-07-13 19:43:29 +02:00
|
|
|
bool ok;
|
2021-04-10 15:27:40 +02:00
|
|
|
|
|
|
|
if (attr.hasAttribute("src"))
|
|
|
|
file = resourcePath(attr.value("src").toString(), dir);
|
2021-07-13 19:43:29 +02:00
|
|
|
if (attr.hasAttribute("symbol-height")) {
|
|
|
|
height = attr.value("symbol-height").toInt(&ok);
|
|
|
|
if (!ok || height < 0) {
|
|
|
|
reader.raiseError("invalid symbol-height value");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attr.hasAttribute("symbol-width")) {
|
|
|
|
width = attr.value("symbol-width").toInt(&ok);
|
|
|
|
if (!ok || width < 0) {
|
|
|
|
reader.raiseError("invalid symbol-width value");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-04-10 15:27:40 +02:00
|
|
|
|
|
|
|
if (!file.isNull())
|
2021-04-18 18:10:23 +02:00
|
|
|
ri._img = image(file, width, height, ratio);
|
2021-04-10 15:27:40 +02:00
|
|
|
|
|
|
|
_symbols.append(ri);
|
|
|
|
|
|
|
|
reader.skipCurrentElement();
|
|
|
|
}
|
|
|
|
|
2021-04-18 18:10:23 +02:00
|
|
|
void Style::rule(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
2021-04-10 15:27:40 +02:00
|
|
|
const QSet<QString> &cats, const Rule &parent)
|
|
|
|
{
|
|
|
|
Rule r(parent);
|
|
|
|
const QXmlStreamAttributes &attr = reader.attributes();
|
2021-07-13 19:43:29 +02:00
|
|
|
bool ok;
|
2021-04-10 15:27:40 +02:00
|
|
|
|
|
|
|
if (attr.hasAttribute("cat")
|
|
|
|
&& !cats.contains(attr.value("cat").toString())) {
|
|
|
|
reader.skipCurrentElement();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-10 15:49:48 +02:00
|
|
|
if (attr.value("e").toString() == "way")
|
2021-04-10 15:27:40 +02:00
|
|
|
r.setType(Rule::WayType);
|
2021-04-10 15:49:48 +02:00
|
|
|
else if (attr.value("e").toString() == "node")
|
2021-04-10 15:27:40 +02:00
|
|
|
r.setType(Rule::NodeType);
|
|
|
|
|
2021-07-13 19:43:29 +02:00
|
|
|
if (attr.hasAttribute("zoom-min")) {
|
|
|
|
r.setMinZoom(attr.value("zoom-min").toInt(&ok));
|
|
|
|
if (!ok || r._zooms.min() < 0) {
|
|
|
|
reader.raiseError("invalid zoom-min value");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attr.hasAttribute("zoom-max")) {
|
|
|
|
r.setMaxZoom(attr.value("zoom-max").toInt(&ok));
|
|
|
|
if (!ok || r._zooms.max() < 0) {
|
|
|
|
reader.raiseError("invalid zoom-max value");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-04-10 15:27:40 +02:00
|
|
|
|
|
|
|
if (attr.hasAttribute("closed")) {
|
|
|
|
if (attr.value("closed").toString() == "yes")
|
|
|
|
r.setClosed(Rule::YesClosed);
|
|
|
|
else if (attr.value("closed").toString() == "no")
|
|
|
|
r.setClosed(Rule::NoClosed);
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<QByteArray> keys(attr.value("k").toLatin1().split('|'));
|
|
|
|
QList<QByteArray> vals(attr.value("v").toLatin1().split('|'));
|
2021-04-10 15:49:48 +02:00
|
|
|
r.addFilter(Rule::Filter(keys, vals));
|
2021-04-10 15:27:40 +02:00
|
|
|
|
|
|
|
while (reader.readNextStartElement()) {
|
|
|
|
if (reader.name() == QLatin1String("rule"))
|
2021-04-18 18:10:23 +02:00
|
|
|
rule(reader, dir, ratio, cats, r);
|
2021-04-10 15:27:40 +02:00
|
|
|
else if (reader.name() == QLatin1String("area"))
|
2021-04-18 18:10:23 +02:00
|
|
|
area(reader, dir, ratio, r);
|
2021-04-10 15:27:40 +02:00
|
|
|
else if (reader.name() == QLatin1String("line"))
|
|
|
|
line(reader, r);
|
2021-04-14 22:03:06 +02:00
|
|
|
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);
|
|
|
|
}
|
2021-04-10 15:27:40 +02:00
|
|
|
else if (reader.name() == QLatin1String("symbol"))
|
2021-04-18 18:10:23 +02:00
|
|
|
symbol(reader, dir, ratio, r);
|
2021-04-10 15:27:40 +02:00
|
|
|
else
|
|
|
|
reader.skipCurrentElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Style::cat(QXmlStreamReader &reader, QSet<QString> &cats)
|
|
|
|
{
|
|
|
|
const QXmlStreamAttributes &attr = reader.attributes();
|
|
|
|
|
|
|
|
cats.insert(attr.value("id").toString());
|
|
|
|
|
|
|
|
reader.skipCurrentElement();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Style::layer(QXmlStreamReader &reader, QSet<QString> &cats)
|
|
|
|
{
|
|
|
|
const QXmlStreamAttributes &attr = reader.attributes();
|
|
|
|
bool enabled = (attr.value("enabled").toString() == "true");
|
|
|
|
|
|
|
|
while (reader.readNextStartElement()) {
|
|
|
|
if (enabled && reader.name() == QLatin1String("cat"))
|
|
|
|
cat(reader, cats);
|
|
|
|
else
|
|
|
|
reader.skipCurrentElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Style::stylemenu(QXmlStreamReader &reader, QSet<QString> &cats)
|
|
|
|
{
|
|
|
|
while (reader.readNextStartElement()) {
|
|
|
|
if (reader.name() == QLatin1String("layer"))
|
|
|
|
layer(reader, cats);
|
|
|
|
else
|
|
|
|
reader.skipCurrentElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-18 18:10:23 +02:00
|
|
|
void Style::rendertheme(QXmlStreamReader &reader, const QString &dir,
|
|
|
|
qreal ratio)
|
2021-04-10 15:27:40 +02:00
|
|
|
{
|
|
|
|
Rule r;
|
|
|
|
QSet<QString> cats;
|
|
|
|
|
|
|
|
while (reader.readNextStartElement()) {
|
|
|
|
if (reader.name() == QLatin1String("rule"))
|
2021-04-18 18:10:23 +02:00
|
|
|
rule(reader, dir, ratio, cats, r);
|
2021-04-10 15:27:40 +02:00
|
|
|
else if (reader.name() == QLatin1String("stylemenu"))
|
|
|
|
stylemenu(reader, cats);
|
|
|
|
else
|
|
|
|
reader.skipCurrentElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-18 18:10:23 +02:00
|
|
|
bool Style::loadXml(const QString &path, qreal ratio)
|
2021-04-10 15:27:40 +02:00
|
|
|
{
|
|
|
|
QFile file(path);
|
|
|
|
if (!file.open(QFile::ReadOnly))
|
|
|
|
return false;
|
|
|
|
QXmlStreamReader reader(&file);
|
|
|
|
QFileInfo fi(path);
|
|
|
|
|
|
|
|
if (reader.readNextStartElement()) {
|
|
|
|
if (reader.name() == QLatin1String("rendertheme"))
|
2021-04-18 18:10:23 +02:00
|
|
|
rendertheme(reader, fi.absolutePath(), ratio);
|
2021-04-10 15:27:40 +02:00
|
|
|
else
|
|
|
|
reader.raiseError("Not a Mapsforge style file");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reader.error())
|
|
|
|
qWarning("%s:%lld %s", qPrintable(path), reader.lineNumber(),
|
|
|
|
qPrintable(reader.errorString()));
|
|
|
|
|
|
|
|
return !reader.error();
|
|
|
|
}
|
|
|
|
|
2021-04-18 18:10:23 +02:00
|
|
|
Style::Style(const QString &path, qreal ratio)
|
2021-04-10 15:27:40 +02:00
|
|
|
{
|
2021-04-18 18:10:23 +02:00
|
|
|
if (!QFileInfo::exists(path) || !loadXml(path, ratio))
|
|
|
|
loadXml(":/mapsforge/default.xml", ratio);
|
2021-04-10 15:27:40 +02:00
|
|
|
}
|
|
|
|
|
2021-04-15 23:11:47 +02:00
|
|
|
QVector<const Style::PathRender *> Style::paths(int zoom, bool closed,
|
|
|
|
const QVector<MapData::Tag> &tags) const
|
2021-04-10 15:27:40 +02:00
|
|
|
{
|
2021-04-17 13:23:53 +02:00
|
|
|
QVector<const PathRender*> ri;
|
2021-04-15 23:11:47 +02:00
|
|
|
|
2021-04-10 15:27:40 +02:00
|
|
|
for (int i = 0; i < _paths.size(); i++)
|
|
|
|
if (_paths.at(i).rule().match(zoom, closed, tags))
|
2021-04-15 23:11:47 +02:00
|
|
|
ri.append(&_paths.at(i));
|
|
|
|
|
|
|
|
return ri;
|
2021-04-10 15:27:40 +02:00
|
|
|
}
|
|
|
|
|
2021-04-14 22:03:06 +02:00
|
|
|
QList<const Style::TextRender*> Style::pathLabels(int zoom) const
|
|
|
|
{
|
2021-04-17 13:23:53 +02:00
|
|
|
QList<const TextRender*> list;
|
2021-04-14 22:03:06 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < _pathLabels.size(); i++)
|
2021-04-17 13:23:53 +02:00
|
|
|
if (_pathLabels.at(i).rule()._zooms.contains(zoom))
|
2021-04-14 22:03:06 +02:00
|
|
|
list.append(&_pathLabels.at(i));
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<const Style::TextRender*> Style::pointLabels(int zoom) const
|
|
|
|
{
|
2021-04-17 13:23:53 +02:00
|
|
|
QList<const TextRender*> list;
|
2021-04-14 22:03:06 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < _pointLabels.size(); i++)
|
2021-04-17 13:23:53 +02:00
|
|
|
if (_pointLabels.at(i).rule()._zooms.contains(zoom))
|
2021-04-14 22:03:06 +02:00
|
|
|
list.append(&_pointLabels.at(i));
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<const Style::TextRender*> Style::areaLabels(int zoom) const
|
|
|
|
{
|
2021-04-17 13:23:53 +02:00
|
|
|
QList<const TextRender*> list;
|
2021-04-14 22:03:06 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < _areaLabels.size(); i++)
|
2021-04-17 13:23:53 +02:00
|
|
|
if (_areaLabels.at(i).rule()._zooms.contains(zoom))
|
2021-04-14 22:03:06 +02:00
|
|
|
list.append(&_areaLabels.at(i));
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2021-04-17 13:23:53 +02:00
|
|
|
QList<const Style::Symbol*> Style::pointSymbols(int zoom) const
|
2021-04-14 22:03:06 +02:00
|
|
|
{
|
2021-04-17 13:23:53 +02:00
|
|
|
QList<const Symbol*> list;
|
|
|
|
|
|
|
|
for (int i = 0; i < _symbols.size(); i++) {
|
|
|
|
const Symbol &symbol = _symbols.at(i);
|
|
|
|
const Rule & rule = symbol.rule();
|
|
|
|
if (rule._zooms.contains(zoom) && (rule._type == Rule::AnyType
|
|
|
|
|| rule._type == Rule::NodeType))
|
|
|
|
list.append(&symbol);
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
2021-04-14 22:03:06 +02:00
|
|
|
|
2021-04-17 13:23:53 +02:00
|
|
|
QList<const Style::Symbol*> Style::areaSymbols(int zoom) const
|
|
|
|
{
|
|
|
|
QList<const Symbol*> list;
|
|
|
|
|
|
|
|
for (int i = 0; i < _symbols.size(); i++) {
|
|
|
|
const Symbol &symbol = _symbols.at(i);
|
|
|
|
const Rule & rule = symbol.rule();
|
|
|
|
if (rule._zooms.contains(zoom) && (rule._type == Rule::AnyType
|
|
|
|
|| rule._type == Rule::WayType))
|
|
|
|
list.append(&symbol);
|
|
|
|
}
|
2021-04-14 22:03:06 +02:00
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2021-04-10 15:27:40 +02:00
|
|
|
QPen Style::PathRender::pen(int zoom) const
|
|
|
|
{
|
|
|
|
qreal width = (zoom >= 12)
|
|
|
|
? pow(1.5, zoom - 12) * _strokeWidth : _strokeWidth;
|
|
|
|
|
|
|
|
if (_strokeColor.isValid()) {
|
|
|
|
QPen p(QBrush(_strokeColor), width, Qt::SolidLine, _strokeCap,
|
|
|
|
_strokeJoin);
|
|
|
|
if (!_strokeDasharray.isEmpty()) {
|
|
|
|
QVector<qreal>pattern(_strokeDasharray);
|
|
|
|
for (int i = 0; i < _strokeDasharray.size(); i++)
|
|
|
|
pattern[i] /= width;
|
|
|
|
p.setDashPattern(pattern);
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
} else
|
|
|
|
return Qt::NoPen;
|
|
|
|
}
|
|
|
|
|
|
|
|
QBrush Style::PathRender::brush() const
|
|
|
|
{
|
|
|
|
if (!_fillImage.isNull())
|
|
|
|
return QBrush(_fillImage);
|
|
|
|
else if (_fillColor.isValid())
|
|
|
|
return QBrush(_fillColor);
|
|
|
|
else
|
|
|
|
return Qt::NoBrush;
|
|
|
|
}
|