1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-30 22:51:16 +01:00

Compare commits

..

3 Commits

Author SHA1 Message Date
829d85a70a Optimize TextCodec initialization
QTextCodec initialization is very slow due to it's broken caching in Qt when
ICU is enabled. Make TetCodec initialize fast anyway as it may be used very
often in IMG maps (every LBL subfile has it's own codec!).
2023-12-21 01:31:44 +01:00
e05c2e0383 Version++ 2023-12-21 01:15:12 +01:00
bff27df10c Fixed race conditions on local static data 2023-12-21 01:13:36 +01:00
20 changed files with 196 additions and 188 deletions

View File

@ -1,4 +1,4 @@
version: 13.13.{build}
version: 13.14.{build}
configuration:
- Release

View File

@ -3,7 +3,7 @@ unix:!macx:!android {
} else {
TARGET = GPXSee
}
VERSION = 13.13
VERSION = 13.14
QT += core \
@ -134,6 +134,7 @@ HEADERS += src/common/config.h \
src/map/encjob.h \
src/map/encmap.h \
src/map/ENC/iso8211.h \
src/map/encstyle.h \
src/map/gemfmap.h \
src/map/gmifile.h \
src/map/oruxmap.h \
@ -349,6 +350,7 @@ SOURCES += src/main.cpp \
src/map/encatlas.cpp \
src/map/encmap.cpp \
src/map/ENC/iso8211.cpp \
src/map/encstyle.cpp \
src/map/gemfmap.cpp \
src/map/gmifile.cpp \
src/map/oruxmap.cpp \

View File

@ -37,7 +37,7 @@ Unicode true
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "13.13"
!define VERSION "13.14"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"

View File

@ -1,56 +1,48 @@
#include <QTextCodec>
#include "textcodec.h"
TextCodec::TextCodec()
/* When Qt is compiled with ICU support, QTextCodec::codecForName() is very
slow due to broken codec name caching (the function does dozens of
comparisons and only then asks the cache...), so we use our own map. */
static QMap<int, QTextCodec *> initCodecs()
{
_codec = QTextCodec::codecForName("Windows-1252");
QMap<int, QTextCodec *> map;
map.insert(65001, 0);
map.insert(874, QTextCodec::codecForName("Windows-874"));
map.insert(932, QTextCodec::codecForName("Shift-JIS"));
map.insert(936, QTextCodec::codecForName("GB18030"));
map.insert(949, QTextCodec::codecForName("EUC-KR"));
map.insert(950, QTextCodec::codecForName("Big5"));
map.insert(1250, QTextCodec::codecForName("Windows-1250"));
map.insert(1251, QTextCodec::codecForName("Windows-1251"));
map.insert(1252, QTextCodec::codecForName("Windows-1252"));
map.insert(1253, QTextCodec::codecForName("Windows-1253"));
map.insert(1254, QTextCodec::codecForName("Windows-1254"));
map.insert(1255, QTextCodec::codecForName("Windows-1255"));
map.insert(1256, QTextCodec::codecForName("Windows-1256"));
map.insert(1257, QTextCodec::codecForName("Windows-1257"));
map.insert(1258, QTextCodec::codecForName("Windows-1258"));
return map;
}
const QMap<int, QTextCodec *> &TextCodec::codecs()
{
static QMap<int, QTextCodec *> map = initCodecs();
return map;
}
TextCodec::TextCodec(int codepage)
{
switch (codepage) {
case 65001:
_codec = 0;
break;
case 932:
_codec = QTextCodec::codecForName("Shift-JIS");
break;
case 936:
_codec = QTextCodec::codecForName("GB18030");
break;
case 949:
_codec = QTextCodec::codecForName("EUC-KR");
break;
case 950:
_codec = QTextCodec::codecForName("Big5");
break;
case 1250:
_codec = QTextCodec::codecForName("Windows-1250");
break;
case 1251:
_codec = QTextCodec::codecForName("Windows-1251");
break;
case 1253:
_codec = QTextCodec::codecForName("Windows-1253");
break;
case 1254:
_codec = QTextCodec::codecForName("Windows-1254");
break;
case 1255:
_codec = QTextCodec::codecForName("Windows-1255");
break;
case 1256:
_codec = QTextCodec::codecForName("Windows-1256");
break;
case 1257:
_codec = QTextCodec::codecForName("Windows-1257");
break;
case 1258:
_codec = QTextCodec::codecForName("Windows-1258");
break;
default:
_codec = QTextCodec::codecForName("Windows-1252");
}
const QMap<int, QTextCodec *> &map = codecs();
QMap<int, QTextCodec *>::const_iterator it(map.find(codepage));
if (it == map.cend()) {
qWarning("%d: Unsupported codepage, using UTF-8", codepage);
_codec = 0;
} else
_codec = *it;
}
QString TextCodec::toString(const QByteArray &ba) const

View File

@ -2,19 +2,22 @@
#define TEXTCODEC_H
#include <QString>
#include <QMap>
class QTextCodec;
class TextCodec
{
public:
TextCodec();
TextCodec() : _codec(0) {}
TextCodec(int codepage);
QString toString(const QByteArray &ba) const;
private:
QTextCodec *_codec;
static const QMap<int, QTextCodec *> &codecs();
};
#endif // TEXTCODEC_H

View File

@ -128,7 +128,7 @@ qint64 CryptDevice::readData(char *data, qint64 maxSize)
class DataStream : public QDataStream
{
public:
DataStream(QIODevice *d) : QDataStream(d) {}
DataStream(QIODevice *d) : QDataStream(d), _codec(1252) {}
void setCodepage(quint16 codepage) {_codec = TextCodec(codepage);}

View File

@ -75,7 +75,7 @@ bool TwoNavParser::parse(QFile *file, QList<TrackData> &tracks,
QVector<Waypoint> &waypoints)
{
Q_UNUSED(polygons);
TextCodec codec;
TextCodec codec(1252);
GCS gcs;
bool ok, route = false, track = false, waypoint = false;

View File

@ -17,51 +17,6 @@ typedef QSet<Coordinates> PointSet;
static const float C1 = 0.866025f; /* sqrt(3)/2 */
static const QColor haloColor(Qt::white);
static QFont pixelSizeFont(int pixelSize)
{
QFont f;
f.setPixelSize(pixelSize);
return f;
}
static QFont *font(Style::FontSize size)
{
/* The fonts must be initialized on first usage (after the QGuiApplication
instance is created) */
static QFont large = pixelSizeFont(16);
static QFont normal = pixelSizeFont(12);
static QFont small = pixelSizeFont(10);
switch (size) {
case Style::None:
return 0;
case Style::Large:
return &large;
case Style::Small:
return &small;
default:
return &normal;
}
}
static const QImage *light()
{
static QImage img(":/marine/light.png");
return &img;
}
static const QImage *signal()
{
static QImage img(":/marine/fog-signal.png");
return &img;
}
static const Style& style()
{
static Style s;
return s;
}
static double area(const QVector<Coordinates> &polygon)
{
double area = 0;
@ -223,14 +178,12 @@ void RasterTile::drawArrows(QPainter *painter,
void RasterTile::drawPolygons(QPainter *painter,
const QList<MapData::Poly> &polygons)
{
const Style &s = style();
for (int n = 0; n < s.drawOrder().size(); n++) {
for (int n = 0; n < _style->drawOrder().size(); n++) {
for (int i = 0; i < polygons.size(); i++) {
const MapData::Poly &poly = polygons.at(i);
if (poly.type() != s.drawOrder().at(n))
if (poly.type() != _style->drawOrder().at(n))
continue;
const Style::Polygon &style = s.polygon(poly.type());
const Style::Polygon &style = _style->polygon(poly.type());
if (!style.img().isNull()) {
for (int i = 0; i < poly.path().size(); i++)
@ -257,13 +210,11 @@ void RasterTile::drawPolygons(QPainter *painter,
void RasterTile::drawLines(QPainter *painter, const QList<MapData::Line> &lines)
{
const Style &s = style();
painter->setBrush(Qt::NoBrush);
for (int i = 0; i < lines.size(); i++) {
const MapData::Line &line = lines.at(i);
const Style::Line &style = s.line(line.type());
const Style::Line &style = _style->line(line.type());
if (!style.img().isNull()) {
BitmapLine::draw(painter, polyline(line.path()), style.img());
@ -284,8 +235,6 @@ void RasterTile::drawTextItems(QPainter *painter,
void RasterTile::processPolygons(const QList<MapData::Poly> &polygons,
QList<TextItem*> &textItems)
{
const Style &s = style();
for (int i = 0; i < polygons.size(); i++) {
const MapData::Poly &poly = polygons.at(i);
uint type = poly.type()>>16;
@ -293,7 +242,7 @@ void RasterTile::processPolygons(const QList<MapData::Poly> &polygons,
if (!(type == HRBFAC || type == I_TRNBSN
|| poly.type() == SUBTYPE(I_BERTHS, 6)))
continue;
const Style::Point &style = s.point(poly.type());
const Style::Point &style = _style->point(poly.type());
const QImage *img = style.img().isNull() ? 0 : &style.img();
if (!img)
continue;
@ -311,7 +260,6 @@ void RasterTile::processPolygons(const QList<MapData::Poly> &polygons,
void RasterTile::processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems, QList<TextItem*> &lights)
{
const Style &s = style();
PointSet lightsSet, signalsSet;
int i;
@ -332,12 +280,12 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
for ( ; i < points.size(); i++) {
const MapData::Point &point = points.at(i);
QPoint pos(ll2xy(point.pos()).toPoint());
const Style::Point &style = s.point(point.type());
const Style::Point &style = _style->point(point.type());
const QString *label = point.label().isEmpty() ? 0 : &(point.label());
const QImage *img = style.img().isNull() ? 0 : &style.img();
const QFont *fnt = showLabel(img, _zoomRange, _zoom, point.type())
? font(style.textFontSize()) : 0;
? _style->font(style.textFontSize()) : 0;
const QColor *color = &style.textColor();
const QColor *hColor = style.haloColor().isValid()
? &style.haloColor() : 0;
@ -351,9 +299,11 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
if (item->isValid() && !item->collides(textItems)) {
textItems.append(item);
if (lightsSet.contains(point.pos()))
lights.append(new TextPointItem(pos, 0, 0, light(), 0, 0, 0, 0));
lights.append(new TextPointItem(pos, 0, 0, _style->light(), 0,
0, 0, 0));
if (signalsSet.contains(point.pos()))
lights.append(new TextPointItem(pos, 0, 0, signal(), 0, 0, 0, 0));
lights.append(new TextPointItem(pos, 0, 0, _style->signal(), 0,
0, 0, 0));
} else
delete item;
}
@ -362,18 +312,16 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
void RasterTile::processLines(const QList<MapData::Line> &lines,
QList<TextItem*> &textItems)
{
const Style &s = style();
for (int i = 0; i < lines.size(); i++) {
const MapData::Line &line = lines.at(i);
const Style::Line &style = s.line(line.type());
const Style::Line &style = _style->line(line.type());
if (style.img().isNull() && style.pen() == Qt::NoPen)
continue;
if (line.label().isEmpty() || style.textFontSize() == Style::None)
continue;
const QFont *fnt = font(style.textFontSize());
const QFont *fnt = _style->font(style.textFontSize());
const QColor *color = &style.textColor();
TextPathItem *item = new TextPathItem(polyline(line.path()),

View File

@ -7,6 +7,7 @@
#include "map/transform.h"
#include "map/textpointitem.h"
#include "mapdata.h"
#include "style.h"
#include "atlasdata.h"
class TextItem;
@ -17,15 +18,17 @@ class RasterTile
{
public:
RasterTile(const Projection &proj, const Transform &transform,
const MapData *data, int zoom, const Range &zoomRange, const QRect &rect,
qreal ratio) : _proj(proj), _transform(transform), _map(data), _atlas(0),
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio),
_pixmap(rect.width() * ratio, rect.height() * ratio), _valid(false) {}
const Style *style, const MapData *data, int zoom, const Range &zoomRange,
const QRect &rect, qreal ratio) : _proj(proj), _transform(transform),
_style(style), _map(data), _atlas(0), _zoom(zoom), _zoomRange(zoomRange),
_rect(rect), _ratio(ratio), _pixmap(rect.width() * ratio, rect.height()
* ratio), _valid(false) {}
RasterTile(const Projection &proj, const Transform &transform,
AtlasData *data, int zoom, const Range &zoomRange, const QRect &rect,
qreal ratio) : _proj(proj), _transform(transform), _map(0), _atlas(data),
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio),
_pixmap(rect.width() * ratio, rect.height() * ratio), _valid(false) {}
const Style *style, AtlasData *data, int zoom, const Range &zoomRange,
const QRect &rect, qreal ratio) : _proj(proj), _transform(transform),
_style(style), _map(0), _atlas(data), _zoom(zoom), _zoomRange(zoomRange),
_rect(rect), _ratio(ratio), _pixmap(rect.width() * ratio, rect.height()
* ratio), _valid(false) {}
int zoom() const {return _zoom;}
QPoint xy() const {return _rect.topLeft();}
@ -61,6 +64,7 @@ private:
Projection _proj;
Transform _transform;
const Style *_style;
const MapData *_map;
AtlasData *_atlas;
int _zoom;

View File

@ -14,6 +14,13 @@ static QImage railroad()
return img;
}
static QFont pixelSizeFont(int pixelSize)
{
QFont f;
f.setPixelSize(pixelSize);
return f;
}
void Style::polygonStyle()
{
_polygons[TYPE(M_COVR)] = Polygon(QBrush("#ffffff"));
@ -321,6 +328,13 @@ void Style::pointStyle()
Style::Style()
{
_light = QImage(":/marine/light.png");
_signal = QImage(":/marine/fog-signal.png");
_large = pixelSizeFont(16);
_normal = pixelSizeFont(12);
_small = pixelSizeFont(10);
polygonStyle();
lineStyle();
pointStyle();
@ -349,3 +363,17 @@ const Style::Point &Style::point(uint type) const
QMap<uint, Point>::const_iterator it = _points.find(type);
return (it == _points.constEnd()) ? null : *it;
}
const QFont *Style::font(Style::FontSize size) const
{
switch (size) {
case Style::None:
return 0;
case Style::Large:
return &_large;
case Style::Small:
return &_small;
default:
return &_normal;
}
}

View File

@ -3,6 +3,7 @@
#include <QPen>
#include <QBrush>
#include <QFont>
#include <QMap>
#include "objects.h"
@ -96,6 +97,10 @@ public:
const Point &point(uint type) const;
const QVector<uint> &drawOrder() const {return _drawOrder;}
const QFont *font(Style::FontSize size) const;
const QImage *light() const {return &_light;}
const QImage *signal() const {return &_signal;}
private:
void polygonStyle();
void lineStyle();
@ -105,6 +110,9 @@ private:
QMap<uint, Polygon> _polygons;
QMap<uint, Point> _points;
QVector<uint> _drawOrder;
QFont _small, _normal, _large;
QImage _light, _signal;
};
}

View File

@ -16,14 +16,14 @@ class LBLFile : public SubFile
{
public:
LBLFile(const IMGData *img)
: SubFile(img), _huffmanText(0), _table(0), _rasters(0), _imgIdSize(0),
_poiShift(0), _shift(0), _encoding(0) {}
: SubFile(img), _huffmanText(0), _table(0), _rasters(0), _codec(1252),
_imgIdSize(0), _poiShift(0), _shift(0), _encoding(0) {}
LBLFile(const QString *path)
: SubFile(path), _huffmanText(0), _table(0), _rasters(0), _imgIdSize(0),
_poiShift(0), _shift(0), _encoding(0) {}
: SubFile(path), _huffmanText(0), _table(0), _rasters(0), _codec(1252),
_imgIdSize(0), _poiShift(0), _shift(0), _encoding(0) {}
LBLFile(const SubFile *gmp, quint32 offset)
: SubFile(gmp, offset), _huffmanText(0), _table(0), _rasters(0),
_imgIdSize(0), _poiShift(0), _shift(0), _encoding(0) {}
_codec(1252), _imgIdSize(0), _poiShift(0), _shift(0), _encoding(0) {}
~LBLFile();
bool load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl);

View File

@ -28,57 +28,6 @@ static const QColor shieldBgColor1("#dd3e3e");
static const QColor shieldBgColor2("#379947");
static const QColor shieldBgColor3("#4a7fc1");
static QFont pixelSizeFont(int pixelSize)
{
QFont f;
f.setPixelSize(pixelSize);
return f;
}
static QFont *font(Style::FontSize size, Style::FontSize defaultSize
= Style::Normal)
{
/* The fonts must be initialized on first usage (after the QGuiApplication
instance is created) */
static QFont large = pixelSizeFont(16);
static QFont normal = pixelSizeFont(14);
static QFont small = pixelSizeFont(12);
static QFont extraSmall = pixelSizeFont(10);
switch (size) {
case Style::None:
return 0;
case Style::Large:
return &large;
case Style::Normal:
return &normal;
case Style::Small:
return &small;
case Style::ExtraSmall:
return &extraSmall;
default:
return font(defaultSize);
}
}
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;
default:
return &poi;
}
}
static const QColor *shieldBgColor(Shield::Type type)
{
switch (type) {
@ -152,6 +101,21 @@ static bool rectNearPolygon(const QPolygonF &polygon, const QRectF &rect)
|| polygon.containsPoint(rect.bottomRight(), Qt::OddEvenFill)));
}
const QFont *RasterTile::poiFont(Style::FontSize size, int zoom, bool extended)
{
if (zoom > 25)
size = Style::Normal;
else if (extended)
size = Style::None;
switch (size) {
case Style::None:
return 0;
default:
return _data->style()->font(Style::ExtraSmall);
}
}
void RasterTile::ll2xy(QList<MapData::Poly> &polys)
{
for (int i = 0; i < polys.size(); i++) {
@ -324,7 +288,8 @@ void RasterTile::processStreetNames(const QList<MapData::Poly> &lines,
if (style.img().isNull() && style.foreground() == Qt::NoPen)
continue;
const QFont *fnt = font(style.textFontSize(), Style::Small);
const QFont *fnt = _data->style()->font(style.textFontSize(),
Style::Small);
const QColor *color = style.textColor().isValid()
? &style.textColor() : 0;
const QColor *hColor = Style::isContourLine(poly.type) ? 0 : &haloColor;
@ -435,7 +400,7 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
const QImage *img = style.img().isNull() ? 0 : &style.img();
const QFont *fnt = poi
? poiFont(style.textFontSize(), _zoom, point.classLabel)
: font(style.textFontSize());
: _data->style()->font(style.textFontSize());
const QColor *color = style.textColor().isValid()
? &style.textColor() : &textColor;
const QColor *hcolor = Style::isDepthPoint(point.type)

View File

@ -5,6 +5,7 @@
#include "mapdata.h"
#include "map/projection.h"
#include "map/transform.h"
#include "style.h"
class QPainter;
class IMGMap;
@ -12,8 +13,6 @@ class TextItem;
namespace IMG {
class Style;
class RasterTile
{
public:
@ -53,6 +52,9 @@ private:
void processStreetNames(const QList<MapData::Poly> &lines,
QList<TextItem*> &textItems, const QImage (&arrows)[2]);
const QFont *poiFont(Style::FontSize size = Style::Normal,
int zoom = -1, bool extended = false);
Projection _proj;
Transform _transform;
MapData *_data;

View File

@ -4,6 +4,13 @@
using namespace IMG;
static QFont pixelSizeFont(int pixelSize)
{
QFont f;
f.setPixelSize(pixelSize);
return f;
}
static bool readColor(SubFile *file, SubFile::Handle &hdl, QColor &color)
{
quint8 b, g, r;
@ -1226,6 +1233,11 @@ bool Style::parseTYPFile(SubFile *file)
Style::Style(SubFile *typ)
{
_large = pixelSizeFont(16);
_normal = pixelSizeFont(14);
_small = pixelSizeFont(12);
_extraSmall = pixelSizeFont(10);
defaultLineStyle();
defaultPolygonStyle();
defaultPointStyle();
@ -1258,6 +1270,24 @@ const Style::Point &Style::point(quint32 type) const
return (it == _points.constEnd()) ? null : *it;
}
const QFont *Style::font(Style::FontSize size, Style::FontSize defaultSize) const
{
switch (size) {
case Style::None:
return 0;
case Style::Large:
return &_large;
case Style::Normal:
return &_normal;
case Style::Small:
return &_small;
case Style::ExtraSmall:
return &_extraSmall;
default:
return font(defaultSize);
}
}
#ifndef QT_NO_DEBUG
static QString penColor(const QPen &pen)
{

View File

@ -3,6 +3,7 @@
#include <QPen>
#include <QBrush>
#include <QFont>
#include <QDebug>
#include "subfile.h"
@ -94,6 +95,8 @@ public:
const Polygon &polygon(quint32 type) const;
const Point &point(quint32 type) const;
const QList<quint32> &drawOrder() const {return _drawOrder;}
const QFont *font(Style::FontSize size, Style::FontSize defaultSize
= Style::Normal) const;
static bool isPOI(quint32 type)
{return !((type >= TYPE(0x01) && type <= TYPE(0x1f))
@ -172,6 +175,8 @@ private:
QMap<quint32, Polygon> _polygons;
QMap<quint32, Point> _points;
QList<quint32> _drawOrder;
QFont _large, _normal, _small, _extraSmall;
};
}

View File

@ -5,6 +5,7 @@
#include "rectd.h"
#include "pcs.h"
#include "encjob.h"
#include "encstyle.h"
#include "encatlas.h"
using namespace ENC;
@ -357,7 +358,7 @@ void ENCAtlas::draw(QPainter *painter, const QRectF &rect, Flags flags)
painter->drawPixmap(ttl, pm);
else
tiles.append(RasterTile(_projection, _transform,
_data.value(_usage), _zoom, zooms(_usage),
ENCStyle::style(), _data.value(_usage), _zoom, zooms(_usage),
QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio));
}
}

View File

@ -5,6 +5,7 @@
#include "rectd.h"
#include "pcs.h"
#include "encjob.h"
#include "encstyle.h"
#include "encmap.h"
@ -323,9 +324,9 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
if (QPixmapCache::find(key(_zoom, ttl), &pm))
painter->drawPixmap(ttl, pm);
else
tiles.append(RasterTile(_projection, _transform, _data,
_zoom, _zooms, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)),
_tileRatio));
tiles.append(RasterTile(_projection, _transform,
ENCStyle::style(), _data, _zoom, _zooms,
QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio));
}
}

7
src/map/encstyle.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "encstyle.h"
const ENC::Style *ENCStyle::style()
{
static ENC::Style s;
return &s;
}

12
src/map/encstyle.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef ENCSTYLE_H
#define ENCSTYLE_H
#include "ENC/style.h"
class ENCStyle
{
public:
static const ENC::Style *style();
};
#endif // ENCSTYLE_H