mirror of
https://github.com/tumic0/QtPBFImagePlugin.git
synced 2024-11-24 03:35:54 +01:00
Added support for image scaling
+ improved text path items performance
This commit is contained in:
parent
f8d5a9b6cd
commit
f41ac3bd54
22
src/pbf.cpp
22
src/pbf.cpp
@ -114,7 +114,7 @@ static inline QPoint parameters(quint32 v1, quint32 v2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void drawFeature(const Feature &feature, Style *style, int styleLayer,
|
static void drawFeature(const Feature &feature, Style *style, int styleLayer,
|
||||||
qreal factor, Tile &tile)
|
const QSizeF &factor, Tile &tile)
|
||||||
{
|
{
|
||||||
if (!style->match(styleLayer, feature.tags()))
|
if (!style->match(styleLayer, feature.tags()))
|
||||||
return;
|
return;
|
||||||
@ -133,7 +133,8 @@ static void drawFeature(const Feature &feature, Style *style, int styleLayer,
|
|||||||
feature.data()->geometry(i+2));
|
feature.data()->geometry(i+2));
|
||||||
i += 2;
|
i += 2;
|
||||||
cursor += offset;
|
cursor += offset;
|
||||||
path.moveTo(QPointF(cursor) / factor);
|
path.moveTo(QPointF(cursor.x() * factor.width(),
|
||||||
|
cursor.y() * factor.height()));
|
||||||
}
|
}
|
||||||
} else if (cmdId == LINE_TO) {
|
} else if (cmdId == LINE_TO) {
|
||||||
for (unsigned j = 0; j < cmdCount; j++) {
|
for (unsigned j = 0; j < cmdCount; j++) {
|
||||||
@ -141,7 +142,8 @@ static void drawFeature(const Feature &feature, Style *style, int styleLayer,
|
|||||||
feature.data()->geometry(i+2));
|
feature.data()->geometry(i+2));
|
||||||
i += 2;
|
i += 2;
|
||||||
cursor += offset;
|
cursor += offset;
|
||||||
path.lineTo(QPointF(cursor) / factor);
|
path.lineTo(QPointF(cursor.x() * factor.width(),
|
||||||
|
cursor.y() * factor.height()));
|
||||||
}
|
}
|
||||||
} else if (cmdId == CLOSE_PATH) {
|
} else if (cmdId == CLOSE_PATH) {
|
||||||
path.closeSubpath();
|
path.closeSubpath();
|
||||||
@ -158,21 +160,23 @@ static void drawLayer(const Layer &layer, Style *style, int styleLayer,
|
|||||||
if (layer.data()->version() > 2)
|
if (layer.data()->version() > 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qreal factor = layer.data()->extent() / (qreal)tile.size();
|
QSizeF factor(tile.size().width() / (qreal)layer.data()->extent(),
|
||||||
|
tile.size().height() / (qreal)layer.data()->extent());
|
||||||
|
|
||||||
for (int i = 0; i < layer.features().size(); i++)
|
for (int i = 0; i < layer.features().size(); i++)
|
||||||
drawFeature(layer.features().at(i), style, styleLayer, factor, tile);
|
drawFeature(layer.features().at(i), style, styleLayer, factor, tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage PBF::image(const QByteArray &data, int zoom, Style *style, int size)
|
bool PBF::render(const QByteArray &data, int zoom, Style *style, qreal scale,
|
||||||
|
QImage *image)
|
||||||
{
|
{
|
||||||
vector_tile::Tile tile;
|
vector_tile::Tile tile;
|
||||||
if (!tile.ParseFromArray(data.constData(), data.size())) {
|
if (!tile.ParseFromArray(data.constData(), data.size())) {
|
||||||
qCritical() << "Invalid tile protocol buffer data";
|
qCritical() << "Invalid tile protocol buffer data";
|
||||||
return QImage();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tile t(size);
|
Tile t(image, scale);
|
||||||
|
|
||||||
style->setZoom(zoom);
|
style->setZoom(zoom);
|
||||||
style->drawBackground(t);
|
style->drawBackground(t);
|
||||||
@ -196,5 +200,7 @@ QImage PBF::image(const QByteArray &data, int zoom, Style *style, int size)
|
|||||||
drawLayer(*it, style, i, t);
|
drawLayer(*it, style, i, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
return t.render();
|
t.render();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,8 @@ class Style;
|
|||||||
|
|
||||||
namespace PBF
|
namespace PBF
|
||||||
{
|
{
|
||||||
QImage image(const QByteArray &data, int zoom, Style *style, int size);
|
bool render(const QByteArray &data, int zoom, Style *style, qreal scale,
|
||||||
|
QImage *render);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // PBF_H
|
#endif // PBF_H
|
||||||
|
@ -47,12 +47,10 @@ bool PBFHandler::canRead(QIODevice *device)
|
|||||||
bool PBFHandler::read(QImage *image)
|
bool PBFHandler::read(QImage *image)
|
||||||
{
|
{
|
||||||
quint32 magic;
|
quint32 magic;
|
||||||
qint64 size = device()->peek((char*)&magic, sizeof(magic));
|
if (device()->peek((char*)&magic, sizeof(magic)) != sizeof(magic))
|
||||||
if (size != sizeof(magic))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
|
|
||||||
if (isGZIPPBF(magic))
|
if (isGZIPPBF(magic))
|
||||||
ba = Gzip::uncompress(device()->readAll());
|
ba = Gzip::uncompress(device()->readAll());
|
||||||
else if (isPlainPBF(magic))
|
else if (isPlainPBF(magic))
|
||||||
@ -62,14 +60,28 @@ bool PBFHandler::read(QImage *image)
|
|||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
int zoom = format().toInt(&ok);
|
int zoom = format().toInt(&ok);
|
||||||
*image = PBF::image(ba, ok ? zoom : -1, _style, TILE_SIZE);
|
|
||||||
|
|
||||||
return !image->isNull();
|
QSize size = _scaledSize.isValid()
|
||||||
|
? _scaledSize : QSize(TILE_SIZE, TILE_SIZE);
|
||||||
|
qreal scale = _scaledSize.isValid()
|
||||||
|
? qMax(_scaledSize.width() / TILE_SIZE, _scaledSize.height() / TILE_SIZE)
|
||||||
|
: 1.0;
|
||||||
|
*image = QImage(size, QImage::Format_ARGB32);
|
||||||
|
|
||||||
|
return PBF::render(ba, ok ? zoom : -1, _style, scale, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PBFHandler::supportsOption(ImageOption option) const
|
bool PBFHandler::supportsOption(ImageOption option) const
|
||||||
{
|
{
|
||||||
return (option == Size);
|
return (option == Size || option == ScaledSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PBFHandler::setOption(QImageIOHandler::ImageOption option,
|
||||||
|
const QVariant &value)
|
||||||
|
{
|
||||||
|
if (option == ScaledSize)
|
||||||
|
_scaledSize = value.toSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant PBFHandler::option(ImageOption option) const
|
QVariant PBFHandler::option(ImageOption option) const
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <QImageIOHandler>
|
#include <QImageIOHandler>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QSize>
|
||||||
|
|
||||||
class Style;
|
class Style;
|
||||||
|
|
||||||
@ -19,11 +20,13 @@ public:
|
|||||||
QByteArray name() const;
|
QByteArray name() const;
|
||||||
QVariant option(ImageOption option) const;
|
QVariant option(ImageOption option) const;
|
||||||
bool supportsOption(ImageOption option) const;
|
bool supportsOption(ImageOption option) const;
|
||||||
|
void setOption(QImageIOHandler::ImageOption option, const QVariant &value);
|
||||||
|
|
||||||
static bool canRead(QIODevice *device);
|
static bool canRead(QIODevice *device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Style *_style;
|
Style *_style;
|
||||||
|
QSize _scaledSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PBFHANDLER_H
|
#endif // PBFHANDLER_H
|
||||||
|
@ -473,7 +473,7 @@ void Style::drawFeature(int layer, const QPainterPath &path,
|
|||||||
|
|
||||||
void Style::drawBackground(Tile &tile)
|
void Style::drawBackground(Tile &tile)
|
||||||
{
|
{
|
||||||
QRectF rect(0, 0, tile.size(), tile.size());
|
QRectF rect(QPointF(0, 0), tile.size());
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
path.addRect(rect);
|
path.addRect(rect);
|
||||||
|
|
||||||
|
21
src/text.cpp
21
src/text.cpp
@ -155,7 +155,15 @@ void Text::addLabel(const QString &text, const QPointF &pos, const QFont &font,
|
|||||||
if (text.isEmpty())
|
if (text.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TextPointItem *ti = new TextPointItem(text, pos, font, maxTextWidth);
|
TextPointItem *ti;
|
||||||
|
|
||||||
|
if (_fontScale != 1.0) {
|
||||||
|
QFont scaledFont(font);
|
||||||
|
scaledFont.setPixelSize(font.pixelSize() * _fontScale);
|
||||||
|
ti = new TextPointItem(text, pos, scaledFont, maxTextWidth);
|
||||||
|
} else
|
||||||
|
ti = new TextPointItem(text, pos, font, maxTextWidth);
|
||||||
|
|
||||||
ti->setPen(pen);
|
ti->setPen(pen);
|
||||||
addItem(ti);
|
addItem(ti);
|
||||||
QList<TextItem*> ci = collidingItems(ti);
|
QList<TextItem*> ci = collidingItems(ti);
|
||||||
@ -171,19 +179,20 @@ void Text::addLabel(const QString &text, const QPainterPath &path,
|
|||||||
if (text.isEmpty())
|
if (text.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QFontMetrics fm(font);
|
QFont scaledFont(font);
|
||||||
int textWidth = fm.width(text);
|
scaledFont.setPixelSize(font.pixelSize() * _fontScale);
|
||||||
|
|
||||||
|
int textWidth = text.size() * scaledFont.pixelSize() * 0.6;
|
||||||
if (textWidth > path.length())
|
if (textWidth > path.length())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QPainterPath tp(textPath(path, textWidth, maxAngle, fm.averageCharWidth(),
|
QPainterPath tp(textPath(path, textWidth, maxAngle,
|
||||||
_sceneRect));
|
scaledFont.pixelSize() / 2, _sceneRect));
|
||||||
if (tp.isEmpty())
|
if (tp.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TextPathItem *pi = new TextPathItem(text, reverse(tp) ? tp.toReversed()
|
TextPathItem *pi = new TextPathItem(text, reverse(tp) ? tp.toReversed()
|
||||||
: tp, font);
|
: tp, scaledFont);
|
||||||
if (!_sceneRect.contains(pi->boundingRect())) {
|
if (!_sceneRect.contains(pi->boundingRect())) {
|
||||||
delete pi;
|
delete pi;
|
||||||
return;
|
return;
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
class Text
|
class Text
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Text(int size) : _sceneRect(QRectF(0, 0, size, size)) {}
|
Text(const QSize &size, qreal scale)
|
||||||
|
: _sceneRect(QRectF(QPointF(0, 0), size)), _fontScale(scale) {}
|
||||||
~Text();
|
~Text();
|
||||||
|
|
||||||
void render(QPainter *painter);
|
void render(QPainter *painter);
|
||||||
@ -21,6 +22,7 @@ private:
|
|||||||
QList<TextItem *> collidingItems(const TextItem *item) const;
|
QList<TextItem *> collidingItems(const TextItem *item) const;
|
||||||
|
|
||||||
QRectF _sceneRect;
|
QRectF _sceneRect;
|
||||||
|
qreal _fontScale;
|
||||||
QList<TextItem *> _items;
|
QList<TextItem *> _items;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,9 +6,8 @@
|
|||||||
TextPathItem::TextPathItem(const QString &text, const QPainterPath &path,
|
TextPathItem::TextPathItem(const QString &text, const QPainterPath &path,
|
||||||
const QFont &font) : _text(text), _path(path), _font(font)
|
const QFont &font) : _text(text), _path(path), _font(font)
|
||||||
{
|
{
|
||||||
QFontMetrics fm(font);
|
|
||||||
QPainterPathStroker s;
|
QPainterPathStroker s;
|
||||||
s.setWidth(fm.height());
|
s.setWidth(font.pixelSize());
|
||||||
s.setCapStyle(Qt::FlatCap);
|
s.setCapStyle(Qt::FlatCap);
|
||||||
_shape = s.createStroke(path).simplified();
|
_shape = s.createStroke(path).simplified();
|
||||||
_boundingRect = _shape.boundingRect();
|
_boundingRect = _shape.boundingRect();
|
||||||
|
13
src/tile.h
13
src/tile.h
@ -7,20 +7,17 @@
|
|||||||
|
|
||||||
class Tile {
|
class Tile {
|
||||||
public:
|
public:
|
||||||
Tile(int size) : _background(size, size, QImage::Format_ARGB32),
|
Tile(QImage *img, qreal scale)
|
||||||
_text(size), _painter(&_background) {}
|
: _size(img->size()), _text(img->size(), scale), _painter(img) {}
|
||||||
|
|
||||||
int size() const {return _background.width();}
|
QSize size() const {return _size;}
|
||||||
Text &text() {return _text;}
|
Text &text() {return _text;}
|
||||||
QPainter &painter() {return _painter;}
|
QPainter &painter() {return _painter;}
|
||||||
|
|
||||||
const QImage &render() {
|
void render() {_text.render(&_painter);}
|
||||||
_text.render(&painter());
|
|
||||||
return _background;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QImage _background;
|
QSize _size;
|
||||||
Text _text;
|
Text _text;
|
||||||
QPainter _painter;
|
QPainter _painter;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user