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,
|
||||
qreal factor, Tile &tile)
|
||||
const QSizeF &factor, Tile &tile)
|
||||
{
|
||||
if (!style->match(styleLayer, feature.tags()))
|
||||
return;
|
||||
@ -133,7 +133,8 @@ static void drawFeature(const Feature &feature, Style *style, int styleLayer,
|
||||
feature.data()->geometry(i+2));
|
||||
i += 2;
|
||||
cursor += offset;
|
||||
path.moveTo(QPointF(cursor) / factor);
|
||||
path.moveTo(QPointF(cursor.x() * factor.width(),
|
||||
cursor.y() * factor.height()));
|
||||
}
|
||||
} else if (cmdId == LINE_TO) {
|
||||
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));
|
||||
i += 2;
|
||||
cursor += offset;
|
||||
path.lineTo(QPointF(cursor) / factor);
|
||||
path.lineTo(QPointF(cursor.x() * factor.width(),
|
||||
cursor.y() * factor.height()));
|
||||
}
|
||||
} else if (cmdId == CLOSE_PATH) {
|
||||
path.closeSubpath();
|
||||
@ -158,21 +160,23 @@ static void drawLayer(const Layer &layer, Style *style, int styleLayer,
|
||||
if (layer.data()->version() > 2)
|
||||
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++)
|
||||
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;
|
||||
if (!tile.ParseFromArray(data.constData(), data.size())) {
|
||||
qCritical() << "Invalid tile protocol buffer data";
|
||||
return QImage();
|
||||
return false;
|
||||
}
|
||||
|
||||
Tile t(size);
|
||||
Tile t(image, scale);
|
||||
|
||||
style->setZoom(zoom);
|
||||
style->drawBackground(t);
|
||||
@ -196,5 +200,7 @@ QImage PBF::image(const QByteArray &data, int zoom, Style *style, int size)
|
||||
drawLayer(*it, style, i, t);
|
||||
}
|
||||
|
||||
return t.render();
|
||||
t.render();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -8,7 +8,8 @@ class Style;
|
||||
|
||||
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
|
||||
|
@ -47,12 +47,10 @@ bool PBFHandler::canRead(QIODevice *device)
|
||||
bool PBFHandler::read(QImage *image)
|
||||
{
|
||||
quint32 magic;
|
||||
qint64 size = device()->peek((char*)&magic, sizeof(magic));
|
||||
if (size != sizeof(magic))
|
||||
if (device()->peek((char*)&magic, sizeof(magic)) != sizeof(magic))
|
||||
return false;
|
||||
|
||||
QByteArray ba;
|
||||
|
||||
if (isGZIPPBF(magic))
|
||||
ba = Gzip::uncompress(device()->readAll());
|
||||
else if (isPlainPBF(magic))
|
||||
@ -62,14 +60,28 @@ bool PBFHandler::read(QImage *image)
|
||||
|
||||
bool 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
|
||||
{
|
||||
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
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QImageIOHandler>
|
||||
#include <QImage>
|
||||
#include <QVariant>
|
||||
#include <QSize>
|
||||
|
||||
class Style;
|
||||
|
||||
@ -19,11 +20,13 @@ public:
|
||||
QByteArray name() const;
|
||||
QVariant option(ImageOption option) const;
|
||||
bool supportsOption(ImageOption option) const;
|
||||
void setOption(QImageIOHandler::ImageOption option, const QVariant &value);
|
||||
|
||||
static bool canRead(QIODevice *device);
|
||||
|
||||
private:
|
||||
Style *_style;
|
||||
QSize _scaledSize;
|
||||
};
|
||||
|
||||
#endif // PBFHANDLER_H
|
||||
|
@ -473,7 +473,7 @@ void Style::drawFeature(int layer, const QPainterPath &path,
|
||||
|
||||
void Style::drawBackground(Tile &tile)
|
||||
{
|
||||
QRectF rect(0, 0, tile.size(), tile.size());
|
||||
QRectF rect(QPointF(0, 0), tile.size());
|
||||
QPainterPath path;
|
||||
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())
|
||||
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);
|
||||
addItem(ti);
|
||||
QList<TextItem*> ci = collidingItems(ti);
|
||||
@ -171,19 +179,20 @@ void Text::addLabel(const QString &text, const QPainterPath &path,
|
||||
if (text.isEmpty())
|
||||
return;
|
||||
|
||||
QFontMetrics fm(font);
|
||||
int textWidth = fm.width(text);
|
||||
QFont scaledFont(font);
|
||||
scaledFont.setPixelSize(font.pixelSize() * _fontScale);
|
||||
|
||||
int textWidth = text.size() * scaledFont.pixelSize() * 0.6;
|
||||
if (textWidth > path.length())
|
||||
return;
|
||||
|
||||
QPainterPath tp(textPath(path, textWidth, maxAngle, fm.averageCharWidth(),
|
||||
_sceneRect));
|
||||
QPainterPath tp(textPath(path, textWidth, maxAngle,
|
||||
scaledFont.pixelSize() / 2, _sceneRect));
|
||||
if (tp.isEmpty())
|
||||
return;
|
||||
|
||||
TextPathItem *pi = new TextPathItem(text, reverse(tp) ? tp.toReversed()
|
||||
: tp, font);
|
||||
: tp, scaledFont);
|
||||
if (!_sceneRect.contains(pi->boundingRect())) {
|
||||
delete pi;
|
||||
return;
|
||||
|
@ -6,7 +6,8 @@
|
||||
class Text
|
||||
{
|
||||
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();
|
||||
|
||||
void render(QPainter *painter);
|
||||
@ -21,6 +22,7 @@ private:
|
||||
QList<TextItem *> collidingItems(const TextItem *item) const;
|
||||
|
||||
QRectF _sceneRect;
|
||||
qreal _fontScale;
|
||||
QList<TextItem *> _items;
|
||||
};
|
||||
|
||||
|
@ -6,9 +6,8 @@
|
||||
TextPathItem::TextPathItem(const QString &text, const QPainterPath &path,
|
||||
const QFont &font) : _text(text), _path(path), _font(font)
|
||||
{
|
||||
QFontMetrics fm(font);
|
||||
QPainterPathStroker s;
|
||||
s.setWidth(fm.height());
|
||||
s.setWidth(font.pixelSize());
|
||||
s.setCapStyle(Qt::FlatCap);
|
||||
_shape = s.createStroke(path).simplified();
|
||||
_boundingRect = _shape.boundingRect();
|
||||
|
13
src/tile.h
13
src/tile.h
@ -7,20 +7,17 @@
|
||||
|
||||
class Tile {
|
||||
public:
|
||||
Tile(int size) : _background(size, size, QImage::Format_ARGB32),
|
||||
_text(size), _painter(&_background) {}
|
||||
Tile(QImage *img, qreal scale)
|
||||
: _size(img->size()), _text(img->size(), scale), _painter(img) {}
|
||||
|
||||
int size() const {return _background.width();}
|
||||
QSize size() const {return _size;}
|
||||
Text &text() {return _text;}
|
||||
QPainter &painter() {return _painter;}
|
||||
|
||||
const QImage &render() {
|
||||
_text.render(&painter());
|
||||
return _background;
|
||||
}
|
||||
void render() {_text.render(&_painter);}
|
||||
|
||||
private:
|
||||
QImage _background;
|
||||
QSize _size;
|
||||
Text _text;
|
||||
QPainter _painter;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user