mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-28 05:34:47 +01:00
Improved IMG map memory management
This commit is contained in:
parent
b4cc88446a
commit
53e960fabe
@ -5,6 +5,8 @@
|
||||
#include "img.h"
|
||||
|
||||
|
||||
#define CACHE_SIZE 8388608 /* 8MB */
|
||||
|
||||
#define CHECK(condition) \
|
||||
if (!(condition)) { \
|
||||
_errorString = "Invalid/corrupted IMG file"; \
|
||||
@ -25,7 +27,8 @@ struct CTX
|
||||
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)) {
|
||||
_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)));
|
||||
_name = QString(nba).trimmed();
|
||||
_blockSize = 1 << (e1 + e2);
|
||||
_blockCache.setMaxCost(CACHE_SIZE / _blockSize);
|
||||
|
||||
// Read the FAT table
|
||||
quint8 flag;
|
||||
@ -72,7 +76,7 @@ IMG::IMG(const QString &fileName) : _file(fileName), _valid(false)
|
||||
|
||||
|
||||
QMap<QString, VectorTile*> tileMap;
|
||||
QMap<QString, SubFile*> TYPMap;
|
||||
QString typFile;
|
||||
|
||||
// Read FAT blocks describing the IMG sub-files
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
@ -108,20 +112,22 @@ IMG::IMG(const QString &fileName) : _file(fileName), _valid(false)
|
||||
file->addBlock(block);
|
||||
}
|
||||
} else if (tt == SubFile::TYP) {
|
||||
SubFile *typ;
|
||||
QMap<QString, SubFile*>::iterator it = TYPMap.find(fn);
|
||||
if (it == TYPMap.end()) {
|
||||
typ = new SubFile(this, size);
|
||||
TYPMap.insert(fn, typ);
|
||||
} else
|
||||
typ = *it;
|
||||
SubFile *typ = 0;
|
||||
if (typFile.isNull()) {
|
||||
_typ = new SubFile(this, size);
|
||||
typ = _typ;
|
||||
typFile = fn;
|
||||
} else if (fn == typFile)
|
||||
typ = _typ;
|
||||
|
||||
_file.seek(offset + 0x20);
|
||||
for (int i = 0; i < 240; i++) {
|
||||
CHECK(readValue(block));
|
||||
if (block == 0xFFFF)
|
||||
break;
|
||||
typ->addBlock(block);
|
||||
if (typ) {
|
||||
_file.seek(offset + 0x20);
|
||||
for (int i = 0; i < 240; i++) {
|
||||
CHECK(readValue(block));
|
||||
if (block == 0xFFFF)
|
||||
break;
|
||||
typ->addBlock(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,22 +149,6 @@ IMG::IMG(const QString &fileName) : _file(fileName), _valid(false)
|
||||
_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;
|
||||
}
|
||||
|
||||
@ -167,6 +157,37 @@ IMG::~IMG()
|
||||
TileTree::Iterator it;
|
||||
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(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)
|
||||
|
@ -48,13 +48,16 @@ public:
|
||||
IMG(const QString &fileName);
|
||||
~IMG();
|
||||
|
||||
void load();
|
||||
void clear();
|
||||
|
||||
QString fileName() const {return _file.fileName();}
|
||||
const QString &name() const {return _name;}
|
||||
const RectC &bounds() const {return _bounds;}
|
||||
|
||||
void objects(const RectC &rect, int bits, QList<Poly> *polygons,
|
||||
QList<Poly> *lines, QList<Point> *points);
|
||||
const Style &style() const {return _style;}
|
||||
const Style *style() const {return _style;}
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
const QString &errorString() const {return _errorString;}
|
||||
@ -75,11 +78,11 @@ private:
|
||||
int _blockSize;
|
||||
QCache<int, QByteArray> _blockCache;
|
||||
|
||||
TileTree _tileTree;
|
||||
|
||||
QString _name;
|
||||
RectC _bounds;
|
||||
Style _style;
|
||||
TileTree _tileTree;
|
||||
SubFile *_typ;
|
||||
Style *_style;
|
||||
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
|
@ -40,18 +40,7 @@ static void unlock(quint8 *dst, const quint8 *src, quint32 size, quint32 key)
|
||||
|
||||
TREFile::~TREFile()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
for (QMap<int, SubDivTree*>::iterator it = _subdivs.begin();
|
||||
it != _subdivs.end(); ++it)
|
||||
delete *it;
|
||||
clear();
|
||||
}
|
||||
|
||||
bool TREFile::init()
|
||||
@ -69,7 +58,7 @@ bool TREFile::init()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TREFile::init2()
|
||||
bool TREFile::load()
|
||||
{
|
||||
Handle hdl;
|
||||
quint8 locked;
|
||||
@ -202,9 +191,26 @@ bool TREFile::init2()
|
||||
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)
|
||||
{
|
||||
if (_levels.isEmpty() && !init2())
|
||||
if (_levels.isEmpty() && !load())
|
||||
return -1;
|
||||
|
||||
int l = _levels.first();
|
||||
|
@ -17,6 +17,7 @@ public:
|
||||
~TREFile();
|
||||
|
||||
bool init();
|
||||
void clear();
|
||||
|
||||
const RectC &bounds() const {return _bounds;}
|
||||
QList<SubDiv*> subdivs(const RectC &rect, int bits);
|
||||
@ -24,7 +25,7 @@ public:
|
||||
private:
|
||||
typedef RTree<SubDiv*, double, 2> SubDivTree;
|
||||
|
||||
bool init2();
|
||||
bool load();
|
||||
int level(int bits);
|
||||
bool parsePoly(Handle hdl, quint32 pos, const QMap<int, int> &level2bits,
|
||||
QMap<quint32, int> &map);
|
||||
|
@ -14,6 +14,7 @@ public:
|
||||
~VectorTile() {delete _tre; delete _rgn; delete _lbl; delete _net;}
|
||||
|
||||
bool init();
|
||||
void clear() {_tre->clear();}
|
||||
|
||||
const RectC &bounds() const {return _tre->bounds();}
|
||||
|
||||
|
@ -174,6 +174,16 @@ IMGMap::IMGMap(const QString &fileName, QObject *parent)
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void IMGMap::load()
|
||||
{
|
||||
_img.load();
|
||||
}
|
||||
|
||||
void IMGMap::unload()
|
||||
{
|
||||
_img.clear();
|
||||
}
|
||||
|
||||
QRectF IMGMap::bounds()
|
||||
{
|
||||
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)
|
||||
{
|
||||
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++) {
|
||||
const IMG::Poly &poly = polygons.at(i);
|
||||
if (poly.type != _img.style().drawOrder().at(n))
|
||||
if (poly.type != _img.style()->drawOrder().at(n))
|
||||
continue;
|
||||
const Style::Polygon &style = _img.style().polygon(poly.type);
|
||||
const Style::Polygon &style = _img.style()->polygon(poly.type);
|
||||
|
||||
painter->setPen(style.pen());
|
||||
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++) {
|
||||
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)
|
||||
continue;
|
||||
@ -279,7 +289,7 @@ void IMGMap::drawLines(QPainter *painter, const QList<IMG::Poly> &lines)
|
||||
|
||||
for (int i = 0; i < lines.size(); 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())
|
||||
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) {
|
||||
for (int i = 0; i < lines.size(); 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)
|
||||
continue;
|
||||
@ -415,7 +425,7 @@ void IMGMap::processPoints(QList<IMG::Point> &points,
|
||||
for (int i = 0; i < points.size(); 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)))
|
||||
continue;
|
||||
|
@ -34,6 +34,9 @@ public:
|
||||
|
||||
void setProjection(const Projection &projection);
|
||||
|
||||
void load();
|
||||
void unload();
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
@ -56,6 +59,7 @@ private:
|
||||
Range _zooms;
|
||||
Projection _projection;
|
||||
Transform _transform;
|
||||
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user