Made almost every paint/layout property "zoom-capable"

This commit is contained in:
Martin Tůma 2018-11-24 09:52:54 +01:00
parent 4cab88d79a
commit e9bf62dd2e
4 changed files with 154 additions and 158 deletions

View File

@ -44,24 +44,30 @@ static QColor interpolate(const QPair<qreal, QColor> &p0,
f(p0l, p1l, ratio), f(p0a, p1a, ratio)); f(p0l, p1l, ratio), f(p0a, p1a, ratio));
} }
FunctionF::FunctionF(const QJsonObject &json, qreal dflt) FunctionF::FunctionF(const QJsonValue &json, qreal dflt)
: _default(dflt), _base(1.0) : _default(dflt), _base(1.0)
{ {
if (!(json.contains("stops") && json["stops"].isArray())) if (json.isDouble())
return; _default = json.toDouble();
else if (json.isObject()) {
QJsonObject obj(json.toObject());
QJsonArray stops = json["stops"].toArray(); if (!(obj.contains("stops") && obj["stops"].isArray()))
for (int i = 0; i < stops.size(); i++) {
if (!stops.at(i).isArray())
return; return;
QJsonArray stop = stops.at(i).toArray();
if (stop.size() != 2) QJsonArray stops = obj["stops"].toArray();
return; for (int i = 0; i < stops.size(); i++) {
_stops.append(QPointF(stop.at(0).toDouble(), stop.at(1).toDouble())); if (!stops.at(i).isArray())
return;
QJsonArray stop = stops.at(i).toArray();
if (stop.size() != 2)
return;
_stops.append(QPointF(stop.at(0).toDouble(), stop.at(1).toDouble()));
}
if (obj.contains("base") && obj["base"].isDouble())
_base = obj["base"].toDouble();
} }
if (json.contains("base") && json["base"].isDouble())
_base = json["base"].toDouble();
} }
qreal FunctionF::value(qreal x) const qreal FunctionF::value(qreal x) const
@ -80,26 +86,31 @@ qreal FunctionF::value(qreal x) const
return _stops.last().y(); return _stops.last().y();
} }
FunctionC::FunctionC(const QJsonValue &json, const QColor &dflt)
FunctionC::FunctionC(const QJsonObject &json, const QColor &dflt)
: _default(dflt), _base(1.0) : _default(dflt), _base(1.0)
{ {
if (!(json.contains("stops") && json["stops"].isArray())) if (json.isString())
return; _default = Color::fromJsonString(json.toString());
else if (json.isObject()) {
QJsonObject obj(json.toObject());
QJsonArray stops = json["stops"].toArray(); if (!(obj.contains("stops") && obj["stops"].isArray()))
for (int i = 0; i < stops.size(); i++) {
if (!stops.at(i).isArray())
return; return;
QJsonArray stop = stops.at(i).toArray();
if (stop.size() != 2) QJsonArray stops = obj["stops"].toArray();
return; for (int i = 0; i < stops.size(); i++) {
_stops.append(QPair<qreal, QColor>(stop.at(0).toDouble(), if (!stops.at(i).isArray())
Color::fromJsonString(stop.at(1).toString()))); return;
QJsonArray stop = stops.at(i).toArray();
if (stop.size() != 2)
return;
_stops.append(QPair<qreal, QColor>(stop.at(0).toDouble(),
Color::fromJsonString(stop.at(1).toString())));
}
if (obj.contains("base") && obj["base"].isDouble())
_base = obj["base"].toDouble();
} }
if (json.contains("base") && json["base"].isDouble())
_base = json["base"].toDouble();
} }
QColor FunctionC::value(qreal x) const QColor FunctionC::value(qreal x) const
@ -118,20 +129,26 @@ QColor FunctionC::value(qreal x) const
return _stops.last().second; return _stops.last().second;
} }
FunctionB::FunctionB(const QJsonObject &json, bool dflt) : _default(dflt) FunctionB::FunctionB(const QJsonValue &json, bool dflt) : _default(dflt)
{ {
if (!(json.contains("stops") && json["stops"].isArray())) if (json.isBool())
return; _default = json.toBool();
else if (json.isObject()) {
QJsonObject obj(json.toObject());
QJsonArray stops = json["stops"].toArray(); if (!(obj.contains("stops") && obj["stops"].isArray()))
for (int i = 0; i < stops.size(); i++) {
if (!stops.at(i).isArray())
return; return;
QJsonArray stop = stops.at(i).toArray();
if (stop.size() != 2) QJsonArray stops = obj["stops"].toArray();
return; for (int i = 0; i < stops.size(); i++) {
_stops.append(QPair<qreal, bool>(stop.at(0).toDouble(), if (!stops.at(i).isArray())
stop.at(1).toBool())); return;
QJsonArray stop = stops.at(i).toArray();
if (stop.size() != 2)
return;
_stops.append(QPair<qreal, bool>(stop.at(0).toDouble(),
stop.at(1).toBool()));
}
} }
} }
@ -151,21 +168,27 @@ bool FunctionB::value(qreal x) const
return _stops.last().second; return _stops.last().second;
} }
FunctionS::FunctionS(const QJsonObject &json, const QString &dflt) FunctionS::FunctionS(const QJsonValue &json, const QString &dflt)
: _default(dflt) : _default(dflt)
{ {
if (!(json.contains("stops") && json["stops"].isArray())) if (json.isString())
return; _default = json.toString();
else if (json.isObject()) {
QJsonObject obj(json.toObject());
QJsonArray stops = json["stops"].toArray(); if (!(obj.contains("stops") && obj["stops"].isArray()))
for (int i = 0; i < stops.size(); i++) {
if (!stops.at(i).isArray())
return; return;
QJsonArray stop = stops.at(i).toArray();
if (stop.size() != 2) QJsonArray stops = obj["stops"].toArray();
return; for (int i = 0; i < stops.size(); i++) {
_stops.append(QPair<qreal, QString>(stop.at(0).toDouble(), if (!stops.at(i).isArray())
stop.at(1).toString())); return;
QJsonArray stop = stops.at(i).toArray();
if (stop.size() != 2)
return;
_stops.append(QPair<qreal, QString>(stop.at(0).toDouble(),
stop.at(1).toString()));
}
} }
} }

View File

@ -10,7 +10,7 @@ class QJsonObject;
class FunctionB { class FunctionB {
public: public:
FunctionB(bool deflt = true) : _default(deflt) {} FunctionB(bool deflt = true) : _default(deflt) {}
FunctionB(const QJsonObject &json, bool dflt = true); FunctionB(const QJsonValue &json, bool dflt = true);
bool value(qreal x) const; bool value(qreal x) const;
@ -22,7 +22,7 @@ private:
class FunctionS { class FunctionS {
public: public:
FunctionS(const QString &deflt = QString()) : _default(deflt) {} FunctionS(const QString &deflt = QString()) : _default(deflt) {}
FunctionS(const QJsonObject &json, const QString &dflt = QString()); FunctionS(const QJsonValue &json, const QString &dflt = QString());
const QString value(qreal x) const; const QString value(qreal x) const;
@ -34,7 +34,7 @@ private:
class FunctionF { class FunctionF {
public: public:
FunctionF(qreal deflt = 0) : _default(deflt), _base(1.0) {} FunctionF(qreal deflt = 0) : _default(deflt), _base(1.0) {}
FunctionF(const QJsonObject &json, qreal dflt = 0); FunctionF(const QJsonValue &json, qreal dflt = 0);
qreal value(qreal x) const; qreal value(qreal x) const;
@ -48,7 +48,7 @@ class FunctionC {
public: public:
FunctionC(const QColor &deflt = QColor(Qt::black)) FunctionC(const QColor &deflt = QColor(Qt::black))
: _default(deflt), _base(1.0) {} : _default(deflt), _base(1.0) {}
FunctionC(const QJsonObject &json, const QColor &dflt = QColor(Qt::black)); FunctionC(const QJsonValue &json, const QColor &dflt = QColor(Qt::black));
QColor value(qreal x) const; QColor value(qreal x) const;

View File

@ -13,50 +13,6 @@
#include "style.h" #include "style.h"
static void jsonColor(const QJsonObject &json, const char *name, FunctionC &var)
{
if (json.contains(name)) {
const QJsonValue value = json[name];
if (value.isString())
var = FunctionC(Color::fromJsonString(value.toString()));
else if (value.isObject())
var = FunctionC(value.toObject());
}
}
static void jsonFloat(const QJsonObject &json, const char *name, FunctionF &var)
{
if (json.contains(name)) {
const QJsonValue value = json[name];
if (value.isDouble())
var = FunctionF(value.toDouble());
else if (value.isObject())
var = FunctionF(value.toObject());
}
}
static void jsonBool(const QJsonObject &json, const char *name, FunctionB &var)
{
if (json.contains(name)) {
QJsonValue value = json[name];
if (value.isBool())
var = FunctionB(value.toBool());
else if (value.isObject())
var = FunctionB(value.toObject());
}
}
static void jsonString(const QJsonObject &json, const char *name, FunctionS &var)
{
if (json.contains(name)) {
QJsonValue value = json[name];
if (value.isString())
var = FunctionS(value.toString());
else if (value.isObject())
var = FunctionS(value.toObject());
}
}
Style::Layer::Filter::Filter(const QJsonArray &json) Style::Layer::Filter::Filter(const QJsonArray &json)
: _type(Unknown), _not(false) : _type(Unknown), _not(false)
{ {
@ -202,24 +158,25 @@ QString Style::Layer::Template::value(int zoom, const QVariantHash &tags) const
} }
Style::Layer::Paint::Paint(const QJsonObject &json) Style::Layer::Paint::Paint(const QJsonObject &json)
: _fillOpacity(1.0), _lineOpacity(1.0), _lineWidth(1.0)
{ {
// fill // fill
jsonFloat(json, "fill-opacity", _fillOpacity); _fillOpacity = FunctionF(json["fill-opacity"], 1.0);
jsonColor(json, "fill-color", _fillColor); _fillColor = FunctionC(json["fill-color"]);
_fillOutlineColor = _fillColor; if (json.contains("fill-outline-color"))
jsonColor(json, "fill-outline-color", _fillOutlineColor); _fillOutlineColor = FunctionC(json["fill-outline-color"]);
jsonBool(json, "fill-antialias",_fillAntialias); else
jsonString(json, "fill-pattern", _fillPattern); _fillOutlineColor = _fillColor;
_fillAntialias = FunctionB(json["fill-antialias"]);
if (json.contains("fill-pattern")) { if (json.contains("fill-pattern")) {
_fillPattern = FunctionS(json["fill-pattern"]);
_fillColor = FunctionC(QColor()); _fillColor = FunctionC(QColor());
_fillOutlineColor = FunctionC(QColor()); _fillOutlineColor = FunctionC(QColor());
} }
// line // line
jsonColor(json, "line-color", _lineColor); _lineColor = FunctionC(json["line-color"]);
jsonFloat(json, "line-width", _lineWidth); _lineWidth = FunctionF(json["line-width"], 1.0);
jsonFloat(json, "line-opacity", _lineOpacity); _lineOpacity = FunctionF(json["line-opacity"], 1.0);
if (json.contains("line-dasharray") && json["line-dasharray"].isArray()) { if (json.contains("line-dasharray") && json["line-dasharray"].isArray()) {
QJsonArray array = json["line-dasharray"].toArray(); QJsonArray array = json["line-dasharray"].toArray();
for (int i = 0; i < array.size(); i++) for (int i = 0; i < array.size(); i++)
@ -227,10 +184,10 @@ Style::Layer::Paint::Paint(const QJsonObject &json)
} }
// background // background
jsonColor(json, "background-color", _backgroundColor); _backgroundColor = FunctionC(json["background-color"]);
// text // text
jsonColor(json, "text-color", _textColor); _textColor = FunctionC(json["text-color"]);
} }
QPen Style::Layer::Paint::pen(Type type, int zoom) const QPen Style::Layer::Paint::pen(Type type, int zoom) const
@ -321,31 +278,19 @@ bool Style::Layer::Paint::antialias(Layer::Type type, int zoom) const
} }
Style::Layer::Layout::Layout(const QJsonObject &json) Style::Layer::Layout::Layout(const QJsonObject &json)
: _textSize(16), _textMaxWidth(10), _textMaxAngle(45), _lineCap(Qt::FlatCap), : _lineCap(Qt::FlatCap), _lineJoin(Qt::MiterJoin), _font("Open Sans"),
_lineJoin(Qt::MiterJoin), _font("Open Sans"), _capitalize(false), _capitalize(false), _viewportAlignment(false)
_viewportAlignment(false), _textAnchor(Text::Center)
{ {
// line // line
if (json.contains("line-cap") && json["line-cap"].isString()) { _lineCap = FunctionS(json["line-cap"], "butt");
if (json["line-cap"].toString() == "round") _lineJoin = FunctionS(json["line-join"], "miter");
_lineCap = Qt::RoundCap;
else if (json["line-cap"].toString() == "square")
_lineCap = Qt::SquareCap;
}
if (json.contains("line-join") && json["line-join"].isString()) {
if (json["line-join"].toString() == "bevel")
_lineJoin = Qt::BevelJoin;
else if (json["line-join"].toString() == "round")
_lineJoin = Qt::RoundJoin;
}
// text // text
if (json.contains("text-field") && json["text-field"].isString()) _text = Template(FunctionS(json["text-field"]));
_text = Template(json["text-field"].toString());
jsonFloat(json, "text-size", _textSize); _textSize = FunctionF(json["text-size"], 16);
jsonFloat(json, "text-max-width", _textMaxWidth); _textMaxWidth = FunctionF(json["text-max-width"], 10);
jsonFloat(json, "text-max-angle", _textMaxAngle); _textMaxAngle = FunctionF(json["text-max-angle"], 45);
if (json.contains("text-font") && json["text-font"].isArray()) if (json.contains("text-font") && json["text-font"].isArray())
_font = Font::fromJsonArray(json["text-font"].toArray()); _font = Font::fromJsonArray(json["text-font"].toArray());
if (json.contains("text-transform") && json["text-transform"].isString()) if (json.contains("text-transform") && json["text-transform"].isString())
@ -354,23 +299,11 @@ Style::Layer::Layout::Layout(const QJsonObject &json)
&& json["text-rotation-alignment"].isString()) && json["text-rotation-alignment"].isString())
if (json["text-rotation-alignment"].toString() == "viewport") if (json["text-rotation-alignment"].toString() == "viewport")
_viewportAlignment = true; _viewportAlignment = true;
if (json.contains("text-anchor") && json["text-anchor"].isString()) {
QString anchor(json["text-anchor"].toString()); _textAnchor = FunctionS(json["text-anchor"]);
if (anchor == "center")
_textAnchor = Text::Center;
else if (anchor == "left")
_textAnchor = Text::Left;
else if (anchor == "right")
_textAnchor = Text::Right;
else if (anchor == "top")
_textAnchor = Text::Top;
else if (anchor == "bottom")
_textAnchor = Text::Bottom;
}
// icon // icon
if (json.contains("icon-image") && json["icon-image"].isString()) _icon = Template(FunctionS(json["icon-image"]));
_icon = Template(json["icon-image"].toString());
} }
QFont Style::Layer::Layout::font(int zoom) const QFont Style::Layer::Layout::font(int zoom) const
@ -381,6 +314,46 @@ QFont Style::Layer::Layout::font(int zoom) const
return font; return font;
} }
Text::Anchor Style::Layer::Layout::textAnchor(int zoom) const
{
QString anchor(_textAnchor.value(zoom));
if (anchor == "left")
return Text::Left;
else if (anchor == "right")
return Text::Right;
else if (anchor == "top")
return Text::Top;
else if (anchor == "bottom")
return Text::Bottom;
else
return Text::Center;
}
Qt::PenCapStyle Style::Layer::Layout::lineCap(int zoom) const
{
QString cap(_lineCap.value(zoom));
if (cap == "round")
return Qt::RoundCap;
else if (cap == "square")
return Qt::SquareCap;
else
return Qt::FlatCap;
}
Qt::PenJoinStyle Style::Layer::Layout::lineJoin(int zoom) const
{
QString join(_lineJoin.value(zoom));
if (join == "bevel")
return Qt::BevelJoin;
else if (join == "round")
return Qt::RoundJoin;
else
return Qt::MiterJoin;
}
Style::Layer::Layer(const QJsonObject &json) Style::Layer::Layer(const QJsonObject &json)
: _type(Unknown), _minZoom(-1), _maxZoom(-1) : _type(Unknown), _minZoom(-1), _maxZoom(-1)
{ {
@ -434,8 +407,8 @@ void Style::Layer::setPathPainter(Tile &tile, const Sprites &sprites) const
QPen pen(_paint.pen(_type, tile.zoom())); QPen pen(_paint.pen(_type, tile.zoom()));
QBrush brush(_paint.brush(_type, tile.zoom(), sprites)); QBrush brush(_paint.brush(_type, tile.zoom(), sprites));
pen.setJoinStyle(_layout.lineJoin()); pen.setJoinStyle(_layout.lineJoin(tile.zoom()));
pen.setCapStyle(_layout.lineCap()); pen.setCapStyle(_layout.lineCap(tile.zoom()));
QPainter &p = tile.painter(); QPainter &p = tile.painter();
p.setRenderHint(QPainter::Antialiasing, _paint.antialias(_type, tile.zoom())); p.setRenderHint(QPainter::Antialiasing, _paint.antialias(_type, tile.zoom()));
@ -459,7 +432,7 @@ void Style::Layer::setTextProperties(Tile &tile) const
Text::Properties prop; Text::Properties prop;
prop.maxWidth = _layout.maxTextWidth(tile.zoom()); prop.maxWidth = _layout.maxTextWidth(tile.zoom());
prop.maxAngle = _layout.maxTextAngle(tile.zoom()); prop.maxAngle = _layout.maxTextAngle(tile.zoom());
prop.anchor = _layout.textAnchor(); prop.anchor = _layout.textAnchor(tile.zoom());
tile.text().setProperties(prop); tile.text().setProperties(prop);
} }

View File

@ -96,12 +96,10 @@ private:
class Layout { class Layout {
public: public:
Layout() : _textSize(16), _textMaxWidth(10), _textMaxAngle(45), Layout() : _textSize(16), _textMaxWidth(10), _textMaxAngle(45),
_lineCap(Qt::FlatCap), _lineJoin(Qt::MiterJoin), _font("Open Sans"), _capitalize(false),
_font("Open Sans"), _capitalize(false), _viewportAlignment(false), _viewportAlignment(false) {}
_textAnchor(Text::Center) {}
Layout(const QJsonObject &json); Layout(const QJsonObject &json);
bool capitalize() const {return _capitalize;}
qreal maxTextWidth(int zoom) const qreal maxTextWidth(int zoom) const
{return _textMaxWidth.value(zoom);} {return _textMaxWidth.value(zoom);}
qreal maxTextAngle(int zoom) const qreal maxTextAngle(int zoom) const
@ -111,10 +109,12 @@ private:
QString icon(int zoom, const QVariantHash &tags) const QString icon(int zoom, const QVariantHash &tags) const
{return _icon.value(zoom, tags);} {return _icon.value(zoom, tags);}
QFont font(int zoom) const; QFont font(int zoom) const;
Qt::PenCapStyle lineCap() const {return _lineCap;} Qt::PenCapStyle lineCap(int zoom) const;
Qt::PenJoinStyle lineJoin() const {return _lineJoin;} Qt::PenJoinStyle lineJoin(int zoom) const;
Text::Anchor textAnchor(int zoom) const;
bool viewportAlignment() const {return _viewportAlignment;} bool viewportAlignment() const {return _viewportAlignment;}
Text::Anchor textAnchor() const {return _textAnchor;} bool capitalize() const {return _capitalize;}
private: private:
Template _text; Template _text;
@ -122,12 +122,12 @@ private:
FunctionF _textSize; FunctionF _textSize;
FunctionF _textMaxWidth; FunctionF _textMaxWidth;
FunctionF _textMaxAngle; FunctionF _textMaxAngle;
Qt::PenCapStyle _lineCap; FunctionS _lineCap;
Qt::PenJoinStyle _lineJoin; FunctionS _lineJoin;
FunctionS _textAnchor;
QFont _font; QFont _font;
bool _capitalize; bool _capitalize;
bool _viewportAlignment; bool _viewportAlignment;
Text::Anchor _textAnchor;
}; };
class Paint { class Paint {