diff --git a/src/map/IMG/huffmanstream.h b/src/map/IMG/huffmanstream.h index 8803c105..c1f92e93 100644 --- a/src/map/IMG/huffmanstream.h +++ b/src/map/IMG/huffmanstream.h @@ -24,7 +24,7 @@ public: } bool atEnd() const - {return _symbolDataSize + _bs.bitsAvailable() < _table.maxDataBits();} + {return _symbolDataSize + _bs.bitsAvailable() < _table.symBits();} bool flush() {return _bs.flush();} protected: diff --git a/src/map/IMG/huffmantable.cpp b/src/map/IMG/huffmantable.cpp index ee82c902..930bfebe 100644 --- a/src/map/IMG/huffmantable.cpp +++ b/src/map/IMG/huffmantable.cpp @@ -33,7 +33,7 @@ bool HuffmanTable::load(const RGNFile *rgn, SubFile::Handle &rgnHdl) _aclTable = _bsrchTable + _bsrchEntryBytes * _bsrchEntries; _huffmanTable = _aclTable + (_aclEntryBytes << _aclBits); - return (_symBits <= 32 && _symbolBits <= 32 && _symbolBits >= 8); + return (_symBits <= 32 && _symbolBits <= 32); } quint32 HuffmanTable::symbol(quint32 data, quint8 &size) const @@ -92,8 +92,11 @@ quint32 HuffmanTable::symbol(quint32 data, quint8 &size) const quint32 sbi = si & 7; quint32 shift = 8 - sbi; tp = _huffmanTable + (si >> 3); - quint32 val = readVUint32(tp + 1, bs(_symbolBits - shift)); - return (val << shift) | (*tp >> sbi); + if (shift < _symbolBits) { + quint32 val = readVUint32(tp + 1, bs(_symbolBits - shift)); + return (val << shift) | (*tp >> sbi); + } else + return (*tp >> sbi); } } diff --git a/src/map/IMG/huffmantable.h b/src/map/IMG/huffmantable.h index 973e684a..2fb363ac 100644 --- a/src/map/IMG/huffmantable.h +++ b/src/map/IMG/huffmantable.h @@ -12,11 +12,13 @@ public: HuffmanTable(quint8 id) : _buffer(id) {} bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl); - quint8 maxDataBits() const {return _symBits;} - quint32 symbol(quint32 data, quint8 &size) const; + quint32 symbol(quint32 data, quint8 &size) const; quint8 id() const {return _buffer.id();} + quint8 symBits() const {return _symBits;} + quint8 symbolBits() const {return _symbolBits;} + private: HuffmanBuffer _buffer; const quint8 *_aclTable, *_bsrchTable, *_huffmanTable; diff --git a/src/map/IMG/huffmantext.cpp b/src/map/IMG/huffmantext.cpp index c550e88e..9473bc49 100644 --- a/src/map/IMG/huffmantext.cpp +++ b/src/map/IMG/huffmantext.cpp @@ -5,60 +5,28 @@ using namespace Garmin; using namespace IMG; -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; + bits = _table.symBits() - bits; if (usedBits < bits) { - old = usedBits ? usedData >> (0x20 - usedBits) : 0; + old = usedBits ? usedData >> (32 - usedBits) : 0; if (!file->readVUInt32SW(hdl, 4, usedData)) return false; ls = bits - usedBits; - rs = 0x20 - (bits - usedBits); + rs = 32 - (bits - usedBits); old = usedData >> rs | old << ls; } else { ls = bits; rs = usedBits - bits; - old = usedData >> (0x20 - bits); + old = usedData >> (32 - bits); } usedData = usedData << ls; - data = data | old << (0x20 - _b1); + data = data | old << (32 - _table.symBits()); usedBits = rs; return true; @@ -71,101 +39,29 @@ bool HuffmanText::decode(const SubFile *file, SubFile::Handle &hdl, 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; + quint8 size; + quint32 sym = _table.symbol(data, 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) + if (_table.symBits() < size) return false; data = data << size; - bits = _b1 - size; + bits = _table.symBits() - size; - if ((_b3 & 7) == 0) { - for (quint32 i = 0; i < (_b3 >> 3); i++) { + if (!(_table.symbolBits() & 7)) { + for (quint32 i = 0; i < (_table.symbolBits() >> 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; - } + Q_ASSERT(false); + return false; } } } diff --git a/src/map/IMG/huffmantext.h b/src/map/IMG/huffmantext.h index a48f822b..7d32abdf 100644 --- a/src/map/IMG/huffmantext.h +++ b/src/map/IMG/huffmantext.h @@ -1,16 +1,17 @@ #ifndef IMG_HUFFMANTEXT_H #define IMG_HUFFMANTEXT_H -#include "huffmanbuffer.h" +#include "huffmantable.h" namespace IMG { class HuffmanText { public: - HuffmanText() : _buffer(0) {} + HuffmanText() : _table(0) {} - bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl); + bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl) + {return _table.load(rgn, rgnHdl);} bool decode(const SubFile *file, SubFile::Handle &hdl, QVector &str) const; @@ -18,20 +19,7 @@ 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; + HuffmanTable _table; }; }