1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-24 03:35:53 +01:00

Added support for raster polygon backgrounds

This commit is contained in:
Martin Tůma 2021-01-25 21:37:07 +01:00
parent 6ba7493b59
commit bf613f1b6d
9 changed files with 150 additions and 20 deletions

View File

@ -97,6 +97,7 @@ HEADERS += src/common/config.h \
src/map/IMG/huffmantext.h \
src/map/IMG/nodfile.h \
src/map/IMG/mapdata.h \
src/map/IMG/raster.h \
src/map/IMG/rastertile.h \
src/map/IMG/textpathitem.h \
src/map/IMG/textpointitem.h \

View File

@ -93,6 +93,23 @@ bool LBLFile::load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl)
}
}
if (hdrLen >= 0x19A) {
quint32 size;
if (!(seek(hdl, _gmpOffset + 0x184) && readUInt32(hdl, _imgOffsetsOffset)
&& readUInt32(hdl, size) && readUInt16(hdl, _imgOffsetsRecordSize)
&& readUInt32(hdl, _imgOffsetsFlags) && readUInt32(hdl, _imgOffset)
&& readUInt32(hdl, _imgSize)))
return false;
_imgOffsetsCount = size ? size / _imgOffsetsRecordSize : 0;
quint32 maxId = _imgOffsetsCount - 1;
_imgOffsetIdSize = 0;
do {
_imgOffsetIdSize++;
maxId = maxId >> 8;
} while (maxId != 0);
}
if (_encoding == 11) {
_huffmanText = new HuffmanText();
if (!_huffmanText->load(rgn, rgnHdl))
@ -283,3 +300,32 @@ Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize) con
return Label();
}
}
QByteArray LBLFile::readImage(Handle &hdl, quint32 id) const
{
quint32 offset, nextOffset, size;
if (!_imgOffsetsCount || id >= _imgOffsetsCount)
return QByteArray();
if (!(seek(hdl, _imgOffsetsOffset + id * _imgOffsetsRecordSize)
&& readVUInt32(hdl, _imgOffsetsRecordSize, offset)))
return QByteArray();
if (id == _imgOffsetsCount - 1)
nextOffset = _imgSize;
else {
if (!readVUInt32(hdl, _imgOffsetsRecordSize, nextOffset))
return QByteArray();
}
size = nextOffset - offset;
if (!seek(hdl, _imgOffset + offset))
return QByteArray();
QByteArray ba;
ba.resize(size);
for (quint32 i = 0; i < size; i++)
if (!readUInt8(hdl, *(ba.data() + i)))
return QByteArray();
return ba;
}

View File

@ -30,6 +30,9 @@ public:
Label label(Handle &hdl, quint32 offset, bool poi = false,
bool capitalize = true) const;
quint8 imageIdSize() const {return _imgOffsetIdSize;}
QByteArray readImage(Handle &hdl, quint32 id) const;
private:
Label str2label(const QVector<quint8> &str, bool capitalize) const;
Label label6b(Handle &hdl, quint32 offset, bool capitalize) const;
@ -43,6 +46,13 @@ private:
quint32 _size;
quint32 _poiOffset;
quint32 _poiSize;
quint32 _imgOffsetsOffset;
quint32 _imgOffsetsCount;
quint32 _imgOffsetsRecordSize;
quint32 _imgOffsetsFlags;
quint32 _imgOffset;
quint32 _imgSize;
quint8 _imgOffsetIdSize;
quint8 _poiMultiplier;
quint8 _multiplier;
quint8 _encoding;

View File

@ -9,6 +9,7 @@
#include "common/rtree.h"
#include "common/range.h"
#include "label.h"
#include "raster.h"
class Style;
class SubDiv;
@ -25,6 +26,7 @@ public:
parallel. */
QVector<QPointF> points;
Label label;
Raster raster;
quint32 type;
RectC boundingRect;

37
src/map/IMG/raster.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef RASTER_H
#define RASTER_H
#include <QRect>
#include <QByteArray>
#include <QDebug>
#include "common/rectc.h"
#include "common/garmin.h"
class Raster {
public:
Raster() {}
Raster(const QByteArray &img, const QRect &rect) : _img(img), _rect(rect) {}
const QByteArray &img() const {return _img;}
const RectC rect() const
{
return RectC(Coordinates(toWGS32(_rect.left()), toWGS32(_rect.top())),
Coordinates(toWGS32(_rect.right()), toWGS32(_rect.bottom())));
}
bool isValid() const {return !_img.isNull();}
private:
QByteArray _img;
QRect _rect;
};
#ifndef QT_NO_DEBUG
inline QDebug operator<<(QDebug dbg, const Raster &raster)
{
dbg.nospace() << "Raster(" << raster.img().size() << ", " << raster.rect()
<< ")";
return dbg.space();
}
#endif // QT_NO_DEBUG
#endif // RASTER_H

View File

@ -217,6 +217,20 @@ void RasterTile::drawPolygons(QPainter *painter)
const MapData::Poly &poly = _polygons.at(i);
if (poly.type != _style->drawOrder().at(n))
continue;
if (poly.raster.isValid()) {
RectC r(poly.raster.rect());
QPointF tl(_map->ll2xy(r.topLeft()));
QPointF br(_map->ll2xy(r.bottomRight()));
QSize size(QRectF(tl, br).toRect().size());
painter->drawImage(tl, QImage::fromData(poly.raster.img()).
scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
//painter->setPen(Qt::blue);
//painter->setBrush(Qt::NoBrush);
//painter->drawRect(QRectF(tl, br));
} else {
const Style::Polygon &style = _style->polygon(poly.type);
painter->setPen(style.pen());
@ -225,6 +239,7 @@ void RasterTile::drawPolygons(QPainter *painter)
}
}
}
}
void RasterTile::drawLines(QPainter *painter)
{

View File

@ -29,7 +29,8 @@ RGNFile::~RGNFile()
delete _huffmanTable;
}
bool RGNFile::skipClassFields(Handle &hdl) const
bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType,
MapData::Poly *poly, const LBLFile *lbl, Handle *lblHdl) const
{
quint8 flags;
quint32 rs;
@ -56,6 +57,22 @@ bool RGNFile::skipClassFields(Handle &hdl) const
break;
}
if (segmentType == Polygon && poly->type == 0x10613
&& lbl && rs >= lbl->imageIdSize() + 16U) {
quint32 id;
quint32 top, right, bottom, left;
if (!(readVUInt32(hdl, lbl->imageIdSize(), id)
&& readUInt32(hdl, top) && readUInt32(hdl, right)
&& readUInt32(hdl, bottom) && readUInt32(hdl, left)))
return false;
poly->raster = Raster(lbl->readImage(*lblHdl, id),
QRect(QPoint(left, top), QPoint(right, bottom)));
rs -= lbl->imageIdSize() + 16;
}
return seek(hdl, pos(hdl) + rs);
}
@ -153,7 +170,7 @@ void RGNFile::clear()
bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
SegmentType segmentType, const LBLFile *lbl, Handle &lblHdl, NETFile *net,
Handle &netHdl, QList<IMG::Poly> *polys) const
Handle &netHdl, QList<MapData::Poly> *polys) const
{
const SubDiv::Segment &segment = (segmentType == Line)
? subdiv->lines() : subdiv->polygons();
@ -169,7 +186,7 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
quint16 len;
while (pos(hdl) < segment.end()) {
IMG::Poly poly;
MapData::Poly poly;
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
@ -229,7 +246,7 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
SegmentType segmentType, const LBLFile *lbl, Handle &lblHdl,
QList<IMG::Poly> *polys) const
QList<MapData::Poly> *polys) const
{
quint32 labelPtr, len;
quint8 type, subtype;
@ -244,7 +261,7 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
return false;
while (pos(hdl) < segment.end()) {
IMG::Poly poly;
MapData::Poly poly;
QPoint pos;
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
@ -319,7 +336,8 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
if (subtype & 0x20 && !readUInt24(hdl, labelPtr))
return false;
if (subtype & 0x80 && !skipClassFields(hdl))
if (subtype & 0x80 && !readClassFields(hdl, segmentType, &poly, lbl,
&lblHdl))
return false;
if (subtype & 0x40 && !skipLclFields(hdl, segmentType == Line
? _linesLclFlags : _polygonsLclFlags))
@ -340,7 +358,7 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
SegmentType segmentType, const LBLFile *lbl, Handle &lblHdl,
QList<IMG::Point> *points) const
QList<MapData::Point> *points) const
{
const SubDiv::Segment &segment = (segmentType == IndexedPoint)
? subdiv->idxPoints() : subdiv->points();
@ -352,7 +370,7 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
return false;
while (pos(hdl) < segment.end()) {
IMG::Point point;
MapData::Point point;
quint8 type, subtype;
qint16 lon, lat;
quint32 labelPtr;
@ -383,7 +401,7 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
}
bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv,
const LBLFile *lbl, Handle &lblHdl, QList<IMG::Point> *points) const
const LBLFile *lbl, Handle &lblHdl, QList<MapData::Point> *points) const
{
const SubDiv::Segment &segment = subdiv->extPoints();
@ -394,7 +412,7 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv,
return false;
while (pos(hdl) < segment.end()) {
IMG::Point point;
MapData::Point point;
qint16 lon, lat;
quint8 type, subtype;
quint32 labelPtr = 0;
@ -405,7 +423,7 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv,
if (subtype & 0x20 && !readUInt24(hdl, labelPtr))
return false;
if (subtype & 0x80 && !skipClassFields(hdl))
if (subtype & 0x80 && !readClassFields(hdl, Point))
return false;
if (subtype & 0x40 && !skipLclFields(hdl, _pointsLclFlags))
return false;
@ -434,7 +452,7 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv,
bool RGNFile::links(Handle &hdl, const SubDiv *subdiv, quint32 shift,
const NETFile *net, Handle &netHdl, const NODFile *nod, Handle &nodHdl,
const LBLFile *lbl, Handle &lblHdl, QList<IMG::Poly> *lines) const
const LBLFile *lbl, Handle &lblHdl, QList<MapData::Poly> *lines) const
{
quint32 size, blockIndexId;
quint8 flags;

View File

@ -60,9 +60,9 @@ public:
private:
QMap<SegmentType, SubDiv::Segment> segments(Handle &hdl, SubDiv *subdiv)
const;
bool skipClassFields(Handle &hdl) const;
bool skipLclFields(Handle &hdl, const quint32 flags[3])
const;
bool readClassFields(Handle &hdl, SegmentType segmentType,
MapData::Poly *poly = 0, const LBLFile *lbl = 0, Handle *lblHdl = 0) const;
bool skipLclFields(Handle &hdl, const quint32 flags[3]) const;
bool skipGblFields(Handle &hdl, quint32 flags) const;
HuffmanTable *_huffmanTable;

View File

@ -113,7 +113,8 @@ void Style::defaultPolygonStyle()
_polygons[0x10c05] = _polygons[TYPE(0x52)];
// Draw order
_drawOrder << TYPE(0x4b) << 0x10d01 << TYPE(0x4a) << TYPE(0x01) << 0x10800
_drawOrder
<< TYPE(0x4b) << 0x10d01 << 0x10613 << TYPE(0x4a) << TYPE(0x01) << 0x10800
<< TYPE(0x02) << 0x10801 << TYPE(0x03) << 0x10802 << TYPE(0x17) << 0x10a04
<< TYPE(0x18) << 0x1090c << TYPE(0x1a) << 0x1090e << TYPE(0x28) << 0x10b01
<< TYPE(0x32) << 0x10b02 << TYPE(0x3c) << 0x10b03 << TYPE(0x3d) << 0x10b04