mirror of
https://github.com/tumic0/QtPBFImagePlugin.git
synced 2024-11-23 19:25:55 +01:00
Added support for HiDPI sprites
This commit is contained in:
parent
0d868f2f2a
commit
08509f0930
@ -3,5 +3,7 @@
|
||||
<file>style/style.json</file>
|
||||
<file>style/sprite.json</file>
|
||||
<file>style/sprite.png</file>
|
||||
<file>style/sprite@2x.json</file>
|
||||
<file>style/sprite@2x.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
15
src/pbf.cpp
15
src/pbf.cpp
@ -156,18 +156,20 @@ static void drawFeature(const Feature &feature, Style *style, int styleLayer,
|
||||
}
|
||||
|
||||
static void drawLayer(const Layer &layer, Style *style, int styleLayer,
|
||||
Tile &tile, const QPointF &scale)
|
||||
Tile &tile)
|
||||
{
|
||||
if (layer.data()->version() > 2)
|
||||
return;
|
||||
|
||||
QSizeF factor(tile.size().width() / scale.x() / (qreal)layer.data()->extent(),
|
||||
tile.size().height() / scale.y() / (qreal)layer.data()->extent());
|
||||
QSizeF factor(tile.size().width() / tile.scale().x() /
|
||||
(qreal)layer.data()->extent(), tile.size().height() / tile.scale().y()
|
||||
/ (qreal)layer.data()->extent());
|
||||
|
||||
tile.painter().save();
|
||||
style->setupLayer(tile, styleLayer);
|
||||
|
||||
for (int i = 0; i < layer.features().size(); i++)
|
||||
drawFeature(layer.features().at(i), style, styleLayer, factor, tile);
|
||||
tile.painter().restore();
|
||||
}
|
||||
|
||||
bool PBF::render(const QByteArray &data, int zoom, Style *style,
|
||||
@ -192,8 +194,6 @@ bool PBF::render(const QByteArray &data, int zoom, Style *style,
|
||||
layers.insert(name, Layer(&layer));
|
||||
}
|
||||
|
||||
t.painter().save();
|
||||
|
||||
// Process source layers in order of style layers
|
||||
for (int i = 0; i < style->sourceLayers().size(); i++) {
|
||||
QMap<QString, Layer>::const_iterator it = layers.find(
|
||||
@ -201,10 +201,9 @@ bool PBF::render(const QByteArray &data, int zoom, Style *style,
|
||||
if (it == layers.constEnd())
|
||||
continue;
|
||||
|
||||
drawLayer(*it, style, i, t, scale);
|
||||
drawLayer(*it, style, i, t);
|
||||
}
|
||||
|
||||
t.painter().restore();
|
||||
t.text().render(&t.painter());
|
||||
|
||||
return true;
|
||||
|
@ -9,12 +9,19 @@
|
||||
Loading the sprites atlas image must be deferred until all image plugins
|
||||
are loaded, otherwise reading the image will cause a deadlock!
|
||||
*/
|
||||
static QImage &atlas(const QString &fileName)
|
||||
static const QImage *atlas(const QString &fileName)
|
||||
{
|
||||
static QImage *img = new QImage(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)
|
||||
{
|
||||
int x, y, width, height;
|
||||
@ -42,7 +49,17 @@ Sprites::Sprite::Sprite(const QJsonObject &json)
|
||||
bool Sprites::load(const QString &jsonFile, const QString &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);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qCritical() << jsonFile << ": error opening file";
|
||||
@ -64,7 +81,7 @@ bool Sprites::load(const QString &jsonFile, const QString &imageFile)
|
||||
if (val.isObject()) {
|
||||
Sprite s(val.toObject());
|
||||
if (s.rect().isValid())
|
||||
_sprites.insert(it.key(), s);
|
||||
map.insert(it.key(), s);
|
||||
else
|
||||
qWarning() << it.key() << ": invalid sprite definition";
|
||||
} else
|
||||
@ -74,20 +91,36 @@ bool Sprites::load(const QString &jsonFile, const QString &imageFile)
|
||||
return true;
|
||||
}
|
||||
|
||||
QImage Sprites::icon(const QString &name) const
|
||||
QImage Sprites::icon(const QString &name, bool hidpi) const
|
||||
{
|
||||
if (_imageFile.isNull())
|
||||
return QImage();
|
||||
const QImage &img = atlas(_imageFile);
|
||||
if (img.isNull())
|
||||
qreal ratio;
|
||||
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();
|
||||
|
||||
QMap<QString, Sprite>::const_iterator it = _sprites.find(name);
|
||||
if (it == _sprites.constEnd())
|
||||
if (img->isNull())
|
||||
return QImage();
|
||||
|
||||
if (!img.rect().contains(it->rect()))
|
||||
|
||||
QMap<QString, Sprite>::const_iterator it = map->find(name);
|
||||
if (it == map->constEnd())
|
||||
return QImage();
|
||||
|
||||
return img.copy(it->rect());
|
||||
if (!img->rect().contains(it->rect()))
|
||||
return QImage();
|
||||
|
||||
QImage ret(img->copy(it->rect()));
|
||||
ret.setDevicePixelRatio(ratio);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -9,8 +9,9 @@ class Sprites
|
||||
{
|
||||
public:
|
||||
bool load(const QString &jsonFile, const QString &imageFile);
|
||||
bool load2x(const QString &jsonFile, const QString &imageFile);
|
||||
|
||||
QImage icon(const QString &name) const;
|
||||
QImage icon(const QString &name, bool hidpi) const;
|
||||
|
||||
private:
|
||||
class Sprite {
|
||||
@ -22,8 +23,10 @@ private:
|
||||
QRect _rect;
|
||||
};
|
||||
|
||||
QMap<QString, Sprite> _sprites;
|
||||
QString _imageFile;
|
||||
bool load(const QString &jsonFile, QMap<QString, Sprite> &map);
|
||||
|
||||
QMap<QString, Sprite> _sprites, _sprites2x;
|
||||
QString _imageFile, _image2xFile;
|
||||
};
|
||||
|
||||
#endif // SPRITES_H
|
||||
|
@ -223,7 +223,8 @@ QPen Style::Layer::Paint::pen(Type type, int zoom) const
|
||||
return pen;
|
||||
}
|
||||
|
||||
QBrush Style::Layer::Paint::brush(Type type, int zoom, const Sprites &sprites) const
|
||||
QBrush Style::Layer::Paint::brush(Type type, int zoom, const Sprites &sprites,
|
||||
bool hidpi) const
|
||||
{
|
||||
QColor color;
|
||||
QBrush brush(Qt::NoBrush);
|
||||
@ -236,7 +237,7 @@ QBrush Style::Layer::Paint::brush(Type type, int zoom, const Sprites &sprites) c
|
||||
brush = QBrush(color);
|
||||
pattern = _fillPattern.value(zoom);
|
||||
if (!pattern.isNull())
|
||||
brush.setTextureImage(sprites.icon(pattern));
|
||||
brush.setTextureImage(sprites.icon(pattern, hidpi));
|
||||
break;
|
||||
case Background:
|
||||
color = _backgroundColor.value(zoom);
|
||||
@ -244,7 +245,7 @@ QBrush Style::Layer::Paint::brush(Type type, int zoom, const Sprites &sprites) c
|
||||
brush = QBrush(color);
|
||||
pattern = _fillPattern.value(zoom);
|
||||
if (!pattern.isNull())
|
||||
brush.setTextureImage(sprites.icon(pattern));
|
||||
brush.setTextureImage(sprites.icon(pattern, hidpi));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -448,7 +449,8 @@ void Style::Layer::setPathPainter(Tile &tile, const Sprites &sprites) const
|
||||
pen.setJoinStyle(_layout.lineJoin(zoom));
|
||||
pen.setCapStyle(_layout.lineCap(zoom));
|
||||
|
||||
QBrush brush(_paint.brush(_type, zoom, sprites));
|
||||
bool hidpi = qMax(tile.scale().x(), tile.scale().y()) > 1.0 ? true : false;
|
||||
QBrush brush(_paint.brush(_type, zoom, sprites, hidpi));
|
||||
|
||||
p.setRenderHint(QPainter::Antialiasing, _paint.antialias(_type, zoom));
|
||||
p.setPen(pen);
|
||||
@ -478,7 +480,8 @@ void Style::Layer::addSymbol(Tile &tile, const QPainterPath &path,
|
||||
return;
|
||||
|
||||
QString icon = _layout.icon(tile.zoom(), tags);
|
||||
tile.text().addLabel(text, sprites.icon(icon), path);
|
||||
bool hidpi = qMax(tile.scale().x(), tile.scale().y()) > 1.0 ? true : false;
|
||||
tile.text().addLabel(text, sprites.icon(icon, hidpi), path);
|
||||
}
|
||||
|
||||
bool Style::load(const QString &fileName)
|
||||
@ -509,7 +512,9 @@ bool Style::load(const QString &fileName)
|
||||
for (int i = 0; i < _layers.size(); i++)
|
||||
_sourceLayers.append(_layers.at(i).sourceLayer());
|
||||
|
||||
|
||||
QDir styleDir = QFileInfo(fileName).absoluteDir();
|
||||
|
||||
QString spritesJSON(styleDir.filePath("sprite.json"));
|
||||
if (QFileInfo::exists(spritesJSON)) {
|
||||
QString spritesImg(styleDir.filePath("sprite.png"));
|
||||
@ -519,6 +524,15 @@ bool Style::load(const QString &fileName)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,8 @@ private:
|
||||
Paint(const QJsonObject &json);
|
||||
|
||||
QPen pen(Layer::Type type, int zoom) const;
|
||||
QBrush brush(Layer::Type type, int zoom, const Sprites &sprites) const;
|
||||
QBrush brush(Layer::Type type, int zoom, const Sprites &sprites,
|
||||
bool hidpi) const;
|
||||
qreal opacity(Layer::Type type, int zoom) const;
|
||||
bool antialias(Layer::Type type, int zoom) const;
|
||||
QString fillPattern(int zoom) const
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <QFontMetrics>
|
||||
#include <QFontMetrics>
|
||||
#include <QPainter>
|
||||
#include "text.h"
|
||||
#include "textpointitem.h"
|
||||
|
@ -34,8 +34,7 @@ public:
|
||||
Auto
|
||||
};
|
||||
|
||||
Text(const QSize &size)
|
||||
: _sceneRect(QRectF(QPointF(0, 0), size)) {}
|
||||
Text(const QSize &size) : _sceneRect(QRectF(QPointF(0, 0), size)) {}
|
||||
~Text();
|
||||
|
||||
void setFont(const QFont &font) {_font = font;}
|
||||
|
@ -71,7 +71,8 @@ QRectF TextPointItem::fuzzyBoundingRect(const QString &str,
|
||||
|
||||
QRectF TextPointItem::computeTextRect(BoundingRectFunction brf) const
|
||||
{
|
||||
QRectF iconRect = _icon.isNull() ? QRectF() : _icon.rect();
|
||||
QRectF iconRect = _icon.isNull() ? QRectF()
|
||||
: QRectF(QPointF(0, 0), QSizeF(_icon.size()) / _icon.devicePixelRatioF());
|
||||
QRectF textRect = brf(text(), font(), _maxWidth);
|
||||
|
||||
switch (_anchor) {
|
||||
@ -108,7 +109,8 @@ TextPointItem::TextPointItem(const QString &text, const QPointF &pos,
|
||||
_boundingRect = computeTextRect(fuzzyBoundingRect);
|
||||
|
||||
if (!_icon.isNull()) {
|
||||
QRectF iconRect(_icon.rect());
|
||||
QRectF iconRect(QPointF(0, 0), QSizeF(_icon.size())
|
||||
/ _icon.devicePixelRatioF());
|
||||
iconRect.moveCenter(pos);
|
||||
_boundingRect |= iconRect;
|
||||
}
|
||||
@ -125,8 +127,9 @@ void TextPointItem::paint(QPainter *painter) const
|
||||
|
||||
if (!_icon.isNull()) {
|
||||
textRect = computeTextRect(exactBoundingRect);
|
||||
painter->drawImage(_pos - QPointF(_icon.width() / 2,
|
||||
_icon.height() / 2), _icon);
|
||||
painter->drawImage(_pos - QPointF(_icon.width()
|
||||
/ _icon.devicePixelRatioF() / 2, _icon.height()
|
||||
/ _icon.devicePixelRatioF() / 2), _icon);
|
||||
} else
|
||||
textRect = computeTextRect(fuzzyBoundingRect);
|
||||
|
||||
|
10
src/tile.h
10
src/tile.h
@ -8,18 +8,22 @@
|
||||
class Tile {
|
||||
public:
|
||||
Tile(QImage *img, int zoom, const QPointF &scale)
|
||||
: _zoom(zoom), _size(img->size()), _text(QSize(img->size().width()
|
||||
/ scale.x(), img->size().height() / scale.y())), _painter(img)
|
||||
: _zoom(zoom), _size(img->size()), _scale(scale),
|
||||
_text(QSize(img->size().width() / scale.x(),
|
||||
img->size().height() / scale.y())), _painter(img)
|
||||
{_painter.scale(scale.x(), scale.y());}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
QSize size() const {return _size;}
|
||||
const QSize &size() const {return _size;}
|
||||
const QPointF &scale() const {return _scale;}
|
||||
|
||||
Text &text() {return _text;}
|
||||
QPainter &painter() {return _painter;}
|
||||
|
||||
private:
|
||||
int _zoom;
|
||||
QSize _size;
|
||||
QPointF _scale;
|
||||
Text _text;
|
||||
QPainter _painter;
|
||||
};
|
||||
|
1682
style/sprite@2x.json
Normal file
1682
style/sprite@2x.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
style/sprite@2x.png
Normal file
BIN
style/sprite@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 114 KiB |
Loading…
Reference in New Issue
Block a user