diff --git a/src/map/IMG/light.h b/src/map/IMG/light.h index 00c8fc0e..f968de21 100644 --- a/src/map/IMG/light.h +++ b/src/map/IMG/light.h @@ -6,30 +6,41 @@ namespace IMG { -struct Light +class Light { +public: enum Color {None, Red, Green, White, Blue, Yellow, Violet, Amber}; - struct Sector + class Sector { public: - Sector() : color(None), angle(0), range(0) {} + Sector() : _color(None), _angle(0), _range(0) {} Sector(Color color, quint32 angle, quint32 range) - : color(color), angle(angle), range(range) {} + : _color(color), _angle(angle), _range(range) {} - Color color; - quint32 angle; - quint32 range; + Color color() const {return _color;} + quint32 angle() const {return _angle;} + quint32 range() const {return _range;} + + private: + Color _color; + quint32 _angle; + quint32 _range; }; - Light() : color(None), range(0) {} - Light(Color color, quint32 range) : color(color), range(range) {} + Light() : _color(None), _range(0) {} + Light(Color color, quint32 range) : _color(color), _range(range) {} Light(const QVector §ors) - : color(None), range(0), sectors(sectors) {} + : _color(None), _range(0), _sectors(sectors) {} - Color color; - quint32 range; - QVector sectors; + Color color() const {return _color;} + quint32 range() const {return _range;} + const QVector §ors() const {return _sectors;} + +private: + Color _color; + quint32 _range; + QVector _sectors; }; } @@ -44,8 +55,8 @@ inline QDebug operator<<(QDebug dbg, const IMG::Light::Sector §or) inline QDebug operator<<(QDebug dbg, const IMG::Light &light) { - dbg.nospace() << "Light(" << light.color << ", " << light.range << ", " - << light.sectors << ")"; + dbg.nospace() << "Light(" << light.color() << ", " << light.range() << ", " + << light.sectors() << ")"; return dbg.space(); } #endif // QT_NO_DEBUG diff --git a/src/map/IMG/rastertile.cpp b/src/map/IMG/rastertile.cpp index 7a49ee17..236dfcbd 100644 --- a/src/map/IMG/rastertile.cpp +++ b/src/map/IMG/rastertile.cpp @@ -243,28 +243,28 @@ void RasterTile::drawSectorLights(QPainter *painter, for (int j = 0; j < p->lights.size(); j++) { const Light &l = p->lights.at(j); - if (l.sectors.size()) { - for (int k = 0; k < l.sectors.size(); k++) { - const Light::Sector &start = l.sectors.at(k); - const Light::Sector &end = (k == l.sectors.size() - 1) - ? l.sectors.at(0) : l.sectors.at(k+1); + if (l.sectors().size()) { + for (int k = 0; k < l.sectors().size(); k++) { + const Light::Sector &start = l.sectors().at(k); + const Light::Sector &end = (k == l.sectors().size() - 1) + ? l.sectors().at(0) : l.sectors().at(k+1); - if (start.color) { - double a1 = -(end.angle / 10.0 + 90.0); - double a2 = -(start.angle / 10.0 + 90.0); + if (start.color()) { + double a1 = -(end.angle() / 10.0 + 90.0); + double a2 = -(start.angle() / 10.0 + 90.0); if (a1 > a2) a2 += 360; double as = (a2 - a1); if (as == 0) as = 360; - QRect rect(lightRect(pos, start.range - ? start.range : RANGE_MIN)); + QRect rect(lightRect(pos, start.range() + ? start.range() : RANGE_MIN)); painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap)); painter->drawArc(rect, a1 * 16, as * 16); - painter->setPen(QPen(Style::color(start.color), 4, + painter->setPen(QPen(Style::color(start.color()), 4, Qt::SolidLine, Qt::FlatCap)); painter->drawArc(rect, a1 * 16, as * 16); @@ -279,12 +279,12 @@ void RasterTile::drawSectorLights(QPainter *painter, } } } - } else if (l.range > RANGE_MIN) { - QRect rect(lightRect(pos, l.range)); + } else if (l.range() > RANGE_MIN) { + QRect rect(lightRect(pos, l.range())); painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap)); painter->drawArc(rect, 0, 360 * 16); - painter->setPen(QPen(Style::color(l.color), 4, Qt::SolidLine, + painter->setPen(QPen(Style::color(l.color()), 4, Qt::SolidLine, Qt::FlatCap)); painter->drawArc(rect, 0, 360 * 16); } @@ -467,7 +467,7 @@ static bool showAsSector(const QVector &lights) { for (int i = 0; i < lights.size(); i++) { const Light &l = lights.at(i); - if ((l.color && l.range > RANGE_MIN) || !l.sectors.isEmpty()) + if ((l.color() && l.range() > RANGE_MIN) || !l.sectors().isEmpty()) return true; } @@ -513,9 +513,9 @@ void RasterTile::processPoints(QList &points, textItems.append(item); for (int j = 0; j < point.lights.size(); j++) { const Light &l = point.lights.at(j); - if (l.color && l.range <= RANGE_MIN) { + if (l.color() && l.range() <= RANGE_MIN) { textItems.append(new TextPointItem(pos + style->lightOffset(), - 0, 0, style->light(l.color), 0, 0, 0, 0)); + 0, 0, style->light(l.color()), 0, 0, 0, 0)); break; } } diff --git a/src/map/IMG/rgnfile.cpp b/src/map/IMG/rgnfile.cpp index 0deb400a..a2668ff1 100644 --- a/src/map/IMG/rgnfile.cpp +++ b/src/map/IMG/rgnfile.cpp @@ -13,6 +13,7 @@ using namespace Garmin; using namespace IMG; #define MASK(bits) ((1U << (bits)) - 1U) +#define COLOR(color) ((Light::Color)(color)) static quint64 pointId(const QPoint &pos, quint32 type, const QString &label) { @@ -124,7 +125,7 @@ bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, quint32 size, lc = (val >> 6) & 7; if (lc) - point->lights.append(Light((Light::Color)lc, 0)); + point->lights.append(Light(COLOR(lc), 0)); return true; } @@ -198,7 +199,7 @@ bool RGNFile::readLightInfo(Handle &hdl, quint8 flags, quint32 size, size -= 2; cf = la >> 8; - Light::Color c = (Light::Color)(cf >> 4 & 7); + Light::Color c = COLOR(cf >> 4 & 7); if (c) { if (!(size >= 1 && readUInt8(hdl, range))) return false; @@ -223,7 +224,7 @@ bool RGNFile::readLightInfo(Handle &hdl, quint8 flags, quint32 size, range += v2; } - point->lights.append(Light((Light::Color)(v1 >> 5), range)); + point->lights.append(Light(COLOR(v1 >> 5), range)); } return true; @@ -291,11 +292,123 @@ bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType, return seek(hdl, off + rs); } +bool RGNFile::readLclSectors(Handle &hdl, quint32 &size, quint32 flags, + Light &light) const +{ + quint32 unused, cnt = flags & 0x1f; + QVector sectors; + + for (quint32 j = 0; j < cnt; j++) { + quint32 cf, range = 0; + + if (!(size >= 1 && readUInt8(hdl, cf))) + return false; + size--; + if (cf >> 6) { + if (!(size >= (cf >> 6) && readVUInt32(hdl, cf >> 6, range))) + return false; + size -= (cf >> 6); + } + + if (cnt > 1) { + quint32 angle; + + if (!(size >= 2 && readUInt16(hdl, angle))) + return false; + size -= 2; + if ((flags >> 0x13) & 1) { + quint32 sflags; + + if (!(size >= 1 && readUInt8(hdl, sflags))) + return false; + size--; + if (0x3f < sflags) { + if (sflags & 0x80) { + if (!(size >= 1 && readUInt8(hdl, unused))) + return false; + size--; + unused |= (sflags & 0x40) << 2; + } else { + if (!(size >= 2 && readUInt16(hdl, unused))) + return false; + size -= 2; + } + } + } + + sectors.append(Light::Sector(COLOR(cf & 0x7), angle, range)); + } else { + light = Light(COLOR(cf & 0x7), range); + return true; + } + } + + light = Light(sectors); + + return true; +} + +bool RGNFile::readLclLights(Handle &hdl, quint32 &size, quint32 lights, + MapData::Point *point) const +{ + quint32 unused; + + for (quint32 i = 0; i < lights; i++) { + quint32 fs, vs, flags; + Light light; + + if (!(readVUInt32(hdl, fs, &vs) && size >= vs)) + return false; + size -= vs; + if (!(size >= 4 && readUInt32(hdl, flags))) + return false; + size -= 4; + if (flags >> 0x11 & 3) { + if (!(size >= (flags >> 0x11 & 3) + && readVUInt32(hdl, flags >> 0x11 & 3, unused))) + return false; + size -= (flags >> 0x11 & 3); + } + if (flags & 0x3000) { + if (flags & 0x2000) { + if (!(size >= 1 && readUInt8(hdl, unused))) + return false; + size--; + unused |= (flags >> 4) & 0x100; + } else { + if (!(size >= 2 && readUInt16(hdl, unused))) + return false; + size -= 2; + } + } + if (flags & 0x100000) { + if (!(size >= 1 && readUInt8(hdl, unused))) + return false; + size--; + if (unused & 0x80) { + if (!(size >= 1 && readUInt8(hdl, unused))) + return false; + size--; + } + } + + if (!readLclSectors(hdl, size, flags, light)) + return false; + + point->lights.append(light); + } + + return true; +} + bool RGNFile::readLclNavaid(Handle &hdl, quint32 size, MapData::Point *point) const { quint32 unused, flags; + // Discard the class lights info if any (marine points may have both!) + point->lights.clear(); + if (!(size >= 4 && readUInt32(hdl, flags))) return false; size -= 4; @@ -338,97 +451,8 @@ bool RGNFile::readLclNavaid(Handle &hdl, quint32 size, } while (b & 0x80); } - quint8 lights = (flags >> 6) & 7; - - for (quint32 i = 0; i < lights; i ++) { - quint32 fs, vs, lflags; - Light light; - - if (!(readVUInt32(hdl, fs, &vs) && size >= vs)) - return false; - size -= vs; - if (!(size >= 4 && readUInt32(hdl, lflags))) - return false; - size -= 4; - if (lflags >> 0x11 & 3) { - if (!(size >= (lflags >> 0x11 & 3) - && readVUInt32(hdl, lflags >> 0x11 & 3, unused))) - return false; - size -= (lflags >> 0x11 & 3); - } - if (lflags & 0x3000) { - if (lflags & 0x2000) { - if (!(size >= 1 && readUInt8(hdl, unused))) - return false; - size--; - unused |= (lflags >> 4) & 0x100; - } else { - if (!(size >= 2 && readUInt16(hdl, unused))) - return false; - size -= 2; - } - } - if (lflags & 0x100000) { - if (!(size >= 1 && readUInt8(hdl, unused))) - return false; - size--; - if (unused & 0x80) { - if (!(size >= 1 && readUInt8(hdl, unused))) - return false; - size--; - } - } - - quint8 sectors = lflags & 0x1f; - - for (quint32 j = 0; j < sectors; j++) { - quint32 cf, range = 0; - - if (!(size >= 1 && readUInt8(hdl, cf))) - return false; - size--; - if (cf >> 6) { - if (!(size >= (cf >> 6) && readVUInt32(hdl, cf >> 6, range))) - return false; - size -= (cf >> 6); - } - - if (sectors > 1) { - quint32 angle; - - if (!(size >= 2 && readUInt16(hdl, angle))) - return false; - size -= 2; - if ((lflags >> 0x13) & 1) { - quint32 sflags; - - if (!(size >= 1 && readUInt8(hdl, sflags))) - return false; - size--; - if (0x3f < sflags) { - if (sflags & 0x80) { - if (!(size >= 1 && readUInt8(hdl, unused))) - return false; - size--; - unused |= (sflags & 0x40) << 2; - } else { - if (!(size >= 2 && readUInt16(hdl, unused))) - return false; - size -= 2; - } - } - } - - light.sectors.append(Light::Sector((Light::Color)(cf & 0x7), - angle, range)); - } else { - light.color = (Light::Color)(cf & 0x7); - light.range = range; - } - } - - point->lights.append(light); - } + if (!readLclLights(hdl, size, (flags >> 6) & 7, point)) + return false; return (size == 0); } @@ -457,7 +481,6 @@ bool RGNFile::readLclFields(Handle &hdl, const quint32 flags[3], size = m + 1; if (i == 2 && point) { - point->lights.clear(); if (!readLclNavaid(hdl, size, point)) return false; } else { diff --git a/src/map/IMG/rgnfile.h b/src/map/IMG/rgnfile.h index fd19b97a..47558dc8 100644 --- a/src/map/IMG/rgnfile.h +++ b/src/map/IMG/rgnfile.h @@ -73,6 +73,10 @@ private: quint8 flags, quint32 size, MapData::Point *point) const; bool readLclNavaid(Handle &hdl, quint32 size, MapData::Point *point) const; + bool readLclSectors(Handle &hdl, quint32 &size, quint32 flags, + Light &light) const; + bool readLclLights(Handle &hdl, quint32 &size, quint32 lights, + MapData::Point *point) const; HuffmanTable *_huffmanTable; Section _base, _dict, _polygons, _lines, _points;