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:
parent
b4cc88446a
commit
53e960fabe
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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();}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user