mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-06-28 12:09:15 +02:00
Added support for label shields
This commit is contained in:
@ -10,6 +10,7 @@
|
||||
#include "common/rectc.h"
|
||||
#include "common/range.h"
|
||||
#include "style.h"
|
||||
#include "label.h"
|
||||
|
||||
class VectorTile;
|
||||
class SubFile;
|
||||
@ -23,7 +24,7 @@ public:
|
||||
ll2xy() the points in the IMG class as this can not be done in
|
||||
parallel. */
|
||||
QVector<QPointF> points;
|
||||
QString label;
|
||||
Label label;
|
||||
quint32 type;
|
||||
|
||||
bool operator<(const Poly &other) const
|
||||
@ -34,7 +35,7 @@ public:
|
||||
Point() : id(0) {}
|
||||
|
||||
Coordinates coordinates;
|
||||
QString label;
|
||||
Label label;
|
||||
quint32 type;
|
||||
bool poi;
|
||||
quint64 id;
|
||||
|
74
src/map/IMG/label.h
Normal file
74
src/map/IMG/label.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef LABEL_H
|
||||
#define LABEL_H
|
||||
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
class Label {
|
||||
public:
|
||||
class Shield
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
None,
|
||||
USInterstate,
|
||||
USShield,
|
||||
USRound,
|
||||
Hbox,
|
||||
Box,
|
||||
Oval
|
||||
};
|
||||
|
||||
Shield() : _type(None) {}
|
||||
Shield(Type type, const QString &name) : _type(type), _text(name) {}
|
||||
|
||||
Type type() const {return _type;}
|
||||
const QString &text() const {return _text;}
|
||||
bool isValid() const {return _type > None && !_text.isEmpty();}
|
||||
|
||||
bool operator==(const Shield &other) const
|
||||
{return _type == other._type && _text == other._text;}
|
||||
|
||||
private:
|
||||
Type _type;
|
||||
QString _text;
|
||||
};
|
||||
|
||||
Label() {}
|
||||
Label(const QString &text, const Shield &shield = Shield())
|
||||
: _text(text), _shield(shield) {}
|
||||
|
||||
const Shield &shield() const {return _shield;}
|
||||
const QString &text() const {return _text;}
|
||||
bool isValid() const {return _shield.isValid() || !_text.isEmpty();}
|
||||
|
||||
void setText(const QString &text) {_text = text;}
|
||||
|
||||
private:
|
||||
QString _text;
|
||||
Shield _shield;
|
||||
};
|
||||
|
||||
inline uint qHash(const Label::Shield &shield)
|
||||
{
|
||||
return qHash(shield.text()) ^ shield.type();
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const Label::Shield &shield)
|
||||
{
|
||||
dbg.nospace() << "Shield(" << shield.type() << ", " << shield.text() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
inline QDebug operator<<(QDebug dbg, const Label &label)
|
||||
{
|
||||
dbg.nospace() << "Label(";
|
||||
if (label.shield().isValid())
|
||||
dbg << label.shield() << ", ";
|
||||
dbg << label.text() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // LABEL_H
|
@ -7,7 +7,7 @@ static quint8 NORMAL_CHARS[] = {
|
||||
' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
||||
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
|
||||
'X', 'Y', 'Z', '~', '~', '~', '~', '~',
|
||||
'X', 'Y', 'Z', '~', '~', '~', ' ', ' ',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', '~', '~', '~', '~', '~', '~'
|
||||
};
|
||||
@ -48,6 +48,7 @@ static QString capitalize(const QString &str)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool LBLFile::init()
|
||||
{
|
||||
Handle hdl;
|
||||
@ -73,45 +74,48 @@ bool LBLFile::init()
|
||||
return true;
|
||||
}
|
||||
|
||||
QString LBLFile::label6b(Handle &hdl, quint32 offset) const
|
||||
Label LBLFile::label6b(Handle &hdl, quint32 offset) const
|
||||
{
|
||||
QByteArray result;
|
||||
Label::Shield::Type shieldType = Label::Shield::None;
|
||||
QByteArray label, shieldLabel;
|
||||
QByteArray *bap = &label;
|
||||
Charset curCharSet = Normal;
|
||||
quint8 b1, b2, b3;
|
||||
|
||||
if (!seek(hdl, offset))
|
||||
return QString();
|
||||
return Label();
|
||||
|
||||
while (true) {
|
||||
if (!(readByte(hdl, b1) && readByte(hdl, b2) && readByte(hdl, b3)))
|
||||
return QString();
|
||||
return Label();
|
||||
|
||||
int c[]= {b1>>2, (b1&0x3)<<4|b2>>4, (b2&0xF)<<2|b3>>6, b3&0x3F};
|
||||
|
||||
for (int cpt = 0; cpt < 4; cpt++) {
|
||||
if (c[cpt] > 0x2F)
|
||||
return QString::fromLatin1(result);
|
||||
if (c[cpt] > 0x2f || (curCharSet == Normal && c[cpt] == 0x1d))
|
||||
return Label(capitalize(QString::fromLatin1(label)),
|
||||
Label::Shield(shieldType, shieldLabel));
|
||||
switch (curCharSet) {
|
||||
case Normal:
|
||||
if (c[cpt] == 0x1c)
|
||||
curCharSet = Symbol;
|
||||
else if (c[cpt] == 0x1b)
|
||||
curCharSet = Special;
|
||||
else if(c[cpt] == 0x1d)
|
||||
result.append('|');
|
||||
else if (c[cpt] == 0x1f)
|
||||
result.append(' ');
|
||||
else if (c[cpt] == 0x1e)
|
||||
result.append(' ');
|
||||
else if (c[cpt] >= 0x2a && c[cpt] <= 0x2f) {
|
||||
shieldType = (Label::Shield::Type)(c[cpt] - 0x29);
|
||||
bap = &shieldLabel;
|
||||
} else if (bap == &shieldLabel
|
||||
&& NORMAL_CHARS[c[cpt]] == ' ')
|
||||
bap = &label;
|
||||
else
|
||||
result.append(NORMAL_CHARS[c[cpt]]);
|
||||
bap->append(NORMAL_CHARS[c[cpt]]);
|
||||
break;
|
||||
case Symbol:
|
||||
result.append(SYMBOL_CHARS[c[cpt]]);
|
||||
bap->append(SYMBOL_CHARS[c[cpt]]);
|
||||
curCharSet = Normal;
|
||||
break;
|
||||
case Special:
|
||||
result.append(SPECIAL_CHARS[c[cpt]]);
|
||||
bap->append(SPECIAL_CHARS[c[cpt]]);
|
||||
curCharSet = Normal;
|
||||
break;
|
||||
}
|
||||
@ -119,30 +123,39 @@ QString LBLFile::label6b(Handle &hdl, quint32 offset) const
|
||||
}
|
||||
}
|
||||
|
||||
QString LBLFile::label8b(Handle &hdl, quint32 offset) const
|
||||
Label LBLFile::label8b(Handle &hdl, quint32 offset) const
|
||||
{
|
||||
QByteArray result;
|
||||
Label::Shield::Type shieldType = Label::Shield::None;
|
||||
QByteArray label, shieldLabel;
|
||||
QByteArray *bap = &label;
|
||||
quint8 c;
|
||||
|
||||
if (!seek(hdl, offset))
|
||||
return QString();
|
||||
return Label();
|
||||
|
||||
while (true) {
|
||||
if (!readByte(hdl, c))
|
||||
return QString();
|
||||
if (!c)
|
||||
return Label();
|
||||
if (!c || c == 0x1d)
|
||||
break;
|
||||
|
||||
if (c >= 0x1B && c <= 0x1F)
|
||||
result.append(' ');
|
||||
else if (c > 0x07)
|
||||
result.append(c);
|
||||
if ((c >= 0x1e && c <= 0x1f))
|
||||
bap->append(' ');
|
||||
else if (c <= 0x07) {
|
||||
shieldType = (Label::Shield::Type)c;
|
||||
bap = &shieldLabel;
|
||||
} else if (bap == &shieldLabel && QChar(c).isSpace()) {
|
||||
bap = &label;
|
||||
} else
|
||||
bap->append(c);
|
||||
}
|
||||
|
||||
return _codec ? _codec->toUnicode(result) : QString::fromLatin1(result);
|
||||
return Label(capitalize(_codec ? _codec->toUnicode(label)
|
||||
: QString::fromLatin1(label)), Label::Shield(shieldType, _codec
|
||||
? _codec->toUnicode(shieldLabel) : QString::fromLatin1(shieldLabel)));
|
||||
}
|
||||
|
||||
QString LBLFile::label(Handle &hdl, quint32 offset, bool poi)
|
||||
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi)
|
||||
{
|
||||
if (!_init) {
|
||||
if (!(_init = init()))
|
||||
@ -163,11 +176,11 @@ QString LBLFile::label(Handle &hdl, quint32 offset, bool poi)
|
||||
|
||||
switch (_encoding) {
|
||||
case 6:
|
||||
return capitalize(label6b(hdl, labelOffset));
|
||||
return label6b(hdl, labelOffset);
|
||||
case 9:
|
||||
case 10:
|
||||
return capitalize(label8b(hdl, labelOffset));
|
||||
return label8b(hdl, labelOffset);
|
||||
default:
|
||||
return QString();
|
||||
return Label();
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define LBLFILE_H
|
||||
|
||||
#include "subfile.h"
|
||||
#include "label.h"
|
||||
|
||||
class QTextCodec;
|
||||
|
||||
@ -10,13 +11,13 @@ class LBLFile : public SubFile
|
||||
public:
|
||||
LBLFile(IMG *img, quint32 size) : SubFile(img, size), _init(false) {}
|
||||
|
||||
QString label(Handle &hdl, quint32 offset, bool poi = false);
|
||||
Label label(Handle &hdl, quint32 offset, bool poi = false);
|
||||
|
||||
private:
|
||||
bool init();
|
||||
|
||||
QString label6b(Handle &hdl, quint32 offset) const;
|
||||
QString label8b(Handle &hdl, quint32 offset) const;
|
||||
Label label6b(Handle &hdl, quint32 offset) const;
|
||||
Label label8b(Handle &hdl, quint32 offset) const;
|
||||
|
||||
quint32 _offset;
|
||||
quint32 _size;
|
||||
|
@ -977,7 +977,12 @@ bool Style::isSpot(quint32 type)
|
||||
|
||||
bool Style::isSummit(quint32 type)
|
||||
{
|
||||
return (type == 0x6616);
|
||||
return (type == 0x6616);
|
||||
}
|
||||
|
||||
bool Style::isMajorRoad(quint32 type)
|
||||
{
|
||||
return (type <= TYPE(0x04));
|
||||
}
|
||||
|
||||
Style::POIClass Style::poiClass(quint32 type)
|
||||
|
@ -106,6 +106,7 @@ public:
|
||||
static bool isContourLine(quint32 type);
|
||||
static bool isSpot(quint32 type);
|
||||
static bool isSummit(quint32 type);
|
||||
static bool isMajorRoad(quint32 type);
|
||||
static POIClass poiClass(quint32 type);
|
||||
|
||||
private:
|
||||
|
@ -7,29 +7,48 @@
|
||||
|
||||
#define FLAGS (Qt::AlignCenter | Qt::TextWordWrap | Qt::TextDontClip)
|
||||
#define MAX_TEXT_WIDTH 8
|
||||
#define MIN_BOX_WIDTH 2
|
||||
|
||||
|
||||
static void expand(QRect &rect, int width)
|
||||
{
|
||||
rect.adjust(-(width/2 - rect.width()/2), 0, width/2 - rect.width()/2, 0);
|
||||
}
|
||||
|
||||
TextPointItem::TextPointItem(const QPoint &point, const QString *text,
|
||||
const QFont *font, const QImage *img, const QColor *color)
|
||||
: _text(text), _font(font), _img(img), _color(color)
|
||||
const QFont *font, const QImage *img, const QColor *color,
|
||||
const QColor *bgColor) : _text(text), _font(font), _img(img), _color(color),
|
||||
_bgColor(bgColor)
|
||||
{
|
||||
QRect iconRect;
|
||||
|
||||
if (text) {
|
||||
QFontMetrics fm(*font);
|
||||
int limit = font->pixelSize() * MAX_TEXT_WIDTH;
|
||||
_textRect = fm.boundingRect(QRect(0, 0, limit, 0), FLAGS, *text);
|
||||
_textRect.adjust(0, 0, 1, 1);
|
||||
}
|
||||
if (img) {
|
||||
iconRect = QRect(QPoint(point.x() - img->width()/2, point.y()
|
||||
- img->height()/2), img->size());
|
||||
_textRect.moveTopLeft(QPoint(point.x() + img->width(), point.y()
|
||||
|
||||
if (_bgColor && _textRect.width() < font->pixelSize() * MIN_BOX_WIDTH)
|
||||
expand(_textRect, font->pixelSize() * MIN_BOX_WIDTH);
|
||||
|
||||
setPos(point);
|
||||
}
|
||||
|
||||
void TextPointItem::setPos(const QPoint &point)
|
||||
{
|
||||
QPainterPath shape;
|
||||
QRect iconRect;
|
||||
|
||||
if (_img) {
|
||||
iconRect = QRect(QPoint(point.x() - _img->width()/2, point.y()
|
||||
- _img->height()/2), _img->size());
|
||||
_textRect.moveTopLeft(QPoint(point.x() + _img->width(), point.y()
|
||||
- _textRect.height()/2));
|
||||
} else
|
||||
_textRect.moveCenter(point);
|
||||
|
||||
_rect = _textRect | iconRect;
|
||||
_shape.addRect(_rect);
|
||||
shape.addRect(_rect);
|
||||
_shape = shape;
|
||||
}
|
||||
|
||||
void TextPointItem::paint(QPainter *painter) const
|
||||
@ -54,6 +73,13 @@ void TextPointItem::paint(QPainter *painter) const
|
||||
painter->drawImage(_textRect.x() - 1, _textRect.y(), img);
|
||||
painter->drawImage(_textRect.x() + 1, _textRect.y(), img);
|
||||
|
||||
|
||||
if (_bgColor) {
|
||||
painter->setPen(*_color);
|
||||
painter->setBrush(*_bgColor);
|
||||
painter->drawRect(_textRect);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
}
|
||||
if (_color) {
|
||||
painter->setFont(*_font);
|
||||
painter->setPen(*_color);
|
||||
|
@ -16,7 +16,7 @@ class TextPointItem : public TextItem
|
||||
public:
|
||||
TextPointItem() : _text(0), _font(0), _img(0) {}
|
||||
TextPointItem(const QPoint &point, const QString *text, const QFont *font,
|
||||
const QImage *img, const QColor *color);
|
||||
const QImage *img, const QColor *color, const QColor *bgColor = 0);
|
||||
|
||||
bool isValid() const {return !_rect.isEmpty();}
|
||||
|
||||
@ -24,11 +24,13 @@ public:
|
||||
QPainterPath shape() const {return _shape;}
|
||||
void paint(QPainter *painter) const;
|
||||
|
||||
void setPos(const QPoint &point);
|
||||
|
||||
private:
|
||||
const QString *_text;
|
||||
const QFont *_font;
|
||||
const QImage *_img;
|
||||
const QColor *_color;
|
||||
const QColor *_color, *_bgColor;
|
||||
QRect _rect, _textRect;
|
||||
QPainterPath _shape;
|
||||
};
|
||||
|
Reference in New Issue
Block a user