2 #include "huffmanstream.h"
9 using namespace Garmin
;
12 static bool readAdjCounts(BitStream4R
&bs
, QVector
<quint16
> &cnts
, quint16
&mask
)
14 quint32 val
, cnt
, bits
;
18 cnt
= ((val
>> 2) & 3) + 2;
19 bits
= ((val
* 2) & 6) + 4;
20 mask
= 1<<(3 + ((val
* 2) & 6));
29 for (int i
= 0; i
< cnts
.size(); i
++)
30 if (!bs
.read(bits
, cnts
[i
]))
36 static bool skipShape(BitStream4R
&bs
)
40 if (!bs
.readVUint32SM(v1
, v2
, v2b
))
46 static bool skipAdjShapes(BitStream4R
&bs
, const QVector
<quint16
> &cnts
,
47 quint16 mask
, bool firstIsShape
)
49 if (firstIsShape
&& !skipShape(bs
))
52 for (int i
= 0; i
< cnts
.size(); i
++) {
53 if (cnts
.at(i
) & mask
) {
62 static bool seekToLevel(BitStream4R
&bs
, quint8 level
)
66 for (quint8 i
= 1; i
< level
; ) {
67 if (!bs
.readVUint32SM(v1
, v2
, v2b
))
81 static bool seekToLine(BitStream4R
&bs
, quint8 line
)
85 for (quint8 i
= 0; i
< line
; i
++) {
86 if (!bs
.readVUint32SM(v1
, v2
, v2b
))
98 static bool readNodeGeometry(const NODFile
*nod
, SubFile::Handle
&nodHdl
,
99 NODFile::AdjacencyInfo
&adj
, quint16 cnt
, MapData::Poly
&poly
)
101 for (int i
= 0; i
<= cnt
; i
++) {
102 int ret
= nod
->nextNode(nodHdl
, adj
);
106 return (cnt
== 0xFFFF);
108 Coordinates
c(toWGS32(adj
.nodeInfo
.pos
.x()),
109 toWGS32(adj
.nodeInfo
.pos
.y()));
110 poly
.points
.append(QPointF(c
.lon(), c
.lat()));
111 poly
.boundingRect
= poly
.boundingRect
.united(c
);
117 static bool skipNodes(const NODFile
*nod
, SubFile::Handle
&nodHdl
,
118 NODFile::AdjacencyInfo
&adj
, int cnt
)
120 for (int i
= 0; i
< cnt
; i
++)
121 if (nod
->nextNode(nodHdl
, adj
))
128 bool NETFile::readLine(BitStream4R
&bs
, const SubDiv
*subdiv
,
129 MapData::Poly
&poly
) const
132 if (!bs
.readVUint32SM(v1
, v2
, v2b
))
137 if (!(bs
.read(0x12 - v2b
, lon
) && bs
.read(16, lat
)))
140 lon
|= (v2
>> 2) << (0x12U
- v2b
);
142 QPoint pos
= QPoint(LS(subdiv
->lon(), 8) + LS((qint16
)lon
, 32-subdiv
->bits()),
143 LS(subdiv
->lat(), 8) + LS((qint16
)lat
, 32-subdiv
->bits()));
144 Coordinates
c(toWGS32(pos
.x()), toWGS32(pos
.y()));
146 poly
.boundingRect
= RectC(c
, c
);
147 poly
.points
.append(QPointF(c
.lon(), c
.lat()));
149 HuffmanDeltaStreamR
stream(bs
, *_tp
);
152 qint32 lonDelta
, latDelta
;
154 while (stream
.readNext(lonDelta
, latDelta
)) {
155 if (!(lonDelta
| latDelta
))
158 pos
.rx() += LS(lonDelta
, 32-subdiv
->bits());
159 pos
.ry() += LS(latDelta
, 32-subdiv
->bits());
161 Coordinates
c(toWGS32(pos
.x()), toWGS32(pos
.y()));
162 poly
.points
.append(QPointF(c
.lon(), c
.lat()));
163 poly
.boundingRect
= poly
.boundingRect
.united(c
);
166 return stream
.atEnd();
169 bool NETFile::readShape(const NODFile
*nod
, SubFile::Handle
&nodHdl
,
170 NODFile::AdjacencyInfo
&adj
, BitStream4R
&bs
, const SubDiv
*subdiv
,
171 quint32 shift
, quint16 cnt
, bool check
, MapData::Poly
&poly
) const
174 if (!bs
.readVUint32SM(v1
, v2
, v2b
))
176 BitStream4R::State state
;
181 if (!bs
.read(8, flags
))
185 bool hasAdjustBit
= flags
& (1 << (v2b
+ 7));
186 bool startWithStream
= flags
& (1 << (v2b
+ 6));
187 bool useEosBit
= flags
& (1 << (v2b
+ 5));
189 HuffmanDeltaStreamR
stream(bs
, *_tp
);
190 if (!stream
.init(flags
, v2b
+ 5))
194 if (nod
->nextNode(nodHdl
, adj
))
196 QPoint
pos(adj
.nodeInfo
.pos
);
199 if (!startWithStream
) {
200 Coordinates
c(toWGS32(adj
.nodeInfo
.pos
.x()),
201 toWGS32(adj
.nodeInfo
.pos
.y()));
202 poly
.points
.append(QPointF(c
.lon(), c
.lat()));
203 poly
.boundingRect
= poly
.boundingRect
.united(c
);
206 int ret
= nod
->nextNode(nodHdl
, adj
);
213 c
= Coordinates(toWGS32(adj
.nodeInfo
.pos
.x()),
214 toWGS32(adj
.nodeInfo
.pos
.y()));
215 poly
.points
.append(QPointF(c
.lon(), c
.lat()));
216 poly
.boundingRect
= poly
.boundingRect
.united(c
);
217 pos
= adj
.nodeInfo
.pos
;
222 qint32 lonDelta
, latDelta
;
223 QVector
<QPoint
> deltas
;
224 quint32 adjustBit
= 0;
225 quint32 stepsCnt
= 0;
230 if ((stepsCnt
== steps
) && !useEosBit
) {
231 if (!stream
.readSymbol(steps
))
237 if (!stream
.readNext(lonDelta
, latDelta
))
239 if (hasAdjustBit
&& !stream
.read(1, adjustBit
))
242 if (!(lonDelta
| latDelta
) && !startWithStream
&& !hasAdjustBit
)
248 if (!stream
.read(1, eos
))
251 if (steps
== stepsCnt
)
255 if (!startWithStream
) {
256 pos
.rx() += LS(lonDelta
, 32-subdiv
->bits()-shift
);
257 pos
.ry() += LS(latDelta
, 32-subdiv
->bits()-shift
);
259 Coordinates
c(toWGS32(pos
.x()), toWGS32(pos
.y()));
260 poly
.points
.append(QPointF(c
.lon(), c
.lat()));
261 poly
.boundingRect
= poly
.boundingRect
.united(c
);
263 deltas
.append(QPoint(lonDelta
, latDelta
));
264 poly
.points
.append(QPointF());
267 if (startWithStream
&& eos
) {
268 for (int i
= deltas
.size() - 1, j
= 0; i
>= 0; i
--, j
++) {
269 pos
.rx() -= LS(deltas
.at(i
).x(), 32-subdiv
->bits()-shift
);
270 pos
.ry() -= LS(deltas
.at(i
).y(), 32-subdiv
->bits()-shift
);
272 Coordinates
c(toWGS32(pos
.x()), toWGS32(pos
.y()));
273 poly
.points
[poly
.points
.size() - 1 - j
] = QPointF(c
.lon(), c
.lat());
274 poly
.boundingRect
= poly
.boundingRect
.united(c
);
277 pos
= adj
.nodeInfo
.pos
;
278 Coordinates
c(toWGS32(pos
.x()), toWGS32(pos
.y()));
279 poly
.points
.append(QPointF(c
.lon(), c
.lat()));
280 poly
.boundingRect
= poly
.boundingRect
.united(c
);
284 startWithStream
= false;
295 int ret
= nod
->nextNode(nodHdl
, adj
);
302 if (check
&& nodes
== cnt
) {
303 if (!(bs
.restore(state
) && bs
.skip(v1
)
304 && bs
.readVUint32SM(v1
, v2
, v2b
)))
312 Coordinates
c(toWGS32(adj
.nodeInfo
.pos
.x()),
313 toWGS32(adj
.nodeInfo
.pos
.y()));
314 poly
.points
.append(QPointF(c
.lon(), c
.lat()));
315 poly
.boundingRect
= poly
.boundingRect
.united(c
);
316 pos
= adj
.nodeInfo
.pos
;
317 } while (!adj
.eog
&& nodes
< cnt
);
331 bool NETFile::linkLabel(Handle
&hdl
, quint32 offset
,
332 const LBLFile
*lbl
, Handle
&lblHdl
, Label
&label
) const
334 if (!seek(hdl
, offset
))
336 BitStream1
bs(*this, hdl
, _links
.size
- (offset
- _links
.offset
));
338 quint32 flags
, labelPtr
;
339 if (!bs
.read(8, flags
))
344 if (!bs
.readUInt24(labelPtr
))
346 if (labelPtr
& 0x3FFFFF)
347 label
= lbl
->label(lblHdl
, labelPtr
& 0x3FFFFF);
352 bool NETFile::load(Handle
&hdl
, const RGNFile
*rgn
, Handle
&rgnHdl
)
356 if (!(seek(hdl
, _gmpOffset
) && readUInt16(hdl
, hdrLen
)
357 && seek(hdl
, _gmpOffset
+ 0x15) && readUInt32(hdl
, _base
.offset
)
358 && readUInt32(hdl
, _base
.size
) && readByte(hdl
, &_netShift
)))
361 if (hdrLen
>= 0x4C) {
363 if (!(seek(hdl
, _gmpOffset
+ 0x37) && readUInt32(hdl
, info
)))
365 if (!(seek(hdl
, _gmpOffset
+ 0x43) && readUInt32(hdl
, _links
.offset
)
366 && readUInt32(hdl
, _links
.size
) && readByte(hdl
, &_linksShift
)))
369 quint8 tableId
= ((info
>> 2) & 0x0F);
370 if (_links
.size
&& (!rgn
->huffmanTable() || rgn
->huffmanTable()->id()
372 _huffmanTable
= new HuffmanTable(tableId
);
373 if (!_huffmanTable
->load(rgn
, rgnHdl
))
377 _tp
= _huffmanTable
? _huffmanTable
: rgn
->huffmanTable();
383 void NETFile::clear()
385 delete _huffmanTable
;
391 delete _huffmanTable
;
394 bool NETFile::link(const SubDiv
*subdiv
, quint32 shift
, Handle
&hdl
,
395 const NODFile
*nod
, Handle
&nodHdl2
, Handle
&nodHdl
, const LBLFile
*lbl
,
396 Handle
&lblHdl
, const NODFile::BlockInfo
&blockInfo
, quint8 linkId
,
397 quint8 lineId
, QList
<MapData::Poly
> *lines
) const
400 if (!nod
->linkType(nodHdl
, blockInfo
, linkId
, poly
.type
))
403 NODFile::LinkInfo linkInfo
;
404 if (!nod
->linkInfo(nodHdl
, blockInfo
, linkId
, linkInfo
))
407 quint32 linkOffset
= _links
.offset
+ (linkInfo
.linkOffset
<< _linksShift
);
408 if (linkOffset
> _links
.offset
+ _links
.size
)
410 if (!seek(hdl
, linkOffset
))
412 BitStream4R
bs(*this, hdl
, linkOffset
- _links
.offset
);
417 bool firstIsShape
= (linkInfo
.flags
>> 10) & 1;
418 bool singleTopology
= (linkInfo
.flags
>> 9) & 1;
419 bool hasLevels
= (linkInfo
.flags
>> 11) & 1;
421 if (!singleTopology
|| hasLevels
) {
422 if (!bs
.readVUInt32(size
))
425 if (!singleTopology
) {
426 if (!readAdjCounts(bs
, ca
, mask
))
430 if (!subdiv
->level()) {
431 NODFile::AdjacencyInfo
adj(nodHdl2
, blockInfo
, linkId
, linkInfo
);
433 if (singleTopology
) {
435 if (!readShape(nod
, nodHdl
, adj
, bs
, subdiv
, shift
, 0xFFFF,
439 if (!readNodeGeometry(nod
, nodHdl
, adj
, 0xFFFF, poly
))
443 quint16 mask2
= mask
+ 0xffff;
444 for (int i
= 0; i
<= ca
.size(); i
++) {
445 quint16 step
= (i
< ca
.size()) ? ca
.at(i
) & mask2
: 0xFFFF;
446 bool shape
= (i
> 0) ? ca
.at(i
-1) & mask
: firstIsShape
;
449 bool check
= (i
< ca
.size()) ? (ca
.at(i
) & mask
) : false;
450 if (!readShape(nod
, nodHdl
, adj
, bs
, subdiv
, shift
,
454 if (!readNodeGeometry(nod
, nodHdl
, adj
, step
, poly
))
460 if (shape
&& !skipShape(bs
))
462 if (!skipNodes(nod
, nodHdl
, adj
, step
))
469 if (!skipAdjShapes(bs
, ca
, mask
, firstIsShape
))
472 if (!seekToLevel(bs
, subdiv
->level()))
474 if (!seekToLine(bs
, lineId
))
476 if (!readLine(bs
, subdiv
, poly
))
481 linkLabel(hdl
, linkOffset
, lbl
, lblHdl
, poly
.label
);
482 if ((linkInfo
.flags
>> 3) & 1)
490 bool NETFile::lblOffset(Handle
&hdl
, quint32 netOffset
, quint32
&lblOffset
) const
492 if (!(seek(hdl
, _base
.offset
+ (netOffset
<< _netShift
))
493 && readUInt24(hdl
, lblOffset
)))
496 lblOffset
&= 0x3FFFFF;