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

Improved IMG map memory management

This commit is contained in:
Martin Tůma 2019-07-04 18:18:03 +02:00
parent b4cc88446a
commit 53e960fabe
7 changed files with 103 additions and 57 deletions

View File

@ -5,6 +5,8 @@
#include "img.h" #include "img.h"
#define CACHE_SIZE 8388608 /* 8MB */
#define CHECK(condition) \ #define CHECK(condition) \
if (!(condition)) { \ if (!(condition)) { \
_errorString = "Invalid/corrupted IMG file"; \ _errorString = "Invalid/corrupted IMG file"; \
@ -25,7 +27,8 @@ struct CTX
QList<IMG::Point> *points; QList<IMG::Point> *points;
}; };
IMG::IMG(const QString &fileName) : _file(fileName), _valid(false) IMG::IMG(const QString &fileName)
: _file(fileName), _typ(0), _style(0), _valid(false)
{ {
if (!_file.open(QFile::ReadOnly)) { if (!_file.open(QFile::ReadOnly)) {
_errorString = _file.errorString(); _errorString = _file.errorString();
@ -50,6 +53,7 @@ IMG::IMG(const QString &fileName) : _file(fileName), _valid(false)
QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2))); QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2)));
_name = QString(nba).trimmed(); _name = QString(nba).trimmed();
_blockSize = 1 << (e1 + e2); _blockSize = 1 << (e1 + e2);
_blockCache.setMaxCost(CACHE_SIZE / _blockSize);
// Read the FAT table // Read the FAT table
quint8 flag; quint8 flag;
@ -72,7 +76,7 @@ IMG::IMG(const QString &fileName) : _file(fileName), _valid(false)
QMap<QString, VectorTile*> tileMap; QMap<QString, VectorTile*> tileMap;
QMap<QString, SubFile*> TYPMap; QString typFile;
// Read FAT blocks describing the IMG sub-files // Read FAT blocks describing the IMG sub-files
for (int i = 0; i < cnt; i++) { for (int i = 0; i < cnt; i++) {
@ -108,20 +112,22 @@ IMG::IMG(const QString &fileName) : _file(fileName), _valid(false)
file->addBlock(block); file->addBlock(block);
} }
} else if (tt == SubFile::TYP) { } else if (tt == SubFile::TYP) {
SubFile *typ; SubFile *typ = 0;
QMap<QString, SubFile*>::iterator it = TYPMap.find(fn); if (typFile.isNull()) {
if (it == TYPMap.end()) { _typ = new SubFile(this, size);
typ = new SubFile(this, size); typ = _typ;
TYPMap.insert(fn, typ); typFile = fn;
} else } else if (fn == typFile)
typ = *it; typ = _typ;
_file.seek(offset + 0x20); if (typ) {
for (int i = 0; i < 240; i++) { _file.seek(offset + 0x20);
CHECK(readValue(block)); for (int i = 0; i < 240; i++) {
if (block == 0xFFFF) CHECK(readValue(block));
break; if (block == 0xFFFF)
typ->addBlock(block); break;
typ->addBlock(block);
}
} }
} }
@ -143,22 +149,6 @@ IMG::IMG(const QString &fileName) : _file(fileName), _valid(false)
_bounds |= (*it)->bounds(); _bounds |= (*it)->bounds();
} }
// Read TYP file if any
if (!TYPMap.isEmpty()) {
if (TYPMap.size() > 1)
qWarning("%s: Multiple TYP files, using %s",
qPrintable(_file.fileName()), qPrintable(TYPMap.keys().first()));
SubFile *typ = TYPMap.values().first();
_style = Style(typ);
qDeleteAll(TYPMap);
} else {
QFile typFile(ProgramPaths::typFile());
if (typFile.exists()) {
SubFile typ(&typFile);
_style = Style(&typ);
}
}
_valid = true; _valid = true;
} }
@ -167,6 +157,37 @@ IMG::~IMG()
TileTree::Iterator it; TileTree::Iterator it;
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it)) for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it))
delete _tileTree.GetAt(it); delete _tileTree.GetAt(it);
delete _typ;
delete _style;
}
void IMG::load()
{
Q_ASSERT(!_style);
if (_typ && _typ->isValid())
_style = new Style(_typ);
else {
QFile typFile(ProgramPaths::typFile());
if (typFile.exists()) {
SubFile typ(&typFile);
_style = new Style(&typ);
} else
_style = new Style();
}
}
void IMG::clear()
{
TileTree::Iterator it;
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it))
_tileTree.GetAt(it)->clear();
delete _style;
_style = 0;
_blockCache.clear();
} }
static bool cb(VectorTile *tile, void *context) static bool cb(VectorTile *tile, void *context)

View File

@ -48,13 +48,16 @@ public:
IMG(const QString &fileName); IMG(const QString &fileName);
~IMG(); ~IMG();
void load();
void clear();
QString fileName() const {return _file.fileName();} QString fileName() const {return _file.fileName();}
const QString &name() const {return _name;} const QString &name() const {return _name;}
const RectC &bounds() const {return _bounds;} const RectC &bounds() const {return _bounds;}
void objects(const RectC &rect, int bits, QList<Poly> *polygons, void objects(const RectC &rect, int bits, QList<Poly> *polygons,
QList<Poly> *lines, QList<Point> *points); QList<Poly> *lines, QList<Point> *points);
const Style &style() const {return _style;} const Style *style() const {return _style;}
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;} const QString &errorString() const {return _errorString;}
@ -75,11 +78,11 @@ private:
int _blockSize; int _blockSize;
QCache<int, QByteArray> _blockCache; QCache<int, QByteArray> _blockCache;
TileTree _tileTree;
QString _name; QString _name;
RectC _bounds; RectC _bounds;
Style _style; TileTree _tileTree;
SubFile *_typ;
Style *_style;
bool _valid; bool _valid;
QString _errorString; QString _errorString;

View File

@ -40,18 +40,7 @@ static void unlock(quint8 *dst, const quint8 *src, quint32 size, quint32 key)
TREFile::~TREFile() TREFile::~TREFile()
{ {
SubDivTree::Iterator jt; clear();
for (QMap<int, SubDivTree*>::iterator it = _subdivs.begin();
it != _subdivs.end(); ++it) {
SubDivTree *tree = *it;
for (tree->GetFirst(jt); !tree->IsNull(jt); tree->GetNext(jt))
delete tree->GetAt(jt);
}
for (QMap<int, SubDivTree*>::iterator it = _subdivs.begin();
it != _subdivs.end(); ++it)
delete *it;
} }
bool TREFile::init() bool TREFile::init()
@ -69,7 +58,7 @@ bool TREFile::init()
return true; return true;
} }
bool TREFile::init2() bool TREFile::load()
{ {
Handle hdl; Handle hdl;
quint8 locked; quint8 locked;
@ -202,9 +191,26 @@ bool TREFile::init2()
return true; return true;
} }
void TREFile::clear()
{
SubDivTree::Iterator jt;
for (QMap<int, SubDivTree*>::iterator it = _subdivs.begin();
it != _subdivs.end(); ++it) {
SubDivTree *tree = *it;
for (tree->GetFirst(jt); !tree->IsNull(jt); tree->GetNext(jt))
delete tree->GetAt(jt);
}
qDeleteAll(_subdivs);
_subdivs.clear();
_levels.clear();
}
int TREFile::level(int bits) int TREFile::level(int bits)
{ {
if (_levels.isEmpty() && !init2()) if (_levels.isEmpty() && !load())
return -1; return -1;
int l = _levels.first(); int l = _levels.first();

View File

@ -17,6 +17,7 @@ public:
~TREFile(); ~TREFile();
bool init(); bool init();
void clear();
const RectC &bounds() const {return _bounds;} const RectC &bounds() const {return _bounds;}
QList<SubDiv*> subdivs(const RectC &rect, int bits); QList<SubDiv*> subdivs(const RectC &rect, int bits);
@ -24,7 +25,7 @@ public:
private: private:
typedef RTree<SubDiv*, double, 2> SubDivTree; typedef RTree<SubDiv*, double, 2> SubDivTree;
bool init2(); bool load();
int level(int bits); int level(int bits);
bool parsePoly(Handle hdl, quint32 pos, const QMap<int, int> &level2bits, bool parsePoly(Handle hdl, quint32 pos, const QMap<int, int> &level2bits,
QMap<quint32, int> &map); QMap<quint32, int> &map);

View File

@ -14,6 +14,7 @@ public:
~VectorTile() {delete _tre; delete _rgn; delete _lbl; delete _net;} ~VectorTile() {delete _tre; delete _rgn; delete _lbl; delete _net;}
bool init(); bool init();
void clear() {_tre->clear();}
const RectC &bounds() const {return _tre->bounds();} const RectC &bounds() const {return _tre->bounds();}

View File

@ -174,6 +174,16 @@ IMGMap::IMGMap(const QString &fileName, QObject *parent)
_valid = true; _valid = true;
} }
void IMGMap::load()
{
_img.load();
}
void IMGMap::unload()
{
_img.clear();
}
QRectF IMGMap::bounds() QRectF IMGMap::bounds()
{ {
RectD prect(_img.bounds(), _projection); RectD prect(_img.bounds(), _projection);
@ -248,12 +258,12 @@ Coordinates IMGMap::xy2ll(const QPointF &p)
void IMGMap::drawPolygons(QPainter *painter, const QList<IMG::Poly> &polygons) void IMGMap::drawPolygons(QPainter *painter, const QList<IMG::Poly> &polygons)
{ {
for (int n = 0; n < _img.style().drawOrder().size(); n++) { for (int n = 0; n < _img.style()->drawOrder().size(); n++) {
for (int i = 0; i < polygons.size(); i++) { for (int i = 0; i < polygons.size(); i++) {
const IMG::Poly &poly = polygons.at(i); const IMG::Poly &poly = polygons.at(i);
if (poly.type != _img.style().drawOrder().at(n)) if (poly.type != _img.style()->drawOrder().at(n))
continue; continue;
const Style::Polygon &style = _img.style().polygon(poly.type); const Style::Polygon &style = _img.style()->polygon(poly.type);
painter->setPen(style.pen()); painter->setPen(style.pen());
painter->setBrush(style.brush()); painter->setBrush(style.brush());
@ -268,7 +278,7 @@ void IMGMap::drawLines(QPainter *painter, const QList<IMG::Poly> &lines)
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
const IMG::Poly &poly = lines.at(i); const IMG::Poly &poly = lines.at(i);
const Style::Line &style = _img.style().line(poly.type); const Style::Line &style = _img.style()->line(poly.type);
if (style.background() == Qt::NoPen) if (style.background() == Qt::NoPen)
continue; continue;
@ -279,7 +289,7 @@ void IMGMap::drawLines(QPainter *painter, const QList<IMG::Poly> &lines)
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
const IMG::Poly &poly = lines.at(i); const IMG::Poly &poly = lines.at(i);
const Style::Line &style = _img.style().line(poly.type); const Style::Line &style = _img.style()->line(poly.type);
if (!style.img().isNull()) if (!style.img().isNull())
BitmapLine::draw(painter, poly.points, style.img()); BitmapLine::draw(painter, poly.points, style.img());
@ -326,7 +336,7 @@ void IMGMap::processLines(QList<IMG::Poly> &lines, const QPoint &tile,
if (_zoom >= LINE_TEXT_MIN_ZOOM) { if (_zoom >= LINE_TEXT_MIN_ZOOM) {
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
IMG::Poly &poly = lines[i]; IMG::Poly &poly = lines[i];
const Style::Line &style = _img.style().line(poly.type); const Style::Line &style = _img.style()->line(poly.type);
if (style.img().isNull() && style.foreground() == Qt::NoPen) if (style.img().isNull() && style.foreground() == Qt::NoPen)
continue; continue;
@ -415,7 +425,7 @@ void IMGMap::processPoints(QList<IMG::Point> &points,
for (int i = 0; i < points.size(); i++) { for (int i = 0; i < points.size(); i++) {
IMG::Point &point = points[i]; IMG::Point &point = points[i];
const Style::Point &style = _img.style().point(point.type); const Style::Point &style = _img.style()->point(point.type);
if (point.poi && _zoom < minPOIZoom(Style::poiClass(point.type))) if (point.poi && _zoom < minPOIZoom(Style::poiClass(point.type)))
continue; continue;

View File

@ -34,6 +34,9 @@ public:
void setProjection(const Projection &projection); void setProjection(const Projection &projection);
void load();
void unload();
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
@ -56,6 +59,7 @@ private:
Range _zooms; Range _zooms;
Projection _projection; Projection _projection;
Transform _transform; Transform _transform;
bool _valid; bool _valid;
QString _errorString; QString _errorString;
}; };