mirror of
https://github.com/tumic0/QtPBFImagePlugin.git
synced 2025-02-22 11:00:48 +01:00
Compare commits
No commits in common. "c12c2b44975ea0bbfe962eff22a64f855f3d8790" and "caf0a29b74a586e2a18c8b249283888859e079a1" have entirely different histories.
c12c2b4497
...
caf0a29b74
@ -1,4 +1,4 @@
|
|||||||
version: 4.0.{build}
|
version: 3.2.{build}
|
||||||
|
|
||||||
configuration:
|
configuration:
|
||||||
- Release
|
- Release
|
||||||
@ -14,18 +14,20 @@ environment:
|
|||||||
|
|
||||||
install:
|
install:
|
||||||
- cmd: |-
|
- cmd: |-
|
||||||
set PATH=%QTDIR%\bin;%PATH%
|
set PATH=%QTDIR%\bin;%VCPKGDIR%\tools\protobuf;%PATH%
|
||||||
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat
|
||||||
|
vcpkg install pkgconf:x64-windows-static-md-release
|
||||||
|
vcpkg install protobuf:x64-windows-static-md-release
|
||||||
vcpkg install zlib:x64-windows-static-md-release
|
vcpkg install zlib:x64-windows-static-md-release
|
||||||
copy /y %VCPKGDIR%\lib\zlib.lib %VCPKGDIR%\lib\zlibstatic.lib
|
copy /y %VCPKGDIR%\lib\zlib.lib %VCPKGDIR%\lib\zlibstatic.lib
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- cmd: |-
|
- cmd: |-
|
||||||
qmake ZLIB=%VCPKGDIR% pbfplugin.pro
|
qmake USE_PKGCONFIG=true pbfplugin.pro
|
||||||
nmake release
|
nmake release
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: release\pbf4.dll
|
- path: release\pbf3.dll
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
- C:\tools\vcpkg\installed\
|
- C:\tools\vcpkg\installed\
|
||||||
|
8
.github/workflows/android.yml
vendored
8
.github/workflows/android.yml
vendored
@ -12,6 +12,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
- name: Install protobuf compiler
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install protobuf-compiler
|
||||||
- name: set up JDK 11
|
- name: set up JDK 11
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
@ -37,8 +41,10 @@ jobs:
|
|||||||
version: '6.4.0'
|
version: '6.4.0'
|
||||||
target: 'android'
|
target: 'android'
|
||||||
arch: 'android_arm64_v8a'
|
arch: 'android_arm64_v8a'
|
||||||
|
- name: Install Android Google Protocol Buffers
|
||||||
|
run: git clone https://github.com/tumic0/android_protobuf.git
|
||||||
- name: Configure build
|
- name: Configure build
|
||||||
run: qmake pbfplugin.pro
|
run: qmake pbfplugin.pro PROTOBUF=android_protobuf
|
||||||
- name: Build project
|
- name: Build project
|
||||||
run: make -j2
|
run: make -j2
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
|
2
.github/workflows/linux.yml
vendored
2
.github/workflows/linux.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install qtbase5-dev qtbase5-dev-tools qt5-qmake zlib1g-dev
|
sudo apt-get install qtbase5-dev qtbase5-dev-tools qt5-qmake libprotobuf-dev protobuf-compiler zlib1g-dev
|
||||||
- name: Configure build
|
- name: Configure build
|
||||||
run: qmake pbfplugin.pro
|
run: qmake pbfplugin.pro
|
||||||
- name: Build project
|
- name: Build project
|
||||||
|
38
.github/workflows/osx.yml
vendored
38
.github/workflows/osx.yml
vendored
@ -6,22 +6,36 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
qt5:
|
||||||
name: QtPBFImagePlugin
|
name: QtPBFImagePlugin Qt5 build
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
|
- name: Set environment variables
|
||||||
|
run: echo "PATH=/opt/homebrew/opt/qt@5/bin:/opt/homebrew/opt/protobuf@21/bin:$PATH" >> $GITHUB_ENV
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Install Qt
|
- name: Install dependencies
|
||||||
uses: jurplel/install-qt-action@v4
|
run: |
|
||||||
with:
|
brew update
|
||||||
version: '6.8.1'
|
brew install qt@5 protobuf@21
|
||||||
- name: Configure build
|
- name: Configure build
|
||||||
run: qmake pbfplugin.pro QMAKE_APPLE_DEVICE_ARCHS="x86_64h arm64"
|
run: qmake PROTOBUF=/opt/homebrew/opt/protobuf@21 pbfplugin.pro
|
||||||
|
- name: Build project
|
||||||
|
run: make -j3
|
||||||
|
|
||||||
|
qt6:
|
||||||
|
name: QtPBFImagePlugin Qt6 build
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- name: Set environment variables
|
||||||
|
run: echo "PATH=/opt/homebrew/opt/qt@6/bin:/opt/homebrew/opt/protobuf@21/bin:$PATH" >> $GITHUB_ENV
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
brew update
|
||||||
|
brew install qt@6 protobuf@21
|
||||||
|
- name: Configure build
|
||||||
|
run: qmake PROTOBUF=/opt/homebrew/opt/protobuf@21 pbfplugin.pro
|
||||||
- name: Build project
|
- name: Build project
|
||||||
run: make -j3
|
run: make -j3
|
||||||
- name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
path: libpbf.dylib
|
|
||||||
name: libpbf.dylib
|
|
||||||
|
10
README.md
10
README.md
@ -68,19 +68,25 @@ repository.
|
|||||||
## Build
|
## Build
|
||||||
### Requirements
|
### Requirements
|
||||||
* Qt5 >= 5.11 or Qt6
|
* Qt5 >= 5.11 or Qt6
|
||||||
|
* Google Protocol Buffers (protobuf-lite)
|
||||||
* Zlib
|
* Zlib
|
||||||
|
|
||||||
### Build steps
|
### Build steps
|
||||||
#### Linux, OS X and Android
|
#### Linux
|
||||||
```shell
|
```shell
|
||||||
qmake pbfplugin.pro
|
qmake pbfplugin.pro
|
||||||
make
|
make
|
||||||
```
|
```
|
||||||
#### Windows
|
#### Windows
|
||||||
```shell
|
```shell
|
||||||
qmake ZLIB=path/to/zlib pbfplugin.pro
|
qmake PROTOBUF=path/to/protobuf ZLIB=path/to/zlib pbfplugin.pro
|
||||||
nmake
|
nmake
|
||||||
```
|
```
|
||||||
|
#### OS X
|
||||||
|
```shell
|
||||||
|
qmake PROTOBUF=path/to/protobuf pbfplugin.pro
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
Copy the plugin to the system Qt image plugins path to make it work. You may
|
Copy the plugin to the system Qt image plugins path to make it work. You may
|
||||||
|
@ -2,10 +2,13 @@ TARGET = pbf
|
|||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
CONFIG += plugin
|
CONFIG += plugin
|
||||||
QT += gui
|
QT += gui
|
||||||
VERSION = 4.0
|
VERSION = 3.3
|
||||||
|
|
||||||
|
PROTOS = protobuf/vector_tile.proto
|
||||||
|
include(protobuf/vector_tile.pri)
|
||||||
|
|
||||||
|
INCLUDEPATH += ./protobuf
|
||||||
HEADERS += src/pbfhandler.h \
|
HEADERS += src/pbfhandler.h \
|
||||||
src/data.h \
|
|
||||||
src/pbfplugin.h \
|
src/pbfplugin.h \
|
||||||
src/gzip.h \
|
src/gzip.h \
|
||||||
src/pbf.h \
|
src/pbf.h \
|
||||||
@ -20,7 +23,6 @@ HEADERS += src/pbfhandler.h \
|
|||||||
src/textitem.h \
|
src/textitem.h \
|
||||||
src/sprites.h
|
src/sprites.h
|
||||||
SOURCES += src/pbfplugin.cpp \
|
SOURCES += src/pbfplugin.cpp \
|
||||||
src/data.cpp \
|
|
||||||
src/pbfhandler.cpp \
|
src/pbfhandler.cpp \
|
||||||
src/gzip.cpp \
|
src/gzip.cpp \
|
||||||
src/pbf.cpp \
|
src/pbf.cpp \
|
||||||
@ -37,25 +39,45 @@ RESOURCES += pbfplugin.qrc
|
|||||||
|
|
||||||
DEFINES += QT_NO_DEPRECATED_WARNINGS
|
DEFINES += QT_NO_DEPRECATED_WARNINGS
|
||||||
|
|
||||||
|
equals(USE_PKGCONFIG, "true") {
|
||||||
|
CONFIG += link_pkgconfig
|
||||||
|
PKGCONFIG += protobuf-lite zlib
|
||||||
|
}
|
||||||
|
|
||||||
unix:!macx:!android {
|
unix:!macx:!android {
|
||||||
LIBS += -lz
|
!equals(USE_PKGCONFIG, "true") {
|
||||||
|
LIBS += -lprotobuf-lite \
|
||||||
|
-lz
|
||||||
|
}
|
||||||
|
|
||||||
target.path += $$[QT_INSTALL_PLUGINS]/imageformats
|
target.path += $$[QT_INSTALL_PLUGINS]/imageformats
|
||||||
INSTALLS += target
|
INSTALLS += target
|
||||||
}
|
}
|
||||||
win32 {
|
win32 {
|
||||||
INCLUDEPATH += $$ZLIB/include
|
!equals(USE_PKGCONFIG, "true") {
|
||||||
LIBS += $$ZLIB/lib/zlibstatic.lib
|
INCLUDEPATH += $$PROTOBUF/include \
|
||||||
|
$$ZLIB/include
|
||||||
|
LIBS += $$PROTOBUF/lib/libprotobuf-lite.lib \
|
||||||
|
$$ZLIB/lib/zlibstatic.lib
|
||||||
|
}
|
||||||
|
|
||||||
QMAKE_TARGET_PRODUCT = QtPBFImagePlugin
|
QMAKE_TARGET_PRODUCT = QtPBFImagePlugin
|
||||||
QMAKE_TARGET_DESCRIPTION = Qt $$QT_VERSION MVT/PBF image plugin
|
QMAKE_TARGET_DESCRIPTION = Qt $$QT_VERSION MVT/PBF image plugin
|
||||||
QMAKE_TARGET_COPYRIGHT = Copyright (c) 2018-2025 Martin Tuma
|
QMAKE_TARGET_COPYRIGHT = Copyright (c) 2018-2025 Martin Tuma
|
||||||
}
|
}
|
||||||
macx {
|
macx {
|
||||||
LIBS += -lz
|
!equals(USE_PKGCONFIG, "true") {
|
||||||
|
INCLUDEPATH += $$PROTOBUF/include
|
||||||
|
LIBS += $$PROTOBUF/lib/libprotobuf-lite.a \
|
||||||
|
-lz
|
||||||
|
}
|
||||||
}
|
}
|
||||||
android {
|
android {
|
||||||
LIBS += -lz
|
!equals(USE_PKGCONFIG, "true") {
|
||||||
|
INCLUDEPATH += $$PROTOBUF/include
|
||||||
|
LIBS += $$PROTOBUF/$$ANDROID_TARGET_ARCH/libprotobuf-lite.a \
|
||||||
|
-lz
|
||||||
|
}
|
||||||
|
|
||||||
top_builddir=$$shadowed($$PWD)
|
top_builddir=$$shadowed($$PWD)
|
||||||
DESTDIR = $$top_builddir/plugins
|
DESTDIR = $$top_builddir/plugins
|
||||||
|
17
protobuf/vector_tile.pri
Normal file
17
protobuf/vector_tile.pri
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
INCLUDEPATH += $$PWD
|
||||||
|
DEPENDPATH += $$PWD
|
||||||
|
|
||||||
|
protobuf_decl.name = protobuf headers
|
||||||
|
protobuf_decl.input = PROTOS
|
||||||
|
protobuf_decl.output = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.h
|
||||||
|
protobuf_decl.commands = protoc --cpp_out=${QMAKE_FILE_IN_PATH} --proto_path=${QMAKE_FILE_IN_PATH} ${QMAKE_FILE_NAME}
|
||||||
|
protobuf_decl.variable_out = HEADERS
|
||||||
|
QMAKE_EXTRA_COMPILERS += protobuf_decl
|
||||||
|
|
||||||
|
protobuf_impl.name = protobuf sources
|
||||||
|
protobuf_impl.input = PROTOS
|
||||||
|
protobuf_impl.output = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.cc
|
||||||
|
protobuf_impl.depends = ${QMAKE_FILE_IN_PATH}/${QMAKE_FILE_BASE}.pb.h
|
||||||
|
protobuf_impl.commands = $$escape_expand(\n)
|
||||||
|
protobuf_impl.variable_out = SOURCES
|
||||||
|
QMAKE_EXTRA_COMPILERS += protobuf_impl
|
78
protobuf/vector_tile.proto
Normal file
78
protobuf/vector_tile.proto
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package vector_tile;
|
||||||
|
|
||||||
|
option optimize_for = LITE_RUNTIME;
|
||||||
|
|
||||||
|
message Tile {
|
||||||
|
|
||||||
|
// GeomType is described in section 4.3.4 of the specification
|
||||||
|
enum GeomType {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
POINT = 1;
|
||||||
|
LINESTRING = 2;
|
||||||
|
POLYGON = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variant type encoding
|
||||||
|
// The use of values is described in section 4.1 of the specification
|
||||||
|
message Value {
|
||||||
|
// Exactly one of these values must be present in a valid message
|
||||||
|
optional string string_value = 1;
|
||||||
|
optional float float_value = 2;
|
||||||
|
optional double double_value = 3;
|
||||||
|
optional int64 int_value = 4;
|
||||||
|
optional uint64 uint_value = 5;
|
||||||
|
optional sint64 sint_value = 6;
|
||||||
|
optional bool bool_value = 7;
|
||||||
|
|
||||||
|
extensions 8 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Features are described in section 4.2 of the specification
|
||||||
|
message Feature {
|
||||||
|
optional uint64 id = 1 [ default = 0 ];
|
||||||
|
|
||||||
|
// Tags of this feature are encoded as repeated pairs of
|
||||||
|
// integers.
|
||||||
|
// A detailed description of tags is located in sections
|
||||||
|
// 4.2 and 4.4 of the specification
|
||||||
|
repeated uint32 tags = 2 [ packed = true ];
|
||||||
|
|
||||||
|
// The type of geometry stored in this feature.
|
||||||
|
optional GeomType type = 3 [ default = UNKNOWN ];
|
||||||
|
|
||||||
|
// Contains a stream of commands and parameters (vertices).
|
||||||
|
// A detailed description on geometry encoding is located in
|
||||||
|
// section 4.3 of the specification.
|
||||||
|
repeated uint32 geometry = 4 [ packed = true ];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layers are described in section 4.1 of the specification
|
||||||
|
message Layer {
|
||||||
|
// Any compliant implementation must first read the version
|
||||||
|
// number encoded in this message and choose the correct
|
||||||
|
// implementation for this version number before proceeding to
|
||||||
|
// decode other parts of this message.
|
||||||
|
required uint32 version = 15 [ default = 1 ];
|
||||||
|
|
||||||
|
required string name = 1;
|
||||||
|
|
||||||
|
// The actual features in this tile.
|
||||||
|
repeated Feature features = 2;
|
||||||
|
|
||||||
|
// Dictionary encoding for keys
|
||||||
|
repeated string keys = 3;
|
||||||
|
|
||||||
|
// Dictionary encoding for values
|
||||||
|
repeated Value values = 4;
|
||||||
|
|
||||||
|
// Although this is an "optional" field it is required by the specification.
|
||||||
|
// See https://github.com/mapbox/vector-tile-spec/issues/47
|
||||||
|
optional uint32 extent = 5 [ default = 4096 ];
|
||||||
|
|
||||||
|
extensions 16 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
repeated Layer layers = 3;
|
||||||
|
|
||||||
|
extensions 16 to 8191;
|
||||||
|
}
|
301
src/data.cpp
301
src/data.cpp
@ -1,301 +0,0 @@
|
|||||||
#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;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline qint64 zigzag64decode(quint64 value)
|
|
||||||
{
|
|
||||||
return static_cast<qint64>((value >> 1u) ^ static_cast<quint64>(
|
|
||||||
-static_cast<qint64>(value & 1u)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static bool varint(CTX &ctx, T &val)
|
|
||||||
{
|
|
||||||
val = 0;
|
|
||||||
uint shift = 0;
|
|
||||||
const char *end = qMin(ctx.be, ctx.bp + sizeof(val));
|
|
||||||
|
|
||||||
while (ctx.bp < end) {
|
|
||||||
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(static_cast<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(zigzag64decode(num));
|
|
||||||
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
43
src/data.h
@ -1,43 +0,0 @@
|
|||||||
#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,6 +4,7 @@
|
|||||||
#define LINE_TO 2
|
#define LINE_TO 2
|
||||||
#define CLOSE_PATH 7
|
#define CLOSE_PATH 7
|
||||||
|
|
||||||
|
|
||||||
static inline qint32 zigzag32decode(quint32 value)
|
static inline qint32 zigzag32decode(quint32 value)
|
||||||
{
|
{
|
||||||
return static_cast<qint32>((value >> 1u) ^ static_cast<quint32>(
|
return static_cast<qint32>((value >> 1u) ^ static_cast<quint32>(
|
||||||
@ -15,6 +16,26 @@ static inline QPoint parameters(quint32 v1, quint32 v2)
|
|||||||
return QPoint(zigzag32decode(v1), zigzag32decode(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 QVariant *PBF::Feature::value(const QByteArray &key) const
|
||||||
{
|
{
|
||||||
const KeyHash &keys(_layer->keys());
|
const KeyHash &keys(_layer->keys());
|
||||||
@ -22,10 +43,10 @@ const QVariant *PBF::Feature::value(const QByteArray &key) const
|
|||||||
if (it == keys.constEnd())
|
if (it == keys.constEnd())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
quint32 index = *it;
|
google::protobuf::uint32 index = *it;
|
||||||
for (int i = 0; i < _data->tags.size(); i = i + 2)
|
for (int i = 0; i < _data->tags_size(); i = i + 2)
|
||||||
if (_data->tags.at(i) == index)
|
if (_data->tags(i) == index)
|
||||||
return &(_layer->values().at(_data->tags.at(i+1)));
|
return &(_layer->values().at(_data->tags(i+1)));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -35,15 +56,15 @@ QPainterPath PBF::Feature::path(const QSizeF &factor) const
|
|||||||
QPoint cursor;
|
QPoint cursor;
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
|
|
||||||
for (int i = 0; i < _data->geometry.size(); i++) {
|
for (int i = 0; i < _data->geometry_size(); i++) {
|
||||||
quint32 g = _data->geometry.at(i);
|
quint32 g = _data->geometry(i);
|
||||||
unsigned cmdId = g & 0x7;
|
unsigned cmdId = g & 0x7;
|
||||||
unsigned cmdCount = g >> 3;
|
unsigned cmdCount = g >> 3;
|
||||||
|
|
||||||
if (cmdId == MOVE_TO) {
|
if (cmdId == MOVE_TO) {
|
||||||
for (unsigned j = 0; j < cmdCount; j++) {
|
for (unsigned j = 0; j < cmdCount; j++) {
|
||||||
QPoint offset = parameters(_data->geometry.at(i+1),
|
QPoint offset = parameters(_data->geometry(i+1),
|
||||||
_data->geometry.at(i+2));
|
_data->geometry(i+2));
|
||||||
i += 2;
|
i += 2;
|
||||||
cursor += offset;
|
cursor += offset;
|
||||||
path.moveTo(QPointF(cursor.x() * factor.width(),
|
path.moveTo(QPointF(cursor.x() * factor.width(),
|
||||||
@ -51,8 +72,8 @@ QPainterPath PBF::Feature::path(const QSizeF &factor) const
|
|||||||
}
|
}
|
||||||
} else if (cmdId == LINE_TO) {
|
} else if (cmdId == LINE_TO) {
|
||||||
for (unsigned j = 0; j < cmdCount; j++) {
|
for (unsigned j = 0; j < cmdCount; j++) {
|
||||||
QPoint offset = parameters(_data->geometry.at(i+1),
|
QPoint offset = parameters(_data->geometry(i+1),
|
||||||
_data->geometry.at(i+2));
|
_data->geometry(i+2));
|
||||||
i += 2;
|
i += 2;
|
||||||
cursor += offset;
|
cursor += offset;
|
||||||
path.lineTo(QPointF(cursor.x() * factor.width(),
|
path.lineTo(QPointF(cursor.x() * factor.width(),
|
||||||
@ -67,23 +88,27 @@ QPainterPath PBF::Feature::path(const QSizeF &factor) const
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
PBF::Layer::Layer(const Data::Layer *layer) : _data(layer)
|
PBF::Layer::Layer(const vector_tile::Tile_Layer *data) : _data(data)
|
||||||
{
|
{
|
||||||
_keys.reserve(layer->keys.size());
|
_keys.reserve(data->keys_size());
|
||||||
for (int i = 0; i < layer->keys.size(); i++)
|
for (int i = 0; i < data->keys_size(); i++)
|
||||||
_keys.insert(layer->keys.at(i), 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)));
|
||||||
|
|
||||||
_features.reserve(layer->features.size());
|
_features.reserve(data->features_size());
|
||||||
for (int i = 0; i < layer->features.size(); i++)
|
for (int i = 0; i < data->features_size(); i++)
|
||||||
_features.append(Feature(&(layer->features.at(i)), this));
|
_features.append(Feature(&(data->features(i)), this));
|
||||||
std::sort(_features.begin(), _features.end());
|
std::sort(_features.begin(), _features.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
PBF::PBF(const Data &data)
|
PBF::PBF(const vector_tile::Tile &tile)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < data.layers().size(); i++) {
|
for (int i = 0; i < tile.layers_size(); i++) {
|
||||||
const Data::Layer &layer = data.layers().at(i);
|
const vector_tile::Tile_Layer &layer = tile.layers(i);
|
||||||
_layers.insert(layer.name, new Layer(&layer));
|
_layers.insert(QByteArray::fromStdString(layer.name()),
|
||||||
|
new Layer(&layer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
src/pbf.h
23
src/pbf.h
@ -5,10 +5,10 @@
|
|||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
#include "data.h"
|
#include "vector_tile.pb.h"
|
||||||
|
|
||||||
|
|
||||||
typedef QHash<QByteArray, quint32> KeyHash;
|
typedef QHash<QByteArray, google::protobuf::uint32> KeyHash;
|
||||||
|
|
||||||
class PBF
|
class PBF
|
||||||
{
|
{
|
||||||
@ -19,17 +19,17 @@ public:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Feature() : _data(0), _layer(0) {}
|
Feature() : _data(0), _layer(0) {}
|
||||||
Feature(const Data::Feature *data, const Layer *layer)
|
Feature(const vector_tile::Tile_Feature *data, const Layer *layer)
|
||||||
: _data(data), _layer(layer) {}
|
: _data(data), _layer(layer) {}
|
||||||
|
|
||||||
const QVariant *value(const QByteArray &key) const;
|
const QVariant *value(const QByteArray &key) const;
|
||||||
Data::GeomType type() const {return _data->type;}
|
vector_tile::Tile_GeomType type() const {return _data->type();}
|
||||||
QPainterPath path(const QSizeF &factor) const;
|
QPainterPath path(const QSizeF &factor) const;
|
||||||
|
|
||||||
friend bool operator<(const Feature &f1, const Feature &f2);
|
friend bool operator<(const Feature &f1, const Feature &f2);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Data::Feature *_data;
|
const vector_tile::Tile_Feature *_data;
|
||||||
const Layer *_layer;
|
const Layer *_layer;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -37,21 +37,22 @@ public:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Layer(const Data::Layer *layer);
|
Layer(const vector_tile::Tile_Layer *data);
|
||||||
|
|
||||||
const QVector<Feature> &features() const {return _features;}
|
const QVector<Feature> &features() const {return _features;}
|
||||||
const QVector<QVariant> &values() const {return _data->values;}
|
const QVector<QVariant> &values() const {return _values;}
|
||||||
const KeyHash &keys() const {return _keys;}
|
const KeyHash &keys() const {return _keys;}
|
||||||
const Data::Layer *data() const {return _data;}
|
const vector_tile::Tile_Layer *data() const {return _data;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Data::Layer *_data;
|
const vector_tile::Tile_Layer *_data;
|
||||||
QVector<Feature> _features;
|
QVector<Feature> _features;
|
||||||
|
QVector<QVariant> _values;
|
||||||
KeyHash _keys;
|
KeyHash _keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PBF(const Data &data);
|
PBF(const vector_tile::Tile &tile);
|
||||||
~PBF();
|
~PBF();
|
||||||
|
|
||||||
const QHash<QByteArray, Layer*> &layers() const {return _layers;}
|
const QHash<QByteArray, Layer*> &layers() const {return _layers;}
|
||||||
@ -61,6 +62,6 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator<(const PBF::Feature &f1, const PBF::Feature &f2)
|
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
|
#endif // PBF_H
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include <QtEndian>
|
#include <QtEndian>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "gzip.h"
|
#include "gzip.h"
|
||||||
#include "data.h"
|
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
#include "style.h"
|
#include "style.h"
|
||||||
#include "pbfhandler.h"
|
#include "pbfhandler.h"
|
||||||
@ -74,8 +73,8 @@ bool PBFHandler::read(QImage *image)
|
|||||||
}
|
}
|
||||||
} else if (isPlainPBF(magic))
|
} else if (isPlainPBF(magic))
|
||||||
ba = device()->readAll();
|
ba = device()->readAll();
|
||||||
Data data;
|
vector_tile::Tile data;
|
||||||
if (!data.load(ba)) {
|
if (!data.ParseFromArray(ba.constData(), ba.size())) {
|
||||||
qCritical() << "Invalid PBF data";
|
qCritical() << "Invalid PBF data";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -14,16 +14,16 @@
|
|||||||
#include "style.h"
|
#include "style.h"
|
||||||
|
|
||||||
|
|
||||||
static Data::GeomType geometryType(const QString &str)
|
static vector_tile::Tile_GeomType geometryType(const QString &str)
|
||||||
{
|
{
|
||||||
if (str == "Point")
|
if (str == "Point")
|
||||||
return Data::GeomType::POINT;
|
return vector_tile::Tile_GeomType_POINT;
|
||||||
else if (str == "LineString")
|
else if (str == "LineString")
|
||||||
return Data::GeomType::LINESTRING;
|
return vector_tile::Tile_GeomType_LINESTRING;
|
||||||
else if (str == "Polygon")
|
else if (str == "Polygon")
|
||||||
return Data::GeomType::POLYGON;
|
return vector_tile::Tile_GeomType_POLYGON;
|
||||||
else
|
else
|
||||||
return Data::GeomType::UNKNOWN;
|
return vector_tile::Tile_GeomType_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QVariant variant(const QJsonValue &val)
|
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,
|
void Style::drawLayer(const PBF::Layer &pbfLayer, const Layer &styleLayer,
|
||||||
Tile &tile)
|
Tile &tile)
|
||||||
{
|
{
|
||||||
if (pbfLayer.data()->version > 2)
|
if (pbfLayer.data()->version() > 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!styleLayer.isVisible())
|
if (!styleLayer.isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QSizeF factor(tile.size().width() / tile.scale().x() /
|
QSizeF factor(tile.size().width() / tile.scale().x() /
|
||||||
(qreal)pbfLayer.data()->extent, tile.size().height() / tile.scale().y()
|
(qreal)pbfLayer.data()->extent(), tile.size().height() / tile.scale().y()
|
||||||
/ (qreal)pbfLayer.data()->extent);
|
/ (qreal)pbfLayer.data()->extent());
|
||||||
|
|
||||||
tile.painter().save();
|
tile.painter().save();
|
||||||
setupLayer(tile, styleLayer);
|
setupLayer(tile, styleLayer);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user