1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-07 16:02:51 +02:00

Compare commits

..

13 Commits
10.6 ... 10.7

Author SHA1 Message Date
8f9af0d973 Be more tolerant to broken TYP files
Where possible, only skip the point/line/polygon entry, not the whole TYP file.
2022-04-24 17:19:26 +02:00
208e31c6de Explicitly marking the basemaps is not required 2022-04-24 09:17:28 +02:00
959d08ba94 Removed broken coordinates adjustment 2022-04-22 22:26:47 +02:00
5f16f7b367 Fixed/improved IMG basemaps handling 2022-04-20 19:40:44 +02:00
baee8b3484 Version++ 2022-04-19 22:19:44 +02:00
c694c3e300 A (hopefully) complete path shape parsing fix
fixes #430
2022-04-19 22:17:19 +02:00
1458d66798 Fixed path shape parsing 2022-04-16 23:39:03 +02:00
62fa0cce36 Merge branch 'origin/master' into Weblate. 2022-04-14 23:33:26 +02:00
b115c041be Do not recompute the adjacency info offset as we are lready there 2022-04-14 23:32:50 +02:00
f63c1fee1c Translated using Weblate (Esperanto)
Currently translated at 94.0% (413 of 439 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/eo/
2022-04-14 18:10:22 +02:00
88d9f10a78 Translated using Weblate (Ukrainian)
Currently translated at 92.4% (406 of 439 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/uk/
2022-04-14 18:10:21 +02:00
ec06793a19 Code cleanup 2022-04-14 04:31:46 +02:00
53cdc86aa0 Improved error handling + code cleanup 2022-04-13 22:13:57 +02:00
21 changed files with 622 additions and 587 deletions

View File

@ -1,4 +1,4 @@
version: 10.6.{build}
version: 10.7.{build}
configuration:
- Release

View File

@ -3,7 +3,7 @@ unix:!macx {
} else {
TARGET = GPXSee
}
VERSION = 10.6
VERSION = 10.7
QT += core \
gui \

View File

@ -516,7 +516,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="418"/>
<source>Download DEM data</source>
<translation type="unfinished"></translation>
<translation>Elŝuti DEM-datumojn</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="423"/>
@ -1192,17 +1192,17 @@
<message>
<location filename="../src/GUI/motioninfoitem.cpp" line="87"/>
<source>kn</source>
<translation type="unfinished">kn</translation>
<translation>kn</translation>
</message>
<message>
<location filename="../src/GUI/motioninfoitem.cpp" line="90"/>
<source>mi/h</source>
<translation type="unfinished">mi/h</translation>
<translation>mi/h</translation>
</message>
<message>
<location filename="../src/GUI/motioninfoitem.cpp" line="93"/>
<source>km/h</source>
<translation type="unfinished">km/h</translation>
<translation>km/h</translation>
</message>
<message>
<location filename="../src/GUI/motioninfoitem.cpp" line="100"/>
@ -1629,7 +1629,7 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="290"/>
<source>Info color:</source>
<translation type="unfinished"></translation>
<translation>Teksta koloro:</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="523"/>
@ -1687,7 +1687,7 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="622"/>
<source>Plugin:</source>
<translation type="unfinished"></translation>
<translation>Kromprogramo:</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="642"/>

View File

@ -6,7 +6,7 @@
<message>
<location filename="../src/GUI/authenticationwidget.cpp" line="15"/>
<source>Username:</source>
<translation type="unfinished"></translation>
<translation>Ім&apos;я користувача:</translation>
</message>
<message>
<location filename="../src/GUI/authenticationwidget.cpp" line="16"/>
@ -157,7 +157,7 @@
<message>
<location filename="../src/data/data.cpp" line="167"/>
<source>TwoNav files</source>
<translation type="unfinished"></translation>
<translation>TwoNav файли</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="168"/>
@ -379,7 +379,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="263"/>
<source>Unselect all files</source>
<translation type="unfinished"></translation>
<translation>Скасування виділення всіх файлів</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="268"/>
@ -436,7 +436,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="335"/>
<source>Show position</source>
<translation type="unfinished"></translation>
<translation>Показати позицію</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="341"/>
@ -446,7 +446,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="346"/>
<source>Show coordinates</source>
<translation type="unfinished"></translation>
<translation>Показати координати</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="352"/>
@ -516,7 +516,7 @@
<message>
<location filename="../src/GUI/gui.cpp" line="418"/>
<source>Download DEM data</source>
<translation type="unfinished"></translation>
<translation>Завантажити DEM дані</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="423"/>
@ -1208,7 +1208,7 @@
<message>
<location filename="../src/GUI/motioninfoitem.cpp" line="100"/>
<source>ft/min</source>
<translation type="unfinished"></translation>
<translation>фут/хв</translation>
</message>
<message>
<location filename="../src/GUI/motioninfoitem.cpp" line="103"/>
@ -1603,7 +1603,7 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="289"/>
<source>Crosshair color:</source>
<translation type="unfinished"></translation>
<translation>Колір перехрестя:</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="290"/>

View File

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

View File

@ -10,11 +10,17 @@ public:
Range() {_min = 0; _max = 0;}
Range(int min, int max) : _min(min), _max(max) {}
bool operator==(const Range &other) const
{return _min == other._min && _max == other._max;}
bool operator!=(const Range &other) const
{return _min != other._min || _max != other._max;}
int min() const {return _min;}
int max() const {return _max;}
int size() const {return (_max - _min);}
bool isValid() const {return size() >= 0;}
bool isNull() const {return _min == 0 && _max == 0;}
void setMin(int min) {_min = min;}
void setMax(int max) {_max = max;}

View File

@ -94,8 +94,6 @@ bool GMAPData::loadTile(const QDir &dir, bool baseMap)
delete tile;
return false;
}
if (baseMap)
tile->markAsBasemap();
double min[2], max[2];
min[0] = tile->bounds().left();
@ -108,6 +106,9 @@ bool GMAPData::loadTile(const QDir &dir, bool baseMap)
if (tile->zooms().min() < _zooms.min())
_zooms.setMin(tile->zooms().min());
if (baseMap)
_baseMap = tile->zooms();
return true;
}
@ -124,10 +125,7 @@ GMAPData::GMAPData(const QString &fileName) : MapData(fileName)
}
QDir dataDir(baseDir.filePath(dataDirPath));
QFileInfoList ml = dataDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
QFileInfo baseMap(dataDir.filePath(baseMapPath));
_baseMap = !baseMapPath.isEmpty() && baseMap.exists();
for (int i = 0; i < ml.size(); i++) {
const QFileInfo &fi = ml.at(i);

View File

@ -84,10 +84,7 @@ public:
bool readNext(qint32 &lonDelta, qint32 &latDelta)
{
if (!(readDelta(_lonSign, lonDelta) && readDelta(_latSign, latDelta)))
return false;
return (lonDelta || latDelta);
return (readDelta(_lonSign, lonDelta) && readDelta(_latSign, latDelta));
}
protected:

View File

@ -137,8 +137,6 @@ bool IMGData::readFAT(QFile &file, TileMap &tileMap)
bool IMGData::createTileTree(const TileMap &tileMap)
{
int minMapZoom = 24;
for (TileMap::const_iterator it = tileMap.constBegin();
it != tileMap.constEnd(); ++it) {
VectorTile *tile = it.value();
@ -160,23 +158,31 @@ bool IMGData::createTileTree(const TileMap &tileMap)
_bounds |= tile->bounds();
if (tile->zooms().min() < _zooms.min())
_zooms.setMin(tile->zooms().min());
if (tile->zooms().min() < minMapZoom)
minMapZoom = tile->zooms().min();
}
// Detect and mark basemap
TileTree::Iterator it;
bool baseMap = false;
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it)) {
VectorTile *tile = _tileTree.GetAt(it);
if (tile->zooms().min() > minMapZoom)
_baseMap = true;
if (tile->zooms().min() == minMapZoom)
tile->markAsBasemap();
if (tile->zooms().min() > _zooms.min()) {
baseMap = true;
break;
}
// Allow some extra zoom out on maps without basemaps, but not too much as
// this would kill the rendering performance
if (!_baseMap)
}
if (baseMap) {
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it);
_tileTree.GetNext(it)) {
VectorTile *tile = _tileTree.GetAt(it);
if (tile->zooms().min() == _zooms.min())
_baseMap = tile->zooms();
}
} else {
/* Allow some extra zoom out on maps without basemaps, but not too much
as this would kill the rendering performance. */
_zooms.setMin(_zooms.min() - 2);
}
return (_tileTree.Count() > 0);
}

View File

@ -26,8 +26,7 @@ bool MapData::pointCb(VectorTile *tile, void *context)
MapData::MapData(const QString &fileName)
: _fileName(fileName), _typ(0), _style(0), _zooms(24, 28), _baseMap(false),
_valid(false)
: _fileName(fileName), _typ(0), _style(0), _zooms(24, 28), _valid(false)
{
_polyCache.setMaxCost(CACHED_SUBDIVS_COUNT);
_pointCache.setMaxCost(CACHED_SUBDIVS_COUNT);

View File

@ -79,7 +79,7 @@ protected:
Style *_style;
TileTree _tileTree;
Range _zooms;
bool _baseMap;
Range _baseMap;
bool _valid;
QString _errorString;
@ -96,7 +96,7 @@ private:
struct PolyCTX
{
PolyCTX(const RectC &rect, int bits, bool baseMap,
PolyCTX(const RectC &rect, int bits, const Range &baseMap,
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
QCache<const SubDiv*, MapData::Polys> *polyCache)
: rect(rect), bits(bits), baseMap(baseMap), polygons(polygons),
@ -104,7 +104,7 @@ private:
const RectC &rect;
int bits;
bool baseMap;
const Range &baseMap;
QList<MapData::Poly> *polygons;
QList<MapData::Poly> *lines;
QCache<const SubDiv*, MapData::Polys> *polyCache;
@ -112,7 +112,7 @@ private:
struct PointCTX
{
PointCTX(const RectC &rect, int bits, bool baseMap,
PointCTX(const RectC &rect, int bits, const Range &baseMap,
QList<MapData::Point> *points,
QCache<const SubDiv*, QList<MapData::Point> > *pointCache)
: rect(rect), bits(bits), baseMap(baseMap), points(points),
@ -120,7 +120,7 @@ private:
const RectC &rect;
int bits;
bool baseMap;
const Range &baseMap;
QList<MapData::Point> *points;
QCache<const SubDiv*, QList<MapData::Point> > *pointCache;
};

View File

@ -152,9 +152,10 @@ bool NETFile::readLine(BitStream4R &bs, const SubDiv *subdiv,
qint32 lonDelta, latDelta;
while (stream.readNext(lonDelta, latDelta)) {
if (!(lonDelta | latDelta))
break;
pos.rx() += LS(lonDelta, 32-subdiv->bits());
if (pos.rx() < 0 && subdiv->lon() >= 0)
pos.rx() = 0x7fffffff;
pos.ry() += LS(latDelta, 32-subdiv->bits());
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
@ -235,10 +236,12 @@ bool NETFile::readShape(const NODFile *nod, SubFile::Handle &nodHdl,
if (!stream.readNext(lonDelta, latDelta))
break;
if (hasAdjustBit && !stream.read(1, adjustBit))
return false;
if (!(lonDelta | latDelta) && !startWithStream && !hasAdjustBit)
break;
stepsCnt++;
if (useEosBit) {

View File

@ -6,6 +6,8 @@ using namespace IMG;
#define ARRAY_SIZE(array) \
(sizeof(array) / sizeof(array[0]))
#define DELTA(val, llBits, maxBits) \
(((int)((val) << (32 - (llBits))) >> (32 - (llBits))) << (32 - (maxBits)))
static const struct
{
@ -166,6 +168,7 @@ bool NODFile::linkInfo(Handle &hdl, const BlockInfo &blockInfo, quint32 linkId,
if (!(linkInfo.flags & 0x100)) {
if (!bs.read(s1, linkInfo.linkOffset))
return false;
linkInfo.nodeOffset = 0xFFFFFFFF;
} else {
if (!bs.read(s1 - s2, linkInfo.linkOffset))
return false;
@ -180,50 +183,45 @@ bool NODFile::linkInfo(Handle &hdl, const BlockInfo &blockInfo, quint32 linkId,
return true;
}
bool NODFile::nodeInfo(Handle &hdl, const BlockInfo &blockInfo,
quint32 nodeOffset, NodeInfo &nodeInfo) const
bool NODFile::nodeInfo(Handle &hdl, AdjacencyInfo &adj) const
{
quint32 infoOffset = (nodeOffset << _nodeShift) + _block.offset;
if (infoOffset > _block.offset + _block.size || infoOffset < blockInfo.offset)
quint32 infoOffset = (adj.nodeOffset << _nodeShift) + _block.offset;
if (infoOffset > _block.offset + _block.size
|| infoOffset < adj.blockInfo.offset)
return false;
if (!seek(hdl, infoOffset))
return false;
BitStream1 bs(*this, hdl, _block.offset + _block.size - infoOffset);
if (!bs.read(8, nodeInfo.flags))
if (!bs.read(8, adj.nodeInfo.flags))
return false;
if ((nodeInfo.flags & 7) >= ARRAY_SIZE(LLBITS))
if ((adj.nodeInfo.flags & 7) >= ARRAY_SIZE(LLBITS))
return false;
quint8 lonBits = LLBITS[nodeInfo.flags & 7].lon;
quint8 latBits = LLBITS[nodeInfo.flags & 7].lat;
quint8 lonBits = LLBITS[adj.nodeInfo.flags & 7].lon;
quint8 latBits = LLBITS[adj.nodeInfo.flags & 7].lat;
quint8 maxBits = ((_flags >> 10) & 7) | 0x18;
quint32 lon, lat;
if (!(bs.read(lonBits, lon) && bs.read(latBits, lat)))
return false;
quint8 lonShift = 0x20 - lonBits;
quint8 latShift = 0x20 - latBits;
quint8 shift = 0x20 - maxBits;
QPoint pos(
(((int)(lon << lonShift) >> lonShift) << shift) + blockInfo.hdr.nodeLonBase,
(((int)(lat << latShift) >> latShift) << shift) + blockInfo.hdr.nodeLatBase);
nodeInfo.bytes = ((lonBits + latBits) >> 3) + 1;
adj.blockInfo.hdr.nodeLonBase + DELTA(lon, lonBits, maxBits),
adj.blockInfo.hdr.nodeLatBase + DELTA(lat, latBits, maxBits));
if ((maxBits < 0x1c) && (nodeInfo.flags & 8)) {
if ((maxBits < 0x1c) && (adj.nodeInfo.flags & 8)) {
quint8 extraBits = 0x1c - maxBits;
quint32 extraLon, extraLat;
if (!(bs.read(extraBits, extraLon) && bs.read(extraBits, extraLat)))
return false;
pos.setX(pos.x() | extraLon << 4); pos.setY(pos.y() | extraLat << 4);
nodeInfo.bytes++;
}
// TODO?: check and adjust (shift) coordinates
nodeInfo.pos = pos;
adj.nodeInfo.pos = pos;
return true;
}
@ -282,11 +280,7 @@ bool NODFile::nodeBlock(Handle &hdl, quint32 nodeOffset,
bool NODFile::absAdjInfo(Handle &hdl, AdjacencyInfo &adj) const
{
quint32 infoOffset = (adj.nodeOffset << _nodeShift) + _block.offset
+ adj.nodeInfo.bytes;
if (!seek(hdl, infoOffset))
return false;
BitStream1 bs(*this, hdl, _block.offset + _block.size - infoOffset);
BitStream1 bs(*this, hdl, _block.offset + _block.size - pos(hdl));
quint8 linkId = adj.blockInfo.hdr.linksCount;
quint32 m2p = 2;
@ -386,12 +380,7 @@ bool NODFile::absAdjInfo(Handle &hdl, AdjacencyInfo &adj) const
bool NODFile::relAdjInfo(Handle &hdl, AdjacencyInfo &adj) const
{
quint32 infoOffset = (adj.nodeOffset << _nodeShift) + _block.offset
+ adj.nodeInfo.bytes;
if (!seek(hdl, infoOffset))
return false;
BitStream1 bs(*this, hdl, _block.offset + _block.size - infoOffset);
BitStream1 bs(*this, hdl, _block.offset + _block.size - pos(hdl));
quint32 linkId = adj.blockInfo.hdr.linksCount;
quint32 skip = 8;
@ -480,14 +469,14 @@ bool NODFile::relAdjInfo(Handle &hdl, AdjacencyInfo &adj) const
return true;
}
int NODFile::nextNode(Handle &hdl, AdjacencyInfo &adjInfo) const
int NODFile::nextNode(Handle &hdl, AdjacencyInfo &adj) const
{
if (adjInfo.nodeOffset == 0xFFFFFFFF)
if (adj.nodeOffset == 0xFFFFFFFF)
return 1;
if (!nodeInfo(hdl, adjInfo.blockInfo, adjInfo.nodeOffset, adjInfo.nodeInfo))
if (!nodeInfo(hdl, adj))
return -1;
if (!adjacencyInfo(hdl, adjInfo))
if (!adjacencyInfo(hdl, adj))
return -1;
return 0;

View File

@ -40,7 +40,6 @@ public:
{
QPoint pos;
quint8 flags;
quint8 bytes;
};
struct AdjacencyInfo
@ -78,13 +77,14 @@ public:
LinkInfo &linkInfo) const;
bool linkType(Handle &hdl, const BlockInfo &blockInfo, quint8 linkId,
quint32 &type) const;
int nextNode(Handle &hdl, AdjacencyInfo &adjInfo) const;
int nextNode(Handle &hdl, AdjacencyInfo &adj) const;
private:
bool nodeInfo(Handle &hdl, const BlockInfo &blockInfo, quint32 nodeOffset,
NodeInfo &nodeInfo) const;
bool nodeOffset(Handle &hdl, const BlockInfo &blockInfo, quint8 nodeId,
quint32 &nodeOffset) const;
bool nodeBlock(Handle &hdl, quint32 nodeOffset, BlockInfo &blockInfo) const;
bool readBlock(Handle &hdl, quint32 blockOffset, BlockInfo &blockInfo) const;
bool nodeInfo(Handle &hdl, AdjacencyInfo &adj) const;
bool absAdjInfo(Handle &hdl, AdjacencyInfo &adj) const;
bool relAdjInfo(Handle &hdl, AdjacencyInfo &adj) const;
bool adjacencyInfo(Handle &hdl, AdjacencyInfo &adj) const
@ -92,8 +92,6 @@ private:
return (adj.nodeInfo.flags & 0x20) ? absAdjInfo(hdl, adj)
: relAdjInfo(hdl, adj);
}
bool nodeBlock(Handle &hdl, quint32 nodeOffset, BlockInfo &blockInfo) const;
bool readBlock(Handle &hdl, quint32 blockOffset, BlockInfo &blockInfo) const;
Section _block, _index;
quint32 _flags, _indexFlags;

View File

@ -387,9 +387,10 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
poly.points.append(QPointF(c.lon(), c.lat()));
while (stream.readNext(lonDelta, latDelta)) {
if (!(lonDelta | latDelta))
break;
pos.rx() += LS(lonDelta, 32-subdiv->bits()-shift);
if (pos.rx() < 0 && subdiv->lon() >= 0)
pos.rx() = 0x7fffffff;
pos.ry() += LS(latDelta, 32-subdiv->bits()-shift);
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));

View File

@ -4,6 +4,153 @@
using namespace IMG;
static bool readColor(SubFile *file, SubFile::Handle &hdl, QColor &color)
{
quint8 b, g, r;
if (!(file->readByte(hdl, &b) && file->readByte(hdl, &g)
&& file->readByte(hdl, &r)))
return false;
color = qRgb(r, g, b);
return true;
}
static bool readColorTable(SubFile *file, SubFile::Handle &hdl, QImage& img,
int colors, int bpp, bool transparent)
{
img.setColorCount(colors);
if (transparent) {
quint8 byte;
quint32 bits = 0, reg = 0, mask = 0x000000FF;
for (int i = 0; i < colors; i++) {
while (bits < 28) {
if (!file->readByte(hdl, &byte))
return false;
mask = 0x000000FF << bits;
reg = reg & (~mask);
reg = reg | (byte << bits);
bits += 8;
}
img.setColor(i, qRgba((reg >> 16) & 0x0FF, (reg >> 8) & 0x0FF,
reg & 0x0FF, ~((reg >> 24) & 0x0F) << 4));
reg = reg >> 28;
bits -= 28;
}
for (int i = colors; i < 1<<bpp; i++)
img.setColor(i, qRgba(0, 0, 0, 0));
} else {
QColor color;
for (int i = 0; i < colors; i++) {
if (!readColor(file, hdl, color))
return false;
img.setColor(i, color.rgb());
}
for (int i = colors; i < 1<<bpp; i++)
img.setColor(i, qRgba(0, 0, 0, 0));
}
return true;
}
static bool readBitmap(SubFile *file, SubFile::Handle &hdl, QImage &img,
int bpp)
{
if (!bpp)
return true;
for (int y = 0; y < img.height(); y++) {
for (int x = 0; x < img.width(); x += 8/bpp) {
quint8 color;
if (!file->readByte(hdl, &color))
return false;
for (int i = 0; i < 8/bpp && x + i < img.width(); i++) {
int value = (i > 0) ? (color >>= bpp) : color;
if (bpp == 4)
value = value & 0xf;
else if (bpp == 2)
value = value & 0x3;
else if (bpp == 1)
value = value & 0x1;
img.setPixel(x + i, y, value);
}
}
}
return true;
}
static int colors2bpp(quint8 colors, quint8 flags)
{
switch (flags) {
case 0x00:
if (colors < 3)
return colors;
else if (colors == 3)
return 2;
else if (colors < 16)
return 4;
else
return 8;
case 0x10:
if (colors == 0)
return 1;
else if (colors < 3)
return 2;
else if (colors < 15)
return 4;
else
return 8;
case 0x20:
if (colors == 0)
return -1;
else if (colors < 3)
return colors;
else if (colors < 4)
return 2;
else if (colors < 16)
return 4;
else
return 8;
default:
return -1;
}
}
static bool skipLabel(SubFile *file, SubFile::Handle &hdl)
{
quint32 len;
if (!file->readVUInt32(hdl, len))
return false;
if (!file->seek(hdl, file->pos(hdl) + len))
return false;
return true;
}
static QImage railroad()
{
QImage img(16, 4, QImage::Format_ARGB32_Premultiplied);
img.fill(QColor("#717171"));
QPainter p(&img);
p.setPen(QPen(Qt::white, 2));
p.drawLine(9, 2, 15, 2);
return img;
}
void Style::defaultPolygonStyle()
{
_polygons[TYPE(0x01)] = Polygon(QBrush("#dfd3b5"));
@ -151,17 +298,6 @@ void Style::defaultPolygonStyle()
<< TYPE(0x13) << 0x10900;
}
static QImage railroad()
{
QImage img(16, 4, QImage::Format_ARGB32_Premultiplied);
img.fill(QColor("#717171"));
QPainter p(&img);
p.setPen(QPen(Qt::white, 2));
p.drawLine(9, 2, 15, 2);
return img;
}
void Style::defaultLineStyle()
{
_lines[TYPE(0x01)] = Line(QPen(QColor("#9bd772"), 2, Qt::SolidLine),
@ -537,62 +673,6 @@ void Style::defaultPointStyle()
_points[0x10705] = Point(QImage(":/IMG/anchoring-prohibited.png"));
}
static bool readBitmap(SubFile *file, SubFile::Handle &hdl, QImage &img,
int bpp)
{
if (!bpp)
return true;
for (int y = 0; y < img.height(); y++) {
for (int x = 0; x < img.width(); x += 8/bpp) {
quint8 color;
if (!file->readByte(hdl, &color))
return false;
for (int i = 0; i < 8/bpp && x + i < img.width(); i++) {
int value = (i > 0) ? (color >>= bpp) : color;
if (bpp == 4)
value = value & 0xf;
else if (bpp == 2)
value = value & 0x3;
else if (bpp == 1)
value = value & 0x1;
img.setPixel(x + i, y, value);
}
}
}
return true;
}
static bool readColor(SubFile *file, SubFile::Handle &hdl, QColor &color)
{
quint8 b, g, r;
if (!(file->readByte(hdl, &b) && file->readByte(hdl, &g)
&& file->readByte(hdl, &r)))
return false;
color = qRgb(r, g, b);
return true;
}
static bool skipLabel(SubFile *file, SubFile::Handle &hdl)
{
quint32 len;
if (!file->readVUInt32(hdl, len))
return false;
if (!file->seek(hdl, file->pos(hdl) + len))
return false;
return true;
}
bool Style::itemInfo(SubFile *file, SubFile::Handle &hdl,
const Section &section, ItemInfo &info)
{
@ -623,21 +703,9 @@ bool Style::itemInfo(SubFile *file, SubFile::Handle &hdl,
return true;
}
bool Style::parsePolygons(SubFile *file, SubFile::Handle &hdl,
const Section &section)
bool Style::parsePolygon(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
quint8 t8, flags;
if (!(file->seek(hdl, section.offset + info.offset)
&& file->readByte(hdl, &t8)))
@ -734,26 +802,13 @@ bool Style::parsePolygons(SubFile *file, SubFile::Handle &hdl,
default:
return false;
}
}
return true;
}
bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
const Section &section)
bool Style::parseLine(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
quint8 t8_1, t8_2, flags, rows;
if (!(file->seek(hdl, section.offset + info.offset)
&& file->readByte(hdl, &t8_1) && file->readByte(hdl, &t8_2)))
@ -938,108 +993,15 @@ bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
}
_lines[type].setTextFontSize((FontSize)(labelFlags & 0x07));
}
}
return true;
}
static int colors2bpp(quint8 colors, quint8 flags)
bool Style::parsePoint(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type)
{
switch (flags) {
case 0x00:
if (colors < 3)
return colors;
else if (colors == 3)
return 2;
else if (colors < 16)
return 4;
else
return 8;
case 0x10:
if (colors == 0)
return 1;
else if (colors < 3)
return 2;
else if (colors < 15)
return 4;
else
return 8;
case 0x20:
if (colors == 0)
return -1;
else if (colors < 3)
return colors;
else if (colors < 4)
return 2;
else if (colors < 16)
return 4;
else
return 8;
default:
return -1;
}
}
static bool readColorTable(SubFile *file, SubFile::Handle &hdl, QImage& img,
int colors, int bpp, bool transparent)
{
img.setColorCount(colors);
if (transparent) {
quint8 byte;
quint32 bits = 0, reg = 0, mask = 0x000000FF;
for (int i = 0; i < colors; i++) {
while (bits < 28) {
if (!file->readByte(hdl, &byte))
return false;
mask = 0x000000FF << bits;
reg = reg & (~mask);
reg = reg | (byte << bits);
bits += 8;
}
img.setColor(i, qRgba((reg >> 16) & 0x0FF, (reg >> 8) & 0x0FF,
reg & 0x0FF, ~((reg >> 24) & 0x0F) << 4));
reg = reg >> 28;
bits -= 28;
}
for (int i = colors; i < 1<<bpp; i++)
img.setColor(i, qRgba(0, 0, 0, 0));
} else {
QColor color;
for (int i = 0; i < colors; i++) {
if (!readColor(file, hdl, color))
return false;
img.setColor(i, color.rgb());
}
for (int i = colors; i < 1<<bpp; i++)
img.setColor(i, qRgba(0, 0, 0, 0));
}
return true;
}
bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
const Section &section)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype
: (info.type << 8) | info.subtype;
quint8 t8_1, width, height, numColors, imgType;
if (!(file->seek(hdl, section.offset + info.offset)
&& file->readByte(hdl, &t8_1) && file->readByte(hdl, &width)
&& file->readByte(hdl, &height) && file->readByte(hdl, &numColors)
@ -1051,7 +1013,7 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
int bpp = colors2bpp(numColors, imgType);
if (bpp <= 0)
continue;
return true;
QImage img(width, height, QImage::Format_Indexed8);
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
return false;
@ -1064,7 +1026,7 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
&& file->readByte(hdl, &imgType)))
return false;
if ((bpp = colors2bpp(numColors, imgType)) < 0)
continue;
return true;
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
return false;
if (!readBitmap(file, hdl, img, bpp))
@ -1074,7 +1036,7 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
&& file->readByte(hdl, &imgType)))
return false;
if ((bpp = colors2bpp(numColors, imgType)) < 0)
continue;
return true;
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
return false;
}
@ -1094,6 +1056,79 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
}
_points[type].setTextFontSize((FontSize)(labelFlags & 0x07));
}
return true;
}
bool Style::parsePolygons(SubFile *file, SubFile::Handle &hdl,
const Section &section)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
if (!parsePolygon(file, hdl, section, info, type))
qWarning("%s: %x: broken polygon style",
qPrintable(file->fileName()), type);
}
return true;
}
bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
const Section &section)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
if (!parseLine(file, hdl, section, info, type))
qWarning("%s: %x: broken line style", qPrintable(file->fileName()),
type);
}
return true;
}
bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
const Section &section)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype
: (info.type << 8) | info.subtype;
if (!parsePoint(file, hdl, section, info, type))
qWarning("%s: %x: broken point style", qPrintable(file->fileName()),
type);
}
return true;

View File

@ -147,18 +147,25 @@ private:
bool parseTYPFile(SubFile *file);
bool parsePoints(SubFile *file, SubFile::Handle &hdl,
const Section &section);
bool parsePoint(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type);
bool parseLines(SubFile *file, SubFile::Handle &hdl,
const Section &section);
bool parseLine(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type);
bool parsePolygons(SubFile *file, SubFile::Handle &hdl,
const Section &section);
bool parsePolygon(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type);
bool parseDrawOrder(SubFile *file, SubFile::Handle &hdl,
const Section &section);
bool itemInfo(SubFile *file, SubFile::Handle &hdl,
const Section &section, ItemInfo &info);
void defaultPolygonStyle();
void defaultLineStyle();
void defaultPointStyle();
static bool itemInfo(SubFile *file, SubFile::Handle &hdl,
const Section &section, ItemInfo &info);
QMap<quint32, Line> _lines;
QMap<quint32, Polygon> _polygons;
QMap<quint32, Point> _points;

View File

@ -122,8 +122,6 @@ bool TREFile::init()
}
}
_isBaseMap = false;
return (_firstLevel >= 0);
}
@ -284,12 +282,12 @@ void TREFile::clear()
_subdivs.clear();
}
int TREFile::level(int bits, bool baseMap)
int TREFile::level(int bits, const Range &baseMap)
{
if (baseMap) {
if (!_isBaseMap && _levels.at(_firstLevel).bits > bits)
if (!baseMap.isNull()) {
if (zooms() != baseMap && bits <= baseMap.max())
return -1;
if (_isBaseMap && bits > _levels.last().bits)
if (zooms() == baseMap && bits > baseMap.max())
return -1;
}
@ -314,7 +312,8 @@ static bool cb(SubDiv *subdiv, void *context)
return true;
}
QList<SubDiv*> TREFile::subdivs(const RectC &rect, int bits, bool baseMap)
QList<SubDiv*> TREFile::subdivs(const RectC &rect, int bits,
const Range &baseMap)
{
QList<SubDiv*> list;
SubDivTree *tree = _subdivs.value(level(bits, baseMap));

View File

@ -25,11 +25,10 @@ public:
~TREFile();
bool init();
void markAsBasemap() {_isBaseMap = true;}
void clear();
const RectC &bounds() const {return _bounds;}
QList<SubDiv*> subdivs(const RectC &rect, int bits, bool baseMap);
QList<SubDiv*> subdivs(const RectC &rect, int bits, const Range &baseMap);
quint32 shift(quint8 bits) const
{return (bits == _levels.last().bits) ? (_flags >> 0xb) & 7 : 0;}
Range zooms() const
@ -46,7 +45,7 @@ private:
friend QDebug operator<<(QDebug dbg, const MapLevel &level);
bool load(int idx);
int level(int bits, bool baseMap);
int level(int bits, const Range &baseMap);
int readExtEntry(Handle &hdl, quint32 &polygons, quint32 &lines,
quint32 &points);
@ -56,7 +55,6 @@ private:
quint32 _flags;
quint16 _extItemSize;
int _firstLevel;
bool _isBaseMap;
QMap<int, SubDivTree*> _subdivs;
};

View File

@ -100,7 +100,7 @@ void VectorTile::clear()
_loaded = 0;
}
void VectorTile::polys(const RectC &rect, int bits, bool baseMap,
void VectorTile::polys(const RectC &rect, int bits, const Range &baseMap,
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
QCache<const SubDiv *, MapData::Polys> *polyCache)
{
@ -169,7 +169,7 @@ void VectorTile::polys(const RectC &rect, int bits, bool baseMap,
delete rgnHdl; delete lblHdl; delete netHdl; delete nodHdl; delete nodHdl2;
}
void VectorTile::points(const RectC &rect, int bits, bool baseMap,
void VectorTile::points(const RectC &rect, int bits, const Range &baseMap,
QList<MapData::Point> *points, QCache<const SubDiv *,
QList<MapData::Point> > *pointCache)
{

View File

@ -20,7 +20,6 @@ public:
}
bool init();
void markAsBasemap() {_tre->markAsBasemap();}
void clear();
const RectC &bounds() const {return _tre->bounds();}
@ -28,10 +27,10 @@ public:
SubFile *file(SubFile::Type type);
void polys(const RectC &rect, int bits, bool baseMap,
void polys(const RectC &rect, int bits, const Range &baseMap,
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
QCache<const SubDiv *, MapData::Polys> *polyCache);
void points(const RectC &rect, int bits, bool baseMap,
void points(const RectC &rect, int bits, const Range &baseMap,
QList<MapData::Point> *points, QCache<const SubDiv*,
QList<MapData::Point> > *pointCache);