mirror of
https://github.com/tumic0/QtPBFImagePlugin.git
synced 2025-06-30 04:59:16 +02:00
Removed Google protobuf dependency
This commit is contained in:
294
src/data.cpp
Normal file
294
src/data.cpp
Normal file
@ -0,0 +1,294 @@
|
||||
#include "data.h"
|
||||
|
||||
#define TYPE(tag) (tag & 0x07)
|
||||
#define FIELD(tag) (tag >> 3)
|
||||
|
||||
struct CTX
|
||||
{
|
||||
CTX(const QByteArray &ba)
|
||||
: bp(ba.constData()), be(bp + ba.size()) {}
|
||||
|
||||
const char *bp;
|
||||
const char *be;
|
||||
quint64 tag;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static bool varint(CTX &ctx, T &val)
|
||||
{
|
||||
val = 0;
|
||||
uint shift = 0;
|
||||
|
||||
while (ctx.bp < ctx.be) {
|
||||
val |= ((quint8)*ctx.bp & 0x7F) << shift;
|
||||
shift += 7;
|
||||
if (!((quint8)*ctx.bp++ & 0x80))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool str(CTX &ctx, QByteArray &val)
|
||||
{
|
||||
quint64 len;
|
||||
|
||||
if (!varint(ctx, len))
|
||||
return false;
|
||||
if (ctx.bp + len > ctx.be)
|
||||
return false;
|
||||
val = QByteArray::fromRawData(ctx.bp, len);
|
||||
ctx.bp += len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dbl(CTX &ctx, double &val)
|
||||
{
|
||||
if (ctx.bp + sizeof(val) > ctx.be)
|
||||
return false;
|
||||
|
||||
memcpy(&val, ctx.bp, sizeof(val));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool flt(CTX &ctx, float &val)
|
||||
{
|
||||
if (ctx.bp + sizeof(val) > ctx.be)
|
||||
return false;
|
||||
|
||||
memcpy(&val, ctx.bp, sizeof(val));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool packed(CTX &ctx, QVector<quint32> &vals)
|
||||
{
|
||||
quint32 v;
|
||||
|
||||
if (TYPE(ctx.tag) == 2) {
|
||||
quint64 len;
|
||||
if (!varint(ctx, len))
|
||||
return false;
|
||||
const char *ee = ctx.bp + len;
|
||||
if (ee > ctx.be)
|
||||
return false;
|
||||
while (ctx.bp < ee) {
|
||||
if (!varint(ctx, v))
|
||||
return false;
|
||||
vals.append(v);
|
||||
}
|
||||
return (ctx.bp == ee);
|
||||
} else if (TYPE(ctx.tag) == 0) {
|
||||
if (!varint(ctx, v))
|
||||
return false;
|
||||
vals.append(v);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool skip(CTX &ctx)
|
||||
{
|
||||
quint64 len = 0;
|
||||
|
||||
switch (TYPE(ctx.tag)) {
|
||||
case 0:
|
||||
return varint(ctx, len);
|
||||
case 1:
|
||||
len = 8;
|
||||
break;
|
||||
case 2:
|
||||
if (!varint(ctx, len))
|
||||
return false;
|
||||
break;
|
||||
case 5:
|
||||
len = 4;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx.bp + len > ctx.be)
|
||||
return false;
|
||||
ctx.bp += len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool value(CTX &ctx, QVariant &val)
|
||||
{
|
||||
QByteArray ba;
|
||||
quint64 len, num;
|
||||
double dnum;
|
||||
float fnum;
|
||||
|
||||
if (!varint(ctx, len))
|
||||
return false;
|
||||
|
||||
const char *ee = ctx.bp + len;
|
||||
if (ee > ctx.be)
|
||||
return false;
|
||||
|
||||
while (ctx.bp < ee) {
|
||||
if (!varint(ctx, ctx.tag))
|
||||
return false;
|
||||
|
||||
switch (FIELD(ctx.tag)) {
|
||||
case 1:
|
||||
if (!str(ctx, ba))
|
||||
return false;
|
||||
val = QVariant(ba);
|
||||
break;
|
||||
case 2:
|
||||
if (!flt(ctx, fnum))
|
||||
return false;
|
||||
val = QVariant(fnum);
|
||||
break;
|
||||
case 3:
|
||||
if (!dbl(ctx, dnum))
|
||||
return false;
|
||||
val = QVariant(dnum);
|
||||
break;
|
||||
case 4:
|
||||
if (!varint(ctx, num))
|
||||
return false;
|
||||
val = QVariant((qint64)num);
|
||||
break;
|
||||
case 5:
|
||||
if (!varint(ctx, num))
|
||||
return false;
|
||||
val = QVariant(num);
|
||||
break;
|
||||
case 6:
|
||||
if (!varint(ctx, num))
|
||||
return false;
|
||||
val = QVariant((qint64)((num >> 1) ^ -(num & 1)));
|
||||
break;
|
||||
case 7:
|
||||
if (!varint(ctx, num))
|
||||
return false;
|
||||
val = QVariant(num ? true : false);
|
||||
break;
|
||||
default:
|
||||
if (!skip(ctx))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (ctx.bp == ee);
|
||||
}
|
||||
|
||||
static bool feature(CTX &ctx, Data::Feature &f)
|
||||
{
|
||||
quint64 len;
|
||||
quint8 e;
|
||||
if (!varint(ctx, len))
|
||||
return false;
|
||||
|
||||
const char *ee = ctx.bp + len;
|
||||
if (ee > ctx.be)
|
||||
return false;
|
||||
|
||||
while (ctx.bp < ee) {
|
||||
if (!varint(ctx, ctx.tag))
|
||||
return false;
|
||||
|
||||
switch (FIELD(ctx.tag)) {
|
||||
case 1:
|
||||
if (!varint(ctx, f.id))
|
||||
return false;
|
||||
break;
|
||||
case 2:
|
||||
if (!packed(ctx, f.tags))
|
||||
return false;
|
||||
break;
|
||||
case 3:
|
||||
if (!varint(ctx, e))
|
||||
return false;
|
||||
if (e > Data::GeomType::POLYGON)
|
||||
return false;
|
||||
f.type = (Data::GeomType)e;
|
||||
break;
|
||||
case 4:
|
||||
if (!packed(ctx, f.geometry))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!skip(ctx))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (ctx.bp == ee);
|
||||
}
|
||||
|
||||
static bool layer(CTX &ctx, Data::Layer &l)
|
||||
{
|
||||
if (ctx.tag == 0x1a) {
|
||||
quint64 len;
|
||||
if (!varint(ctx, len))
|
||||
return false;
|
||||
|
||||
const char *ee = ctx.bp + len;
|
||||
if (ee > ctx.be)
|
||||
return false;
|
||||
|
||||
while (ctx.bp < ee) {
|
||||
if (!varint(ctx, ctx.tag))
|
||||
return false;
|
||||
|
||||
switch (FIELD(ctx.tag)) {
|
||||
case 1:
|
||||
if (!str(ctx, l.name))
|
||||
return false;
|
||||
break;
|
||||
case 2:
|
||||
l.features.append(Data::Feature());
|
||||
if (!feature(ctx, l.features.last()))
|
||||
return false;
|
||||
break;
|
||||
case 3:
|
||||
l.keys.append(QByteArray());
|
||||
if (!str(ctx, l.keys.last()))
|
||||
return false;
|
||||
break;
|
||||
case 4:
|
||||
l.values.append(QVariant());
|
||||
if (!value(ctx, l.values.last()))
|
||||
return false;
|
||||
break;
|
||||
case 5:
|
||||
if (!varint(ctx, l.extent))
|
||||
return false;
|
||||
break;
|
||||
case 15:
|
||||
if (!varint(ctx, l.version))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!skip(ctx))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (ctx.bp == ee);
|
||||
} else
|
||||
return skip(ctx);
|
||||
}
|
||||
|
||||
bool Data::load(const QByteArray &ba)
|
||||
{
|
||||
CTX ctx(ba);
|
||||
|
||||
while (ctx.bp < ctx.be) {
|
||||
if (!varint(ctx, ctx.tag))
|
||||
return false;
|
||||
_layers.append(Layer());
|
||||
if (!layer(ctx, _layers.last()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return (ctx.bp == ctx.be);
|
||||
}
|
43
src/data.h
Normal file
43
src/data.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef DATA_H
|
||||
#define DATA_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QVector>
|
||||
#include <QVariant>
|
||||
|
||||
class Data
|
||||
{
|
||||
public:
|
||||
enum GeomType {
|
||||
UNKNOWN = 0,
|
||||
POINT = 1,
|
||||
LINESTRING = 2,
|
||||
POLYGON = 3
|
||||
};
|
||||
|
||||
struct Feature
|
||||
{
|
||||
quint64 id;
|
||||
QVector<quint32> tags;
|
||||
GeomType type;
|
||||
QVector<quint32> geometry;
|
||||
};
|
||||
|
||||
struct Layer
|
||||
{
|
||||
quint32 version;
|
||||
QByteArray name;
|
||||
QVector<Feature> features;
|
||||
QVector<QByteArray> keys;
|
||||
QVector<QVariant> values;
|
||||
quint32 extent;
|
||||
};
|
||||
|
||||
bool load(const QByteArray &ba);
|
||||
const QVector<Layer> &layers() const {return _layers;}
|
||||
|
||||
private:
|
||||
QVector<Layer> _layers;
|
||||
};
|
||||
|
||||
#endif // DATA_H
|
67
src/pbf.cpp
67
src/pbf.cpp
@ -4,7 +4,6 @@
|
||||
#define LINE_TO 2
|
||||
#define CLOSE_PATH 7
|
||||
|
||||
|
||||
static inline qint32 zigzag32decode(quint32 value)
|
||||
{
|
||||
return static_cast<qint32>((value >> 1u) ^ static_cast<quint32>(
|
||||
@ -16,26 +15,6 @@ static inline QPoint parameters(quint32 v1, quint32 v2)
|
||||
return QPoint(zigzag32decode(v1), zigzag32decode(v2));
|
||||
}
|
||||
|
||||
static QVariant value(const vector_tile::Tile_Value &val)
|
||||
{
|
||||
if (val.has_bool_value())
|
||||
return QVariant(val.bool_value());
|
||||
else if (val.has_int_value())
|
||||
return QVariant((qlonglong)val.int_value());
|
||||
else if (val.has_sint_value())
|
||||
return QVariant((qlonglong)val.sint_value());
|
||||
else if (val.has_uint_value())
|
||||
return QVariant((qulonglong)val.uint_value());
|
||||
else if (val.has_float_value())
|
||||
return QVariant(val.float_value());
|
||||
else if (val.has_double_value())
|
||||
return QVariant(val.double_value());
|
||||
else if (val.has_string_value())
|
||||
return QVariant(QByteArray::fromStdString(val.string_value()));
|
||||
else
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const QVariant *PBF::Feature::value(const QByteArray &key) const
|
||||
{
|
||||
const KeyHash &keys(_layer->keys());
|
||||
@ -43,10 +22,10 @@ const QVariant *PBF::Feature::value(const QByteArray &key) const
|
||||
if (it == keys.constEnd())
|
||||
return 0;
|
||||
|
||||
google::protobuf::uint32 index = *it;
|
||||
for (int i = 0; i < _data->tags_size(); i = i + 2)
|
||||
if (_data->tags(i) == index)
|
||||
return &(_layer->values().at(_data->tags(i+1)));
|
||||
quint32 index = *it;
|
||||
for (int i = 0; i < _data->tags.size(); i = i + 2)
|
||||
if (_data->tags.at(i) == index)
|
||||
return &(_layer->values().at(_data->tags.at(i+1)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -56,15 +35,15 @@ QPainterPath PBF::Feature::path(const QSizeF &factor) const
|
||||
QPoint cursor;
|
||||
QPainterPath path;
|
||||
|
||||
for (int i = 0; i < _data->geometry_size(); i++) {
|
||||
quint32 g = _data->geometry(i);
|
||||
for (int i = 0; i < _data->geometry.size(); i++) {
|
||||
quint32 g = _data->geometry.at(i);
|
||||
unsigned cmdId = g & 0x7;
|
||||
unsigned cmdCount = g >> 3;
|
||||
|
||||
if (cmdId == MOVE_TO) {
|
||||
for (unsigned j = 0; j < cmdCount; j++) {
|
||||
QPoint offset = parameters(_data->geometry(i+1),
|
||||
_data->geometry(i+2));
|
||||
QPoint offset = parameters(_data->geometry.at(i+1),
|
||||
_data->geometry.at(i+2));
|
||||
i += 2;
|
||||
cursor += offset;
|
||||
path.moveTo(QPointF(cursor.x() * factor.width(),
|
||||
@ -72,8 +51,8 @@ QPainterPath PBF::Feature::path(const QSizeF &factor) const
|
||||
}
|
||||
} else if (cmdId == LINE_TO) {
|
||||
for (unsigned j = 0; j < cmdCount; j++) {
|
||||
QPoint offset = parameters(_data->geometry(i+1),
|
||||
_data->geometry(i+2));
|
||||
QPoint offset = parameters(_data->geometry.at(i+1),
|
||||
_data->geometry.at(i+2));
|
||||
i += 2;
|
||||
cursor += offset;
|
||||
path.lineTo(QPointF(cursor.x() * factor.width(),
|
||||
@ -88,27 +67,23 @@ QPainterPath PBF::Feature::path(const QSizeF &factor) const
|
||||
return path;
|
||||
}
|
||||
|
||||
PBF::Layer::Layer(const vector_tile::Tile_Layer *data) : _data(data)
|
||||
PBF::Layer::Layer(const Data::Layer *layer) : _data(layer)
|
||||
{
|
||||
_keys.reserve(data->keys_size());
|
||||
for (int i = 0; i < data->keys_size(); i++)
|
||||
_keys.insert(QByteArray::fromStdString(data->keys(i)), i);
|
||||
_values.reserve(data->values_size());
|
||||
for (int i = 0; i < data->values_size(); i++)
|
||||
_values.append(value(data->values(i)));
|
||||
_keys.reserve(layer->keys.size());
|
||||
for (int i = 0; i < layer->keys.size(); i++)
|
||||
_keys.insert(layer->keys.at(i), i);
|
||||
|
||||
_features.reserve(data->features_size());
|
||||
for (int i = 0; i < data->features_size(); i++)
|
||||
_features.append(Feature(&(data->features(i)), this));
|
||||
_features.reserve(layer->features.size());
|
||||
for (int i = 0; i < layer->features.size(); i++)
|
||||
_features.append(Feature(&(layer->features.at(i)), this));
|
||||
std::sort(_features.begin(), _features.end());
|
||||
}
|
||||
|
||||
PBF::PBF(const vector_tile::Tile &tile)
|
||||
PBF::PBF(const Data &data)
|
||||
{
|
||||
for (int i = 0; i < tile.layers_size(); i++) {
|
||||
const vector_tile::Tile_Layer &layer = tile.layers(i);
|
||||
_layers.insert(QByteArray::fromStdString(layer.name()),
|
||||
new Layer(&layer));
|
||||
for (int i = 0; i < data.layers().size(); i++) {
|
||||
const Data::Layer &layer = data.layers().at(i);
|
||||
_layers.insert(layer.name, new Layer(&layer));
|
||||
}
|
||||
}
|
||||
|
||||
|
23
src/pbf.h
23
src/pbf.h
@ -5,10 +5,10 @@
|
||||
#include <QVector>
|
||||
#include <QHash>
|
||||
#include <QPainterPath>
|
||||
#include "vector_tile.pb.h"
|
||||
#include "data.h"
|
||||
|
||||
|
||||
typedef QHash<QByteArray, google::protobuf::uint32> KeyHash;
|
||||
typedef QHash<QByteArray, quint32> KeyHash;
|
||||
|
||||
class PBF
|
||||
{
|
||||
@ -19,17 +19,17 @@ public:
|
||||
{
|
||||
public:
|
||||
Feature() : _data(0), _layer(0) {}
|
||||
Feature(const vector_tile::Tile_Feature *data, const Layer *layer)
|
||||
Feature(const Data::Feature *data, const Layer *layer)
|
||||
: _data(data), _layer(layer) {}
|
||||
|
||||
const QVariant *value(const QByteArray &key) const;
|
||||
vector_tile::Tile_GeomType type() const {return _data->type();}
|
||||
Data::GeomType type() const {return _data->type;}
|
||||
QPainterPath path(const QSizeF &factor) const;
|
||||
|
||||
friend bool operator<(const Feature &f1, const Feature &f2);
|
||||
|
||||
private:
|
||||
const vector_tile::Tile_Feature *_data;
|
||||
const Data::Feature *_data;
|
||||
const Layer *_layer;
|
||||
};
|
||||
|
||||
@ -37,22 +37,21 @@ public:
|
||||
{
|
||||
public:
|
||||
|
||||
Layer(const vector_tile::Tile_Layer *data);
|
||||
Layer(const Data::Layer *layer);
|
||||
|
||||
const QVector<Feature> &features() const {return _features;}
|
||||
const QVector<QVariant> &values() const {return _values;}
|
||||
const QVector<QVariant> &values() const {return _data->values;}
|
||||
const KeyHash &keys() const {return _keys;}
|
||||
const vector_tile::Tile_Layer *data() const {return _data;}
|
||||
const Data::Layer *data() const {return _data;}
|
||||
|
||||
private:
|
||||
const vector_tile::Tile_Layer *_data;
|
||||
const Data::Layer *_data;
|
||||
QVector<Feature> _features;
|
||||
QVector<QVariant> _values;
|
||||
KeyHash _keys;
|
||||
};
|
||||
|
||||
|
||||
PBF(const vector_tile::Tile &tile);
|
||||
PBF(const Data &data);
|
||||
~PBF();
|
||||
|
||||
const QHash<QByteArray, Layer*> &layers() const {return _layers;}
|
||||
@ -62,6 +61,6 @@ private:
|
||||
};
|
||||
|
||||
inline bool operator<(const PBF::Feature &f1, const PBF::Feature &f2)
|
||||
{return f1._data->id() < f2._data->id();}
|
||||
{return f1._data->id < f2._data->id;}
|
||||
|
||||
#endif // PBF_H
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <QtEndian>
|
||||
#include <QDebug>
|
||||
#include "gzip.h"
|
||||
#include "data.h"
|
||||
#include "tile.h"
|
||||
#include "style.h"
|
||||
#include "pbfhandler.h"
|
||||
@ -73,8 +74,8 @@ bool PBFHandler::read(QImage *image)
|
||||
}
|
||||
} else if (isPlainPBF(magic))
|
||||
ba = device()->readAll();
|
||||
vector_tile::Tile data;
|
||||
if (!data.ParseFromArray(ba.constData(), ba.size())) {
|
||||
Data data;
|
||||
if (!data.load(ba)) {
|
||||
qCritical() << "Invalid PBF data";
|
||||
return false;
|
||||
}
|
||||
|
@ -14,16 +14,16 @@
|
||||
#include "style.h"
|
||||
|
||||
|
||||
static vector_tile::Tile_GeomType geometryType(const QString &str)
|
||||
static Data::GeomType geometryType(const QString &str)
|
||||
{
|
||||
if (str == "Point")
|
||||
return vector_tile::Tile_GeomType_POINT;
|
||||
return Data::GeomType::POINT;
|
||||
else if (str == "LineString")
|
||||
return vector_tile::Tile_GeomType_LINESTRING;
|
||||
return Data::GeomType::LINESTRING;
|
||||
else if (str == "Polygon")
|
||||
return vector_tile::Tile_GeomType_POLYGON;
|
||||
return Data::GeomType::POLYGON;
|
||||
else
|
||||
return vector_tile::Tile_GeomType_UNKNOWN;
|
||||
return Data::GeomType::UNKNOWN;
|
||||
}
|
||||
|
||||
static QVariant variant(const QJsonValue &val)
|
||||
@ -680,15 +680,15 @@ void Style::drawFeature(const PBF::Feature &feature, const Layer &layer,
|
||||
void Style::drawLayer(const PBF::Layer &pbfLayer, const Layer &styleLayer,
|
||||
Tile &tile)
|
||||
{
|
||||
if (pbfLayer.data()->version() > 2)
|
||||
if (pbfLayer.data()->version > 2)
|
||||
return;
|
||||
|
||||
if (!styleLayer.isVisible())
|
||||
return;
|
||||
|
||||
QSizeF factor(tile.size().width() / tile.scale().x() /
|
||||
(qreal)pbfLayer.data()->extent(), tile.size().height() / tile.scale().y()
|
||||
/ (qreal)pbfLayer.data()->extent());
|
||||
(qreal)pbfLayer.data()->extent, tile.size().height() / tile.scale().y()
|
||||
/ (qreal)pbfLayer.data()->extent);
|
||||
|
||||
tile.painter().save();
|
||||
setupLayer(tile, styleLayer);
|
||||
|
Reference in New Issue
Block a user