diff --git a/src/pbf.cpp b/src/pbf.cpp index 48c3a52..e1f3339 100644 --- a/src/pbf.cpp +++ b/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; } diff --git a/src/pbf.h b/src/pbf.h index 9a0bcb9..e18149d 100644 --- a/src/pbf.h +++ b/src/pbf.h @@ -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 diff --git a/src/pbfhandler.cpp b/src/pbfhandler.cpp index d7dc3c7..6f7a1f7 100644 --- a/src/pbfhandler.cpp +++ b/src/pbfhandler.cpp @@ -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 diff --git a/src/pbfhandler.h b/src/pbfhandler.h index 77a4883..f47b74d 100644 --- a/src/pbfhandler.h +++ b/src/pbfhandler.h @@ -4,6 +4,7 @@ #include #include #include +#include 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 diff --git a/src/style.cpp b/src/style.cpp index fb6c8c7..6c57490 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -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); diff --git a/src/text.cpp b/src/text.cpp index c38776b..243cba2 100644 --- a/src/text.cpp +++ b/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 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; diff --git a/src/text.h b/src/text.h index cd5de88..0f6762e 100644 --- a/src/text.h +++ b/src/text.h @@ -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 collidingItems(const TextItem *item) const; QRectF _sceneRect; + qreal _fontScale; QList _items; }; diff --git a/src/textpathitem.cpp b/src/textpathitem.cpp index 62a97fc..3814862 100644 --- a/src/textpathitem.cpp +++ b/src/textpathitem.cpp @@ -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(); diff --git a/src/tile.h b/src/tile.h index a143125..02ee011 100644 --- a/src/tile.h +++ b/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; };