mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-24 03:35:53 +01:00
Be more tolerant to broken TYP files
Where possible, only skip the point/line/polygon entry, not the whole TYP file.
This commit is contained in:
parent
208e31c6de
commit
8f9af0d973
@ -4,6 +4,153 @@
|
||||
|
||||
using namespace IMG;
|
||||
|
||||
static bool readColor(SubFile *file, SubFile::Handle &hdl, QColor &color)
|
||||
{
|
||||
quint8 b, g, r;
|
||||
|
||||
if (!(file->readByte(hdl, &b) && file->readByte(hdl, &g)
|
||||
&& file->readByte(hdl, &r)))
|
||||
return false;
|
||||
|
||||
color = qRgb(r, g, b);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readColorTable(SubFile *file, SubFile::Handle &hdl, QImage& img,
|
||||
int colors, int bpp, bool transparent)
|
||||
{
|
||||
img.setColorCount(colors);
|
||||
|
||||
if (transparent) {
|
||||
quint8 byte;
|
||||
quint32 bits = 0, reg = 0, mask = 0x000000FF;
|
||||
|
||||
for (int i = 0; i < colors; i++) {
|
||||
while (bits < 28) {
|
||||
if (!file->readByte(hdl, &byte))
|
||||
return false;
|
||||
|
||||
mask = 0x000000FF << bits;
|
||||
reg = reg & (~mask);
|
||||
reg = reg | (byte << bits);
|
||||
bits += 8;
|
||||
}
|
||||
|
||||
img.setColor(i, qRgba((reg >> 16) & 0x0FF, (reg >> 8) & 0x0FF,
|
||||
reg & 0x0FF, ~((reg >> 24) & 0x0F) << 4));
|
||||
|
||||
reg = reg >> 28;
|
||||
bits -= 28;
|
||||
}
|
||||
for (int i = colors; i < 1<<bpp; i++)
|
||||
img.setColor(i, qRgba(0, 0, 0, 0));
|
||||
} else {
|
||||
QColor color;
|
||||
|
||||
for (int i = 0; i < colors; i++) {
|
||||
if (!readColor(file, hdl, color))
|
||||
return false;
|
||||
img.setColor(i, color.rgb());
|
||||
}
|
||||
for (int i = colors; i < 1<<bpp; i++)
|
||||
img.setColor(i, qRgba(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readBitmap(SubFile *file, SubFile::Handle &hdl, QImage &img,
|
||||
int bpp)
|
||||
{
|
||||
if (!bpp)
|
||||
return true;
|
||||
|
||||
for (int y = 0; y < img.height(); y++) {
|
||||
for (int x = 0; x < img.width(); x += 8/bpp) {
|
||||
quint8 color;
|
||||
if (!file->readByte(hdl, &color))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < 8/bpp && x + i < img.width(); i++) {
|
||||
int value = (i > 0) ? (color >>= bpp) : color;
|
||||
|
||||
if (bpp == 4)
|
||||
value = value & 0xf;
|
||||
else if (bpp == 2)
|
||||
value = value & 0x3;
|
||||
else if (bpp == 1)
|
||||
value = value & 0x1;
|
||||
|
||||
img.setPixel(x + i, y, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int colors2bpp(quint8 colors, quint8 flags)
|
||||
{
|
||||
switch (flags) {
|
||||
case 0x00:
|
||||
if (colors < 3)
|
||||
return colors;
|
||||
else if (colors == 3)
|
||||
return 2;
|
||||
else if (colors < 16)
|
||||
return 4;
|
||||
else
|
||||
return 8;
|
||||
case 0x10:
|
||||
if (colors == 0)
|
||||
return 1;
|
||||
else if (colors < 3)
|
||||
return 2;
|
||||
else if (colors < 15)
|
||||
return 4;
|
||||
else
|
||||
return 8;
|
||||
case 0x20:
|
||||
if (colors == 0)
|
||||
return -1;
|
||||
else if (colors < 3)
|
||||
return colors;
|
||||
else if (colors < 4)
|
||||
return 2;
|
||||
else if (colors < 16)
|
||||
return 4;
|
||||
else
|
||||
return 8;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool skipLabel(SubFile *file, SubFile::Handle &hdl)
|
||||
{
|
||||
quint32 len;
|
||||
|
||||
if (!file->readVUInt32(hdl, len))
|
||||
return false;
|
||||
if (!file->seek(hdl, file->pos(hdl) + len))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static QImage railroad()
|
||||
{
|
||||
QImage img(16, 4, QImage::Format_ARGB32_Premultiplied);
|
||||
img.fill(QColor("#717171"));
|
||||
QPainter p(&img);
|
||||
p.setPen(QPen(Qt::white, 2));
|
||||
p.drawLine(9, 2, 15, 2);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
void Style::defaultPolygonStyle()
|
||||
{
|
||||
_polygons[TYPE(0x01)] = Polygon(QBrush("#dfd3b5"));
|
||||
@ -151,17 +298,6 @@ void Style::defaultPolygonStyle()
|
||||
<< TYPE(0x13) << 0x10900;
|
||||
}
|
||||
|
||||
static QImage railroad()
|
||||
{
|
||||
QImage img(16, 4, QImage::Format_ARGB32_Premultiplied);
|
||||
img.fill(QColor("#717171"));
|
||||
QPainter p(&img);
|
||||
p.setPen(QPen(Qt::white, 2));
|
||||
p.drawLine(9, 2, 15, 2);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
void Style::defaultLineStyle()
|
||||
{
|
||||
_lines[TYPE(0x01)] = Line(QPen(QColor("#9bd772"), 2, Qt::SolidLine),
|
||||
@ -537,62 +673,6 @@ void Style::defaultPointStyle()
|
||||
_points[0x10705] = Point(QImage(":/IMG/anchoring-prohibited.png"));
|
||||
}
|
||||
|
||||
static bool readBitmap(SubFile *file, SubFile::Handle &hdl, QImage &img,
|
||||
int bpp)
|
||||
{
|
||||
if (!bpp)
|
||||
return true;
|
||||
|
||||
for (int y = 0; y < img.height(); y++) {
|
||||
for (int x = 0; x < img.width(); x += 8/bpp) {
|
||||
quint8 color;
|
||||
if (!file->readByte(hdl, &color))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < 8/bpp && x + i < img.width(); i++) {
|
||||
int value = (i > 0) ? (color >>= bpp) : color;
|
||||
|
||||
if (bpp == 4)
|
||||
value = value & 0xf;
|
||||
else if (bpp == 2)
|
||||
value = value & 0x3;
|
||||
else if (bpp == 1)
|
||||
value = value & 0x1;
|
||||
|
||||
img.setPixel(x + i, y, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readColor(SubFile *file, SubFile::Handle &hdl, QColor &color)
|
||||
{
|
||||
quint8 b, g, r;
|
||||
|
||||
if (!(file->readByte(hdl, &b) && file->readByte(hdl, &g)
|
||||
&& file->readByte(hdl, &r)))
|
||||
return false;
|
||||
|
||||
color = qRgb(r, g, b);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool skipLabel(SubFile *file, SubFile::Handle &hdl)
|
||||
{
|
||||
quint32 len;
|
||||
|
||||
if (!file->readVUInt32(hdl, len))
|
||||
return false;
|
||||
if (!file->seek(hdl, file->pos(hdl) + len))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Style::itemInfo(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion, ItemInfo &info)
|
||||
{
|
||||
@ -623,21 +703,9 @@ bool Style::itemInfo(SubFile *file, SubFile::Handle &hdl,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::parsePolygons(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion)
|
||||
bool Style::parsePolygon(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion, const ItemInfo &info, quint32 type)
|
||||
{
|
||||
if (!section.arrayItemSize)
|
||||
return section.arraySize ? false : true;
|
||||
|
||||
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
|
||||
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
|
||||
return false;
|
||||
ItemInfo info;
|
||||
if (!itemInfo(file, hdl, section, info))
|
||||
return false;
|
||||
quint32 type = info.extended
|
||||
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
|
||||
|
||||
quint8 t8, flags;
|
||||
if (!(file->seek(hdl, section.offset + info.offset)
|
||||
&& file->readByte(hdl, &t8)))
|
||||
@ -734,26 +802,13 @@ bool Style::parsePolygons(SubFile *file, SubFile::Handle &hdl,
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion)
|
||||
bool Style::parseLine(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion, const ItemInfo &info, quint32 type)
|
||||
{
|
||||
if (!section.arrayItemSize)
|
||||
return section.arraySize ? false : true;
|
||||
|
||||
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
|
||||
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
|
||||
return false;
|
||||
ItemInfo info;
|
||||
if (!itemInfo(file, hdl, section, info))
|
||||
return false;
|
||||
quint32 type = info.extended
|
||||
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
|
||||
|
||||
quint8 t8_1, t8_2, flags, rows;
|
||||
if (!(file->seek(hdl, section.offset + info.offset)
|
||||
&& file->readByte(hdl, &t8_1) && file->readByte(hdl, &t8_2)))
|
||||
@ -938,108 +993,15 @@ bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
}
|
||||
_lines[type].setTextFontSize((FontSize)(labelFlags & 0x07));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int colors2bpp(quint8 colors, quint8 flags)
|
||||
bool Style::parsePoint(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion, const ItemInfo &info, quint32 type)
|
||||
{
|
||||
switch (flags) {
|
||||
case 0x00:
|
||||
if (colors < 3)
|
||||
return colors;
|
||||
else if (colors == 3)
|
||||
return 2;
|
||||
else if (colors < 16)
|
||||
return 4;
|
||||
else
|
||||
return 8;
|
||||
case 0x10:
|
||||
if (colors == 0)
|
||||
return 1;
|
||||
else if (colors < 3)
|
||||
return 2;
|
||||
else if (colors < 15)
|
||||
return 4;
|
||||
else
|
||||
return 8;
|
||||
case 0x20:
|
||||
if (colors == 0)
|
||||
return -1;
|
||||
else if (colors < 3)
|
||||
return colors;
|
||||
else if (colors < 4)
|
||||
return 2;
|
||||
else if (colors < 16)
|
||||
return 4;
|
||||
else
|
||||
return 8;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool readColorTable(SubFile *file, SubFile::Handle &hdl, QImage& img,
|
||||
int colors, int bpp, bool transparent)
|
||||
{
|
||||
img.setColorCount(colors);
|
||||
|
||||
if (transparent) {
|
||||
quint8 byte;
|
||||
quint32 bits = 0, reg = 0, mask = 0x000000FF;
|
||||
|
||||
for (int i = 0; i < colors; i++) {
|
||||
while (bits < 28) {
|
||||
if (!file->readByte(hdl, &byte))
|
||||
return false;
|
||||
|
||||
mask = 0x000000FF << bits;
|
||||
reg = reg & (~mask);
|
||||
reg = reg | (byte << bits);
|
||||
bits += 8;
|
||||
}
|
||||
|
||||
img.setColor(i, qRgba((reg >> 16) & 0x0FF, (reg >> 8) & 0x0FF,
|
||||
reg & 0x0FF, ~((reg >> 24) & 0x0F) << 4));
|
||||
|
||||
reg = reg >> 28;
|
||||
bits -= 28;
|
||||
}
|
||||
for (int i = colors; i < 1<<bpp; i++)
|
||||
img.setColor(i, qRgba(0, 0, 0, 0));
|
||||
} else {
|
||||
QColor color;
|
||||
|
||||
for (int i = 0; i < colors; i++) {
|
||||
if (!readColor(file, hdl, color))
|
||||
return false;
|
||||
img.setColor(i, color.rgb());
|
||||
}
|
||||
for (int i = colors; i < 1<<bpp; i++)
|
||||
img.setColor(i, qRgba(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion)
|
||||
{
|
||||
if (!section.arrayItemSize)
|
||||
return section.arraySize ? false : true;
|
||||
|
||||
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
|
||||
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
|
||||
return false;
|
||||
ItemInfo info;
|
||||
if (!itemInfo(file, hdl, section, info))
|
||||
return false;
|
||||
quint32 type = info.extended
|
||||
? 0x10000 | (info.type << 8) | info.subtype
|
||||
: (info.type << 8) | info.subtype;
|
||||
|
||||
quint8 t8_1, width, height, numColors, imgType;
|
||||
|
||||
if (!(file->seek(hdl, section.offset + info.offset)
|
||||
&& file->readByte(hdl, &t8_1) && file->readByte(hdl, &width)
|
||||
&& file->readByte(hdl, &height) && file->readByte(hdl, &numColors)
|
||||
@ -1051,7 +1013,7 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
|
||||
int bpp = colors2bpp(numColors, imgType);
|
||||
if (bpp <= 0)
|
||||
continue;
|
||||
return true;
|
||||
QImage img(width, height, QImage::Format_Indexed8);
|
||||
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
|
||||
return false;
|
||||
@ -1064,7 +1026,7 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
&& file->readByte(hdl, &imgType)))
|
||||
return false;
|
||||
if ((bpp = colors2bpp(numColors, imgType)) < 0)
|
||||
continue;
|
||||
return true;
|
||||
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
|
||||
return false;
|
||||
if (!readBitmap(file, hdl, img, bpp))
|
||||
@ -1074,7 +1036,7 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
&& file->readByte(hdl, &imgType)))
|
||||
return false;
|
||||
if ((bpp = colors2bpp(numColors, imgType)) < 0)
|
||||
continue;
|
||||
return true;
|
||||
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
|
||||
return false;
|
||||
}
|
||||
@ -1094,6 +1056,79 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
}
|
||||
_points[type].setTextFontSize((FontSize)(labelFlags & 0x07));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::parsePolygons(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion)
|
||||
{
|
||||
if (!section.arrayItemSize)
|
||||
return section.arraySize ? false : true;
|
||||
|
||||
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
|
||||
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
|
||||
return false;
|
||||
ItemInfo info;
|
||||
if (!itemInfo(file, hdl, section, info))
|
||||
return false;
|
||||
quint32 type = info.extended
|
||||
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
|
||||
|
||||
if (!parsePolygon(file, hdl, section, info, type))
|
||||
qWarning("%s: %x: broken polygon style",
|
||||
qPrintable(file->fileName()), type);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion)
|
||||
{
|
||||
if (!section.arrayItemSize)
|
||||
return section.arraySize ? false : true;
|
||||
|
||||
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
|
||||
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
|
||||
return false;
|
||||
|
||||
ItemInfo info;
|
||||
if (!itemInfo(file, hdl, section, info))
|
||||
return false;
|
||||
|
||||
quint32 type = info.extended
|
||||
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
|
||||
|
||||
if (!parseLine(file, hdl, section, info, type))
|
||||
qWarning("%s: %x: broken line style", qPrintable(file->fileName()),
|
||||
type);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion)
|
||||
{
|
||||
if (!section.arrayItemSize)
|
||||
return section.arraySize ? false : true;
|
||||
|
||||
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
|
||||
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
|
||||
return false;
|
||||
|
||||
ItemInfo info;
|
||||
if (!itemInfo(file, hdl, section, info))
|
||||
return false;
|
||||
|
||||
quint32 type = info.extended
|
||||
? 0x10000 | (info.type << 8) | info.subtype
|
||||
: (info.type << 8) | info.subtype;
|
||||
|
||||
if (!parsePoint(file, hdl, section, info, type))
|
||||
qWarning("%s: %x: broken point style", qPrintable(file->fileName()),
|
||||
type);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -147,18 +147,25 @@ private:
|
||||
bool parseTYPFile(SubFile *file);
|
||||
bool parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion);
|
||||
bool parsePoint(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion, const ItemInfo &info, quint32 type);
|
||||
bool parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion);
|
||||
bool parseLine(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion, const ItemInfo &info, quint32 type);
|
||||
bool parsePolygons(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion);
|
||||
bool parsePolygon(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion, const ItemInfo &info, quint32 type);
|
||||
bool parseDrawOrder(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion);
|
||||
bool itemInfo(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion, ItemInfo &info);
|
||||
void defaultPolygonStyle();
|
||||
void defaultLineStyle();
|
||||
void defaultPointStyle();
|
||||
|
||||
static bool itemInfo(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion, ItemInfo &info);
|
||||
|
||||
QMap<quint32, Line> _lines;
|
||||
QMap<quint32, Polygon> _polygons;
|
||||
QMap<quint32, Point> _points;
|
||||
|
Loading…
Reference in New Issue
Block a user