1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-06 06:43:22 +02:00

Huffman encoded labels

+ more or less related fixes/refactoring
This commit is contained in:
Martin Tůma 2020-11-10 00:58:19 +01:00
parent 0644bb72a0
commit f139d33502
23 changed files with 660 additions and 309 deletions

View File

@ -93,8 +93,10 @@ HEADERS += src/common/config.h \
src/map/IMG/bitstream.h \
src/map/IMG/deltastream.h \
src/map/IMG/gmap.h \
src/map/IMG/huffmanbuffer.h \
src/map/IMG/huffmanstream.h \
src/map/IMG/huffmantable.h \
src/map/IMG/huffmantext.h \
src/map/IMG/nodfile.h \
src/map/IMG/mapdata.h \
src/map/IMG/rastertile.h \
@ -258,8 +260,10 @@ SOURCES += src/main.cpp \
src/map/IMG/bitstream.cpp \
src/map/IMG/deltastream.cpp \
src/map/IMG/gmap.cpp \
src/map/IMG/huffmanbuffer.cpp \
src/map/IMG/huffmanstream.cpp \
src/map/IMG/huffmantable.cpp \
src/map/IMG/huffmantext.cpp \
src/map/IMG/nodfile.cpp \
src/map/IMG/mapdata.cpp \
src/map/IMG/rastertile.cpp \

View File

@ -15,4 +15,15 @@ inline double toWGS24(qint32 v)
return toWGS32(LS(v, 8));
}
inline quint8 vs(const quint8 b0)
{
static const quint8 sizes[] = {4, 1, 2, 1, 3, 1, 2, 1};
return sizes[b0 & 0x07];
}
inline quint8 bs(const quint8 val)
{
return (val + 7) >> 3;
}
#endif // GARMIN_H

View File

@ -81,7 +81,11 @@ bool GMAP::loadTile(const QDir &dir, bool baseMap)
QFileInfoList ml = dir.entryInfoList(QDir::Files);
for (int i = 0; i < ml.size(); i++) {
const QFileInfo &fi = ml.at(i);
tile->addFile(fi.absoluteFilePath(), tileType(fi.suffix()));
SubFile::Type tt = tileType(fi.suffix());
if (VectorTile::isTileFile(tt)) {
_files.append(new QString(fi.absoluteFilePath()));
tile->addFile(_files.last(), tt);
}
}
if (!tile->init()) {
@ -131,8 +135,10 @@ GMAP::GMAP(const QString &fileName) : _fileName(fileName)
fi.absoluteFilePath() == baseMap.absoluteFilePath());
}
if (baseDir.exists(typFilePath))
_typ = new SubFile(baseDir.filePath(typFilePath));
if (baseDir.exists(typFilePath)) {
_files.append(new QString(baseDir.filePath(typFilePath)));
_typ = new SubFile(_files.last());
}
if (!_tileTree.Count())
_errorString = "No usable map tile found";
@ -140,6 +146,11 @@ GMAP::GMAP(const QString &fileName) : _fileName(fileName)
_valid = true;
}
GMAP::~GMAP()
{
qDeleteAll(_files);
}
bool GMAP::isGMAP(const QString &path)
{
QFile file(path);

View File

@ -10,6 +10,7 @@ class GMAP : public MapData
{
public:
GMAP(const QString &fileName);
~GMAP();
QString fileName() const {return _fileName;}
@ -25,6 +26,7 @@ private:
bool loadTile(const QDir &dir, bool baseMap);
QString _fileName;
QList<const QString*> _files;
};
#endif // GMAP_H

View File

@ -0,0 +1,24 @@
#include "rgnfile.h"
#include "huffmanbuffer.h"
bool HuffmanBuffer::load(const RGNFile *rgn, SubFile::Handle &rgnHdl)
{
quint32 recordSize, recordOffset = rgn->dictOffset();
for (int i = 0; i <= _id; i++) {
if (!rgn->seek(rgnHdl, recordOffset))
return false;
if (!rgn->readVUInt32(rgnHdl, recordSize))
return false;
recordOffset = rgn->pos(rgnHdl) + recordSize;
if (recordOffset > rgn->dictOffset() + rgn->dictSize())
return false;
};
resize(recordSize);
for (int i = 0; i < QByteArray::size(); i++)
if (!rgn->readUInt8(rgnHdl, *((quint8*)(data() + i))))
return false;
return true;
}

View File

@ -0,0 +1,21 @@
#ifndef HUFFMANBUFFER_H
#define HUFFMANBUFFER_H
#include <QByteArray>
#include "subfile.h"
class RGNFile;
class HuffmanBuffer : public QByteArray
{
public:
HuffmanBuffer(quint8 id) : _id(id) {}
quint8 id() const {return _id;}
bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl);
private:
quint8 _id;
};
#endif // HUFFMANBUFFER_H

View File

@ -1,17 +1,7 @@
#include "common/garmin.h"
#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;
@ -22,10 +12,9 @@ static inline quint32 readVUint32(const quint8 *buffer, quint32 bytes)
return val;
}
bool HuffmanTable::load(const SubFile &file, SubFile::Handle &hdl,
quint32 offset, quint32 size, quint32 id)
bool HuffmanTable::load(const RGNFile *rgn, SubFile::Handle &rgnHdl)
{
if (!getBuffer(file, hdl, offset, size, id))
if (!_buffer.load(rgn, rgnHdl))
return false;
_s0 = (quint8)_buffer.at(0) & 0x0F;
@ -42,31 +31,6 @@ bool HuffmanTable::load(const SubFile &file, SubFile::Handle &hdl,
_s10 = _s14 + _s1c * _s1d;
_s18 = _s10 + (_s1 << _s0);
_id = id;
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 = file.pos(hdl) + 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;
}

View File

@ -1,31 +1,26 @@
#ifndef HUFFMANTABLE_H
#define HUFFMANTABLE_H
#include "subfile.h"
#include "huffmanbuffer.h"
class RGNFile;
class HuffmanTable {
public:
HuffmanTable() : _s2(0) {}
HuffmanTable(quint8 id) : _buffer(id) {}
bool load(const SubFile &file, SubFile::Handle &hdl, quint32 offset,
quint32 size, quint32 id);
bool isNull() const {return _s2 == 0;}
bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl);
quint8 maxSymbolSize() const {return _s2;}
quint32 symbol(quint32 data, quint8 &size) const;
quint8 id() const {return _id;}
quint8 id() const {return _buffer.id();}
private:
bool getBuffer(const SubFile &file, SubFile::Handle &hdl, quint32 offset,
quint32 size, quint8 id);
QByteArray _buffer;
HuffmanBuffer _buffer;
quint8 _s0, _s1, _s2, _s3;
quint8 *_s10, *_s14, *_s18;
quint8 _s1c, _s1d, _s1e, _s1f, _s20;
quint16 _s22;
quint8 _id;
};
#endif // HUFFMANTABLE_H

169
src/map/IMG/huffmantext.cpp Normal file
View File

@ -0,0 +1,169 @@
#include "common/garmin.h"
#include "subfile.h"
#include "huffmantext.h"
static inline quint32 readVUint32(const quint8 *buffer, quint32 bytes)
{
quint32 val = 0;
for (quint32 i = 0; i < bytes; i++)
val = val | (quint32)*(buffer - i) << ((bytes - i - 1) << 3);
return val;
}
bool HuffmanText::load(const RGNFile *rgn, SubFile::Handle &rgnHdl)
{
if (!_buffer.load(rgn, rgnHdl))
return false;
quint8 *buffer = (quint8 *)_buffer.constData();
_b0 = buffer[0];
_b1 = buffer[1];
_b2 = buffer[2];
_b3 = buffer[3];
_vs = vs(buffer[4]);
_bs3 = bs(_b3);
_bs1 = bs(_b1);
_mul = _bs1 + 1 + _vs;
_bp1 = buffer + _vs + 4;
_bp2 = _bp1 + _mul * _b2;
_bp3 = _bp2 + ((_bs3 + 1) << (_b0 & 0xf));
_bp4 = _bp3 - 1;
return true;
}
bool HuffmanText::fetch(const SubFile *file, SubFile::Handle &hdl,
quint32 &data, quint32 &bits, quint32 &usedBits, quint32 &usedData) const
{
quint32 rs, ls, old;
bits = _b1 - bits;
if (usedBits < bits) {
old = usedBits ? usedData >> (0x20 - usedBits) : 0;
if (!file->readVUInt32SW(hdl, 4, usedData))
return false;
ls = bits - usedBits;
rs = 0x20 - (bits - usedBits);
old = usedData >> rs | old << ls;
} else {
ls = bits;
rs = usedBits - bits;
old = usedData >> (0x20 - bits);
}
usedData = usedData << ls;
data = data | old << (0x20 - _b1);
usedBits = rs;
return true;
}
bool HuffmanText::decode(const SubFile *file, SubFile::Handle &hdl,
QVector<quint8> &str) const
{
quint32 bits = 0;
quint32 data = 0;
quint32 usedBits = 0;
quint32 usedData = 0;
quint32 ls = 8;
quint32 lo = _vs * 8 - 8;
while (true) {
if (!fetch(file, hdl, data, bits, usedBits, usedData))
return false;
quint32 off = (data >> (0x20 - (_b0 & 0xf))) * (_bs3 + 1);
quint32 sb = _bp2[off];
quint32 ss = 0;
quint32 sym = _b2 - 1;
quint32 size;
if ((_b0 & 0xf) == 0 || (sb & 1) == 0) {
if ((_b0 & 0xf) != 0) {
ss = sb >> 1;
sym = _bp2[off + 1];
}
quint8 *tp = _bp1 + ss * _mul;
quint32 sd = data >> (0x20 - _b1);
while (ss < sym) {
quint32 cnt = (sym + 1 + ss) >> 1;
quint8 *prev = _bp1 + cnt * _mul;
quint32 nd = readVUint32(prev + _bs1 - 1, _bs1);
if (sd <= nd) {
sym = cnt - (sd < nd);
if (sd < nd) {
prev = tp;
cnt = ss;
}
}
tp = prev;
ss = cnt;
}
quint32 o1 = readVUint32(tp + _bs1 - 1, _bs1);
tp = tp + _bs1;
quint32 o2 = readVUint32(tp + _vs, _vs);
size = tp[0];
quint32 os = (sd - o1) >> (_b1 - size);
if ((_b0 & 0x10) == 0) {
sym = readVUint32(_bp4 + (o2 + 1 + os) * _bs3, _bs3);
} else {
quint32 v = (os + o2) * _b3;
quint32 idx = v >> 3;
quint32 r = v & 7;
quint32 shift = 8 - r;
sym = _bp3[idx] >> r;
if (shift < _b3) {
quint32 sz = bs(_b3 - shift);
quint32 val = readVUint32(_bp3 + idx + sz, sz);
sym = sym | val << shift;
}
}
} else {
sym = readVUint32(_bp2 + off + _bs3, _bs3);
size = (sb >> 1);
}
if (_b1 < size)
return false;
data = data << size;
bits = _b1 - size;
if ((_b3 & 7) == 0) {
for (quint32 i = 0; i < (_b3 >> 3); i++) {
str.append((quint8)sym);
if (((quint8)sym == '\0'))
return true;
sym = sym >> 8;
}
} else {
quint32 cnt = _b3;
if (ls <= _b3) {
do {
quint32 shift = ls;
lo = sym << (8 - shift) | (quint32)((quint8)lo >> shift);
sym = sym >> shift;
str.append((uchar)lo);
if (((uchar)lo == '\0'))
return true;
cnt = cnt - ls;
ls = 8;
} while (7 < cnt);
ls = 8;
}
if (cnt != 0) {
lo = sym << (8 - cnt) | (quint32)((quint8)lo >> cnt);
ls = ls - cnt;
}
}
}
}

35
src/map/IMG/huffmantext.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef HUFFMANTEXT_H
#define HUFFMANTEXT_H
#include "huffmanbuffer.h"
class HuffmanText
{
public:
HuffmanText() : _buffer(0) {}
bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl);
bool decode(const SubFile *file, SubFile::Handle &hdl,
QVector<quint8> &str) const;
private:
bool fetch(const SubFile *file, SubFile::Handle &hdl, quint32 &data,
quint32 &bits, quint32 &usedBits, quint32 &usedData) const;
HuffmanBuffer _buffer;
quint32 _b0;
quint32 _b1;
quint32 _b2;
quint32 _b3;
quint32 _vs;
quint32 _bs3;
quint32 _bs1;
quint32 _mul;
quint8 *_bp1;
quint8 *_bp2;
quint8 *_bp3;
quint8 *_bp4;
};
#endif // HUFFMANTEXT_H

View File

@ -1,4 +1,6 @@
#include <QTextCodec>
#include "huffmantext.h"
#include "rgnfile.h"
#include "lblfile.h"
enum Charset {Normal, Symbol, Special};
@ -55,21 +57,48 @@ static QString capitalized(const QString &str)
}
bool LBLFile::init(Handle &hdl)
LBLFile::~LBLFile()
{
quint16 codepage;
quint8 multiplier, poiMultiplier;
delete _huffmanText;
delete _table;
}
if (!(seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
&& readUInt32(hdl, _size) && readUInt8(hdl, multiplier)
bool LBLFile::load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl)
{
quint16 hdrLen, codepage;
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
&& seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
&& readUInt32(hdl, _size) && readUInt8(hdl, _multiplier)
&& readUInt8(hdl, _encoding) && seek(hdl, _gmpOffset + 0x57)
&& readUInt32(hdl, _poiOffset) && readUInt32(hdl, _poiSize)
&& readUInt8(hdl, poiMultiplier) && seek(hdl, _gmpOffset + 0xAA)
&& readUInt8(hdl, _poiMultiplier) && seek(hdl, _gmpOffset + 0xAA)
&& readUInt16(hdl, codepage)))
return false;
_multiplier = 1<<multiplier;
_poiMultiplier = 1<<poiMultiplier;
if (hdrLen >= 0x132) {
quint32 offset, size;
quint16 recordSize;
if (!(seek(hdl, _gmpOffset + 0x124) && readUInt32(hdl, offset)
&& readUInt32(hdl, size) && readUInt16(hdl, recordSize)))
return false;
if (size && recordSize) {
_table = new quint32[size / recordSize];
if (!seek(hdl, offset))
return false;
for (quint32 i = 0; i < size / recordSize; i++) {
if (!readVUInt32(hdl, recordSize, _table[i]))
return false;
}
}
}
if (_encoding == 11) {
_huffmanText = new HuffmanText();
if (!_huffmanText->load(rgn, rgnHdl))
return false;
}
if (codepage == 65001)
_codec = QTextCodec::codecForName("UTF-8");
@ -82,6 +111,14 @@ bool LBLFile::init(Handle &hdl)
return true;
}
void LBLFile::clear()
{
delete _huffmanText;
delete _table;
_huffmanText = 0;
_table = 0;
}
Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize) const
{
Label::Shield::Type shieldType = Label::Shield::None;
@ -135,20 +172,16 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize) const
}
}
Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
Label LBLFile::str2label(const QVector<quint8> &str, bool capitalize) const
{
Label::Shield::Type shieldType = Label::Shield::None;
QByteArray label, shieldLabel;
QByteArray *bap = &label;
quint8 c;
if (!seek(hdl, offset))
return Label();
for (int i = 0; i < str.size(); i++) {
const quint8 &c = str.at(i);
while (true) {
if (!readUInt8(hdl, c))
return Label();
if (!c || c == 0x1d)
if (c == 0 || c == 0x1d)
break;
if (c == 0x1c)
@ -158,7 +191,7 @@ Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
bap = &label;
else
bap->append(' ');
} else if (c <= 0x07) {
} else if (c < 0x07) {
shieldType = static_cast<Label::Shield::Type>(c);
bap = &shieldLabel;
} else if (bap == &shieldLabel && c == 0x20) {
@ -175,21 +208,74 @@ Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
Label::Shield(shieldType, shieldText));
}
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize)
Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize) const
{
if (!_multiplier && !init(hdl))
return QString();
QVector<quint8> str;
quint8 c;
if (!seek(hdl, offset))
return Label();
do {
if (!readUInt8(hdl, c))
return Label();
str.append(c);
} while (c);
return str2label(str, capitalize);
}
Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize) const
{
QVector<quint8> str;
if (!seek(hdl, offset))
return Label();
if (!_huffmanText->decode(this, hdl, str))
return Label();
if (!_table)
return str2label(str, capitalize);
QVector<quint8> str2;
for (int i = 0; i < str.size(); i++) {
quint32 val = _table[str.at(i)];
if (val) {
if (!seek(hdl, _offset + ((val & 0x7fffff) << _multiplier)))
return Label();
if (str2.size() && str2.back() == '\0')
str2[str2.size() - 1] = ' ';
else if (str2.size())
str2.append(' ');
if (!_huffmanText->decode(this, hdl, str2))
return Label();
} else {
if (str.at(i) == 7) {
str2.append(0);
break;
}
if (str2.size() && str2.back() == '\0')
str2[str2.size() - 1] = ' ';
str2.append(str.at(i));
}
}
return str2label(str2, capitalize);
}
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize) const
{
quint32 labelOffset;
if (poi) {
quint32 poiOffset;
if (!(_poiSize >= offset * _poiMultiplier
&& seek(hdl, _poiOffset + offset * _poiMultiplier)
if (!(_poiSize >= (offset << _poiMultiplier)
&& seek(hdl, _poiOffset + (offset << _poiMultiplier))
&& readUInt24(hdl, poiOffset) && (poiOffset & 0x3FFFFF)))
return QString();
labelOffset = _offset + (poiOffset & 0x3FFFFF) * _multiplier;
labelOffset = _offset + ((poiOffset & 0x3FFFFF) << _multiplier);
} else
labelOffset = _offset + offset * _multiplier;
labelOffset = _offset + (offset << _multiplier);
if (labelOffset > _offset + _size)
return QString();
@ -200,6 +286,8 @@ Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize)
case 9:
case 10:
return label8b(hdl, labelOffset, capitalize);
case 11:
return labelHuffman(hdl, labelOffset, capitalize);
default:
return Label();
}

View File

@ -5,28 +5,40 @@
#include "label.h"
class QTextCodec;
class HuffmanText;
class RGNFile;
class LBLFile : public SubFile
{
public:
LBLFile(IMG *img)
: SubFile(img), _codec(0), _offset(0), _size(0), _poiOffset(0),
_poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {}
LBLFile(const QString &path)
: SubFile(path), _codec(0), _offset(0), _size(0), _poiOffset(0),
_poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {}
: SubFile(img), _huffmanText(0), _table(0), _codec(0), _offset(0),
_size(0), _poiOffset(0), _poiSize(0), _poiMultiplier(0), _multiplier(0),
_encoding(0) {}
LBLFile(const QString *path)
: SubFile(path), _huffmanText(0), _table(0), _codec(0), _offset(0),
_size(0), _poiOffset(0), _poiSize(0), _poiMultiplier(0), _multiplier(0),
_encoding(0) {}
LBLFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
_codec(0), _offset(0), _size(0), _poiOffset(0), _poiSize(0),
_poiMultiplier(0), _multiplier(0), _encoding(0) {}
_huffmanText(0), _table(0), _codec(0), _offset(0), _size(0),
_poiOffset(0), _poiSize(0), _poiMultiplier(0), _multiplier(0),
_encoding(0) {}
~LBLFile();
bool load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl);
void clear();
Label label(Handle &hdl, quint32 offset, bool poi = false,
bool capitalize = true);
bool capitalize = true) const;
private:
bool init(Handle &hdl);
Label str2label(const QVector<quint8> &str, bool capitalize) const;
Label label6b(Handle &hdl, quint32 offset, bool capitalize) const;
Label label8b(Handle &hdl, quint32 offset, bool capitalize) const;
Label labelHuffman(Handle &hdl, quint32 offset, bool capitalize) const;
HuffmanText *_huffmanText;
quint32 *_table;
QTextCodec *_codec;
quint32 _offset;

View File

@ -107,7 +107,7 @@ void MapData::load()
else {
QString typFile(ProgramPaths::typFile());
if (!typFile.isEmpty()) {
SubFile typ(typFile);
SubFile typ(&typFile);
_style = new Style(&typ);
} else
_style = new Style();

View File

@ -3,6 +3,7 @@
#include "subdiv.h"
#include "nodfile.h"
#include "lblfile.h"
#include "rgnfile.h"
#include "netfile.h"
@ -93,7 +94,7 @@ static bool seekToLine(BitStream4R &bs, quint8 line)
}
static bool readLine(BitStream4R &bs, const SubDiv *subdiv,
const HuffmanTable &table, IMG::Poly &poly)
const HuffmanTable *table, MapData::Poly &poly)
{
quint32 v1, v2, v2b;
if (!bs.readVuint32SM(v1, v2, v2b))
@ -113,7 +114,7 @@ static bool readLine(BitStream4R &bs, const SubDiv *subdiv,
poly.boundingRect = RectC(c, c);
poly.points.append(QPointF(c.lon(), c.lat()));
HuffmanStreamR stream(bs, table);
HuffmanStreamR stream(bs, *table);
if (!stream.init())
return false;
qint32 lonDelta, latDelta;
@ -132,8 +133,8 @@ static bool readLine(BitStream4R &bs, const SubDiv *subdiv,
return stream.atEnd();
}
static bool readNodeGeometry(NODFile *nod, SubFile::Handle &nodHdl,
NODFile::AdjacencyInfo &adj, IMG::Poly &poly, quint16 cnt = 0xFFFF)
static bool readNodeGeometry(const NODFile *nod, SubFile::Handle &nodHdl,
NODFile::AdjacencyInfo &adj, MapData::Poly &poly, quint16 cnt = 0xFFFF)
{
for (int i = 0; i <= cnt; i++) {
int ret = nod->nextNode(nodHdl, adj);
@ -151,7 +152,7 @@ static bool readNodeGeometry(NODFile *nod, SubFile::Handle &nodHdl,
return true;
}
static bool skipNodes(NODFile *nod, SubFile::Handle &nodHdl,
static bool skipNodes(const NODFile *nod, SubFile::Handle &nodHdl,
NODFile::AdjacencyInfo &adj, int cnt)
{
for (int i = 0; i < cnt; i++)
@ -161,10 +162,10 @@ static bool skipNodes(NODFile *nod, SubFile::Handle &nodHdl,
return true;
}
static bool readShape(NODFile *nod, SubFile::Handle &nodHdl,
NODFile::AdjacencyInfo &adj, BitStream4R &bs, const HuffmanTable &table,
const SubDiv *subdiv, quint32 shift, IMG::Poly &poly, quint16 cnt = 0xFFFF,
bool check = false)
static bool readShape(const NODFile *nod, SubFile::Handle &nodHdl,
NODFile::AdjacencyInfo &adj, BitStream4R &bs, const HuffmanTable *table,
const SubDiv *subdiv, quint32 shift, MapData::Poly &poly,
quint16 cnt = 0xFFFF, bool check = false)
{
quint32 v1, v2, v2b;
if (!bs.readVuint32SM(v1, v2, v2b))
@ -233,7 +234,7 @@ static bool readShape(NODFile *nod, SubFile::Handle &nodHdl,
}
}
HuffmanStreamR stream(bs, table);
HuffmanStreamR stream(bs, *table);
if (!stream.init(lonSign, latSign, flags, extraBits))
return false;
qint32 lonDelta, latDelta;
@ -345,8 +346,13 @@ static bool readShape(NODFile *nod, SubFile::Handle &nodHdl,
}
bool NETFile::linkLabel(Handle &hdl, quint32 offset, quint32 size, LBLFile *lbl,
Handle &lblHdl, Label &label)
NETFile::~NETFile()
{
delete _huffmanTable;
}
bool NETFile::linkLabel(Handle &hdl, quint32 offset, quint32 size,
const LBLFile *lbl, Handle &lblHdl, Label &label) const
{
if (!seek(hdl, offset))
return false;
@ -360,19 +366,13 @@ bool NETFile::linkLabel(Handle &hdl, quint32 offset, quint32 size, LBLFile *lbl,
if (!bs.readUInt24(labelPtr))
return false;
if (labelPtr & 0x3FFFFF) {
if (labelPtr & 0x400000) {
quint32 lblOff;
if (lblOffset(hdl, labelPtr & 0x3FFFFF, lblOff) && lblOff)
label = lbl->label(lblHdl, lblOff);
} else
label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
}
if (labelPtr & 0x3FFFFF)
label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
return true;
}
bool NETFile::init(Handle &hdl)
bool NETFile::load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl)
{
quint16 hdrLen;
@ -385,31 +385,36 @@ bool NETFile::init(Handle &hdl)
quint32 info;
if (!(seek(hdl, _gmpOffset + 0x37) && readUInt32(hdl, info)))
return false;
_tableId = ((info >> 2) & 0xF);
if (!(seek(hdl, _gmpOffset + 0x43) && readUInt32(hdl, _linksOffset)
&& readUInt32(hdl, _linksSize) && readUInt8(hdl, _linksShift)))
return false;
}
_init = true;
quint8 tableId = ((info >> 2) & 0xF);
if (_linksSize && (!rgn->huffmanTable() || rgn->huffmanTable()->id()
!= tableId)) {
_huffmanTable = new HuffmanTable(tableId);
if (!_huffmanTable->load(rgn, rgnHdl))
return false;
}
_tp = _huffmanTable ? _huffmanTable : rgn->huffmanTable();
}
return true;
}
bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
NODFile *nod, Handle &nodHdl, LBLFile *lbl, Handle &lblHdl,
const NODFile::BlockInfo &blockInfo, quint8 linkId, quint8 lineId,
const HuffmanTable &table, QList<IMG::Poly> *lines)
void NETFile::clear()
{
if (!_init && !init(hdl))
return false;
delete _huffmanTable;
_huffmanTable = 0;
}
Q_ASSERT(_tableId == table.id());
if (_tableId != table.id())
return false;
IMG::Poly poly;
bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
const NODFile *nod, Handle &nodHdl, const LBLFile *lbl, Handle &lblHdl,
const NODFile::BlockInfo &blockInfo, quint8 linkId, quint8 lineId,
QList<MapData::Poly> *lines) const
{
MapData::Poly poly;
if (!nod->linkType(nodHdl, blockInfo, linkId, poly.type))
return false;
@ -445,7 +450,7 @@ bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
if (s69 == 1) {
if (s68 == 1) {
if (!readShape(nod, nodHdl, adj, bs, table, subdiv, shift, poly))
if (!readShape(nod, nodHdl, adj, bs, _tp, subdiv, shift, poly))
return false;
} else {
if (!readNodeGeometry(nod, nodHdl, adj, poly))
@ -459,7 +464,7 @@ bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
if (i == lineId) {
if (shape) {
bool check = (i < ca.size()) ? (ca.at(i) & mask) : false;
if (!readShape(nod, nodHdl, adj, bs, table, subdiv,
if (!readShape(nod, nodHdl, adj, bs, _tp, subdiv,
shift, poly, step, check))
return false;
} else {
@ -483,7 +488,7 @@ bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
return false;
if (!seekToLine(bs, lineId))
return false;
if (!readLine(bs, subdiv, table, poly))
if (!readLine(bs, subdiv, _tp, poly))
return false;
}
@ -496,11 +501,8 @@ bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
return true;
}
bool NETFile::lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset)
bool NETFile::lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset) const
{
if (!_init && !init(hdl))
return false;
if (!(seek(hdl, _offset + (netOffset << _shift))
&& readUInt24(hdl, lblOffset)))
return false;

View File

@ -1,42 +1,44 @@
#ifndef NETFILE_H
#define NETFILE_H
#include "img.h"
#include "subfile.h"
#include "nodfile.h"
class NODFile;
class LBLFile;
class RGNFile;
class SubDiv;
class HuffmanTable;
class NETFile : public SubFile
{
public:
NETFile(IMG *img) : SubFile(img), _offset(0), _size(0), _linksOffset(0),
_linksSize(0), _shift(0), _linksShift(0), _init(false) {}
NETFile(const QString &path) : SubFile(path), _offset(0), _size(0),
_linksOffset(0), _linksSize(0), _shift(0), _linksShift(0),
_init(false) {}
NETFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
NETFile(IMG *img) : SubFile(img), _huffmanTable(0), _tp(0), _offset(0),
_size(0), _linksOffset(0), _linksSize(0), _shift(0), _linksShift(0) {}
NETFile(const QString *path) : SubFile(path), _huffmanTable(0), _tp(0),
_offset(0), _size(0), _linksOffset(0), _linksSize(0), _shift(0),
_linksShift(0), _init(false) {}
_linksShift(0) {}
NETFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
_huffmanTable(0), _tp(0), _offset(0), _size(0), _linksOffset(0),
_linksSize(0), _shift(0), _linksShift(0) {}
~NETFile();
bool lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset);
bool link(const SubDiv *subdiv, quint32 shift, Handle &hdl, NODFile *nod,
Handle &nodHdl, LBLFile *lbl, Handle &lblHdl,
bool load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl);
void clear();
bool lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset) const;
bool link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
const NODFile *nod, Handle &nodHdl, const LBLFile *lbl, Handle &lblHdl,
const NODFile::BlockInfo &blockInfo, quint8 linkId, quint8 lineId,
const HuffmanTable &table, QList<IMG::Poly> *lines);
QList<MapData::Poly> *lines) const;
private:
bool init(Handle &hdl);
bool linkLabel(Handle &hdl, quint32 offset, quint32 size, LBLFile *lbl,
Handle &lblHdl, Label &label);
bool linkLabel(Handle &hdl, quint32 offset, quint32 size,
const LBLFile *lbl, Handle &lblHdl, Label &label) const;
HuffmanTable *_huffmanTable;
const HuffmanTable *_tp;
quint32 _offset, _size, _linksOffset, _linksSize;
quint8 _shift, _linksShift;
quint8 _tableId;
bool _init;
};
#endif // NETFILE_H

View File

@ -81,14 +81,14 @@ static bool skipOptAdjData(BitStream1 &bs)
}
bool NODFile::init(Handle &hdl)
bool NODFile::load(Handle &hdl)
{
quint16 hdrLen;
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)))
return false;
if (hdrLen < 0x7b)
return false;
return true;
if (!(seek(hdl, _gmpOffset + 0x1d) && readUInt32(hdl, _flags)
&& readUInt8(hdl, _blockShift) && readUInt8(hdl, _nodeShift)))
@ -113,14 +113,6 @@ bool NODFile::init(Handle &hdl)
return (_indexIdSize > 0);
}
quint32 NODFile::indexIdSize(Handle &hdl)
{
if (!_indexIdSize && !init(hdl))
return 0;
return _indexIdSize;
}
bool NODFile::readBlock(Handle &hdl, quint32 blockOffset,
BlockInfo &blockInfo) const
{
@ -494,7 +486,7 @@ bool NODFile::relAdjInfo(Handle &hdl, AdjacencyInfo &adj) const
return true;
}
int NODFile::nextNode(Handle &hdl, AdjacencyInfo &adjInfo)
int NODFile::nextNode(Handle &hdl, AdjacencyInfo &adjInfo) const
{
if (adjInfo.nodeOffset == 0xFFFFFFFF)
return 1;

View File

@ -1,7 +1,6 @@
#ifndef NODFILE_H
#define NODFILE_H
#include "img.h"
#include "subfile.h"
class NODFile : public SubFile
@ -57,7 +56,7 @@ public:
NODFile(IMG *img) : SubFile(img), _indexOffset(0), _indexSize(0),
_indexFlags(0), _blockOffset(0), _blockSize(0), _indexRecordSize(0),
_blockRecordSize(0), _blockShift(0), _nodeShift(0), _indexIdSize(0) {}
NODFile(const QString &path) : SubFile(path), _indexOffset(0), _indexSize(0),
NODFile(const QString *path) : SubFile(path), _indexOffset(0), _indexSize(0),
_indexFlags(0), _blockOffset(0), _blockSize(0), _indexRecordSize(0),
_blockRecordSize(0), _blockShift(0), _nodeShift(0), _indexIdSize(0) {}
NODFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
@ -65,16 +64,17 @@ public:
_blockSize(0), _indexRecordSize(0), _blockRecordSize(0), _blockShift(0),
_nodeShift(0), _indexIdSize(0) {}
quint32 indexIdSize(Handle &hdl);
bool load(Handle &hdl);
quint32 indexIdSize() const {return _indexIdSize;}
bool blockInfo(Handle &hdl, quint32 blockId, BlockInfo &blockInfo) const;
bool linkInfo(Handle &hdl, const BlockInfo &blockInfo, quint32 linkId,
LinkInfo &linkInfo) const;
bool linkType(Handle &hdl, const BlockInfo &blockInfo, quint8 linkId,
quint32 &type) const;
int nextNode(Handle &hdl, AdjacencyInfo &adjInfo);
int nextNode(Handle &hdl, AdjacencyInfo &adjInfo) const;
private:
bool init(Handle &hdl);
bool nodeInfo(Handle &hdl, const BlockInfo &blockInfo, quint32 nodeOffset,
NodeInfo &nodeInfo) const;
bool nodeOffset(Handle &hdl, const BlockInfo &blockInfo, quint8 nodeId,

View File

@ -24,6 +24,11 @@ static quint64 pointId(const QPoint &pos, quint32 type, quint32 labelPtr)
return id;
}
RGNFile::~RGNFile()
{
delete _huffmanTable;
}
bool RGNFile::skipClassFields(Handle &hdl) const
{
quint8 flags;
@ -96,7 +101,7 @@ bool RGNFile::skipGblFields(Handle &hdl, quint32 flags) const
return seek(hdl, pos(hdl) + cnt);
}
bool RGNFile::init(Handle &hdl)
bool RGNFile::load(Handle &hdl)
{
quint16 hdrLen;
@ -125,24 +130,29 @@ bool RGNFile::init(Handle &hdl)
}
if (hdrLen >= 0x7D) {
quint32 dictOffset, dictSize, info;
if (!(seek(hdl, _gmpOffset + 0x71) && readUInt32(hdl, dictOffset)
&& readUInt32(hdl, dictSize) && readUInt32(hdl, info)))
quint32 info;
if (!(seek(hdl, _gmpOffset + 0x71) && readUInt32(hdl, _dictOffset)
&& readUInt32(hdl, _dictSize) && readUInt32(hdl, info)))
return false;
if (dictSize && dictOffset && (info & 0x1E))
if (!_huffmanTable.load(*this, hdl, dictOffset, dictSize,
((info >> 1) & 0xF) - 1))
if (_dictSize && _dictOffset && (info & 0x1E)) {
_huffmanTable = new HuffmanTable(((info >> 1) & 0xF) - 1);
if (!_huffmanTable->load(this, hdl))
return false;
}
}
_init = true;
return true;
}
void RGNFile::clear()
{
delete _huffmanTable;
_huffmanTable = 0;
}
bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl, NETFile *net,
SegmentType segmentType, const LBLFile *lbl, Handle &lblHdl, NETFile *net,
Handle &netHdl, QList<IMG::Poly> *polys) const
{
const SubDiv::Segment &segment = (segmentType == Line)
@ -218,7 +228,7 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
}
bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
SegmentType segmentType, const LBLFile *lbl, Handle &lblHdl,
QList<IMG::Poly> *polys) const
{
quint32 labelPtr, len;
@ -246,13 +256,13 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
poly.type = 0x10000 | (quint16(type)<<8) | (subtype & 0x1F);
labelPtr = 0;
if (!_huffmanTable.isNull()) {
if (_huffmanTable) {
pos = QPoint(LS(subdiv->lon(), 8) + LS(lon, 32-subdiv->bits()),
LS(subdiv->lat(), 8) + LS(lat, (32-subdiv->bits())));
qint32 lonDelta, latDelta;
BitStream4F bs(*this, hdl, len);
HuffmanStreamF stream(bs, _huffmanTable);
HuffmanStreamF stream(bs, *_huffmanTable);
if (!stream.init(segmentType == Line))
return false;
@ -329,7 +339,7 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
}
bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
SegmentType segmentType, const LBLFile *lbl, Handle &lblHdl,
QList<IMG::Point> *points) const
{
const SubDiv::Segment &segment = (segmentType == IndexedPoint)
@ -363,9 +373,8 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
point.coordinates = Coordinates(toWGS24(pos.x()), toWGS24(pos.y()));
point.id = pointId(pos, point.type, labelPtr & 0x3FFFFF);
if (lbl && (labelPtr & 0x3FFFFF))
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF,
labelPtr & 0x400000, !(point.type == 0x1400 || point.type == 0x1500
|| point.type == 0x1e00));
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, labelPtr & 0x400000,
!(point.type == 0x1400 || point.type == 0x1500 || point.type == 0x1e00));
points->append(point);
}
@ -373,11 +382,12 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
return true;
}
bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
Handle &lblHdl, QList<IMG::Point> *points) const
bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv,
const LBLFile *lbl, Handle &lblHdl, QList<IMG::Point> *points) const
{
const SubDiv::Segment &segment = subdiv->extPoints();
if (!segment.isValid())
return true;
if (!seek(hdl, segment.offset()))
@ -423,30 +433,27 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
}
bool RGNFile::links(Handle &hdl, const SubDiv *subdiv, quint32 shift,
NETFile *net, Handle &netHdl, NODFile *nod, Handle &nodHdl, LBLFile *lbl,
Handle &lblHdl, QList<IMG::Poly> *lines) const
const NETFile *net, Handle &netHdl, const NODFile *nod, Handle &nodHdl,
const LBLFile *lbl, Handle &lblHdl, QList<IMG::Poly> *lines) const
{
quint32 size, blockIndexIdSize, blockIndexId;
quint32 size, blockIndexId;
quint8 flags;
const SubDiv::Segment &segment = subdiv->roadReferences();
if (!net || !nod)
return false;
if (!segment.isValid())
return true;
if (!seek(hdl, segment.offset()))
return false;
if (!net || !nod)
return false;
if (!(blockIndexIdSize = nod->indexIdSize(nodHdl)))
return false;
while (pos(hdl) < segment.end()) {
if (!readVUInt32(hdl, size))
return false;
quint32 entryStart = pos(hdl);
if (!(readUInt8(hdl, flags) && readVUInt32(hdl, blockIndexIdSize,
if (!(readUInt8(hdl, flags) && readVUInt32(hdl, nod->indexIdSize(),
blockIndexId)))
return false;
@ -494,10 +501,11 @@ bool RGNFile::links(Handle &hdl, const SubDiv *subdiv, quint32 shift,
}
net->link(subdiv, shift, netHdl, nod, nodHdl, lbl, lblHdl,
blockInfo, linkId, lineId, _huffmanTable, lines);
blockInfo, linkId, lineId, lines);
}
Q_ASSERT(entryStart + size == pos(hdl));
if (entryStart + size != pos(hdl))
return false;
}
return true;
@ -546,7 +554,7 @@ QMap<RGNFile::SegmentType, SubDiv::Segment> RGNFile::segments(Handle &hdl,
return ret;
}
bool RGNFile::subdivInit(Handle &hdl, SubDiv *subdiv) const
bool RGNFile::subdivInit(Handle &hdl, SubDiv *subdiv)
{
QMap<RGNFile::SegmentType, SubDiv::Segment> seg(segments(hdl, subdiv));
SubDiv::Segment extPoints, extLines, extPolygons;

View File

@ -1,14 +1,13 @@
#ifndef RGNFILE_H
#define RGNFILE_H
#include "img.h"
#include "subfile.h"
#include "subdiv.h"
#include "huffmantable.h"
class LBLFile;
class NETFile;
class NODFile;
class HuffmanTable;
class RGNFile : public SubFile
{
@ -22,35 +21,41 @@ public:
};
RGNFile(IMG *img)
: SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
: SubFile(img), _huffmanTable(0), _offset(0), _size(0), _polygonsOffset(0),
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
_pointsSize(0), _init(false) {}
RGNFile(const QString &path)
: SubFile(path), _offset(0), _size(0), _polygonsOffset(0),
_pointsSize(0) {}
RGNFile(const QString *path)
: SubFile(path), _huffmanTable(0), _offset(0), _size(0), _polygonsOffset(0),
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
_pointsSize(0), _init(false) {}
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) {}
_pointsSize(0) {}
RGNFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
_huffmanTable(0), _offset(0), _size(0), _polygonsOffset(0),
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
_pointsSize(0) {}
~RGNFile();
bool initialized() const {return _init;}
bool init(Handle &hdl);
void clear();
bool load(Handle &hdl);
bool polyObjects(Handle &hdl, const SubDiv *subdiv, SegmentType segmentType,
LBLFile *lbl, Handle &lblHdl, NETFile *net, Handle &netHdl,
QList<IMG::Poly> *polys) const;
const LBLFile *lbl, Handle &lblHdl, NETFile *net, Handle &netHdl,
QList<MapData::Poly> *polys) const;
bool pointObjects(Handle &hdl, const SubDiv *subdiv, SegmentType segmentType,
LBLFile *lbl, Handle &lblHdl, QList<IMG::Point> *points) const;
const LBLFile *lbl, Handle &lblHdl, QList<MapData::Point> *points) const;
bool extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
QList<IMG::Poly> *polys) const;
bool extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
Handle &lblHdl, QList<IMG::Point> *points) const;
bool links(Handle &hdl, const SubDiv *subdiv, quint32 shift, NETFile *net,
Handle &netHdl, NODFile *nod, Handle &nodHdl, LBLFile *lbl, Handle &lblHdl,
QList<IMG::Poly> *lines) const;
SegmentType segmentType, const LBLFile *lbl, Handle &lblHdl,
QList<MapData::Poly> *polys) const;
bool extPointObjects(Handle &hdl, const SubDiv *subdiv, const LBLFile *lbl,
Handle &lblHdl, QList<MapData::Point> *points) const;
bool links(Handle &hdl, const SubDiv *subdiv, quint32 shift,
const NETFile *net, Handle &netHdl, const NODFile *nod, Handle &nodHdl,
const LBLFile *lbl, Handle &lblHdl, QList<MapData::Poly> *lines) const;
bool subdivInit(Handle &hdl, SubDiv *subdiv) const;
bool subdivInit(Handle &hdl, SubDiv *subdiv);
const HuffmanTable *huffmanTable() const {return _huffmanTable;}
quint32 dictOffset() const {return _dictOffset;}
quint32 dictSize() const {return _dictSize;}
private:
QMap<SegmentType, SubDiv::Segment> segments(Handle &hdl, SubDiv *subdiv)
@ -60,8 +65,12 @@ private:
const;
bool skipGblFields(Handle &hdl, quint32 flags) const;
HuffmanTable *_huffmanTable;
quint32 _offset;
quint32 _size;
quint32 _dictOffset;
quint32 _dictSize;
quint32 _polygonsOffset;
quint32 _polygonsSize;
@ -75,10 +84,6 @@ private:
quint32 _pointsSize;
quint32 _pointsLclFlags[3];
quint32 _pointsGblFlags;
HuffmanTable _huffmanTable;
bool _init;
};
#endif // RGNFILE_H

View File

@ -42,14 +42,12 @@ public:
: _gmpOffset(0), _img(img), _blocks(new QVector<quint16>()), _path(0) {}
SubFile(SubFile *gmp, quint32 offset) : _gmpOffset(offset), _img(gmp->_img),
_blocks(gmp->_blocks), _path(gmp->_path) {}
SubFile(const QString &path)
: _gmpOffset(0), _img(0), _blocks(0), _path(new QString(path)) {}
SubFile(const QString *path)
: _gmpOffset(0), _img(0), _blocks(0), _path(path) {}
~SubFile()
{
if (!_gmpOffset) {
if (!_gmpOffset)
delete _blocks;
delete _path;
}
}
void addBlock(quint16 block) {_blocks->append(block);}
@ -151,7 +149,7 @@ private:
IMG *_img;
QVector<quint16> *_blocks;
QString *_path;
const QString *_path;
};
#endif // SUBFILE_H

View File

@ -14,7 +14,7 @@ class TREFile : public SubFile
{
public:
TREFile(IMG *img) : SubFile(img) {}
TREFile(const QString &path) : SubFile(path) {}
TREFile(const QString *path) : SubFile(path) {}
TREFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset) {}
~TREFile();

View File

@ -1,16 +1,16 @@
#include "vectortile.h"
static void copyPolys(const RectC &rect, QList<IMG::Poly> *src,
QList<IMG::Poly> *dst)
static void copyPolys(const RectC &rect, QList<MapData::Poly> *src,
QList<MapData::Poly> *dst)
{
for (int i = 0; i < src->size(); i++)
if (rect.intersects(src->at(i).boundingRect))
dst->append(src->at(i));
}
static void copyPoints(const RectC &rect, QList<IMG::Point> *src,
QList<IMG::Point> *dst)
static void copyPoints(const RectC &rect, QList<MapData::Point> *src,
QList<MapData::Point> *dst)
{
for (int j = 0; j < src->size(); j++)
if (rect.contains(src->at(j).coordinates))
@ -38,58 +38,6 @@ SubFile *VectorTile::file(SubFile::Type type)
}
}
SubFile *VectorTile::addFile(IMG *img, SubFile::Type type)
{
switch (type) {
case SubFile::TRE:
_tre = new TREFile(img);
return _tre;
case SubFile::RGN:
_rgn = new RGNFile(img);
return _rgn;
case SubFile::LBL:
_lbl = new LBLFile(img);
return _lbl;
case SubFile::NET:
_net = new NETFile(img);
return _net;
case SubFile::NOD:
_nod = new NODFile(img);
return _nod;
case SubFile::GMP:
_gmp = new SubFile(img);
return _gmp;
default:
return 0;
}
}
SubFile *VectorTile::addFile(const QString &path, SubFile::Type type)
{
switch (type) {
case SubFile::TRE:
_tre = new TREFile(path);
return _tre;
case SubFile::RGN:
_rgn = new RGNFile(path);
return _rgn;
case SubFile::LBL:
_lbl = new LBLFile(path);
return _lbl;
case SubFile::NET:
_net = new NETFile(path);
return _net;
case SubFile::NOD:
_nod = new NODFile(path);
return _nod;
case SubFile::GMP:
_gmp = new SubFile(path);
return _gmp;
default:
return 0;
}
}
bool VectorTile::init()
{
if (_gmp && !initGMP())
@ -120,23 +68,54 @@ bool VectorTile::initGMP()
return true;
}
bool VectorTile::load(SubFile::Handle &rgnHdl, SubFile::Handle &lblHdl,
SubFile::Handle &netHdl, SubFile::Handle &nodHdl)
{
_loaded = -1;
if (!_rgn->load(rgnHdl))
return false;
if (_lbl && !_lbl->load(lblHdl, _rgn, rgnHdl))
return false;
if (_net && !_net->load(netHdl, _rgn, rgnHdl))
return false;
if (_nod && !_nod->load(nodHdl))
return false;
_loaded = 1;
return true;
}
void VectorTile::clear()
{
_tre->clear();
_rgn->clear();
if (_lbl)
_lbl->clear();
if (_net)
_net->clear();
_loaded = 0;
}
void VectorTile::polys(const RectC &rect, int bits, bool baseMap,
QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
QCache<const SubDiv *, IMG::Polys> *polyCache) const
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
QCache<const SubDiv *, MapData::Polys> *polyCache)
{
SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl), netHdl(_net), nodHdl(_nod);
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
if (_loaded < 0 || (!_loaded && !load(rgnHdl, lblHdl, netHdl, nodHdl)))
return;
QList<SubDiv*> subdivs = _tre->subdivs(rect, bits, baseMap);
for (int i = 0; i < subdivs.size(); i++) {
SubDiv *subdiv = subdivs.at(i);
IMG::Polys *polys = polyCache->object(subdiv);
MapData::Polys *polys = polyCache->object(subdiv);
if (!polys) {
quint32 shift = _tre->shift(subdiv->bits());
QList<IMG::Poly> p, l;
QList<MapData::Poly> p, l;
if (!subdiv->initialized() && !_rgn->subdivInit(rgnHdl, subdiv))
continue;
@ -154,7 +133,7 @@ void VectorTile::polys(const RectC &rect, int bits, bool baseMap,
copyPolys(rect, &p, polygons);
copyPolys(rect, &l, lines);
polyCache->insert(subdiv, new IMG::Polys(p, l));
polyCache->insert(subdiv, new MapData::Polys(p, l));
} else {
copyPolys(rect, &(polys->polygons), polygons);
copyPolys(rect, &(polys->lines), lines);
@ -163,21 +142,21 @@ void VectorTile::polys(const RectC &rect, int bits, bool baseMap,
}
void VectorTile::points(const RectC &rect, int bits, bool baseMap,
QList<IMG::Point> *points, QCache<const SubDiv *,
QList<IMG::Point> > *pointCache) const
QList<MapData::Point> *points, QCache<const SubDiv *,
QList<MapData::Point> > *pointCache)
{
SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl);
SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl), netHdl(_net), nodHdl(_nod);
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
if (_loaded < 0 || (!_loaded && !load(rgnHdl, lblHdl, netHdl, nodHdl)))
return;
QList<SubDiv*> subdivs = _tre->subdivs(rect, bits, baseMap);
for (int i = 0; i < subdivs.size(); i++) {
SubDiv *subdiv = subdivs.at(i);
QList<IMG::Point> *pl = pointCache->object(subdiv);
QList<MapData::Point> *pl = pointCache->object(subdiv);
if (!pl) {
QList<IMG::Point> p;
QList<MapData::Point> p;
if (!subdiv->initialized() && !_rgn->subdivInit(rgnHdl, subdiv))
continue;
@ -189,7 +168,7 @@ void VectorTile::points(const RectC &rect, int bits, bool baseMap,
_rgn->extPointObjects(rgnHdl, subdiv, _lbl, lblHdl, &p);
copyPoints(rect, &p, points);
pointCache->insert(subdiv, new QList<IMG::Point>(p));
pointCache->insert(subdiv, new QList<MapData::Point>(p));
} else
copyPoints(rect, pl, points);
}

View File

@ -1,7 +1,6 @@
#ifndef VECTORTILE_H
#define VECTORTILE_H
#include "trefile.h"
#include "trefile.h"
#include "rgnfile.h"
#include "lblfile.h"
@ -10,7 +9,8 @@
class VectorTile {
public:
VectorTile() : _tre(0), _rgn(0), _lbl(0), _net(0), _nod(0), _gmp(0) {}
VectorTile()
: _tre(0), _rgn(0), _lbl(0), _net(0), _nod(0), _gmp(0), _loaded(0) {}
~VectorTile()
{
delete _tre; delete _rgn; delete _lbl; delete _net; delete _nod;
@ -19,21 +19,19 @@ public:
bool init();
void markAsBasemap() {_tre->markAsBasemap();}
void clear() {_tre->clear();}
void clear();
const RectC &bounds() const {return _tre->bounds();}
Range zooms() const {return _tre->zooms();}
SubFile *file(SubFile::Type type);
SubFile *addFile(IMG *img, SubFile::Type type);
SubFile *addFile(const QString &path, SubFile::Type type);
void polys(const RectC &rect, int bits, bool baseMap,
QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
QCache<const SubDiv *, IMG::Polys> *polyCache) const;
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
QCache<const SubDiv *, MapData::Polys> *polyCache);
void points(const RectC &rect, int bits, bool baseMap,
QList<IMG::Point> *points, QCache<const SubDiv*,
QList<IMG::Point> > *pointCache) const;
QList<MapData::Point> *points, QCache<const SubDiv*,
QList<MapData::Point> > *pointCache);
static bool isTileFile(SubFile::Type type)
{
@ -42,8 +40,37 @@ public:
|| type == SubFile::NOD || type == SubFile::GMP);
}
template<typename T>
SubFile *addFile(T *container, SubFile::Type type)
{
switch (type) {
case SubFile::TRE:
_tre = new TREFile(container);
return _tre;
case SubFile::RGN:
_rgn = new RGNFile(container);
return _rgn;
case SubFile::LBL:
_lbl = new LBLFile(container);
return _lbl;
case SubFile::NET:
_net = new NETFile(container);
return _net;
case SubFile::NOD:
_nod = new NODFile(container);
return _nod;
case SubFile::GMP:
_gmp = new SubFile(container);
return _gmp;
default:
return 0;
}
}
private:
bool initGMP();
bool load(SubFile::Handle &rgnHdl, SubFile::Handle &lblHdl,
SubFile::Handle &netHdl, SubFile::Handle &nodHdl);
TREFile *_tre;
RGNFile *_rgn;
@ -51,6 +78,8 @@ private:
NETFile *_net;
NODFile *_nod;
SubFile *_gmp;
int _loaded;
};
#ifndef QT_NO_DEBUG