mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-27 21:24:47 +01:00
Added support for Huffman compressed RGN data
This commit is contained in:
parent
7cc39f25e1
commit
cd22e6207a
@ -89,6 +89,10 @@ HEADERS += src/common/config.h \
|
||||
src/GUI/areaitem.h \
|
||||
src/data/link.h \
|
||||
src/map/IMG/bitmapline.h \
|
||||
src/map/IMG/bitstream.h \
|
||||
src/map/IMG/deltastream.h \
|
||||
src/map/IMG/huffmanstream.h \
|
||||
src/map/IMG/huffmantable.h \
|
||||
src/map/IMG/textpathitem.h \
|
||||
src/map/IMG/textpointitem.h \
|
||||
src/map/projection.h \
|
||||
@ -243,6 +247,10 @@ SOURCES += src/main.cpp \
|
||||
src/GUI/mapview.cpp \
|
||||
src/GUI/areaitem.cpp \
|
||||
src/map/IMG/bitmapline.cpp \
|
||||
src/map/IMG/bitstream.cpp \
|
||||
src/map/IMG/deltastream.cpp \
|
||||
src/map/IMG/huffmanstream.cpp \
|
||||
src/map/IMG/huffmantable.cpp \
|
||||
src/map/IMG/textpathitem.cpp \
|
||||
src/map/IMG/textpointitem.cpp \
|
||||
src/map/maplist.cpp \
|
||||
|
83
src/map/IMG/bitstream.cpp
Normal file
83
src/map/IMG/bitstream.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include "bitstream.h"
|
||||
|
||||
|
||||
bool BitStream1::read(int bits, quint32 &val)
|
||||
{
|
||||
val = 0;
|
||||
|
||||
for (int pos = 0; pos < bits; ) {
|
||||
if (!_remaining) {
|
||||
if (!_length || !_file.readUInt8(_hdl, _data))
|
||||
return false;
|
||||
_remaining = 8;
|
||||
_length--;
|
||||
}
|
||||
|
||||
quint32 get = bits - pos;
|
||||
if (get >= _remaining) {
|
||||
val |= _data << pos;
|
||||
pos += _remaining;
|
||||
_remaining = 0;
|
||||
} else {
|
||||
quint32 mask = (1<<get) - 1;
|
||||
val |= (_data & mask)<<pos;
|
||||
_data >>= get;
|
||||
_remaining -= get;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitStream1::flush()
|
||||
{
|
||||
if (_length && !_file.seek(_hdl, _hdl.pos + _length))
|
||||
return false;
|
||||
|
||||
_length = 0;
|
||||
_remaining = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool BitStream4::read(int bits, quint32 &val)
|
||||
{
|
||||
if (bits <= 32 - (int)(_used + _unused)) {
|
||||
val = bits ? (_data << _used) >> (32 - bits) : 0;
|
||||
_used += bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
quint32 old = 0;
|
||||
if (_used < 32) {
|
||||
old = (_data << _used) >> (32 - bits);
|
||||
bits = (bits - 32) + _used;
|
||||
}
|
||||
_used = bits;
|
||||
|
||||
quint32 bytes = qMin(_length, (quint32)4);
|
||||
|
||||
if (!_file.readVUInt32SW(_hdl, bytes, _data))
|
||||
return false;
|
||||
|
||||
_length -= bytes;
|
||||
_unused = (4 - bytes) * 8;
|
||||
_data <<= _unused;
|
||||
|
||||
val = _data >> (32 - _used) | old;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitStream4::flush()
|
||||
{
|
||||
if (_length && !_file.seek(_hdl, _hdl.pos + _length))
|
||||
return false;
|
||||
|
||||
_length = 0;
|
||||
_unused = 32;
|
||||
|
||||
return true;
|
||||
}
|
39
src/map/IMG/bitstream.h
Normal file
39
src/map/IMG/bitstream.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef BITSTREAM_H
|
||||
#define BITSTREAM_H
|
||||
|
||||
#include "subfile.h"
|
||||
|
||||
class BitStream1 {
|
||||
public:
|
||||
BitStream1(const SubFile &file, SubFile::Handle &hdl, quint32 length)
|
||||
: _file(file), _hdl(hdl), _length(length), _remaining(0) {}
|
||||
|
||||
bool read(int bits, quint32 &val);
|
||||
bool flush();
|
||||
quint32 bitsAvailable() const {return _length * 8 + _remaining;}
|
||||
|
||||
private:
|
||||
const SubFile &_file;
|
||||
SubFile::Handle &_hdl;
|
||||
quint32 _length, _remaining;
|
||||
quint8 _data;
|
||||
};
|
||||
|
||||
class BitStream4 {
|
||||
public:
|
||||
BitStream4(const SubFile &file, SubFile::Handle &hdl, quint32 length)
|
||||
: _file(file), _hdl(hdl), _length(length), _used(32), _unused(0),
|
||||
_data(0) {}
|
||||
|
||||
bool read(int bits, quint32 &val);
|
||||
bool flush();
|
||||
quint32 bitsAvailable() const {return _length * 8 + (32 - _used) - _unused;}
|
||||
|
||||
private:
|
||||
const SubFile &_file;
|
||||
SubFile::Handle &_hdl;
|
||||
quint32 _length, _used, _unused;
|
||||
quint32 _data;
|
||||
};
|
||||
|
||||
#endif // BITSTREAM_H
|
86
src/map/IMG/deltastream.cpp
Normal file
86
src/map/IMG/deltastream.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include "deltastream.h"
|
||||
|
||||
|
||||
static int bitSize(quint8 baseSize, bool variableSign, bool extraBit)
|
||||
{
|
||||
int bits = 2;
|
||||
if (baseSize <= 9)
|
||||
bits += baseSize;
|
||||
else
|
||||
bits += 2 * baseSize - 9;
|
||||
|
||||
if (variableSign)
|
||||
bits++;
|
||||
if (extraBit)
|
||||
bits++;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
DeltaStream::DeltaStream(const SubFile &file, SubFile::Handle &hdl,
|
||||
quint32 length, quint8 info, bool extraBit, bool extended)
|
||||
: BitStream1(file, hdl, length), _readBits(0xFFFFFFFF)
|
||||
{
|
||||
_extraBit = extraBit ? 1 : 0;
|
||||
if (!(sign(_lonSign) && sign(_latSign)))
|
||||
return;
|
||||
if (extended) {
|
||||
quint32 b;
|
||||
if (!read(1, b))
|
||||
return;
|
||||
}
|
||||
_lonBits = bitSize(info & 0x0F, !_lonSign, extraBit);
|
||||
_latBits = bitSize(info >> 4, !_latSign, false);
|
||||
_readBits = _lonBits + _latBits;
|
||||
}
|
||||
|
||||
bool DeltaStream::readDelta(int bits, int sign, int extraBit,
|
||||
qint32 &delta)
|
||||
{
|
||||
quint32 value;
|
||||
|
||||
if (!read(bits, value))
|
||||
return false;
|
||||
|
||||
value >>= extraBit;
|
||||
|
||||
if (!sign) {
|
||||
qint32 signMask = 1 << (bits - extraBit - 1);
|
||||
if (value & signMask) {
|
||||
qint32 comp = value ^ signMask;
|
||||
if (comp)
|
||||
delta = comp - signMask;
|
||||
else {
|
||||
qint32 other;
|
||||
if (!readDelta(bits - extraBit, sign, false, other))
|
||||
return false;
|
||||
if (other < 0)
|
||||
delta = 1 - signMask + other;
|
||||
else
|
||||
delta = signMask - 1 + other;
|
||||
}
|
||||
} else {
|
||||
delta = value;
|
||||
}
|
||||
} else {
|
||||
delta = value * sign;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeltaStream::sign(int &val)
|
||||
{
|
||||
quint32 bit;
|
||||
val = 0;
|
||||
|
||||
if (!read(1, bit))
|
||||
return false;
|
||||
if (bit) {
|
||||
if (!read(1, bit))
|
||||
return false;
|
||||
val = bit ? -1 : 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
28
src/map/IMG/deltastream.h
Normal file
28
src/map/IMG/deltastream.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef DELTASTREAM_H
|
||||
#define DELTASTREAM_H
|
||||
|
||||
#include "bitstream.h"
|
||||
|
||||
class DeltaStream : public BitStream1 {
|
||||
public:
|
||||
DeltaStream(const SubFile &file, SubFile::Handle &hdl, quint32 length,
|
||||
quint8 info, bool extraBit, bool extended);
|
||||
|
||||
bool readNext(qint32 &lonDelta, qint32 &latDelta)
|
||||
{
|
||||
return hasNext()
|
||||
? (readDelta(_lonBits, _lonSign, _extraBit, lonDelta)
|
||||
&& readDelta(_latBits, _latSign, false, latDelta)) : false;
|
||||
}
|
||||
bool atEnd() const {return (_readBits != 0xFFFFFFFF && !hasNext());}
|
||||
|
||||
private:
|
||||
bool hasNext() const {return bitsAvailable() >= _readBits;}
|
||||
bool sign(int &val);
|
||||
bool readDelta(int bits, int sign, int extraBit, qint32 &delta);
|
||||
|
||||
int _lonSign, _latSign, _extraBit;
|
||||
quint32 _lonBits, _latBits, _readBits;
|
||||
};
|
||||
|
||||
#endif // DELTASTREAM_H
|
101
src/map/IMG/huffmanstream.cpp
Normal file
101
src/map/IMG/huffmanstream.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include "huffmanstream.h"
|
||||
|
||||
|
||||
HuffmanStream::HuffmanStream(const SubFile &file, SubFile::Handle &hdl,
|
||||
quint32 length, const HuffmanTable &table, bool line)
|
||||
: BitStream4(file, hdl, length), _table(table), _symbolDataSize(0),
|
||||
_symbolData(0)
|
||||
{
|
||||
if (line) {
|
||||
if (!(sign(_lonSign) && sign(_latSign)))
|
||||
return;
|
||||
} else {
|
||||
_lonSign = 0;
|
||||
_latSign = 0;
|
||||
}
|
||||
|
||||
quint32 eb;
|
||||
if (!read(1, eb))
|
||||
return;
|
||||
if (eb) {
|
||||
qWarning("Extended polygon/lines not supported");
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
bool HuffmanStream::readNext(qint32 &lonDelta, qint32 &latDelta)
|
||||
{
|
||||
if (!readDelta(_lonSign, lonDelta))
|
||||
return false;
|
||||
if (!readDelta(_latSign, latDelta))
|
||||
return false;
|
||||
|
||||
if (!(lonDelta|latDelta))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HuffmanStream::readOffset(qint32 &lonDelta, qint32 &latDelta)
|
||||
{
|
||||
if (!readDelta(1, lonDelta))
|
||||
return false;
|
||||
if (!readDelta(1, latDelta))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HuffmanStream::sign(int &val)
|
||||
{
|
||||
quint32 bit;
|
||||
val = 0;
|
||||
|
||||
if (!read(1, bit))
|
||||
return false;
|
||||
if (bit) {
|
||||
if (!read(1, bit))
|
||||
return false;
|
||||
val = bit ? -1 : 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HuffmanStream::readDelta(int sign, qint32 &symbol)
|
||||
{
|
||||
uchar size;
|
||||
|
||||
if (_symbolDataSize < 32) {
|
||||
quint32 next;
|
||||
quint8 nextSize = qMin((quint32)(32 - _symbolDataSize),
|
||||
bitsAvailable());
|
||||
|
||||
if (!read(nextSize, next))
|
||||
return false;
|
||||
|
||||
_symbolData = (_symbolData << nextSize) | next;
|
||||
_symbolDataSize += nextSize;
|
||||
}
|
||||
|
||||
symbol = _table.symbol(_symbolData << (32U - _symbolDataSize), size);
|
||||
|
||||
if (size <= _symbolDataSize)
|
||||
_symbolDataSize -= size;
|
||||
else
|
||||
return false;
|
||||
|
||||
if (symbol && !sign) {
|
||||
if (!_symbolDataSize)
|
||||
return false;
|
||||
else {
|
||||
sign = ((1U << (_symbolDataSize - 1)) & _symbolData) ? -1 : 1;
|
||||
_symbolDataSize--;
|
||||
}
|
||||
}
|
||||
symbol = sign * symbol;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
27
src/map/IMG/huffmanstream.h
Normal file
27
src/map/IMG/huffmanstream.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef HUFFMANSTREAM_H
|
||||
#define HUFFMANSTREAM_H
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "huffmantable.h"
|
||||
|
||||
class HuffmanStream : public BitStream4 {
|
||||
public:
|
||||
HuffmanStream(const SubFile &file, SubFile::Handle &hdl, quint32 length,
|
||||
const HuffmanTable &table, bool line);
|
||||
|
||||
bool readNext(qint32 &lonDelta, qint32 &latDelta);
|
||||
bool readOffset(qint32 &lonDelta, qint32 &latDelta);
|
||||
bool atEnd() const
|
||||
{return _symbolDataSize + bitsAvailable() < _table.maxSymbolSize();}
|
||||
|
||||
private:
|
||||
bool sign(int &val);
|
||||
bool readDelta(int sign, qint32 &delta);
|
||||
|
||||
const HuffmanTable &_table;
|
||||
quint32 _symbolDataSize;
|
||||
quint32 _symbolData;
|
||||
int _lonSign, _latSign;
|
||||
};
|
||||
|
||||
#endif // HUFFMANSTREAM_H
|
139
src/map/IMG/huffmantable.cpp
Normal file
139
src/map/IMG/huffmantable.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
#include "huffmantable.h"
|
||||
|
||||
|
||||
static quint8 vs(const quint8 b0)
|
||||
{
|
||||
static const quint8 sizes[] = {4, 1, 2, 1, 3, 1, 2, 1};
|
||||
return sizes[b0 & 0x07];
|
||||
}
|
||||
|
||||
static inline quint8 bs(const quint8 val)
|
||||
{
|
||||
return (val + 7) >> 3;
|
||||
}
|
||||
|
||||
static inline quint32 readVUint32(const quint8 *buffer, quint32 bytes)
|
||||
{
|
||||
quint32 val = 0;
|
||||
|
||||
for (quint32 i = bytes; i; i--)
|
||||
val |= ((quint32)*(buffer + i)) << ((i-1) * 8);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
bool HuffmanTable::load(const SubFile &file, SubFile::Handle &hdl,
|
||||
quint32 offset, quint32 size, quint32 id)
|
||||
{
|
||||
if (!getBuffer(file, hdl, offset, size, id))
|
||||
return false;
|
||||
|
||||
_s0 = (quint8)_buffer.at(0) & 0x0F;
|
||||
_s1e = (quint8)_buffer.at(0) & 0x10 ? 1 : 8;
|
||||
_s2 = (quint8)_buffer.at(1);
|
||||
_s3 = bs(_s2);
|
||||
_s1d = (quint8)_buffer.at(2);
|
||||
_s1f = (quint8)_buffer.at(3);
|
||||
_s20 = bs(_s1f);
|
||||
_s1 = _s20 + 1;
|
||||
_s22 = vs(_buffer.at(4));
|
||||
_s1c = _s3 + 1 + _s22;
|
||||
_s14 = (quint8*)(_buffer.data()) + 4 + _s22;
|
||||
_s10 = _s14 + _s1c * _s1d;
|
||||
_s18 = _s10 + (_s1 << _s0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HuffmanTable::getBuffer(const SubFile &file, SubFile::Handle &hdl,
|
||||
quint32 offset, quint32 size, quint8 id)
|
||||
{
|
||||
quint32 recordSize, recordOffset = offset;
|
||||
|
||||
for (int i = 0; i <= id; i++) {
|
||||
if (!file.seek(hdl, recordOffset))
|
||||
return false;
|
||||
if (!file.readVUInt32(hdl, recordSize))
|
||||
return false;
|
||||
recordOffset = hdl.pos + recordSize;
|
||||
if (recordOffset > offset + size)
|
||||
return false;
|
||||
};
|
||||
|
||||
_buffer.resize(recordSize);
|
||||
for (int i = 0; i < _buffer.size(); i++)
|
||||
if (!file.readUInt8(hdl, *((quint8*)(_buffer.data() + i))))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
quint32 HuffmanTable::symbol(quint32 data, quint8 &size) const
|
||||
{
|
||||
quint32 ss, sym;
|
||||
quint8 *tp;
|
||||
|
||||
|
||||
if (_s0 == 0) {
|
||||
sym = _s1d - 1;
|
||||
ss = 0;
|
||||
} else {
|
||||
quint32 offset = _s1 * (data >> (0x20U - _s0));
|
||||
tp = _s10 + offset;
|
||||
|
||||
if ((*tp & 1) != 0) {
|
||||
sym = readVUint32(tp, _s20);
|
||||
size = *tp >> 1;
|
||||
return sym;
|
||||
}
|
||||
|
||||
ss = *tp >> 1;
|
||||
sym = tp[1];
|
||||
}
|
||||
|
||||
tp = ss * _s1c + _s14;
|
||||
data = data >> (0x20U - _s2);
|
||||
|
||||
quint8 *prev = tp;
|
||||
while (ss < sym) {
|
||||
quint32 cnt = (ss + 1 + sym) >> 1;
|
||||
tp = _s14 + (cnt * _s1c);
|
||||
quint32 nd = readVUint32(tp - 1, _s3);
|
||||
|
||||
if (data <= nd) {
|
||||
if (data == nd)
|
||||
ss = cnt;
|
||||
else
|
||||
tp = prev;
|
||||
|
||||
sym = cnt - (data < nd);
|
||||
cnt = ss;
|
||||
}
|
||||
ss = cnt;
|
||||
prev = tp;
|
||||
}
|
||||
|
||||
sym = readVUint32(tp - 1, _s3);
|
||||
tp = tp + _s3;
|
||||
ss = readVUint32(tp, _s22);
|
||||
size = *tp;
|
||||
sym = (data - sym) >> (_s2 - *tp);
|
||||
|
||||
if (_s1e == 8)
|
||||
sym = readVUint32(tp, _s20);
|
||||
else {
|
||||
sym = (sym + ss) * _s1f;
|
||||
ss = sym >> 3;
|
||||
sym = sym & 7;
|
||||
quint32 shift = 8 - sym;
|
||||
sym = *(_s18 + ss) >> sym;
|
||||
|
||||
if (shift < _s1f) {
|
||||
tp = _s18 + ss;
|
||||
ss = readVUint32(tp, ((_s1f + 7) - shift) >> 3);
|
||||
sym = (ss << shift) | sym;
|
||||
}
|
||||
}
|
||||
|
||||
return sym;
|
||||
}
|
27
src/map/IMG/huffmantable.h
Normal file
27
src/map/IMG/huffmantable.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef HUFFMANTABLE_H
|
||||
#define HUFFMANTABLE_H
|
||||
|
||||
#include "subfile.h"
|
||||
|
||||
class HuffmanTable {
|
||||
public:
|
||||
HuffmanTable() : _s2(0) {}
|
||||
|
||||
bool load(const SubFile &file, SubFile::Handle &hdl, quint32 offset,
|
||||
quint32 size, quint32 id);
|
||||
bool isNull() const {return _s2 == 0;}
|
||||
quint8 maxSymbolSize() const {return _s2;}
|
||||
quint32 symbol(quint32 data, quint8 &size) const;
|
||||
|
||||
private:
|
||||
bool getBuffer(const SubFile &file, SubFile::Handle &hdl, quint32 offset,
|
||||
quint32 size, quint8 id);
|
||||
|
||||
QByteArray _buffer;
|
||||
quint8 _s0, _s1, _s2, _s3;
|
||||
quint8 *_s10, *_s14, *_s18;
|
||||
quint8 _s1c, _s1d, _s1e, _s1f, _s20;
|
||||
quint16 _s22;
|
||||
};
|
||||
|
||||
#endif // HUFFMANTABLE_H
|
@ -1,4 +1,4 @@
|
||||
#include <QSet>
|
||||
#include <QMap>
|
||||
#include <QtEndian>
|
||||
#include "common/programpaths.h"
|
||||
#include "vectortile.h"
|
||||
@ -110,8 +110,8 @@ IMG::IMG(const QString &fileName)
|
||||
QString fn(QByteArray(name, sizeof(name)));
|
||||
if (VectorTile::isTileFile(tt)) {
|
||||
VectorTile *tile;
|
||||
QMap<QString, VectorTile*>::iterator it = tileMap.find(fn);
|
||||
if (it == tileMap.end()) {
|
||||
TileMap::const_iterator it = tileMap.find(fn);
|
||||
if (it == tileMap.constEnd()) {
|
||||
tile = new VectorTile();
|
||||
tileMap.insert(fn, tile);
|
||||
} else
|
||||
@ -152,7 +152,8 @@ IMG::IMG(const QString &fileName)
|
||||
}
|
||||
|
||||
// Create tile tree
|
||||
for (TileMap::iterator it = tileMap.begin(); it != tileMap.end(); ++it) {
|
||||
for (TileMap::const_iterator it = tileMap.constBegin();
|
||||
it != tileMap.constEnd(); ++it) {
|
||||
VectorTile *tile = it.value();
|
||||
|
||||
if (!tile->init()) {
|
||||
|
@ -56,10 +56,10 @@ bool LBLFile::init(Handle &hdl)
|
||||
quint8 multiplier, poiMultiplier;
|
||||
|
||||
if (!(seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
|
||||
&& readUInt32(hdl, _size) && readByte(hdl, multiplier)
|
||||
&& readByte(hdl, _encoding) && seek(hdl, _gmpOffset + 0x57)
|
||||
&& readUInt32(hdl, _size) && readUInt8(hdl, multiplier)
|
||||
&& readUInt8(hdl, _encoding) && seek(hdl, _gmpOffset + 0x57)
|
||||
&& readUInt32(hdl, _poiOffset) && readUInt32(hdl, _poiSize)
|
||||
&& readByte(hdl, poiMultiplier) && seek(hdl, _gmpOffset + 0xAA)
|
||||
&& readUInt8(hdl, poiMultiplier) && seek(hdl, _gmpOffset + 0xAA)
|
||||
&& readUInt16(hdl, codepage)))
|
||||
return false;
|
||||
|
||||
@ -89,7 +89,7 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset) const
|
||||
return Label();
|
||||
|
||||
while (true) {
|
||||
if (!(readByte(hdl, b1) && readByte(hdl, b2) && readByte(hdl, b3)))
|
||||
if (!(readUInt8(hdl, b1) && readUInt8(hdl, b2) && readUInt8(hdl, b3)))
|
||||
return Label();
|
||||
|
||||
int c[]= {b1>>2, (b1&0x3)<<4|b2>>4, (b2&0xF)<<2|b3>>6, b3&0x3F};
|
||||
@ -138,7 +138,7 @@ Label LBLFile::label8b(Handle &hdl, quint32 offset) const
|
||||
return Label();
|
||||
|
||||
while (true) {
|
||||
if (!readByte(hdl, c))
|
||||
if (!readUInt8(hdl, c))
|
||||
return Label();
|
||||
if (!c || c == 0x1d)
|
||||
break;
|
||||
|
@ -3,9 +3,11 @@
|
||||
bool NETFile::init(Handle &hdl)
|
||||
{
|
||||
quint8 multiplier;
|
||||
quint16 hdrLen;
|
||||
|
||||
if (!(seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
|
||||
&& readUInt32(hdl, _size) && readByte(hdl, multiplier)))
|
||||
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
|
||||
&& seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
|
||||
&& readUInt32(hdl, _size) && readUInt8(hdl, multiplier)))
|
||||
return false;
|
||||
|
||||
_multiplier = 1<<multiplier;
|
||||
|
@ -15,8 +15,7 @@ public:
|
||||
private:
|
||||
bool init(Handle &hdl);
|
||||
|
||||
quint32 _offset;
|
||||
quint32 _size;
|
||||
quint32 _offset, _size;
|
||||
quint8 _multiplier;
|
||||
};
|
||||
|
||||
|
@ -1,123 +1,81 @@
|
||||
#include <cstring>
|
||||
#include "common/rectc.h"
|
||||
#include "common/garmin.h"
|
||||
#include "deltastream.h"
|
||||
#include "huffmanstream.h"
|
||||
#include "lblfile.h"
|
||||
#include "netfile.h"
|
||||
#include "rgnfile.h"
|
||||
|
||||
|
||||
static int bitSize(quint8 baseSize, bool variableSign, bool extraBit)
|
||||
bool RGNFile::skipClassFields(Handle &hdl) const
|
||||
{
|
||||
int bits = 2;
|
||||
if (baseSize <= 9)
|
||||
bits += baseSize;
|
||||
else
|
||||
bits += 2 * baseSize - 9;
|
||||
quint8 flags;
|
||||
quint32 rs;
|
||||
|
||||
if (variableSign)
|
||||
bits++;
|
||||
if (extraBit)
|
||||
bits++;
|
||||
if (!readUInt8(hdl, flags))
|
||||
return false;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
bool RGNFile::BitStream::read(int bits, quint32 &val)
|
||||
{
|
||||
val = 0;
|
||||
|
||||
for (int pos = 0; pos < bits; ) {
|
||||
if (!_remaining) {
|
||||
if (!_length || !_file.readByte(_hdl, _data))
|
||||
return false;
|
||||
_remaining = 8;
|
||||
_length--;
|
||||
}
|
||||
|
||||
quint32 get = bits - pos;
|
||||
if (get >= _remaining) {
|
||||
val |= _data << pos;
|
||||
pos += _remaining;
|
||||
_remaining = 0;
|
||||
} else {
|
||||
quint32 mask = (1<<get) - 1;
|
||||
val |= (_data & mask)<<pos;
|
||||
_data >>= get;
|
||||
_remaining -= get;
|
||||
switch (flags >> 5) {
|
||||
case 4:
|
||||
rs = 1;
|
||||
break;
|
||||
case 5:
|
||||
rs = 2;
|
||||
break;
|
||||
case 6:
|
||||
rs = 3;
|
||||
break;
|
||||
case 7:
|
||||
if (!readVUInt32(hdl, rs))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
rs = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return seek(hdl, hdl.pos + rs);
|
||||
}
|
||||
|
||||
RGNFile::DeltaStream::DeltaStream(const SubFile &file, Handle &hdl,
|
||||
quint32 length, quint8 info, bool extraBit, bool extended)
|
||||
: BitStream(file, hdl, length), _readBits(0xFFFFFFFF)
|
||||
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
|
||||
Segment::Type type) const
|
||||
{
|
||||
_extraBit = extraBit ? 1 : 0;
|
||||
if (!(sign(_lonSign) && sign(_latSign)))
|
||||
return;
|
||||
if (extended) {
|
||||
quint32 b;
|
||||
if (!read(1, b))
|
||||
return;
|
||||
}
|
||||
_lonBits = bitSize(info & 0x0F, !_lonSign, extraBit);
|
||||
_latBits = bitSize(info >> 4, !_latSign, false);
|
||||
_readBits = _lonBits + _latBits;
|
||||
}
|
||||
quint32 bitfield = 0xFFFFFFFF;
|
||||
|
||||
bool RGNFile::DeltaStream::readDelta(int bits, int sign, int extraBit,
|
||||
qint32 &delta)
|
||||
{
|
||||
quint32 value;
|
||||
|
||||
if (!read(bits, value))
|
||||
return false;
|
||||
|
||||
value >>= extraBit;
|
||||
|
||||
if (!sign) {
|
||||
qint32 signMask = 1 << (bits - extraBit - 1);
|
||||
if (value & signMask) {
|
||||
qint32 comp = value ^ signMask;
|
||||
if (comp)
|
||||
delta = comp - signMask;
|
||||
else {
|
||||
qint32 other;
|
||||
if (!readDelta(bits - extraBit, sign, false, other))
|
||||
return false;
|
||||
if (other < 0)
|
||||
delta = 1 - signMask + other;
|
||||
else
|
||||
delta = signMask - 1 + other;
|
||||
}
|
||||
} else {
|
||||
delta = value;
|
||||
}
|
||||
} else {
|
||||
delta = value * sign;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RGNFile::DeltaStream::sign(int &val)
|
||||
{
|
||||
quint32 bit;
|
||||
val = 0;
|
||||
|
||||
if (!read(1, bit))
|
||||
return false;
|
||||
if (bit) {
|
||||
if (!read(1, bit))
|
||||
if (flags[0] & 0x20000000)
|
||||
if (!readVBitfield32(hdl, bitfield))
|
||||
return false;
|
||||
val = bit ? -1 : 1;
|
||||
|
||||
for (int i = 0; i < 29; i++) {
|
||||
if ((flags[0] >> i) & 1) {
|
||||
if (bitfield & 1) {
|
||||
quint32 m = flags[(i >> 4) + 1] >> ((i * 2) & 0x1e) & 3;
|
||||
switch (i) {
|
||||
case 5:
|
||||
if (m == 1 && type == Segment::Point) {
|
||||
quint16 u16;
|
||||
if (!readUInt16(hdl, u16))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
bitfield >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RGNFile::clearFlags()
|
||||
{
|
||||
memset(_polygonsFlags, 0, sizeof(_polygonsFlags));
|
||||
memset(_linesFlags, 0, sizeof(_linesFlags));
|
||||
memset(_pointsFlags, 0, sizeof(_pointsFlags));
|
||||
}
|
||||
|
||||
bool RGNFile::init(Handle &hdl)
|
||||
{
|
||||
@ -128,25 +86,29 @@ bool RGNFile::init(Handle &hdl)
|
||||
&& readUInt32(hdl, _size)))
|
||||
return false;
|
||||
|
||||
if (hdrLen >= 0x5D) {
|
||||
if (hdrLen >= 0x68) {
|
||||
if (!(readUInt32(hdl, _polygonsOffset) && readUInt32(hdl, _polygonsSize)
|
||||
&& seek(hdl, _gmpOffset + 0x39) && readUInt32(hdl, _linesOffset)
|
||||
&& readUInt32(hdl, _linesSize) && seek(hdl, _gmpOffset + 0x55)
|
||||
&& readUInt32(hdl, _pointsOffset) && readUInt32(hdl, _pointsSize)))
|
||||
&& seek(hdl, _gmpOffset + 0x2D) && readUInt32(hdl, _polygonsFlags[0])
|
||||
&& readUInt32(hdl, _polygonsFlags[1]) && readUInt32(hdl, _polygonsFlags[2])
|
||||
&& readUInt32(hdl, _linesOffset) && readUInt32(hdl, _linesSize)
|
||||
&& seek(hdl, _gmpOffset + 0x49) && readUInt32(hdl, _linesFlags[0])
|
||||
&& readUInt32(hdl, _linesFlags[1]) && readUInt32(hdl, _linesFlags[2])
|
||||
&& readUInt32(hdl, _pointsOffset) && readUInt32(hdl, _pointsSize)
|
||||
&& seek(hdl, _gmpOffset + 0x65) && readUInt32(hdl, _pointsFlags[0])
|
||||
&& readUInt32(hdl, _pointsFlags[1]) && readUInt32(hdl, _pointsFlags[2])))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hdrLen >= 0x7D) {
|
||||
quint32 dictOffset, dictSize;
|
||||
quint32 dictOffset, dictSize, info;
|
||||
if (!(seek(hdl, _gmpOffset + 0x71) && readUInt32(hdl, dictOffset)
|
||||
&& readUInt32(hdl, dictSize)))
|
||||
&& readUInt32(hdl, dictSize) && readUInt32(hdl, info)))
|
||||
return false;
|
||||
|
||||
// NT maps
|
||||
if (dictSize || dictOffset) {
|
||||
qWarning("NT compression not supported");
|
||||
return false;
|
||||
}
|
||||
if (dictSize && dictOffset && (info & 0x1E))
|
||||
if (!_huffmanTable.load(*this, hdl, dictOffset, dictSize,
|
||||
((info >> 1) & 0xF) - 1))
|
||||
return false;
|
||||
}
|
||||
|
||||
_init = true;
|
||||
@ -158,9 +120,6 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net,
|
||||
Handle &netHdl, QList<IMG::Poly> *polys) const
|
||||
{
|
||||
if (segment.start() == segment.end())
|
||||
return true;
|
||||
|
||||
if (!seek(hdl, segment.start()))
|
||||
return false;
|
||||
|
||||
@ -172,18 +131,18 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
while (hdl.pos < (int)segment.end()) {
|
||||
IMG::Poly poly;
|
||||
|
||||
if (!(readByte(hdl, type) && readUInt24(hdl, labelPtr)
|
||||
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
|
||||
return false;
|
||||
if (type & 0x80) {
|
||||
if (!readUInt16(hdl, len))
|
||||
return false;
|
||||
} else {
|
||||
if (!readByte(hdl, len8))
|
||||
if (!readUInt8(hdl, len8))
|
||||
return false;
|
||||
len = len8;
|
||||
}
|
||||
if (!readByte(hdl, bitstreamInfo))
|
||||
if (!readUInt8(hdl, bitstreamInfo))
|
||||
return false;
|
||||
|
||||
poly.type = (segment.type() == Segment::Polygon)
|
||||
@ -230,11 +189,11 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
}
|
||||
|
||||
bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
||||
const SubDiv *subdiv, const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Poly> *polys) const
|
||||
const SubDiv *subdiv, quint32 shift, const Segment &segment, LBLFile *lbl,
|
||||
Handle &lblHdl, QList<IMG::Poly> *polys, bool line) const
|
||||
{
|
||||
quint32 len, labelPtr = 0;
|
||||
quint8 type, subtype, bitstreamInfo;
|
||||
quint32 labelPtr, len;
|
||||
quint8 type, subtype;
|
||||
qint16 lon, lat;
|
||||
|
||||
|
||||
@ -243,43 +202,78 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
||||
|
||||
while (hdl.pos < (int)segment.end()) {
|
||||
IMG::Poly poly;
|
||||
QPoint pos;
|
||||
RectC br;
|
||||
|
||||
if (!(readByte(hdl, type) && readByte(hdl, subtype)
|
||||
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)
|
||||
&& readVUInt32(hdl, len) && readByte(hdl, bitstreamInfo)))
|
||||
&& readVUInt32(hdl, len)))
|
||||
return false;
|
||||
|
||||
if (subtype & 0x80) {
|
||||
qWarning("Polygons/lines with extra bytes not supported");
|
||||
return false;
|
||||
}
|
||||
poly.type = 0x10000 | (quint16(type)<<8) | (subtype & 0x1F);
|
||||
labelPtr = 0;
|
||||
|
||||
poly.type = 0x10000 + (quint16(type) << 8) + (subtype & 0x1F);
|
||||
if (!_huffmanTable.isNull()) {
|
||||
pos = QPoint((subdiv->lon()<<8) + ((qint32)lon<<(32-subdiv->bits())),
|
||||
(subdiv->lat()<<8) + ((qint32)lat<<(32-subdiv->bits())));
|
||||
|
||||
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
RectC br(c, c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
qint32 lonDelta, latDelta;
|
||||
HuffmanStream stream(*this, hdl, len, _huffmanTable, line);
|
||||
|
||||
qint32 lonDelta, latDelta;
|
||||
DeltaStream stream(*this, hdl, len - 1, bitstreamInfo, false, true);
|
||||
while (stream.readNext(lonDelta, latDelta)) {
|
||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
if (shift) {
|
||||
if (!stream.readOffset(lonDelta, latDelta))
|
||||
return false;
|
||||
pos = QPoint(pos.x() | lonDelta<<(32-subdiv->bits()-shift),
|
||||
pos.y() | latDelta<<(32-subdiv->bits()-shift));
|
||||
}
|
||||
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
|
||||
br = RectC(c, c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
br = br.united(c);
|
||||
}
|
||||
if (!(stream.atEnd() && stream.flush()))
|
||||
return false;
|
||||
|
||||
if ((subtype & 0x20)) {
|
||||
if (!readUInt24(hdl, labelPtr))
|
||||
while (stream.readNext(lonDelta, latDelta)) {
|
||||
pos.rx() += lonDelta<<(32-subdiv->bits()-shift);
|
||||
pos.ry() += latDelta<<(32-subdiv->bits()-shift);
|
||||
|
||||
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
br = br.united(c);
|
||||
}
|
||||
|
||||
if (!(stream.atEnd() && stream.flush()))
|
||||
return false;
|
||||
} else
|
||||
labelPtr = 0;
|
||||
} else {
|
||||
pos = QPoint(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
br = RectC(c, c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
|
||||
quint8 bitstreamInfo;
|
||||
if (!readUInt8(hdl, bitstreamInfo))
|
||||
return false;
|
||||
|
||||
qint32 lonDelta, latDelta;
|
||||
DeltaStream stream(*this, hdl, len - 1, bitstreamInfo, false, true);
|
||||
|
||||
while (stream.readNext(lonDelta, latDelta)) {
|
||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
br = br.united(c);
|
||||
}
|
||||
if (!(stream.atEnd() && stream.flush()))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (subtype & 0x20 && !readUInt24(hdl, labelPtr))
|
||||
return false;
|
||||
if (subtype & 0x80 && !skipClassFields(hdl))
|
||||
return false;
|
||||
if (subtype & 0x40 && !skipLclFields(hdl, line ? _linesFlags
|
||||
: _polygonsFlags, segment.type()))
|
||||
return false;
|
||||
|
||||
if (!rect.intersects(br))
|
||||
continue;
|
||||
@ -307,11 +301,11 @@ bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
while (hdl.pos < (int)segment.end()) {
|
||||
IMG::Point point;
|
||||
|
||||
if (!(readByte(hdl, type) && readUInt24(hdl, labelPtr)
|
||||
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
|
||||
return false;
|
||||
if (labelPtr & 0x800000) {
|
||||
if (!readByte(hdl, subtype))
|
||||
if (!readUInt8(hdl, subtype))
|
||||
return false;
|
||||
} else
|
||||
subtype = 0;
|
||||
@ -340,8 +334,8 @@ bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
}
|
||||
|
||||
bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
|
||||
const SubDiv *subdiv, const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Point> *points) const
|
||||
const SubDiv *subdiv, const Segment &segment, LBLFile *lbl,
|
||||
Handle &lblHdl, QList<IMG::Point> *points) const
|
||||
{
|
||||
quint8 type, subtype;
|
||||
qint16 lon, lat;
|
||||
@ -353,97 +347,104 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
|
||||
while (hdl.pos < (int)segment.end()) {
|
||||
IMG::Point point;
|
||||
|
||||
if (!(readByte(hdl, type) && readByte(hdl, subtype)
|
||||
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
|
||||
return false;
|
||||
|
||||
if (subtype & 0x80) {
|
||||
qWarning("Points with extra bytes not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F);
|
||||
|
||||
qint16 lonOffset = lon<<(24-subdiv->bits());
|
||||
qint16 latOffset = lat<<(24-subdiv->bits());
|
||||
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
|
||||
toWGS24(subdiv->lat() + latOffset));
|
||||
labelPtr = 0;
|
||||
|
||||
if (subtype & 0x20) {
|
||||
if (!readUInt24(hdl, labelPtr))
|
||||
return false;
|
||||
point.poi = labelPtr & 0x400000;
|
||||
if (lbl && (labelPtr & 0x3FFFFF)) {
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
||||
point.id = ((quint64)point.type)<<40
|
||||
| ((quint64)lbl->offset())<<24 | (labelPtr & 0x3FFFFF);
|
||||
}
|
||||
if (subtype & 0x20 && !readUInt24(hdl, labelPtr))
|
||||
return false;
|
||||
if (subtype & 0x80 && !skipClassFields(hdl))
|
||||
return false;
|
||||
if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, segment.type()))
|
||||
return false;
|
||||
|
||||
if (!rect.contains(point.coordinates))
|
||||
continue;
|
||||
|
||||
point.poi = labelPtr & 0x400000;
|
||||
if (lbl && (labelPtr & 0x3FFFFF)) {
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
||||
point.id = ((quint64)point.type)<<40
|
||||
| ((quint64)lbl->offset())<<24 | (labelPtr & 0x3FFFFF);
|
||||
}
|
||||
|
||||
if (rect.contains(point.coordinates))
|
||||
points->append(point);
|
||||
points->append(point);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void RGNFile::objects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
|
||||
NETFile *net, QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
||||
QList<IMG::Point> *points)
|
||||
void RGNFile::objects(const RectC &rect, const SubDiv *subdiv,
|
||||
LBLFile *lbl, NETFile *net, QList<IMG::Poly> *polygons,
|
||||
QList<IMG::Poly> *lines, QList<IMG::Point> *points)
|
||||
{
|
||||
Handle rgnHdl, lblHdl, netHdl;
|
||||
|
||||
if (!_init && !init(rgnHdl))
|
||||
return;
|
||||
|
||||
QVector<RGNFile::Segment> seg(segments(rgnHdl, subdiv));
|
||||
QVector<Segment> seg(segments(rgnHdl, subdiv));
|
||||
|
||||
for (int i = 0; i < seg.size(); i++) {
|
||||
switch (seg.at(i).type()) {
|
||||
const Segment &segment = seg.at(i);
|
||||
|
||||
if (segment.start() == segment.end())
|
||||
continue;
|
||||
|
||||
switch (segment.type()) {
|
||||
case Segment::Point:
|
||||
case Segment::IndexedPoint:
|
||||
if (points)
|
||||
pointObjects(rect, rgnHdl, subdiv, seg.at(i), lbl, lblHdl,
|
||||
pointObjects(rect, rgnHdl, subdiv, segment, lbl, lblHdl,
|
||||
points);
|
||||
break;
|
||||
case Segment::Line:
|
||||
if (lines)
|
||||
polyObjects(rect, rgnHdl, subdiv, seg.at(i), lbl, lblHdl,
|
||||
net, netHdl, lines);
|
||||
polyObjects(rect, rgnHdl, subdiv, segment, lbl, lblHdl, net,
|
||||
netHdl, lines);
|
||||
break;
|
||||
case Segment::Polygon:
|
||||
if (polygons)
|
||||
polyObjects(rect, rgnHdl, subdiv, seg.at(i), lbl, lblHdl,
|
||||
net, netHdl, polygons);
|
||||
polyObjects(rect, rgnHdl, subdiv, segment, lbl, lblHdl, net,
|
||||
netHdl, polygons);
|
||||
break;
|
||||
case Segment::RoadReference:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RGNFile::extObjects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
|
||||
QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
||||
void RGNFile::extObjects(const RectC &rect, const SubDiv *subdiv, quint32 shift,
|
||||
LBLFile *lbl, QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
||||
QList<IMG::Point> *points)
|
||||
{
|
||||
Handle rgnHdl, lblHdl;
|
||||
|
||||
if (!_init && !init(rgnHdl))
|
||||
return;
|
||||
|
||||
if (polygons && subdiv->polygonsOffset() != subdiv->polygonsEnd()) {
|
||||
quint32 start = _polygonsOffset + subdiv->polygonsOffset();
|
||||
quint32 end = subdiv->polygonsEnd()
|
||||
? _polygonsOffset + subdiv->polygonsEnd()
|
||||
: _polygonsOffset + _polygonsSize;
|
||||
extPolyObjects(rect, rgnHdl, subdiv, Segment(start, end,
|
||||
Segment::Polygon), lbl, lblHdl, polygons);
|
||||
extPolyObjects(rect, rgnHdl, subdiv, shift, Segment(start, end,
|
||||
Segment::Polygon), lbl, lblHdl, polygons, false);
|
||||
}
|
||||
if (lines && subdiv->linesOffset() != subdiv->linesEnd()) {
|
||||
quint32 start = _linesOffset + subdiv->linesOffset();
|
||||
quint32 end = subdiv->linesEnd()
|
||||
? _linesOffset + subdiv->linesEnd()
|
||||
: _linesOffset + _linesSize;
|
||||
extPolyObjects(rect, rgnHdl, subdiv, Segment(start, end, Segment::Line),
|
||||
lbl, lblHdl, lines);
|
||||
extPolyObjects(rect, rgnHdl, subdiv, shift, Segment(start, end,
|
||||
Segment::Line), lbl, lblHdl, lines, true);
|
||||
}
|
||||
if (points && subdiv->pointsOffset() != subdiv->pointsEnd()) {
|
||||
quint32 start = _pointsOffset + subdiv->pointsOffset();
|
||||
@ -458,13 +459,13 @@ void RGNFile::extObjects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
|
||||
QVector<RGNFile::Segment> RGNFile::segments(Handle &hdl, const SubDiv *subdiv)
|
||||
const
|
||||
{
|
||||
if (subdiv->offset() == subdiv->end() || !(subdiv->objects() & 0xF0))
|
||||
if (subdiv->offset() == subdiv->end() || !(subdiv->objects() & 0x1F))
|
||||
return QVector<Segment>();
|
||||
|
||||
quint32 offset = _offset + subdiv->offset();
|
||||
|
||||
int no = 0;
|
||||
for (quint8 mask = 0x10; mask; mask <<= 1)
|
||||
for (quint8 mask = 0x1; mask <= 0x10; mask <<= 1)
|
||||
if (subdiv->objects() & mask)
|
||||
no++;
|
||||
|
||||
@ -476,7 +477,7 @@ QVector<RGNFile::Segment> RGNFile::segments(Handle &hdl, const SubDiv *subdiv)
|
||||
quint16 po;
|
||||
int cnt = 0;
|
||||
|
||||
for (quint8 mask = 0x10; mask; mask <<= 1) {
|
||||
for (quint16 mask = 0x1; mask <= 0x10; mask <<= 1) {
|
||||
if (subdiv->objects() & mask) {
|
||||
if (cnt) {
|
||||
if (!readUInt16(hdl, po))
|
||||
@ -498,8 +499,28 @@ QVector<RGNFile::Segment> RGNFile::segments(Handle &hdl, const SubDiv *subdiv)
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment)
|
||||
{
|
||||
QString type;
|
||||
switch (segment.type()) {
|
||||
case RGNFile::Segment::Point:
|
||||
type = "Point";
|
||||
break;
|
||||
case RGNFile::Segment::IndexedPoint:
|
||||
type = "IndexedPoint";
|
||||
break;
|
||||
case RGNFile::Segment::Line:
|
||||
type = "Line";
|
||||
break;
|
||||
case RGNFile::Segment::Polygon:
|
||||
type = "Polygon";
|
||||
break;
|
||||
case RGNFile::Segment::RoadReference:
|
||||
type = "RoadReference";
|
||||
break;
|
||||
}
|
||||
|
||||
dbg.nospace() << "Segment(" << segment.start() << ", " << segment.end()
|
||||
<< ", " << segment.type() << ")";
|
||||
- segment.start() << ", " << type << ")";
|
||||
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "img.h"
|
||||
#include "subfile.h"
|
||||
#include "subdiv.h"
|
||||
#include "huffmantable.h"
|
||||
|
||||
class LBLFile;
|
||||
class NETFile;
|
||||
@ -14,26 +15,28 @@ public:
|
||||
RGNFile(IMG *img)
|
||||
: SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
|
||||
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
|
||||
_pointsSize(0), _init(false) {}
|
||||
_pointsSize(0), _init(false) {clearFlags();}
|
||||
RGNFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), _offset(0),
|
||||
_size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0),
|
||||
_linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false) {}
|
||||
_linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false)
|
||||
{clearFlags();}
|
||||
|
||||
void objects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
|
||||
NETFile *net, QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
||||
QList<IMG::Point> *points);
|
||||
void extObjects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
|
||||
QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
||||
void objects(const RectC &rect, const SubDiv *subdiv,
|
||||
LBLFile *lbl, NETFile *net, QList<IMG::Poly> *polygons,
|
||||
QList<IMG::Poly> *lines, QList<IMG::Point> *points);
|
||||
void extObjects(const RectC &rect, const SubDiv *subdiv, quint32 shift,
|
||||
LBLFile *lbl, QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
||||
QList<IMG::Point> *points);
|
||||
|
||||
private:
|
||||
class Segment {
|
||||
public:
|
||||
enum Type {
|
||||
Point = 0x10,
|
||||
IndexedPoint = 0x20,
|
||||
Line = 0x40,
|
||||
Polygon = 0x80
|
||||
Point = 0x1,
|
||||
IndexedPoint = 0x2,
|
||||
Line = 0x4,
|
||||
Polygon = 0x8,
|
||||
RoadReference = 0x10
|
||||
};
|
||||
|
||||
Segment() : _start(0), _end(0), _type(Point) {}
|
||||
@ -54,45 +57,6 @@ private:
|
||||
Type _type;
|
||||
};
|
||||
|
||||
class BitStream {
|
||||
public:
|
||||
BitStream(const SubFile &file, Handle &hdl, quint32 length)
|
||||
: _file(file), _hdl(hdl), _length(length), _remaining(0) {}
|
||||
|
||||
bool read(int bits, quint32 &val);
|
||||
bool flush() {return _file.seek(_hdl, _hdl.pos + _length);}
|
||||
quint32 bitsAvailable() const {return _length * 8 + _remaining;}
|
||||
|
||||
private:
|
||||
const SubFile &_file;
|
||||
Handle &_hdl;
|
||||
quint32 _length, _remaining;
|
||||
quint8 _data;
|
||||
};
|
||||
|
||||
class DeltaStream : public BitStream {
|
||||
public:
|
||||
DeltaStream(const SubFile &file, Handle &hdl, quint32 length,
|
||||
quint8 info, bool extraBit, bool extended);
|
||||
|
||||
bool readNext(qint32 &lonDelta, qint32 &latDelta)
|
||||
{
|
||||
return hasNext()
|
||||
? (readDelta(_lonBits, _lonSign, _extraBit, lonDelta)
|
||||
&& readDelta(_latBits, _latSign, false, latDelta))
|
||||
: false;
|
||||
}
|
||||
bool atEnd() const {return (_readBits != 0xFFFFFFFF && !hasNext());}
|
||||
|
||||
private:
|
||||
bool hasNext() const {return bitsAvailable() >= _readBits;}
|
||||
bool sign(int &val);
|
||||
bool readDelta(int bits, int sign, int extraBit, qint32 &delta);
|
||||
|
||||
int _lonSign, _latSign, _extraBit;
|
||||
quint32 _lonBits, _latBits, _readBits;
|
||||
};
|
||||
|
||||
bool init(Handle &hdl);
|
||||
|
||||
QVector<Segment> segments(Handle &hdl, const SubDiv *subdiv) const;
|
||||
@ -103,12 +67,18 @@ private:
|
||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Point> *points) const;
|
||||
bool extPolyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Poly> *polys) const;
|
||||
quint32 shift, const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Poly> *polys, bool line) const;
|
||||
bool extPointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Point> *points) const;
|
||||
|
||||
void clearFlags();
|
||||
|
||||
bool skipClassFields(Handle &hdl) const;
|
||||
bool skipLclFields(Handle &hdl, const quint32 flags[3],
|
||||
Segment::Type type) const;
|
||||
|
||||
friend QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment);
|
||||
|
||||
quint32 _offset;
|
||||
@ -116,10 +86,15 @@ private:
|
||||
|
||||
quint32 _polygonsOffset;
|
||||
quint32 _polygonsSize;
|
||||
quint32 _polygonsFlags[3];
|
||||
quint32 _linesOffset;
|
||||
quint32 _linesSize;
|
||||
quint32 _linesFlags[3];
|
||||
quint32 _pointsOffset;
|
||||
quint32 _pointsSize;
|
||||
quint32 _pointsFlags[3];
|
||||
|
||||
HuffmanTable _huffmanTable;
|
||||
|
||||
bool _init;
|
||||
};
|
||||
|
@ -294,7 +294,7 @@ static bool readBitmap(SubFile *file, SubFile::Handle &hdl, QImage &img,
|
||||
for (int y = 0; y < img.height(); y++) {
|
||||
for (int x = 0; x < img.width(); x += 8/bpp) {
|
||||
quint8 color;
|
||||
if (!file->readByte(hdl, color))
|
||||
if (!file->readUInt8(hdl, color))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < 8/bpp && x + i < img.width(); i++) {
|
||||
@ -319,8 +319,8 @@ static bool readColor(SubFile *file, SubFile::Handle &hdl, QColor &color)
|
||||
{
|
||||
quint8 b, g, r;
|
||||
|
||||
if (!(file->readByte(hdl, b) && file->readByte(hdl, g)
|
||||
&& file->readByte(hdl, r)))
|
||||
if (!(file->readUInt8(hdl, b) && file->readUInt8(hdl, g)
|
||||
&& file->readUInt8(hdl, r)))
|
||||
return false;
|
||||
|
||||
color = qRgb(r, g, b);
|
||||
@ -333,14 +333,14 @@ static bool skipLocalization(SubFile *file, SubFile::Handle &hdl)
|
||||
quint8 t8;
|
||||
quint16 len;
|
||||
|
||||
if (!file->readByte(hdl, t8))
|
||||
if (!file->readUInt8(hdl, t8))
|
||||
return false;
|
||||
len = t8;
|
||||
|
||||
if (len & 0x01)
|
||||
len = len >> 1;
|
||||
else {
|
||||
if (!file->readByte(hdl, t8))
|
||||
if (!file->readUInt8(hdl, t8))
|
||||
return false;
|
||||
len = (((quint16)t8) << 8) | len;
|
||||
len = len >> 2;
|
||||
@ -361,7 +361,7 @@ bool Style::itemInfo(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
if (section.arrayItemSize == 5) {
|
||||
if (!(file->readUInt16(hdl, t16_1) && file->readUInt16(hdl, t16_2)
|
||||
&& file->readByte(hdl, t8)))
|
||||
&& file->readUInt8(hdl, t8)))
|
||||
return false;
|
||||
info.offset = t16_2 | (t8<<16);
|
||||
} else if (section.arrayItemSize == 4) {
|
||||
@ -369,7 +369,7 @@ bool Style::itemInfo(SubFile *file, SubFile::Handle &hdl,
|
||||
return false;
|
||||
info.offset = t16_2;
|
||||
} else if (section.arrayItemSize == 3) {
|
||||
if (!(file->readUInt16(hdl, t16_1) && file->readByte(hdl, t8)))
|
||||
if (!(file->readUInt16(hdl, t16_1) && file->readUInt8(hdl, t8)))
|
||||
return false;
|
||||
info.offset = t8;
|
||||
} else
|
||||
@ -400,7 +400,7 @@ bool Style::parsePolygons(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
quint8 t8, flags;
|
||||
if (!(file->seek(hdl, section.offset + info.offset)
|
||||
&& file->readByte(hdl, t8)))
|
||||
&& file->readUInt8(hdl, t8)))
|
||||
return false;
|
||||
flags = t8 & 0x0F;
|
||||
|
||||
@ -516,7 +516,7 @@ bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
quint8 t8_1, t8_2, flags, rows;
|
||||
if (!(file->seek(hdl, section.offset + info.offset)
|
||||
&& file->readByte(hdl, t8_1) && file->readByte(hdl, t8_2)))
|
||||
&& file->readUInt8(hdl, t8_1) && file->readUInt8(hdl, t8_2)))
|
||||
return false;
|
||||
flags = t8_1 & 0x07;
|
||||
rows = t8_1 >> 3;
|
||||
@ -541,7 +541,7 @@ bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!(file->readByte(hdl, w1) && file->readByte(hdl, w2)))
|
||||
if (!(file->readUInt8(hdl, w1) && file->readUInt8(hdl, w2)))
|
||||
return false;
|
||||
|
||||
_lines[type] = (w2 > w1)
|
||||
@ -568,7 +568,7 @@ bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!(file->readByte(hdl, w1) && file->readByte(hdl, w2)))
|
||||
if (!(file->readUInt8(hdl, w1) && file->readUInt8(hdl, w2)))
|
||||
return false;
|
||||
|
||||
_lines[type] = (w2 > w1)
|
||||
@ -595,7 +595,7 @@ bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!(file->readByte(hdl, w1) && file->readByte(hdl, w2)))
|
||||
if (!(file->readUInt8(hdl, w1) && file->readUInt8(hdl, w2)))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(QPen(c1, w1, Qt::SolidLine,
|
||||
@ -618,7 +618,7 @@ bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!(file->readByte(hdl, w1) && file->readByte(hdl, w2)))
|
||||
if (!(file->readUInt8(hdl, w1) && file->readUInt8(hdl, w2)))
|
||||
return false;
|
||||
|
||||
_lines[type] = (w2 > w1)
|
||||
@ -644,7 +644,7 @@ bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!file->readByte(hdl, w1))
|
||||
if (!file->readUInt8(hdl, w1))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(QPen(c1, w1, Qt::SolidLine,
|
||||
@ -666,7 +666,7 @@ bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!file->readByte(hdl, w1))
|
||||
if (!file->readUInt8(hdl, w1))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(QPen(c1, w1, Qt::SolidLine,
|
||||
@ -689,7 +689,7 @@ bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
if (textColor) {
|
||||
quint8 labelFlags;
|
||||
if (!file->readByte(hdl, labelFlags))
|
||||
if (!file->readUInt8(hdl, labelFlags))
|
||||
return false;
|
||||
if (labelFlags & 0x08) {
|
||||
if (!readColor(file, hdl, c1))
|
||||
@ -751,7 +751,7 @@ static bool readColorTable(SubFile *file, SubFile::Handle &hdl, QImage& img,
|
||||
|
||||
for (int i = 0; i < colors; i++) {
|
||||
while (bits < 28) {
|
||||
if (!file->readByte(hdl, byte))
|
||||
if (!file->readUInt8(hdl, byte))
|
||||
return false;
|
||||
|
||||
mask = 0x000000FF << bits;
|
||||
@ -801,9 +801,9 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
quint8 t8_1, width, height, numColors, imgType;
|
||||
if (!(file->seek(hdl, section.offset + info.offset)
|
||||
&& file->readByte(hdl, t8_1) && file->readByte(hdl, width)
|
||||
&& file->readByte(hdl, height) && file->readByte(hdl, numColors)
|
||||
&& file->readByte(hdl, imgType)))
|
||||
&& file->readUInt8(hdl, t8_1) && file->readUInt8(hdl, width)
|
||||
&& file->readUInt8(hdl, height) && file->readUInt8(hdl, numColors)
|
||||
&& file->readUInt8(hdl, imgType)))
|
||||
return false;
|
||||
|
||||
bool localization = t8_1 & 0x04;
|
||||
@ -820,8 +820,8 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
_points[type] = Point(img);
|
||||
|
||||
if (t8_1 == 0x03) {
|
||||
if (!(file->readByte(hdl, numColors)
|
||||
&& file->readByte(hdl, imgType)))
|
||||
if (!(file->readUInt8(hdl, numColors)
|
||||
&& file->readUInt8(hdl, imgType)))
|
||||
return false;
|
||||
if ((bpp = colors2bpp(numColors, imgType)) < 0)
|
||||
continue;
|
||||
@ -830,8 +830,8 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
if (!readBitmap(file, hdl, img, bpp))
|
||||
return false;
|
||||
} else if (t8_1 == 0x02) {
|
||||
if (!(file->readByte(hdl, numColors)
|
||||
&& file->readByte(hdl, imgType)))
|
||||
if (!(file->readUInt8(hdl, numColors)
|
||||
&& file->readUInt8(hdl, imgType)))
|
||||
return false;
|
||||
if ((bpp = colors2bpp(numColors, imgType)) < 0)
|
||||
continue;
|
||||
@ -845,7 +845,7 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
if (textColor) {
|
||||
quint8 labelFlags;
|
||||
QColor color;
|
||||
if (!file->readByte(hdl, labelFlags))
|
||||
if (!file->readUInt8(hdl, labelFlags))
|
||||
return false;
|
||||
if (labelFlags & 0x08) {
|
||||
if (!readColor(file, hdl, color))
|
||||
@ -874,7 +874,7 @@ bool Style::parseDrawOrder(SubFile *file, SubFile::Handle &hdl,
|
||||
quint8 type;
|
||||
quint32 subtype;
|
||||
|
||||
if (!(file->readByte(hdl, type) && file->readUInt32(hdl, subtype)))
|
||||
if (!(file->readUInt8(hdl, type) && file->readUInt32(hdl, subtype)))
|
||||
return false;
|
||||
|
||||
if (!subtype)
|
||||
@ -944,6 +944,9 @@ Style::Style(SubFile *typ)
|
||||
|
||||
if (typ)
|
||||
parseTYPFile(typ);
|
||||
|
||||
// Override stuff breaking the style display logic
|
||||
_points[0x11400] = Point(None);
|
||||
}
|
||||
|
||||
const Style::Line &Style::line(quint32 type) const
|
||||
@ -973,7 +976,8 @@ const Style::Point &Style::point(quint32 type) const
|
||||
bool Style::isContourLine(quint32 type)
|
||||
{
|
||||
return (type == TYPE(0x20) || type == TYPE(0x21) || type == TYPE(0x22)
|
||||
|| type == TYPE(0x23) || type == TYPE(0x24) || type == TYPE(0x25));
|
||||
|| type == TYPE(0x23) || type == TYPE(0x24) || type == TYPE(0x25)
|
||||
|| (type & 0xffff00) == TYPE(0x109));
|
||||
}
|
||||
|
||||
bool Style::isSpot(quint32 type)
|
||||
@ -1041,4 +1045,11 @@ QDebug operator<<(QDebug dbg, const Style::Line &line)
|
||||
<< penColor(line.background()) << ", " << !line.img().isNull() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const Style::Point &point)
|
||||
{
|
||||
dbg.nospace() << "Point(" << point.textFontSize() << ", "
|
||||
<< point.textColor() << ", " << !point.img().isNull() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -80,6 +80,8 @@ public:
|
||||
class Point {
|
||||
public:
|
||||
Point() : _textFontSize(NotSet) {}
|
||||
Point(FontSize fontSize, const QColor &textColor = QColor())
|
||||
: _textColor(textColor), _textFontSize(fontSize) {}
|
||||
Point(const QImage &img) : _textFontSize(NotSet), _img(img) {}
|
||||
|
||||
void setTextColor(const QColor &color) {_textColor = color;}
|
||||
@ -149,6 +151,7 @@ private:
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Style::Polygon &polygon);
|
||||
QDebug operator<<(QDebug dbg, const Style::Line &line);
|
||||
QDebug operator<<(QDebug dbg, const Style::Point &point);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // STYLE_H
|
||||
|
@ -69,6 +69,49 @@ bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SubFile::readVUInt32SW(Handle &hdl, quint32 bytes, quint32 &val) const
|
||||
{
|
||||
quint8 b;
|
||||
|
||||
val = 0;
|
||||
for (quint32 i = bytes; i; i--) {
|
||||
if (!readByte(hdl, b))
|
||||
return false;
|
||||
val |= ((quint32)b) << ((i-1) * 8);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const
|
||||
{
|
||||
quint8 bits;
|
||||
|
||||
if (!readUInt8(hdl, bits))
|
||||
return false;
|
||||
|
||||
if (!(bits & 1)) {
|
||||
seek(hdl, hdl.pos - 1);
|
||||
if (!((bits>>1) & 1)) {
|
||||
if (!((bits>>2) & 1)) {
|
||||
if (!readUInt32(hdl, bitfield))
|
||||
return false;
|
||||
} else {
|
||||
if (!readUInt24(hdl, bitfield))
|
||||
return false;
|
||||
}
|
||||
bitfield >>= 3;
|
||||
} else {
|
||||
if (!readUInt16(hdl, bitfield))
|
||||
return false;
|
||||
bitfield >>= 2;
|
||||
}
|
||||
} else
|
||||
bitfield = bits>>1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString SubFile::fileName() const
|
||||
{
|
||||
return _file ? _file->fileName() : _img->fileName();
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include <QVector>
|
||||
#include <QDebug>
|
||||
|
||||
class IMG;
|
||||
class QFile;
|
||||
class IMG;
|
||||
|
||||
class SubFile
|
||||
{
|
||||
@ -37,9 +37,19 @@ public:
|
||||
void addBlock(quint16 block) {_blocks->append(block);}
|
||||
|
||||
bool seek(Handle &handle, quint32 pos) const;
|
||||
bool readByte(Handle &handle, quint8 &val) const;
|
||||
|
||||
bool readUInt16(Handle &handle, quint16 &val) const
|
||||
template<typename T>
|
||||
bool readUInt8(Handle &handle, T &val) const
|
||||
{
|
||||
quint8 b;
|
||||
if (!readByte(handle, b))
|
||||
return false;
|
||||
val = b;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool readUInt16(Handle &handle, T &val) const
|
||||
{
|
||||
quint8 b0, b1;
|
||||
if (!(readByte(handle, b0) && readByte(handle, b1)))
|
||||
@ -88,6 +98,8 @@ public:
|
||||
}
|
||||
|
||||
bool readVUInt32(Handle &hdl, quint32 &val) const;
|
||||
bool readVUInt32SW(Handle &hdl, quint32 bytes, quint32 &val) const;
|
||||
bool readVBitfield32(Handle &hdl, quint32 &bitfield) const;
|
||||
|
||||
quint16 offset() const {return _blocks->first();}
|
||||
QString fileName() const;
|
||||
@ -96,6 +108,8 @@ protected:
|
||||
quint32 _gmpOffset;
|
||||
|
||||
private:
|
||||
bool readByte(Handle &handle, quint8 &val) const;
|
||||
|
||||
IMG *_img;
|
||||
QVector<quint16> *_blocks;
|
||||
QFile *_file;
|
||||
|
@ -44,7 +44,7 @@ bool TREFile::init()
|
||||
quint16 hdrLen;
|
||||
|
||||
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
|
||||
&& seek(hdl, _gmpOffset + 0x0D) && readByte(hdl, locked)))
|
||||
&& seek(hdl, _gmpOffset + 0x0D) && readUInt8(hdl, locked)))
|
||||
return false;
|
||||
|
||||
// Tile bounds
|
||||
@ -62,12 +62,15 @@ bool TREFile::init()
|
||||
&& readUInt32(hdl, subdivSize)))
|
||||
return false;
|
||||
|
||||
// TRE7 info
|
||||
if (hdrLen > 0x9A) {
|
||||
// TRE7 info
|
||||
if (!(seek(hdl, _gmpOffset + 0x7C) && readUInt32(hdl, _extended.offset)
|
||||
&& readUInt32(hdl, _extended.size)
|
||||
&& readUInt16(hdl, _extended.itemSize)))
|
||||
return false;
|
||||
// flags
|
||||
if (!(seek(hdl, _gmpOffset + 0x86) && readUInt32(hdl, _flags)))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tile levels
|
||||
@ -75,7 +78,7 @@ bool TREFile::init()
|
||||
return false;
|
||||
quint8 levels[64];
|
||||
for (quint32 i = 0; i < levelsSize; i++)
|
||||
if (!readByte(hdl, levels[i]))
|
||||
if (!readUInt8(hdl, levels[i]))
|
||||
return false;
|
||||
if (locked) {
|
||||
quint32 key;
|
||||
@ -126,15 +129,16 @@ bool TREFile::load(int idx)
|
||||
return false;
|
||||
|
||||
for (int j = 0; j < _levels.at(idx).subdivs; j++) {
|
||||
quint32 offset;
|
||||
quint32 oo;
|
||||
qint32 lon, lat;
|
||||
quint8 objects;
|
||||
quint16 width, height, nextLevel;
|
||||
|
||||
if (!(readUInt24(hdl, offset) && readByte(hdl, objects)
|
||||
&& readInt24(hdl, lon) && readInt24(hdl, lat)
|
||||
if (!(readUInt32(hdl, oo) && readInt24(hdl, lon) && readInt24(hdl, lat)
|
||||
&& readUInt16(hdl, width) && readUInt16(hdl, height)))
|
||||
goto error;
|
||||
quint32 offset = oo & 0xfffffff;
|
||||
quint8 objects = (((qint16)height < 0) << 4) | (oo >> 0x1c);
|
||||
|
||||
if (idx != _levels.size() - 1)
|
||||
if (!readUInt16(hdl, nextLevel))
|
||||
goto error;
|
||||
@ -146,6 +150,7 @@ bool TREFile::load(int idx)
|
||||
width <<= (24 - _levels.at(idx).bits);
|
||||
height <<= (24 - _levels.at(idx).bits);
|
||||
|
||||
|
||||
s = new SubDiv(offset, lon, lat, _levels.at(idx).bits, objects);
|
||||
sl.append(s);
|
||||
|
||||
|
@ -22,6 +22,8 @@ public:
|
||||
|
||||
const RectC &bounds() const {return _bounds;}
|
||||
QList<SubDiv*> subdivs(const RectC &rect, int bits);
|
||||
quint32 shift(quint8 bits) const
|
||||
{return (bits == _levels.last().bits) ? (_flags >> 0xb) & 7 : 0;}
|
||||
|
||||
private:
|
||||
struct MapLevel {
|
||||
@ -51,6 +53,7 @@ private:
|
||||
quint32 _subdivOffset;
|
||||
Extended _extended;
|
||||
int _firstLevel;
|
||||
quint32 _flags;
|
||||
|
||||
QMap<int, SubDivTree*> _subdivs;
|
||||
};
|
||||
|
@ -76,9 +76,11 @@ void VectorTile::objects(const RectC &rect, int bits,
|
||||
{
|
||||
QList<SubDiv*> subdivs = _tre->subdivs(rect, bits);
|
||||
for (int i = 0; i < subdivs.size(); i++) {
|
||||
_rgn->objects(rect, subdivs.at(i), _lbl, _net, polygons, lines, points);
|
||||
_rgn->extObjects(rect, subdivs.at(i), _lbl, polygons, lines,
|
||||
points);
|
||||
const SubDiv *subdiv = subdivs.at(i);
|
||||
quint32 shift = _tre->shift(subdiv->bits());
|
||||
|
||||
_rgn->objects(rect, subdiv, _lbl, _net, polygons, lines, points);
|
||||
_rgn->extObjects(rect, subdiv, shift, _lbl, polygons, lines, points);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,9 @@ class VectorTile {
|
||||
public:
|
||||
VectorTile() : _tre(0), _rgn(0), _lbl(0), _net(0), _gmp(0) {}
|
||||
~VectorTile()
|
||||
{delete _tre; delete _rgn; delete _lbl; delete _net; delete _gmp;}
|
||||
{
|
||||
delete _tre; delete _rgn; delete _lbl; delete _net; delete _gmp;
|
||||
}
|
||||
|
||||
bool init();
|
||||
void clear() {_tre->clear();}
|
||||
|
Loading…
Reference in New Issue
Block a user