1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-15 19:34:24 +02:00

Compare commits

..

17 Commits
7.35 ... 7.36

Author SHA1 Message Date
fa03ecd419 Use the propper array delete operator 2020-11-11 18:47:34 +01:00
609202fe57 Fixed broken QObject parenting 2020-11-11 18:46:26 +01:00
f55d6d8501 API cleanup 2020-11-10 20:14:59 +01:00
731b309ac9 Remove the special timestamps check from the FIT parser
(Use the common logic in the Track class instead)
2020-11-10 20:07:46 +01:00
f85977d881 Merge branch 'origin/master' into Weblate. 2020-11-10 01:04:34 +01:00
12e395270b Version++ 2020-11-10 01:04:28 +01:00
45b637ba17 Merge branch 'origin/master' into Weblate. 2020-11-10 00:58:58 +01:00
f139d33502 Huffman encoded labels
+ more or less related fixes/refactoring
2020-11-10 00:58:19 +01:00
63e7735abe Translated using Weblate (French)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fr/
2020-11-03 15:20:23 +01:00
27122f94ef Merge branch 'origin/master' into Weblate. 2020-11-02 20:16:38 +01:00
0644bb72a0 Broken subdivs are more common than one would expect... 2020-11-02 20:16:02 +01:00
a4d14511de Merge branch 'origin/master' into Weblate. 2020-11-02 00:19:09 +01:00
1225d350d4 Allow broken subdiv bounds produced by mkgmap 2020-11-02 00:18:27 +01:00
a1d93cc548 Merge branch 'origin/master' into Weblate. 2020-11-01 23:48:14 +01:00
80f5bbfbce Print a warning on invalid subdiv bounds 2020-11-01 23:47:44 +01:00
70c9431ee4 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (374 of 374 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/uk/
2020-10-28 14:26:59 +01:00
de7664ccc7 Added PNG export info 2020-10-28 12:15:46 +01:00
33 changed files with 699 additions and 344 deletions

View File

@ -1,4 +1,4 @@
version: 7.35.{build}
version: 7.36.{build}
configuration:
- Release

View File

@ -9,7 +9,7 @@ GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common G
* Support for DEM files (SRTM HGT).
* Support for multiple tracks in one view.
* Support for POI files.
* Print/export to PDF.
* Print/export to PDF/PNG.
* Full-screen mode.
* HiDPI/Retina displays & maps support.
* Native GUI for Windows, Mac OS X and Linux.

View File

@ -3,7 +3,7 @@ unix:!macx {
} else {
TARGET = GPXSee
}
VERSION = 7.35
VERSION = 7.36
QT += core \
gui \
@ -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

@ -1272,7 +1272,7 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="442"/>
<source>Use segments</source>
<translation type="unfinished"></translation>
<translation>Utiliser des segments</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="481"/>
@ -1529,7 +1529,7 @@
<message>
<location filename="../src/GUI/pdfexportdialog.cpp" line="62"/>
<source>cm</source>
<translation type="unfinished"></translation>
<translation>cm</translation>
</message>
<message>
<location filename="../src/GUI/pdfexportdialog.cpp" line="68"/>
@ -1604,22 +1604,22 @@
<message>
<location filename="../src/GUI/pngexportdialog.cpp" line="41"/>
<source>Use anti-aliasing</source>
<translation type="unfinished">Utiliser l&apos;anticrénelage</translation>
<translation>Utiliser l&apos;anticrénelage</translation>
</message>
<message>
<location filename="../src/GUI/pngexportdialog.cpp" line="45"/>
<source>Image Setup</source>
<translation type="unfinished"></translation>
<translation>Paramètres d&apos;image</translation>
</message>
<message>
<location filename="../src/GUI/pngexportdialog.cpp" line="48"/>
<source>Image width:</source>
<translation type="unfinished"></translation>
<translation>largeur :</translation>
</message>
<message>
<location filename="../src/GUI/pngexportdialog.cpp" line="49"/>
<source>Image height:</source>
<translation type="unfinished"></translation>
<translation>hauteur :</translation>
</message>
<message>
<location filename="../src/GUI/pngexportdialog.cpp" line="50"/>

View File

@ -1525,7 +1525,7 @@
<message>
<location filename="../src/GUI/pdfexportdialog.cpp" line="62"/>
<source>in</source>
<translation type="unfinished">дюйм</translation>
<translation>in</translation>
</message>
<message>
<location filename="../src/GUI/pdfexportdialog.cpp" line="62"/>
@ -1605,22 +1605,22 @@
<message>
<location filename="../src/GUI/pngexportdialog.cpp" line="41"/>
<source>Use anti-aliasing</source>
<translation type="unfinished">Використовувати згладжування</translation>
<translation>Використовувати згладжування</translation>
</message>
<message>
<location filename="../src/GUI/pngexportdialog.cpp" line="45"/>
<source>Image Setup</source>
<translation type="unfinished"></translation>
<translation>Налаштування зображення</translation>
</message>
<message>
<location filename="../src/GUI/pngexportdialog.cpp" line="48"/>
<source>Image width:</source>
<translation type="unfinished"></translation>
<translation>Ширина зображення:</translation>
</message>
<message>
<location filename="../src/GUI/pngexportdialog.cpp" line="49"/>
<source>Image height:</source>
<translation type="unfinished"></translation>
<translation>Висота зображення:</translation>
</message>
<message>
<location filename="../src/GUI/pngexportdialog.cpp" line="50"/>

View File

@ -7,7 +7,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "7.35"
!define VERSION "7.36"
; The file to write
OutFile "GPXSee-${VERSION}.exe"

View File

@ -7,7 +7,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "7.35"
!define VERSION "7.36"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"

View File

@ -140,10 +140,9 @@ void GUI::createMapActions()
MapAction *GUI::createMapAction(Map *map)
{
MapAction *a = new MapAction(map);
MapAction *a = new MapAction(map, _mapsActionGroup);
a->setMenuRole(QAction::NoRole);
a->setCheckable(true);
a->setActionGroup(_mapsActionGroup);
connect(a, SIGNAL(triggered()), this, SLOT(mapChanged()));
return a;

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

@ -51,13 +51,13 @@ class FITParser::CTX {
public:
CTX(QFile *file, QVector<Waypoint> &waypoints)
: file(file), waypoints(waypoints), len(0), endian(0), timestamp(0),
lastWrite(0), ratio(NAN) {}
ratio(NAN) {}
QFile *file;
QVector<Waypoint> &waypoints;
quint32 len;
quint8 endian;
quint32 timestamp, lastWrite;
quint32 timestamp;
MessageDefinition defs[16];
qreal ratio;
Trackpoint trackpoint;
@ -361,14 +361,12 @@ bool FITParser::parseData(CTX &ctx, const MessageDefinition *def)
ctx.ratio = ((qreal)front / (qreal)rear);
}
} else if (def->globalId == RECORD_MESSAGE) {
if (ctx.timestamp > ctx.lastWrite
&& ctx.trackpoint.coordinates().isValid()) {
if (ctx.trackpoint.coordinates().isValid()) {
ctx.trackpoint.setTimestamp(QDateTime::fromTime_t(ctx.timestamp
+ 631065600));
ctx.trackpoint.setRatio(ctx.ratio);
ctx.segment.append(ctx.trackpoint);
ctx.trackpoint = Trackpoint();
ctx.lastWrite = ctx.timestamp;
}
} else if (def->globalId == COURSE_POINT)
if (waypoint.coordinates().isValid())

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

@ -21,7 +21,7 @@ public:
struct Poly {
/* QPointF insted of Coordinates for performance reasons (no need to
duplicate all the vectors for drawing). Note, that we do not want to
ll2xy() the points in the IMG class as this can not be done in
ll2xy() the points in the MapData class as this can not be done in
parallel. */
QVector<QPointF> points;
Label label;
@ -44,15 +44,6 @@ public:
{return id < other.id;}
};
struct Polys {
Polys() {}
Polys(const QList<Poly> &polygons, const QList<Poly> &lines)
: polygons(polygons), lines(lines) {}
QList<Poly> polygons;
QList<Poly> lines;
};
MapData();
virtual ~MapData();
@ -87,8 +78,20 @@ protected:
QString _errorString;
private:
struct Polys {
Polys() {}
Polys(const QList<Poly> &polygons, const QList<Poly> &lines)
: polygons(polygons), lines(lines) {}
QList<Poly> polygons;
QList<Poly> lines;
};
QCache<const SubDiv*, Polys> _polyCache;
QCache<const SubDiv*, QList<Point> > _pointCache;
friend class VectorTile;
friend class PolyCTX;
};
#ifndef QT_NO_DEBUG

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
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;
quint8 tableId = ((info >> 2) & 0xF);
if (_linksSize && (!rgn->huffmanTable() || rgn->huffmanTable()->id()
!= tableId)) {
_huffmanTable = new HuffmanTable(tableId);
if (!_huffmanTable->load(rgn, rgnHdl))
return false;
}
_init = true;
_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

@ -202,14 +202,18 @@ bool TREFile::load(int idx)
double min[2], max[2];
RectC bounds(Coordinates(LB(lon - width), toWGS24(lat + height)),
Coordinates(RB(lon + width), toWGS24(lat - height)));
if (!bounds.isValid())
goto error;
min[0] = bounds.left();
min[1] = bounds.bottom();
max[0] = bounds.right();
max[1] = bounds.top();
/* both mkgmap and cGPSmapper generate all kinds of broken subdiv bounds
(zero lat/lon, zero width/height, ...) so we check only that the
subdiv item does not break the rtree, not for full bounds validity. */
if (!(min[0] <= max[0] && min[1] <= max[1]))
goto error;
tree->Insert(min, max, s);
}

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