From 5d6970c7eea6eed1a900a45c79109b7444398ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Sun, 6 Feb 2022 02:42:37 +0100 Subject: [PATCH] Read/display extended (class) point labels --- src/map/IMG/lblfile.cpp | 124 +++++++++++++++++++------------------ src/map/IMG/lblfile.h | 8 ++- src/map/IMG/mapdata.h | 3 +- src/map/IMG/rastertile.cpp | 10 ++- src/map/IMG/rgnfile.cpp | 22 +++++-- src/map/IMG/rgnfile.h | 4 +- 6 files changed, 97 insertions(+), 74 deletions(-) diff --git a/src/map/IMG/lblfile.cpp b/src/map/IMG/lblfile.cpp index 9fc15fc7..546b2a02 100644 --- a/src/map/IMG/lblfile.cpp +++ b/src/map/IMG/lblfile.cpp @@ -137,7 +137,50 @@ void LBLFile::clear() _rasters = 0; } -Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize, +Label LBLFile::str2label(const QVector &str, bool capitalize, + bool convert) const +{ + Shield::Type shieldType = Shield::None; + QByteArray label, shieldLabel; + QByteArray *bap = &label; + int split = -1; + + for (int i = 0; i < str.size(); i++) { + const quint8 &c = str.at(i); + + if (c == 0 || c == 0x1d || c == 0x07) + break; + + if (c == 0x1c) + capitalize = false; + else if ((c >= 0x1e && c <= 0x1f)) { + if (bap == &shieldLabel) + bap = &label; + else { + if (!bap->isEmpty()) + bap->append('\n'); + if (c == 0x1f && split < 0) + split = bap->size(); + } + } else if (c < 0x07) { + shieldType = static_cast(c); + bap = &shieldLabel; + } else if (bap == &shieldLabel && c == 0x20) { + bap = &label; + } else + bap->append(c); + } + + if (split >= 0) + label = label.left(split) + ft2m(label.mid(split)); + else if (convert) + label = ft2m(label); + QString text(_codec.toString(label)); + return Label(capitalize && isAllUpperCase(text) ? capitalized(text) : text, + Shield(shieldType, _codec.toString(shieldLabel))); +} + +Label LBLFile::label6b(const SubFile *file, Handle &hdl, bool capitalize, bool convert) const { Shield::Type shieldType = Shield::None; @@ -147,11 +190,9 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize, quint8 b1, b2, b3; int split = -1; - if (!seek(hdl, offset)) - return Label(); - while (true) { - if (!(readByte(hdl, &b1) && readByte(hdl, &b2) && readByte(hdl, &b3))) + if (!(file->readByte(hdl, &b1) && file->readByte(hdl, &b2) + && file->readByte(hdl, &b3))) return Label(); int c[]= {b1>>2, (b1&0x3)<<4|b2>>4, (b2&0xF)<<2|b3>>6, b3&0x3F}; @@ -203,60 +244,14 @@ Label LBLFile::label6b(Handle &hdl, quint32 offset, bool capitalize, } } -Label LBLFile::str2label(const QVector &str, bool capitalize, - bool convert) const -{ - Shield::Type shieldType = Shield::None; - QByteArray label, shieldLabel; - QByteArray *bap = &label; - int split = -1; - - for (int i = 0; i < str.size(); i++) { - const quint8 &c = str.at(i); - - if (c == 0 || c == 0x1d || c == 0x07) - break; - - if (c == 0x1c) - capitalize = false; - else if ((c >= 0x1e && c <= 0x1f)) { - if (bap == &shieldLabel) - bap = &label; - else { - if (!bap->isEmpty()) - bap->append('\n'); - if (c == 0x1f && split < 0) - split = bap->size(); - } - } else if (c < 0x07) { - shieldType = static_cast(c); - bap = &shieldLabel; - } else if (bap == &shieldLabel && c == 0x20) { - bap = &label; - } else - bap->append(c); - } - - if (split >= 0) - label = label.left(split) + ft2m(label.mid(split)); - else if (convert) - label = ft2m(label); - QString text(_codec.toString(label)); - return Label(capitalize && isAllUpperCase(text) ? capitalized(text) : text, - Shield(shieldType, _codec.toString(shieldLabel))); -} - -Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize, +Label LBLFile::label8b(const SubFile *file, Handle &hdl, bool capitalize, bool convert) const { QVector str; quint8 c; - if (!seek(hdl, offset)) - return Label(); - do { - if (!readByte(hdl, &c)) + if (!file->readByte(hdl, &c)) return Label(); str.append(c); } while (c); @@ -264,15 +259,13 @@ Label LBLFile::label8b(Handle &hdl, quint32 offset, bool capitalize, return str2label(str, capitalize, convert); } -Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize, +Label LBLFile::labelHuffman(const SubFile *file, Handle &hdl, bool capitalize, bool convert) const { QVector str; quint32 end = _offset + _size; - if (!seek(hdl, offset)) - return Label(); - if (!_huffmanText->decode(this, hdl, end - offset, str)) + if (!_huffmanText->decode(file, hdl, end - pos(hdl), str)) return Label(); if (!_table) return str2label(str, capitalize, convert); @@ -291,7 +284,7 @@ Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize, else if (str2.size()) str2.append(' '); - if (!_huffmanText->decode(this, hdl, end - off, str2)) + if (!_huffmanText->decode(file, hdl, end - off, str2)) return Label(); } else { if (str.at(i) == 7) { @@ -324,14 +317,23 @@ Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize, if (labelOffset > _offset + _size) return QString(); + if (!seek(hdl, labelOffset)) + return Label(); + + return label(this, hdl, capitalize, convert); +} + +Label LBLFile::label(const SubFile *file, Handle &hdl, bool capitalize, + bool convert) const +{ switch (_encoding) { case 6: - return label6b(hdl, labelOffset, capitalize, convert); + return label6b(file, hdl, capitalize, convert); case 9: case 10: - return label8b(hdl, labelOffset, capitalize, convert); + return label8b(file, hdl, capitalize, convert); case 11: - return labelHuffman(hdl, labelOffset, capitalize, convert); + return labelHuffman(file, hdl, capitalize, convert); default: return Label(); } diff --git a/src/map/IMG/lblfile.h b/src/map/IMG/lblfile.h index d4fab03f..5eb6fb41 100644 --- a/src/map/IMG/lblfile.h +++ b/src/map/IMG/lblfile.h @@ -33,6 +33,8 @@ public: Label label(Handle &hdl, quint32 offset, bool poi = false, bool capitalize = true, bool convert = false) const; + Label label(const SubFile *file, Handle &hdl, bool capitalize = true, + bool convert = false) const; quint8 imageIdSize() const {return _imgOffsetIdSize;} QPixmap image(Handle &hdl, quint32 id) const; @@ -45,11 +47,11 @@ private: Label str2label(const QVector &str, bool capitalize, bool convert) const; - Label label6b(Handle &hdl, quint32 offset, bool capitalize, + Label label6b(const SubFile *file, Handle &hdl, bool capitalize, bool convert) const; - Label label8b(Handle &hdl, quint32 offset, bool capitalize, + Label label8b(const SubFile *file, Handle &hdl, bool capitalize, bool convert) const; - Label labelHuffman(Handle &hdl, quint32 offset, bool capitalize, + Label labelHuffman(const SubFile *file, Handle &hdl, bool capitalize, bool convert) const; bool loadRasterTable(Handle &hdl, quint32 offset, quint32 size, quint32 recordSize); diff --git a/src/map/IMG/mapdata.h b/src/map/IMG/mapdata.h index f42f73ec..7220c15e 100644 --- a/src/map/IMG/mapdata.h +++ b/src/map/IMG/mapdata.h @@ -38,12 +38,13 @@ public: }; struct Point { - Point() : id(0) {} + Point() : id(0), classLabel(false) {} Coordinates coordinates; Label label; quint32 type; quint64 id; + bool classLabel; bool operator<(const Point &other) const {return id < other.id;} diff --git a/src/map/IMG/rastertile.cpp b/src/map/IMG/rastertile.cpp index 47cced8d..12c31572 100644 --- a/src/map/IMG/rastertile.cpp +++ b/src/map/IMG/rastertile.cpp @@ -54,10 +54,16 @@ static QFont *font(Style::FontSize size, Style::FontSize defaultSize } } -static QFont *poiFont(Style::FontSize size = Style::Normal) +static QFont *poiFont(Style::FontSize size = Style::Normal, int zoom = -1, + bool extended = false) { static QFont poi = pixelSizeFont(10); + if (zoom > 25) + size = Style::Normal; + else if (extended) + size = Style::None; + switch (size) { case Style::None: return 0; @@ -435,7 +441,7 @@ void RasterTile::processPoints(QList &textItems) ? 0 : &(point.label.text()); const QImage *img = style.img().isNull() ? 0 : &style.img(); const QFont *fnt = poi - ? poiFont(_zoom > 25 ? Style::Normal : style.textFontSize()) + ? poiFont(style.textFontSize(), _zoom, point.classLabel) : font(style.textFontSize()); const QColor *color = style.textColor().isValid() ? &style.textColor() : &textColor; diff --git a/src/map/IMG/rgnfile.cpp b/src/map/IMG/rgnfile.cpp index 5a11f61f..6b7163aa 100644 --- a/src/map/IMG/rgnfile.cpp +++ b/src/map/IMG/rgnfile.cpp @@ -33,10 +33,14 @@ RGNFile::~RGNFile() } bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType, - MapData::Poly *poly, const LBLFile *lbl) const + void *object, const LBLFile *lbl) const { quint8 flags; quint32 rs; + MapData::Poly *poly = (segmentType == Polygon) + ? (MapData::Poly *) object : 0; + MapData::Point *point = (segmentType == Point) + ? (MapData::Point *) object : 0; if (!readByte(hdl, &flags)) return false; @@ -60,8 +64,7 @@ bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType, break; } - if (segmentType == Polygon && Style::isRaster(poly->type) && lbl - && lbl->imageIdSize()) { + if (poly && Style::isRaster(poly->type) && lbl && lbl->imageIdSize()) { quint32 id; quint32 top, right, bottom, left; @@ -78,6 +81,14 @@ bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType, rs -= lbl->imageIdSize() + 16; } + if (point && (flags & 1) && lbl) { + quint32 p = pos(hdl); + point->label = lbl->label(this, hdl); + point->classLabel = true; + + rs -= (pos(hdl) - p); + } + return seek(hdl, pos(hdl) + rs); } @@ -431,9 +442,11 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, && readInt16(hdl, lon) && readInt16(hdl, lat))) return false; + point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F); + if (subtype & 0x20 && !readUInt24(hdl, labelPtr)) return false; - if (subtype & 0x80 && !readClassFields(hdl, Point)) + if (subtype & 0x80 && !readClassFields(hdl, Point, &point, lbl)) return false; if (subtype & 0x40 && !skipLclFields(hdl, _pointsLclFlags)) return false; @@ -443,7 +456,6 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()), subdiv->lat() + LS(lat, 24-subdiv->bits())); - point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F); // Discard NT points breaking style draw order logic (and causing huge // performance drawback) if (point.type == 0x11400) diff --git a/src/map/IMG/rgnfile.h b/src/map/IMG/rgnfile.h index 28e8fa16..fcc6c7e2 100644 --- a/src/map/IMG/rgnfile.h +++ b/src/map/IMG/rgnfile.h @@ -62,8 +62,8 @@ public: private: bool segments(Handle &hdl, SubDiv *subdiv, SubDiv::Segment seg[5]) const; - bool readClassFields(Handle &hdl, SegmentType segmentType, - MapData::Poly *poly = 0, const LBLFile *lbl = 0) const; + bool readClassFields(Handle &hdl, SegmentType segmentType, void *object, + const LBLFile *lbl) const; bool skipLclFields(Handle &hdl, const quint32 flags[3]) const; bool skipGblFields(Handle &hdl, quint32 flags) const;