Refactored sprites handling code

This commit is contained in:
Martin Tůma 2018-12-05 00:03:41 +01:00
parent 08509f0930
commit 7442b76939
4 changed files with 55 additions and 76 deletions

View File

@ -15,17 +15,11 @@ static const QImage *atlas(const QString &fileName)
return img; return img;
} }
static const QImage *atlas2x(const QString &fileName)
{
static QImage *img = new QImage(fileName);
return img;
}
Sprites::Sprite::Sprite(const QJsonObject &json) Sprites::Sprite::Sprite(const QJsonObject &json)
{ {
int x, y, width, height; int x, y, width, height;
if (json.contains("x") && json["x"].isDouble()) if (json.contains("x") && json["x"].isDouble())
x = json["x"].toInt(); x = json["x"].toInt();
else else
@ -44,22 +38,18 @@ Sprites::Sprite::Sprite(const QJsonObject &json)
return; return;
_rect = QRect(x, y, width, height); _rect = QRect(x, y, width, height);
if (json.contains("pixelRatio") && json["pixelRatio"].isDouble())
_pixelRatio = json["pixelRatio"].toDouble();
else
_pixelRatio = 1.0;
} }
bool Sprites::load(const QString &jsonFile, const QString &imageFile) bool Sprites::load(const QString &jsonFile, const QString &imageFile)
{ {
_imageFile = imageFile; _imageFile = imageFile;
return load(jsonFile, _sprites);
}
bool Sprites::load2x(const QString &jsonFile, const QString &imageFile)
{
_image2xFile = imageFile;
return load(jsonFile, _sprites2x);
}
bool Sprites::load(const QString &jsonFile, QMap<QString, Sprite> &map)
{
QFile file(jsonFile); QFile file(jsonFile);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qCritical() << jsonFile << ": error opening file"; qCritical() << jsonFile << ": error opening file";
@ -81,7 +71,7 @@ bool Sprites::load(const QString &jsonFile, QMap<QString, Sprite> &map)
if (val.isObject()) { if (val.isObject()) {
Sprite s(val.toObject()); Sprite s(val.toObject());
if (s.rect().isValid()) if (s.rect().isValid())
map.insert(it.key(), s); _sprites.insert(it.key(), s);
else else
qWarning() << it.key() << ": invalid sprite definition"; qWarning() << it.key() << ": invalid sprite definition";
} else } else
@ -91,36 +81,21 @@ bool Sprites::load(const QString &jsonFile, QMap<QString, Sprite> &map)
return true; return true;
} }
QImage Sprites::icon(const QString &name, bool hidpi) const QImage Sprites::icon(const QString &name) const
{ {
qreal ratio; const QImage *img = atlas(_imageFile);
const QImage *img;
const QMap<QString, Sprite> *map;
if (hidpi && !_image2xFile.isNull()) {
img = atlas2x(_image2xFile);
map = &_sprites2x;
ratio = 2;
} else if (!_imageFile.isNull()) {
img = atlas(_imageFile);
map = &_sprites;
ratio = 1;
} else
return QImage();
if (img->isNull()) if (img->isNull())
return QImage(); return QImage();
QMap<QString, Sprite>::const_iterator it = _sprites.find(name);
QMap<QString, Sprite>::const_iterator it = map->find(name); if (it == _sprites.constEnd())
if (it == map->constEnd())
return QImage(); return QImage();
if (!img->rect().contains(it->rect())) if (!img->rect().contains(it->rect()))
return QImage(); return QImage();
QImage ret(img->copy(it->rect())); QImage ret(img->copy(it->rect()));
ret.setDevicePixelRatio(ratio); ret.setDevicePixelRatio(it->pixelRatio());
return ret; return ret;
} }

View File

@ -9,24 +9,25 @@ class Sprites
{ {
public: public:
bool load(const QString &jsonFile, const QString &imageFile); bool load(const QString &jsonFile, const QString &imageFile);
bool load2x(const QString &jsonFile, const QString &imageFile);
QImage icon(const QString &name, bool hidpi) const; bool isNull() const {return _imageFile.isNull();}
QImage icon(const QString &name) const;
private: private:
class Sprite { class Sprite {
public: public:
Sprite(const QJsonObject &json); Sprite(const QJsonObject &json);
const QRect &rect() const {return _rect;} const QRect &rect() const {return _rect;}
qreal pixelRatio() const {return _pixelRatio;}
private: private:
QRect _rect; QRect _rect;
qreal _pixelRatio;
}; };
bool load(const QString &jsonFile, QMap<QString, Sprite> &map); QMap<QString, Sprite> _sprites;
QString _imageFile;
QMap<QString, Sprite> _sprites, _sprites2x;
QString _imageFile, _image2xFile;
}; };
#endif // SPRITES_H #endif // SPRITES_H

View File

@ -223,8 +223,8 @@ QPen Style::Layer::Paint::pen(Type type, int zoom) const
return pen; return pen;
} }
QBrush Style::Layer::Paint::brush(Type type, int zoom, const Sprites &sprites, QBrush Style::Layer::Paint::brush(Type type, int zoom, const Sprites &sprites)
bool hidpi) const const
{ {
QColor color; QColor color;
QBrush brush(Qt::NoBrush); QBrush brush(Qt::NoBrush);
@ -237,7 +237,7 @@ QBrush Style::Layer::Paint::brush(Type type, int zoom, const Sprites &sprites,
brush = QBrush(color); brush = QBrush(color);
pattern = _fillPattern.value(zoom); pattern = _fillPattern.value(zoom);
if (!pattern.isNull()) if (!pattern.isNull())
brush.setTextureImage(sprites.icon(pattern, hidpi)); brush.setTextureImage(sprites.icon(pattern));
break; break;
case Background: case Background:
color = _backgroundColor.value(zoom); color = _backgroundColor.value(zoom);
@ -245,7 +245,7 @@ QBrush Style::Layer::Paint::brush(Type type, int zoom, const Sprites &sprites,
brush = QBrush(color); brush = QBrush(color);
pattern = _fillPattern.value(zoom); pattern = _fillPattern.value(zoom);
if (!pattern.isNull()) if (!pattern.isNull())
brush.setTextureImage(sprites.icon(pattern, hidpi)); brush.setTextureImage(sprites.icon(pattern));
break; break;
default: default:
break; break;
@ -449,8 +449,7 @@ void Style::Layer::setPathPainter(Tile &tile, const Sprites &sprites) const
pen.setJoinStyle(_layout.lineJoin(zoom)); pen.setJoinStyle(_layout.lineJoin(zoom));
pen.setCapStyle(_layout.lineCap(zoom)); pen.setCapStyle(_layout.lineCap(zoom));
bool hidpi = qMax(tile.scale().x(), tile.scale().y()) > 1.0 ? true : false; QBrush brush(_paint.brush(_type, zoom, sprites));
QBrush brush(_paint.brush(_type, zoom, sprites, hidpi));
p.setRenderHint(QPainter::Antialiasing, _paint.antialias(_type, zoom)); p.setRenderHint(QPainter::Antialiasing, _paint.antialias(_type, zoom));
p.setPen(pen); p.setPen(pen);
@ -480,8 +479,25 @@ void Style::Layer::addSymbol(Tile &tile, const QPainterPath &path,
return; return;
QString icon = _layout.icon(tile.zoom(), tags); QString icon = _layout.icon(tile.zoom(), tags);
bool hidpi = qMax(tile.scale().x(), tile.scale().y()) > 1.0 ? true : false; tile.text().addLabel(text, sprites.icon(icon), path);
tile.text().addLabel(text, sprites.icon(icon, hidpi), path); }
static bool loadSprites(const QDir &styleDir, const QString &json,
const QString &img, Sprites &sprites)
{
QString spritesJSON(styleDir.filePath(json));
if (QFileInfo::exists(spritesJSON)) {
QString spritesImg(styleDir.filePath(img));
if (QFileInfo::exists(spritesImg))
return sprites.load(spritesJSON, spritesImg);
else {
qCritical() << spritesImg << ": no such file";
return false;
}
}
return true;
} }
bool Style::load(const QString &fileName) bool Style::load(const QString &fileName)
@ -512,26 +528,9 @@ bool Style::load(const QString &fileName)
for (int i = 0; i < _layers.size(); i++) for (int i = 0; i < _layers.size(); i++)
_sourceLayers.append(_layers.at(i).sourceLayer()); _sourceLayers.append(_layers.at(i).sourceLayer());
QDir styleDir = QFileInfo(fileName).absoluteDir(); QDir styleDir = QFileInfo(fileName).absoluteDir();
loadSprites(styleDir, "sprite.json", "sprite.png", _sprites);
QString spritesJSON(styleDir.filePath("sprite.json")); loadSprites(styleDir, "sprite@2x.json", "sprite@2x.png", _sprites2x);
if (QFileInfo::exists(spritesJSON)) {
QString spritesImg(styleDir.filePath("sprite.png"));
if (QFileInfo::exists(spritesImg))
_sprites.load(spritesJSON, spritesImg);
else
qCritical() << spritesImg << ": no such file";
}
QString sprites2xJSON(styleDir.filePath("sprite@2x.json"));
if (QFileInfo::exists(sprites2xJSON)) {
QString sprites2xImg(styleDir.filePath("sprite@2x.png"));
if (QFileInfo::exists(sprites2xImg))
_sprites.load2x(sprites2xJSON, sprites2xImg);
else
qCritical() << sprites2xImg << ": no such file";
}
return true; return true;
} }
@ -539,22 +538,26 @@ bool Style::load(const QString &fileName)
void Style::setupLayer(Tile &tile, int layer) const void Style::setupLayer(Tile &tile, int layer) const
{ {
const Layer &sl = _layers.at(layer); const Layer &sl = _layers.at(layer);
const Sprites &sprites = (tile.scale().x() > 1.0 || tile.scale().y() > 1.0)
&& !_sprites2x.isNull() ? _sprites2x : _sprites;
if (sl.isSymbol()) if (sl.isSymbol())
sl.setTextProperties(tile); sl.setTextProperties(tile);
else if (sl.isPath()) else if (sl.isPath())
sl.setPathPainter(tile, _sprites); sl.setPathPainter(tile, sprites);
} }
void Style::drawFeature(Tile &tile, int layer, const QPainterPath &path, void Style::drawFeature(Tile &tile, int layer, const QPainterPath &path,
const QVariantHash &tags) const const QVariantHash &tags) const
{ {
const Layer &sl = _layers.at(layer); const Layer &sl = _layers.at(layer);
const Sprites &sprites = (tile.scale().x() > 1.0 || tile.scale().y() > 1.0)
&& !_sprites2x.isNull() ? _sprites2x : _sprites;
if (sl.isPath()) if (sl.isPath())
tile.painter().drawPath(path); tile.painter().drawPath(path);
else if (sl.isSymbol()) else if (sl.isSymbol())
sl.addSymbol(tile, path, tags, _sprites); sl.addSymbol(tile, path, tags, sprites);
} }
void Style::drawBackground(Tile &tile) const void Style::drawBackground(Tile &tile) const

View File

@ -136,8 +136,8 @@ private:
Paint(const QJsonObject &json); Paint(const QJsonObject &json);
QPen pen(Layer::Type type, int zoom) const; QPen pen(Layer::Type type, int zoom) const;
QBrush brush(Layer::Type type, int zoom, const Sprites &sprites, QBrush brush(Layer::Type type, int zoom, const Sprites &sprites)
bool hidpi) const; const;
qreal opacity(Layer::Type type, int zoom) const; qreal opacity(Layer::Type type, int zoom) const;
bool antialias(Layer::Type type, int zoom) const; bool antialias(Layer::Type type, int zoom) const;
QString fillPattern(int zoom) const QString fillPattern(int zoom) const
@ -167,7 +167,7 @@ private:
QVector<Layer> _layers; QVector<Layer> _layers;
QStringList _sourceLayers; QStringList _sourceLayers;
Sprites _sprites; Sprites _sprites, _sprites2x;
}; };
#endif // STYLE_H #endif // STYLE_H