Compare commits
64 Commits
Author | SHA1 | Date | |
---|---|---|---|
681c83d017 | |||
dbd8750524 | |||
d9489935df | |||
f5d2ccfdb9 | |||
1afd59902b | |||
a253147760 | |||
667a1c350d | |||
d7a9464e37 | |||
d1be147f64 | |||
98708f11ac | |||
c5605eeab1 | |||
f29ac69594 | |||
49101cba6c | |||
c1f746b32a | |||
704be7baf9 | |||
3c6ec704ab | |||
bf6b6fb100 | |||
56a2618f29 | |||
785bf94a01 | |||
3747ae6afc | |||
1f5a051bee | |||
268c42ab03 | |||
8a8595d98e | |||
37c971a720 | |||
f0d71d667b | |||
f652457f19 | |||
1acf603076 | |||
86f5da9355 | |||
3587d29cb6 | |||
beb93bcd1f | |||
dd911a95b0 | |||
1fc644e1d6 | |||
dc628c9554 | |||
ec3eccd580 | |||
a3d22dcd2a | |||
c13d7ae51d | |||
e4085cc25a | |||
8a13355740 | |||
8f799e1bcf | |||
5cd0a3a8b0 | |||
283197612b | |||
2d0ac129ce | |||
499869119a | |||
fdcc431a4e | |||
38a4a4c32b | |||
6efd8e7fd1 | |||
5b3c448582 | |||
054ae32689 | |||
0594774570 | |||
e11d6d280d | |||
897de9920e | |||
82923a4529 | |||
4daa9fd55c | |||
3270625172 | |||
d70c4fefd5 | |||
c364121288 | |||
62eb5a09ae | |||
d0438b3ee8 | |||
5b83f1b86b | |||
241ecb36f2 | |||
f5b9f6e392 | |||
d04775d58e | |||
68644aa25d | |||
acbf72a983 |
@ -1,4 +1,4 @@
|
||||
version: 7.5.{build}
|
||||
version: 7.7.{build}
|
||||
configuration: Release
|
||||
platform: Any CPU
|
||||
environment:
|
||||
|
@ -2,9 +2,9 @@
|
||||
GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common GPS log file formats.
|
||||
|
||||
## Features
|
||||
* Opens GPX, TCX, FIT, KML, IGC, NMEA, SLF, LOC, GeoJSON, OziExplorer (PLT, RTE, WPT) and Garmin CSV files.
|
||||
* Opens GPX, TCX, FIT, KML, IGC, NMEA, SLF, LOC, GeoJSON, OziExplorer (PLT, RTE, WPT), Garmin CSV and geotagged JPEG files.
|
||||
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS).
|
||||
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin JNX maps, TwoNav RMaps, GeoTIFF images).
|
||||
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin IMG & JNX maps, TwoNav RMaps, GeoTIFF images).
|
||||
* Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts graphs.
|
||||
* Support for DEM files (SRTM HGT).
|
||||
* Support for multiple tracks in one view.
|
||||
|
34
gpxsee.pro
@ -3,7 +3,7 @@ unix:!macx {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 7.5
|
||||
VERSION = 7.7
|
||||
|
||||
QT += core \
|
||||
gui \
|
||||
@ -84,6 +84,9 @@ HEADERS += src/common/config.h \
|
||||
src/GUI/mapview.h \
|
||||
src/GUI/font.h \
|
||||
src/GUI/areaitem.h \
|
||||
src/map/IMG/bitmapline.h \
|
||||
src/map/IMG/textpathitem.h \
|
||||
src/map/IMG/textpointitem.h \
|
||||
src/map/projection.h \
|
||||
src/map/ellipsoid.h \
|
||||
src/map/datum.h \
|
||||
@ -163,7 +166,19 @@ HEADERS += src/common/config.h \
|
||||
src/map/calibrationpoint.h \
|
||||
src/map/color.h \
|
||||
src/data/exifparser.h \
|
||||
src/data/imageinfo.h
|
||||
src/data/imageinfo.h \
|
||||
src/map/imgmap.h \
|
||||
src/map/IMG/img.h \
|
||||
src/map/IMG/subfile.h \
|
||||
src/map/IMG/trefile.h \
|
||||
src/map/IMG/rgnfile.h \
|
||||
src/map/IMG/lblfile.h \
|
||||
src/map/IMG/vectortile.h \
|
||||
src/map/IMG/subdiv.h \
|
||||
src/map/IMG/units.h \
|
||||
src/map/IMG/style.h \
|
||||
src/map/IMG/netfile.h \
|
||||
src/GUI/limitedcombobox.h
|
||||
SOURCES += src/main.cpp \
|
||||
src/common/coordinates.cpp \
|
||||
src/common/rectc.cpp \
|
||||
@ -215,6 +230,9 @@ SOURCES += src/main.cpp \
|
||||
src/GUI/gearratiographitem.cpp \
|
||||
src/GUI/mapview.cpp \
|
||||
src/GUI/areaitem.cpp \
|
||||
src/map/IMG/bitmapline.cpp \
|
||||
src/map/IMG/textpathitem.cpp \
|
||||
src/map/IMG/textpointitem.cpp \
|
||||
src/map/maplist.cpp \
|
||||
src/map/onlinemap.cpp \
|
||||
src/map/downloader.cpp \
|
||||
@ -280,7 +298,16 @@ SOURCES += src/main.cpp \
|
||||
src/map/obliquestereographic.cpp \
|
||||
src/GUI/coordinatesitem.cpp \
|
||||
src/map/rmap.cpp \
|
||||
src/data/exifparser.cpp
|
||||
src/data/exifparser.cpp \
|
||||
src/map/imgmap.cpp \
|
||||
src/map/IMG/img.cpp \
|
||||
src/map/IMG/subfile.cpp \
|
||||
src/map/IMG/trefile.cpp \
|
||||
src/map/IMG/rgnfile.cpp \
|
||||
src/map/IMG/lblfile.cpp \
|
||||
src/map/IMG/vectortile.cpp \
|
||||
src/map/IMG/style.cpp \
|
||||
src/map/IMG/netfile.cpp
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4) {
|
||||
HEADERS += src/data/geojsonparser.h
|
||||
@ -362,6 +389,7 @@ win32 {
|
||||
|
||||
unix:!macx {
|
||||
isEmpty(PREFIX):PREFIX = /usr/local
|
||||
DEFINES += PREFIX=\\\"$$PREFIX\\\"
|
||||
|
||||
maps.files = pkg/maps/*
|
||||
maps.path = $$PREFIX/share/gpxsee/maps
|
||||
|
84
gpxsee.qrc
@ -1,46 +1,46 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>icons/dialog-close.png</file>
|
||||
<file>icons/dialog-close@2x.png</file>
|
||||
<file>icons/document-open.png</file>
|
||||
<file>icons/document-open@2x.png</file>
|
||||
<file>icons/document-print.png</file>
|
||||
<file>icons/document-print@2x.png</file>
|
||||
<file>icons/document-export.png</file>
|
||||
<file>icons/document-export@2x.png</file>
|
||||
<file>icons/flag.png</file>
|
||||
<file>icons/flag@2x.png</file>
|
||||
<file>icons/gpxsee.png</file>
|
||||
<file>icons/gpxsee@2x.png</file>
|
||||
<file>icons/application-exit.png</file>
|
||||
<file>icons/application-exit@2x.png</file>
|
||||
<file>icons/applications-internet.png</file>
|
||||
<file>icons/applications-internet@2x.png</file>
|
||||
<file>icons/view-refresh.png</file>
|
||||
<file>icons/view-refresh@2x.png</file>
|
||||
<file>icons/arrow-left.png</file>
|
||||
<file>icons/arrow-left@2x.png</file>
|
||||
<file>icons/arrow-right.png</file>
|
||||
<file>icons/arrow-right@2x.png</file>
|
||||
<file>icons/arrow-left-double.png</file>
|
||||
<file>icons/arrow-left-double@2x.png</file>
|
||||
<file>icons/arrow-right-double.png</file>
|
||||
<file>icons/arrow-right-double@2x.png</file>
|
||||
<file>icons/view-fullscreen.png</file>
|
||||
<file>icons/view-fullscreen@2x.png</file>
|
||||
<file>icons/office-chart-line.png</file>
|
||||
<file>icons/office-chart-line@2x.png</file>
|
||||
<file>icons/format-stroke-color.png</file>
|
||||
<file>icons/format-stroke-color@2x.png</file>
|
||||
<file>icons/flag_32.png</file>
|
||||
<file>icons/flag_32@2x.png</file>
|
||||
<file>icons/preferences-system.png</file>
|
||||
<file>icons/preferences-system@2x.png</file>
|
||||
<file>icons/document-print_32.png</file>
|
||||
<file>icons/document-print_32@2x.png</file>
|
||||
<file>icons/view-filter.png</file>
|
||||
<file>icons/view-filter@2x.png</file>
|
||||
<file>icons/applications-internet_32.png</file>
|
||||
<file>icons/applications-internet_32@2x.png</file>
|
||||
<file alias="gpxsee.png">icons/gpxsee.png</file>
|
||||
<file alias="gpxsee@2x.png">icons/gpxsee@2x.png</file>
|
||||
<file alias="dialog-close.png">icons/GUI/dialog-close.png</file>
|
||||
<file alias="dialog-close@2x.png">icons/GUI/dialog-close@2x.png</file>
|
||||
<file alias="document-open.png">icons/GUI/document-open.png</file>
|
||||
<file alias="document-open@2x.png">icons/GUI/document-open@2x.png</file>
|
||||
<file alias="document-print.png">icons/GUI/document-print.png</file>
|
||||
<file alias="document-print@2x.png">icons/GUI/document-print@2x.png</file>
|
||||
<file alias="document-export.png">icons/GUI/document-export.png</file>
|
||||
<file alias="document-export@2x.png">icons/GUI/document-export@2x.png</file>
|
||||
<file alias="flag.png">icons/GUI/flag.png</file>
|
||||
<file alias="flag@2x.png">icons/GUI/flag@2x.png</file>
|
||||
<file alias="application-exit.png">icons/GUI/application-exit.png</file>
|
||||
<file alias="application-exit@2x.png">icons/GUI/application-exit@2x.png</file>
|
||||
<file alias="applications-internet.png">icons/GUI/applications-internet.png</file>
|
||||
<file alias="applications-internet@2x.png">icons/GUI/applications-internet@2x.png</file>
|
||||
<file alias="view-refresh.png">icons/GUI/view-refresh.png</file>
|
||||
<file alias="view-refresh@2x.png">icons/GUI/view-refresh@2x.png</file>
|
||||
<file alias="arrow-left.png">icons/GUI/arrow-left.png</file>
|
||||
<file alias="arrow-left@2x.png">icons/GUI/arrow-left@2x.png</file>
|
||||
<file alias="arrow-right.png">icons/GUI/arrow-right.png</file>
|
||||
<file alias="arrow-right@2x.png">icons/GUI/arrow-right@2x.png</file>
|
||||
<file alias="arrow-left-double.png">icons/GUI/arrow-left-double.png</file>
|
||||
<file alias="arrow-left-double@2x.png">icons/GUI/arrow-left-double@2x.png</file>
|
||||
<file alias="arrow-right-double.png">icons/GUI/arrow-right-double.png</file>
|
||||
<file alias="arrow-right-double@2x.png">icons/GUI/arrow-right-double@2x.png</file>
|
||||
<file alias="view-fullscreen.png">icons/GUI/view-fullscreen.png</file>
|
||||
<file alias="view-fullscreen@2x.png">icons/GUI/view-fullscreen@2x.png</file>
|
||||
<file alias="office-chart-line.png">icons/GUI/office-chart-line.png</file>
|
||||
<file alias="office-chart-line@2x.png">icons/GUI/office-chart-line@2x.png</file>
|
||||
<file alias="format-stroke-color.png">icons/GUI/format-stroke-color.png</file>
|
||||
<file alias="format-stroke-color@2x.png">icons/GUI/format-stroke-color@2x.png</file>
|
||||
<file alias="flag_32.png">icons/GUI/flag_32.png</file>
|
||||
<file alias="flag_32@2x.png">icons/GUI/flag_32@2x.png</file>
|
||||
<file alias="preferences-system.png">icons/GUI/preferences-system.png</file>
|
||||
<file alias="preferences-system@2x.png">icons/GUI/preferences-system@2x.png</file>
|
||||
<file alias="document-print_32.png">icons/GUI/document-print_32.png</file>
|
||||
<file alias="document-print_32@2x.png">icons/GUI/document-print_32@2x.png</file>
|
||||
<file alias="view-filter.png">icons/GUI/view-filter.png</file>
|
||||
<file alias="view-filter@2x.png">icons/GUI/view-filter@2x.png</file>
|
||||
<file alias="applications-internet_32.png">icons/GUI/applications-internet_32.png</file>
|
||||
<file alias="applications-internet_32@2x.png">icons/GUI/applications-internet_32@2x.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 926 B After Width: | Height: | Size: 926 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 707 B After Width: | Height: | Size: 707 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 924 B After Width: | Height: | Size: 924 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 682 B After Width: | Height: | Size: 682 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 865 B After Width: | Height: | Size: 865 B |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 880 B After Width: | Height: | Size: 880 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
169
icons/GUI/licence.txt
Normal file
@ -0,0 +1,169 @@
|
||||
The GUI icons are Oxygen icons from the KDE project (http://www.kde.org)
|
||||
licensed under LGPLv3.
|
||||
|
||||
-----
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
Before Width: | Height: | Size: 728 B After Width: | Height: | Size: 728 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 885 B After Width: | Height: | Size: 885 B |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 381 B After Width: | Height: | Size: 381 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
@ -7,15 +7,17 @@
|
||||
<name>GPXSee</name>
|
||||
<summary>GPS log file viewer and analyzer</summary>
|
||||
<description>
|
||||
<p>GPXSee is a GPS log file viewer and analyzer that supports GPX, TCX,
|
||||
KML, FIT, IGC, NMEA, SLF, LOC, GeoJSON and OziExplorer files.</p>
|
||||
<p>GPXSee is a GPS log file viewer and analyzer that supports all common
|
||||
GPS log file formats.</p>
|
||||
|
||||
<p>Features:</p>
|
||||
<ul>
|
||||
<li>Opens GPX, TCX, FIT, KML, IGC, NMEA, SLF, LOC, OziExplorer (PLT,
|
||||
WPT, RTE), GeoJSON, Garmin CSV and geotagged JPEG files.</li>
|
||||
<li>User-definable online maps (OpenStreetMap/Google tiles, WMTS,
|
||||
WMS, TMS).</li>
|
||||
<li>Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases,
|
||||
GeoTIFF images).</li>
|
||||
TwoNav RMaps, Garmin IMG & JNX, GeoTIFF images).</li>
|
||||
<li>Elevation, speed, heart rate, cadence, power and temperature
|
||||
graphs.</li>
|
||||
<li>Support for multiple tracks in one view.</li>
|
||||
@ -23,8 +25,6 @@
|
||||
<li>Print/export to PDF.</li>
|
||||
<li>Full-screen mode.</li>
|
||||
<li>HiDPI/Retina displays & maps support.</li>
|
||||
<li>Opens GPX, TCX, FIT, KML, IGC, NMEA, SLF, LOC, OziExplorer (PLT,
|
||||
WPT, RTE), GeoJSON and Garmin CSV files.</li>
|
||||
</ul>
|
||||
</description>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "7.5"
|
||||
!define VERSION "7.7"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}.exe"
|
||||
|
@ -7,7 +7,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "7.5"
|
||||
!define VERSION "7.7"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.0">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3">
|
||||
<name>4UMaps</name>
|
||||
<url>https://4umaps.com/$z/$x/$y.png</url>
|
||||
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © 4UMaps.eu</copyright>
|
||||
<zoom min="2" max="15"/>
|
||||
<bounds bottom="-65"/>
|
||||
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © 4UMaps.eu</copyright>
|
||||
</map>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.0" type="WMTS">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3" type="WMTS">
|
||||
<name>Antarctica</name>
|
||||
<url type="REST">https://gis.ngdc.noaa.gov/arcgis/rest/services/antarctic/antarctic_basemap/MapServer/WMTS/1.0.0/WMTSCapabilities.xml</url>
|
||||
<copyright>NOAA National Centers for Environmental Information (NCEI); International Bathymetric Chart of the Southern Ocean (IBCSO); General Bathymetric Chart of the Oceans (GEBCO); Natural Earth</copyright>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.0">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3">
|
||||
<name>Open Street Map</name>
|
||||
<url>http://tile.openstreetmap.org/$z/$x/$y.png</url>
|
||||
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © OpenStreetMap (CC-BY-SA)</copyright>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.0">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3">
|
||||
<name>Open Topo Map</name>
|
||||
<url>https://a.tile.opentopomap.org/$z/$x/$y.png</url>
|
||||
<copyright>Map data: © OpenStreetMap contributors (ODbL), SRTM | Rendering: © OpenTopoMap (CC-BY-SA)</copyright>
|
||||
<zoom max="17"/>
|
||||
<copyright>Map data: © OpenStreetMap contributors (ODbL), SRTM | Rendering: © OpenTopoMap (CC-BY-SA)</copyright>
|
||||
</map>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.0">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3">
|
||||
<name>USGS Imagery</name>
|
||||
<url>https://basemap.nationalmap.gov/ArcGIS/rest/services/USGSImageryOnly/MapServer/tile/$z/$y/$x</url>
|
||||
<copyright>Map services and data available from U.S. Geological Survey, National Geospatial Program.</copyright>
|
||||
<zoom min="2" max="15"/>
|
||||
<bounds bottom="0" top="74"/>
|
||||
<copyright>Map services and data available from U.S. Geological Survey, National Geospatial Program.</copyright>
|
||||
</map>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map xmlns="http://www.gpxsee.org/map/1.0">
|
||||
<map xmlns="http://www.gpxsee.org/map/1.3">
|
||||
<name>USGS Topo</name>
|
||||
<url>https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/$z/$y/$x</url>
|
||||
<copyright>Map services and data available from U.S. Geological Survey, National Geospatial Program.</copyright>
|
||||
<zoom min="2" max="15"/>
|
||||
<copyright>Map services and data available from U.S. Geological Survey, National Geospatial Program.</copyright>
|
||||
</map>
|
||||
|
@ -51,7 +51,7 @@ App::App(int &argc, char **argv) : QApplication(argc, argv)
|
||||
"QThreadStorage: Thread X exited after QThreadStorage Y destroyed" */
|
||||
Downloader::setNetworkManager(new QNetworkAccessManager(this));
|
||||
DEM::setDir(ProgramPaths::demDir());
|
||||
OPENGL_SET_SAMPLES(4);
|
||||
OPENGL_SET_FORMAT(4, 8);
|
||||
|
||||
loadDatums();
|
||||
loadPCSs();
|
||||
|
@ -11,6 +11,10 @@ CoordinatesItem::CoordinatesItem(QGraphicsItem *parent) : QGraphicsItem(parent)
|
||||
_font.setPixelSize(FONT_SIZE);
|
||||
_font.setFamily(FONT_FAMILY);
|
||||
|
||||
_digitalZoom = 0;
|
||||
|
||||
setAcceptHoverEvents(true);
|
||||
|
||||
updateBoundingRect();
|
||||
}
|
||||
|
||||
@ -48,6 +52,12 @@ void CoordinatesItem::setFormat(const CoordinatesFormat &format)
|
||||
updateBoundingRect();
|
||||
}
|
||||
|
||||
void CoordinatesItem::setDigitalZoom(qreal zoom)
|
||||
{
|
||||
_digitalZoom = zoom;
|
||||
setScale(pow(2, -_digitalZoom));
|
||||
}
|
||||
|
||||
void CoordinatesItem::updateBoundingRect()
|
||||
{
|
||||
QFontMetrics fm(_font);
|
||||
|
@ -17,6 +17,7 @@ public:
|
||||
|
||||
void setCoordinates(const Coordinates &c);
|
||||
void setFormat(const CoordinatesFormat &format);
|
||||
void setDigitalZoom(qreal zoom);
|
||||
|
||||
private:
|
||||
void updateBoundingRect();
|
||||
@ -25,6 +26,7 @@ private:
|
||||
CoordinatesFormat _format;
|
||||
QRectF _boundingRect;
|
||||
QFont _font;
|
||||
qreal _digitalZoom;
|
||||
};
|
||||
|
||||
#endif // COORDINATESITEM_H
|
||||
|
@ -103,7 +103,6 @@ GUI::GUI()
|
||||
readSettings();
|
||||
|
||||
updateGraphTabs();
|
||||
updateMapView();
|
||||
updateStatusBarInfo();
|
||||
}
|
||||
|
||||
@ -725,6 +724,8 @@ void GUI::paths()
|
||||
+ QDir::cleanPath(ProgramPaths::csvDir(true)) + "</code></td></tr><tr><td>"
|
||||
+ tr("DEM directory:") + "</td><td><code>"
|
||||
+ QDir::cleanPath(ProgramPaths::demDir(true)) + "</code></td></tr><tr><td>"
|
||||
+ tr("Styles directory:") + "</td><td><code>"
|
||||
+ QDir::cleanPath(ProgramPaths::styleDir(true)) + "</code></td></tr><tr><td>"
|
||||
+ tr("Tile cache directory:") + "</td><td><code>"
|
||||
+ QDir::cleanPath(ProgramPaths::tilesDir()) + "</code></td></tr></table>"
|
||||
);
|
||||
@ -805,7 +806,7 @@ bool GUI::loadFile(const QString &fileName)
|
||||
|
||||
for (int i = 0; i < _tabs.count(); i++)
|
||||
graphs.append(_tabs.at(i)->loadData(data));
|
||||
if (updateGraphTabs() | updateMapView())
|
||||
if (updateGraphTabs())
|
||||
_splitter->refresh();
|
||||
paths = _mapView->loadData(data);
|
||||
|
||||
@ -828,7 +829,6 @@ bool GUI::loadFile(const QString &fileName)
|
||||
updateStatusBarInfo();
|
||||
updateWindowTitle();
|
||||
updateGraphTabs();
|
||||
updateMapView();
|
||||
|
||||
QString error = tr("Error loading data file:") + "\n\n"
|
||||
+ fileName + "\n\n" + data.errorString();
|
||||
@ -930,6 +930,7 @@ void GUI::openOptions()
|
||||
SET_VIEW_OPTION(pathAntiAliasing, useAntiAliasing);
|
||||
SET_VIEW_OPTION(useOpenGL, useOpenGL);
|
||||
SET_VIEW_OPTION(sliderColor, setMarkerColor);
|
||||
SET_VIEW_OPTION(projection, setProjection);
|
||||
|
||||
SET_TAB_OPTION(palette, setPalette);
|
||||
SET_TAB_OPTION(graphWidth, setGraphWidth);
|
||||
@ -974,8 +975,6 @@ void GUI::openOptions()
|
||||
reloadFile();
|
||||
|
||||
_options = options;
|
||||
|
||||
updateMapView();
|
||||
}
|
||||
|
||||
void GUI::printFile()
|
||||
@ -1230,7 +1229,6 @@ void GUI::closeAll()
|
||||
updateStatusBarInfo();
|
||||
updateWindowTitle();
|
||||
updateGraphTabs();
|
||||
updateMapView();
|
||||
}
|
||||
|
||||
void GUI::showGraphs(bool show)
|
||||
@ -1473,19 +1471,6 @@ bool GUI::updateGraphTabs()
|
||||
return (hidden != _graphTabWidget->isHidden());
|
||||
}
|
||||
|
||||
bool GUI::updateMapView()
|
||||
{
|
||||
bool hidden = _mapView->isHidden();
|
||||
|
||||
if (_options.alwaysShowMap)
|
||||
_mapView->setHidden(false);
|
||||
else
|
||||
_mapView->setHidden(!(_trackCount + _routeCount + _waypointCount
|
||||
+ _areaCount));
|
||||
|
||||
return (hidden != _mapView->isHidden());
|
||||
}
|
||||
|
||||
void GUI::setTimeType(TimeType type)
|
||||
{
|
||||
for (int i = 0; i <_tabs.count(); i++)
|
||||
@ -1847,8 +1832,8 @@ void GUI::writeSettings()
|
||||
_options.separateGraphPage);
|
||||
if (_options.sliderColor != SLIDER_COLOR_DEFAULT)
|
||||
settings.setValue(SLIDER_COLOR_SETTING, _options.sliderColor);
|
||||
if (_options.alwaysShowMap != ALWAYS_SHOW_MAP_DEFAULT)
|
||||
settings.setValue(ALWAYS_SHOW_MAP_SETTING, _options.alwaysShowMap);
|
||||
if (_options.projection != PROJECTION_DEFAULT)
|
||||
settings.setValue(PROJECTION_SETTING, _options.projection);
|
||||
#ifdef ENABLE_HIDPI
|
||||
if (_options.hidpiMap != HIDPI_MAP_DEFAULT)
|
||||
settings.setValue(HIDPI_MAP_SETTING, _options.hidpiMap);
|
||||
@ -2110,8 +2095,8 @@ void GUI::readSettings()
|
||||
SEPARATE_GRAPH_PAGE_DEFAULT).toBool();
|
||||
_options.sliderColor = settings.value(SLIDER_COLOR_SETTING,
|
||||
SLIDER_COLOR_DEFAULT).value<QColor>();
|
||||
_options.alwaysShowMap = settings.value(ALWAYS_SHOW_MAP_SETTING,
|
||||
ALWAYS_SHOW_MAP_DEFAULT).toBool();
|
||||
_options.projection = settings.value(PROJECTION_SETTING, PROJECTION_DEFAULT)
|
||||
.toInt();
|
||||
#ifdef ENABLE_HIDPI
|
||||
_options.hidpiMap = settings.value(HIDPI_MAP_SETTING, HIDPI_MAP_SETTING)
|
||||
.toBool();
|
||||
@ -2139,6 +2124,7 @@ void GUI::readSettings()
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
_options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
#endif // ENABLE_HIDPI
|
||||
_mapView->setProjection(_options.projection);
|
||||
|
||||
for (int i = 0; i < _tabs.count(); i++) {
|
||||
_tabs.at(i)->setPalette(_options.palette);
|
||||
|
@ -116,7 +116,6 @@ private:
|
||||
void updateWindowTitle();
|
||||
void updateNavigationActions();
|
||||
bool updateGraphTabs();
|
||||
bool updateMapView();
|
||||
|
||||
TimeType timeType() const;
|
||||
Units units() const;
|
||||
|
@ -1,30 +1,30 @@
|
||||
#ifndef ICONS_H
|
||||
#define ICONS_H
|
||||
|
||||
#define APP_ICON ":/icons/gpxsee.png"
|
||||
#define APP_ICON ":/gpxsee.png"
|
||||
|
||||
// Toolbar/menu icons
|
||||
#define OPEN_FILE_ICON ":/icons/document-open.png"
|
||||
#define EXPORT_FILE_ICON ":/icons/document-export.png"
|
||||
#define PRINT_FILE_ICON ":/icons/document-print.png"
|
||||
#define CLOSE_FILE_ICON ":/icons/dialog-close.png"
|
||||
#define SHOW_POI_ICON ":/icons/flag.png"
|
||||
#define SHOW_MAP_ICON ":/icons/applications-internet.png"
|
||||
#define SHOW_GRAPHS_ICON ":/icons/office-chart-line.png"
|
||||
#define QUIT_ICON ":/icons/application-exit.png"
|
||||
#define RELOAD_FILE_ICON ":/icons/view-refresh.png"
|
||||
#define NEXT_FILE_ICON ":/icons/arrow-right.png"
|
||||
#define PREV_FILE_ICON ":/icons/arrow-left.png"
|
||||
#define LAST_FILE_ICON ":/icons/arrow-right-double.png"
|
||||
#define FIRST_FILE_ICON ":/icons/arrow-left-double.png"
|
||||
#define FULLSCREEN_ICON ":/icons/view-fullscreen.png"
|
||||
#define OPEN_FILE_ICON ":/document-open.png"
|
||||
#define EXPORT_FILE_ICON ":/document-export.png"
|
||||
#define PRINT_FILE_ICON ":/document-print.png"
|
||||
#define CLOSE_FILE_ICON ":/dialog-close.png"
|
||||
#define SHOW_POI_ICON ":/flag.png"
|
||||
#define SHOW_MAP_ICON ":/applications-internet.png"
|
||||
#define SHOW_GRAPHS_ICON ":/office-chart-line.png"
|
||||
#define QUIT_ICON ":/application-exit.png"
|
||||
#define RELOAD_FILE_ICON ":/view-refresh.png"
|
||||
#define NEXT_FILE_ICON ":/arrow-right.png"
|
||||
#define PREV_FILE_ICON ":/arrow-left.png"
|
||||
#define LAST_FILE_ICON ":/arrow-right-double.png"
|
||||
#define FIRST_FILE_ICON ":/arrow-left-double.png"
|
||||
#define FULLSCREEN_ICON ":/view-fullscreen.png"
|
||||
|
||||
// Options dialog icons
|
||||
#define APPEARANCE_ICON ":/icons/format-stroke-color.png"
|
||||
#define POI_ICON ":/icons/flag_32.png"
|
||||
#define SYSTEM_ICON ":/icons/preferences-system.png"
|
||||
#define PRINT_EXPORT_ICON ":/icons/document-print_32.png"
|
||||
#define DATA_ICON ":/icons/view-filter.png"
|
||||
#define MAPS_ICON ":/icons/applications-internet_32.png"
|
||||
#define APPEARANCE_ICON ":/format-stroke-color.png"
|
||||
#define POI_ICON ":/flag_32.png"
|
||||
#define SYSTEM_ICON ":/preferences-system.png"
|
||||
#define PRINT_EXPORT_ICON ":/document-print_32.png"
|
||||
#define DATA_ICON ":/view-filter.png"
|
||||
#define MAPS_ICON ":/applications-internet_32.png"
|
||||
|
||||
#endif /* ICONS_H */
|
||||
|
39
src/GUI/limitedcombobox.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef LIMITEDCOMBOBOX_H
|
||||
#define LIMITEDCOMBOBOX_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QEvent>
|
||||
|
||||
class LimitedComboBox : public QComboBox
|
||||
{
|
||||
public:
|
||||
LimitedComboBox(int limit, QWidget *parent = 0)
|
||||
: QComboBox(parent), _limit(limit)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||
setStyleSheet("combobox-popup: 0;");
|
||||
}
|
||||
|
||||
QSize sizeHint() const
|
||||
{
|
||||
return QSize(qMin(_limit, QComboBox::sizeHint().width()),
|
||||
QComboBox::sizeHint().height());
|
||||
}
|
||||
QSize minimumSizeHint() const
|
||||
{
|
||||
return QSize(qMin(_limit, QComboBox::minimumSizeHint().width()),
|
||||
QComboBox::minimumSizeHint().height());
|
||||
}
|
||||
|
||||
bool event(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::Polish)
|
||||
view()->setMinimumWidth(QComboBox::sizeHint().width());
|
||||
return QComboBox::event(e);
|
||||
}
|
||||
|
||||
private:
|
||||
int _limit;
|
||||
};
|
||||
|
||||
#endif // LIMITEDCOMBOBOX_H
|
@ -7,6 +7,7 @@
|
||||
#include "data/poi.h"
|
||||
#include "data/data.h"
|
||||
#include "map/map.h"
|
||||
#include "map/pcs.h"
|
||||
#include "opengl.h"
|
||||
#include "trackitem.h"
|
||||
#include "routeitem.h"
|
||||
@ -39,7 +40,6 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setRenderHint(QPainter::Antialiasing, true);
|
||||
setAcceptDrops(false);
|
||||
setMouseTracking(true);
|
||||
|
||||
_mapScale = new ScaleItem();
|
||||
_mapScale->setZValue(2.0);
|
||||
@ -49,8 +49,10 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
|
||||
_coordinates->setVisible(false);
|
||||
_scene->addItem(_coordinates);
|
||||
|
||||
_projection = PCS::pcs(3857);
|
||||
_map = map;
|
||||
_map->load();
|
||||
_map->setProjection(_projection);
|
||||
connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
|
||||
|
||||
_poi = poi;
|
||||
@ -313,6 +315,7 @@ void MapView::setMap(Map *map)
|
||||
|
||||
_map = map;
|
||||
_map->load();
|
||||
_map->setProjection(_projection);
|
||||
#ifdef ENABLE_HIDPI
|
||||
_map->setDevicePixelRatio(_deviceRatio, _mapRatio);
|
||||
#endif // ENABLE_HIDPI
|
||||
@ -476,6 +479,7 @@ void MapView::digitalZoom(int zoom)
|
||||
it.value()->setDigitalZoom(_digitalZoom);
|
||||
|
||||
_mapScale->setDigitalZoom(_digitalZoom);
|
||||
_coordinates->setDigitalZoom(_digitalZoom);
|
||||
}
|
||||
|
||||
void MapView::zoom(int zoom, const QPoint &pos)
|
||||
@ -751,6 +755,7 @@ void MapView::showPOILabels(bool show)
|
||||
void MapView::showCoordinates(bool show)
|
||||
{
|
||||
_coordinates->setVisible(show);
|
||||
setMouseTracking(show);
|
||||
}
|
||||
|
||||
void MapView::setPOIOverlap(bool overlap)
|
||||
@ -1011,3 +1016,17 @@ void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
Q_UNUSED(mapRatio);
|
||||
#endif // ENABLE_HIDPI
|
||||
}
|
||||
|
||||
void MapView::setProjection(int id)
|
||||
{
|
||||
Projection projection(PCS::pcs(id));
|
||||
if (!projection.isValid())
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
|
||||
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
|
||||
_map->setProjection(_projection);
|
||||
rescale();
|
||||
centerOn(_map->ll2xy(center));
|
||||
}
|
||||
|
@ -8,11 +8,13 @@
|
||||
#include "common/rectc.h"
|
||||
#include "common/config.h"
|
||||
#include "data/waypoint.h"
|
||||
#include "data/polygon.h"
|
||||
#include "map/projection.h"
|
||||
#include "searchpointer.h"
|
||||
#include "units.h"
|
||||
#include "format.h"
|
||||
#include "palette.h"
|
||||
#include "data/polygon.h"
|
||||
|
||||
|
||||
class Data;
|
||||
class POI;
|
||||
@ -80,6 +82,7 @@ public slots:
|
||||
void clearMapCache();
|
||||
void setCoordinatesFormat(CoordinatesFormat format);
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
void setProjection(int id);
|
||||
|
||||
private slots:
|
||||
void updatePOI();
|
||||
@ -132,6 +135,7 @@ private:
|
||||
Units _units;
|
||||
CoordinatesFormat _coordinatesFormat;
|
||||
qreal _mapOpacity;
|
||||
Projection _projection;
|
||||
|
||||
bool _showMap, _showTracks, _showRoutes, _showAreas, _showWaypoints,
|
||||
_showWaypointLabels, _showPOI, _showPOILabels, _showRouteWaypoints,
|
||||
|
@ -14,13 +14,15 @@
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0)
|
||||
#define OPENGL_SET_SAMPLES(samples) \
|
||||
#define OPENGL_SET_FORMAT(samples, stencilBuffer) \
|
||||
{QGLFormat fmt; \
|
||||
fmt.setStencilBufferSize(stencilBuffer); \
|
||||
fmt.setSamples(samples); \
|
||||
QGLFormat::setDefaultFormat(fmt);}
|
||||
#else
|
||||
#define OPENGL_SET_SAMPLES(samples) \
|
||||
#define OPENGL_SET_FORMAT(samples, stencilBuffer) \
|
||||
{QSurfaceFormat fmt; \
|
||||
fmt.setSamples(samples);\
|
||||
fmt.setStencilBufferSize(stencilBuffer); \
|
||||
fmt.setSamples(samples); \
|
||||
QSurfaceFormat::setDefaultFormat(fmt);}
|
||||
#endif
|
||||
|
@ -12,11 +12,14 @@
|
||||
#include <QRadioButton>
|
||||
#include <QLabel>
|
||||
#include <QSysInfo>
|
||||
#include <QInputDialog>
|
||||
#include "map/pcs.h"
|
||||
#include "icons.h"
|
||||
#include "colorbox.h"
|
||||
#include "stylecombobox.h"
|
||||
#include "oddspinbox.h"
|
||||
#include "percentslider.h"
|
||||
#include "limitedcombobox.h"
|
||||
#include "optionsdialog.h"
|
||||
|
||||
|
||||
@ -36,10 +39,15 @@ static QFrame *line()
|
||||
|
||||
QWidget *OptionsDialog::createMapPage()
|
||||
{
|
||||
_alwaysShowMap = new QCheckBox(tr("Always show the map"));
|
||||
_alwaysShowMap->setChecked(_options->alwaysShowMap);
|
||||
_alwaysShowMap->setToolTip("<p>" +
|
||||
tr("Show the map even when no files are loaded.") + "</p>");
|
||||
_projection = new LimitedComboBox(200);
|
||||
QList<PCS::Info> projections(PCS::pcsList());
|
||||
qSort(projections);
|
||||
for (int i = 0; i < projections.size(); i++) {
|
||||
QString text = QString::number(projections.at(i).id()) + " - "
|
||||
+ projections.at(i).name();
|
||||
_projection->addItem(text, QVariant(projections.at(i).id()));
|
||||
}
|
||||
_projection->setCurrentIndex(_projection->findData(_options->projection));
|
||||
|
||||
#ifdef ENABLE_HIDPI
|
||||
_hidpi = new QRadioButton(tr("High-resolution"));
|
||||
@ -60,14 +68,14 @@ QWidget *OptionsDialog::createMapPage()
|
||||
llo->setFont(f);
|
||||
#endif // ENABLE_HIDPI
|
||||
|
||||
QFormLayout *showMapLayout = new QFormLayout();
|
||||
showMapLayout->addWidget(_alwaysShowMap);
|
||||
QFormLayout *vectorLayout = new QFormLayout();
|
||||
vectorLayout->addRow(tr("Projection:"), _projection);
|
||||
|
||||
QWidget *mapTab = new QWidget();
|
||||
QVBoxLayout *mapTabLayout = new QVBoxLayout();
|
||||
mapTabLayout->addLayout(showMapLayout);
|
||||
mapTabLayout->addStretch();
|
||||
mapTab->setLayout(mapTabLayout);
|
||||
QWidget *vectorMapsTab = new QWidget();
|
||||
QVBoxLayout *vectorMapsTabLayout = new QVBoxLayout();
|
||||
vectorMapsTabLayout->addLayout(vectorLayout);
|
||||
vectorMapsTabLayout->addStretch();
|
||||
vectorMapsTab->setLayout(vectorMapsTabLayout);
|
||||
|
||||
#ifdef ENABLE_HIDPI
|
||||
QVBoxLayout *hidpiTabLayout = new QVBoxLayout();
|
||||
@ -83,7 +91,7 @@ QWidget *OptionsDialog::createMapPage()
|
||||
#endif // ENABLE_HIDPI
|
||||
|
||||
QTabWidget *mapPage = new QTabWidget();
|
||||
mapPage->addTab(mapTab, tr("General"));
|
||||
mapPage->addTab(vectorMapsTab, tr("Vector maps"));
|
||||
#ifdef ENABLE_HIDPI
|
||||
mapPage->addTab(hidpiTab, tr("HiDPI display mode"));
|
||||
#endif // ENABLE_HIDPI
|
||||
@ -261,6 +269,7 @@ QWidget *OptionsDialog::createAppearancePage()
|
||||
_backgroundColor = new ColorBox();
|
||||
_backgroundColor->setColor(_options->backgroundColor);
|
||||
_backgroundColor->enableAlphaChannel(false);
|
||||
|
||||
QFormLayout *mapLayout = new QFormLayout();
|
||||
mapLayout->addRow(tr("Background color:"), _backgroundColor);
|
||||
mapLayout->addRow(tr("Map opacity:"), _mapOpacity);
|
||||
@ -656,7 +665,8 @@ void OptionsDialog::accept()
|
||||
_options->sliderColor = _sliderColor->color();
|
||||
_options->graphAntiAliasing = _graphAA->isChecked();
|
||||
|
||||
_options->alwaysShowMap = _alwaysShowMap->isChecked();
|
||||
_options->projection = _projection->itemData(_projection->currentIndex())
|
||||
.toInt();
|
||||
#ifdef ENABLE_HIDPI
|
||||
_options->hidpiMap = _hidpi->isChecked();
|
||||
#endif // ENABLE_HIDPI
|
||||
|
@ -15,6 +15,7 @@ class QComboBox;
|
||||
class QCheckBox;
|
||||
class QRadioButton;
|
||||
class PercentSlider;
|
||||
class LimitedComboBox;
|
||||
|
||||
struct Options {
|
||||
// Appearance
|
||||
@ -37,7 +38,7 @@ struct Options {
|
||||
int mapOpacity;
|
||||
QColor backgroundColor;
|
||||
// Map
|
||||
bool alwaysShowMap;
|
||||
int projection;
|
||||
#ifdef ENABLE_HIDPI
|
||||
bool hidpiMap;
|
||||
#endif // ENABLE_HIDPI
|
||||
@ -79,11 +80,14 @@ class OptionsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
|
||||
public:
|
||||
OptionsDialog(Options *options, QWidget *parent = 0);
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
//private slots:
|
||||
// void projectionChanged(int index);
|
||||
|
||||
private:
|
||||
QWidget *createMapPage();
|
||||
@ -116,7 +120,7 @@ private:
|
||||
ColorBox *_sliderColor;
|
||||
QCheckBox *_graphAA;
|
||||
// Map
|
||||
QCheckBox *_alwaysShowMap;
|
||||
LimitedComboBox *_projection;
|
||||
#ifdef ENABLE_HIDPI
|
||||
QRadioButton *_hidpi;
|
||||
QRadioButton *_lodpi;
|
||||
|
@ -171,8 +171,8 @@
|
||||
#define SEPARATE_GRAPH_PAGE_DEFAULT false
|
||||
#define SLIDER_COLOR_SETTING "sliderColor"
|
||||
#define SLIDER_COLOR_DEFAULT QColor(Qt::red)
|
||||
#define ALWAYS_SHOW_MAP_SETTING "alwaysShowMap"
|
||||
#define ALWAYS_SHOW_MAP_DEFAULT true
|
||||
#define PROJECTION_SETTING "projection"
|
||||
#define PROJECTION_DEFAULT 3857
|
||||
#define HIDPI_MAP_SETTING "HiDPIMap"
|
||||
#define HIDPI_MAP_DEFAULT true
|
||||
|
||||
|
@ -14,4 +14,8 @@
|
||||
#define ENABLE_HIDPI
|
||||
#endif // QT >= 5.6
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
#define ENABLE_GEOJSON
|
||||
#endif // QT >= 5.0
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
|
@ -9,9 +9,11 @@
|
||||
#define DEM_DIR "DEM"
|
||||
#define TILES_DIR "tiles"
|
||||
#define TRANSLATIONS_DIR "translations"
|
||||
#define STYLE_DIR "style"
|
||||
#define ELLIPSOID_FILE "ellipsoids.csv"
|
||||
#define GCS_FILE "gcs.csv"
|
||||
#define PCS_FILE "pcs.csv"
|
||||
#define TYP_FILE "style.typ"
|
||||
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0)
|
||||
@ -31,7 +33,7 @@
|
||||
#else
|
||||
#define USER_DIR QDir::homePath() + QString("/.local/share/") \
|
||||
+ qApp->applicationName()
|
||||
#define GLOBAL_DIR QString("/usr/share/") + qApp->applicationName()
|
||||
#define GLOBAL_DIR QString(PREFIX "/share/") + qApp->applicationName()
|
||||
#endif
|
||||
|
||||
static QString dir(const QString &dirName, bool writable = false)
|
||||
@ -79,6 +81,11 @@ QString ProgramPaths::demDir(bool writable)
|
||||
return dir(DEM_DIR, writable);
|
||||
}
|
||||
|
||||
QString ProgramPaths::styleDir(bool writable)
|
||||
{
|
||||
return dir(STYLE_DIR, writable);
|
||||
}
|
||||
|
||||
QString ProgramPaths::tilesDir()
|
||||
{
|
||||
#if defined(Q_OS_WIN32)
|
||||
@ -113,6 +120,11 @@ QString ProgramPaths::pcsFile()
|
||||
return file(dir(CSV_DIR), PCS_FILE);
|
||||
}
|
||||
|
||||
QString ProgramPaths::typFile()
|
||||
{
|
||||
return file(dir(STYLE_DIR), TYP_FILE);
|
||||
}
|
||||
|
||||
#else // QT_VERSION < 5
|
||||
|
||||
#include <QStandardPaths>
|
||||
@ -157,6 +169,16 @@ QString ProgramPaths::demDir(bool writable)
|
||||
DEM_DIR, QStandardPaths::LocateDirectory);
|
||||
}
|
||||
|
||||
QString ProgramPaths::styleDir(bool writable)
|
||||
{
|
||||
if (writable)
|
||||
return QDir(QStandardPaths::writableLocation(
|
||||
QStandardPaths::AppDataLocation)).filePath(STYLE_DIR);
|
||||
else
|
||||
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
|
||||
STYLE_DIR, QStandardPaths::LocateDirectory);
|
||||
}
|
||||
|
||||
QString ProgramPaths::tilesDir()
|
||||
{
|
||||
return QDir(QStandardPaths::writableLocation(
|
||||
@ -187,4 +209,10 @@ QString ProgramPaths::pcsFile()
|
||||
CSV_DIR "/" PCS_FILE, QStandardPaths::LocateFile);
|
||||
}
|
||||
|
||||
QString ProgramPaths::typFile()
|
||||
{
|
||||
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
|
||||
STYLE_DIR "/" TYP_FILE, QStandardPaths::LocateFile);
|
||||
}
|
||||
|
||||
#endif // QT_VERSION < 5
|
||||
|
@ -9,11 +9,13 @@ namespace ProgramPaths
|
||||
QString poiDir(bool writable = false);
|
||||
QString csvDir(bool writable = false);
|
||||
QString demDir(bool writable = false);
|
||||
QString styleDir(bool writable = false);
|
||||
QString tilesDir();
|
||||
QString translationsDir();
|
||||
QString ellipsoidsFile();
|
||||
QString gcsFile();
|
||||
QString pcsFile();
|
||||
QString typFile();
|
||||
}
|
||||
|
||||
#endif // PROGRAMPATHS_H
|
||||
|
@ -28,6 +28,11 @@ public:
|
||||
double left() const {return _tl.lon();}
|
||||
double right() const {return _br.lon();}
|
||||
|
||||
void setLeft(double val) {_tl.rlon() = val;}
|
||||
void setRight(double val) {_br.rlon() = val;}
|
||||
void setTop(double val) {_tl.rlat() = val;}
|
||||
void setBottom(double val) {_br.rlat() = val;}
|
||||
|
||||
RectC operator|(const RectC &r) const;
|
||||
RectC &operator|=(const RectC &r) {*this = *this | r; return *this;}
|
||||
RectC operator&(const RectC &r) const;
|
||||
@ -35,6 +40,13 @@ public:
|
||||
|
||||
RectC united(const Coordinates &c) const;
|
||||
|
||||
bool intersects(const RectC &r) const
|
||||
{return (right() >= r.left() && bottom() <= r.top() && left() <= r.right()
|
||||
&& top() >= r.bottom());}
|
||||
bool contains(const Coordinates&c) const
|
||||
{return (c.lon() >= left() && c.lon() <= right() && c.lat() <= top()
|
||||
&& c.lat() >= bottom());}
|
||||
|
||||
private:
|
||||
Coordinates _tl, _br;
|
||||
};
|
||||
|
@ -215,6 +215,8 @@ public:
|
||||
StackElement m_stack[MAX_STACK];
|
||||
// Top Of Stack index
|
||||
int m_tos;
|
||||
|
||||
friend class RTree;
|
||||
};
|
||||
|
||||
// Get 'first' for iteration
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QLineF>
|
||||
#include "common/config.h"
|
||||
#include "gpxparser.h"
|
||||
#include "tcxparser.h"
|
||||
#include "csvparser.h"
|
||||
@ -12,9 +13,9 @@
|
||||
#include "oziparsers.h"
|
||||
#include "locparser.h"
|
||||
#include "slfparser.h"
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
#ifdef ENABLE_GEOJSON
|
||||
#include "geojsonparser.h"
|
||||
#endif // QT 5
|
||||
#endif // ENABLE_GEOJSON
|
||||
#include "exifparser.h"
|
||||
#include "dem.h"
|
||||
#include "data.h"
|
||||
@ -32,9 +33,9 @@ static WPTParser wpt;
|
||||
static RTEParser rte;
|
||||
static LOCParser loc;
|
||||
static SLFParser slf;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
#ifdef ENABLE_GEOJSON
|
||||
static GeoJSONParser geojson;
|
||||
#endif // QT 5
|
||||
#endif // ENABLE_GEOJSON
|
||||
static EXIFParser exif;
|
||||
|
||||
static QHash<QString, Parser*> parsers()
|
||||
@ -53,10 +54,10 @@ static QHash<QString, Parser*> parsers()
|
||||
hash.insert("rte", &rte);
|
||||
hash.insert("loc", &loc);
|
||||
hash.insert("slf", &slf);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
#ifdef ENABLE_GEOJSON
|
||||
hash.insert("json", &geojson);
|
||||
hash.insert("geojson", &geojson);
|
||||
#endif // QT 5
|
||||
#endif // ENABLE_GEOJSON
|
||||
hash.insert("jpeg", &exif);
|
||||
hash.insert("jpg", &exif);
|
||||
|
||||
@ -147,9 +148,9 @@ QString Data::formats()
|
||||
qApp->translate("Data", "Supported files") + " (" + supported + ");;"
|
||||
+ qApp->translate("Data", "CSV files") + " (*.csv);;"
|
||||
+ qApp->translate("Data", "FIT files") + " (*.fit);;"
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
#ifdef ENABLE_GEOJSON
|
||||
+ qApp->translate("Data", "GeoJSON files") + " (*.geojson *.json);;"
|
||||
#endif // QT5
|
||||
#endif // ENABLE_GEOJSON
|
||||
+ qApp->translate("Data", "GPX files") + " (*.gpx);;"
|
||||
+ qApp->translate("Data", "IGC files") + " (*.igc);;"
|
||||
+ qApp->translate("Data", "JPEG images") + " (*.jpg *.jpeg);;"
|
||||
|
@ -217,7 +217,7 @@ Graph Track::speed() const
|
||||
v = 0;
|
||||
stop.append(gs.size());
|
||||
} else if (_useReportedSpeed && sd.at(j).hasSpeed()
|
||||
&& seg.outliers.contains(j))
|
||||
&& !seg.outliers.contains(j))
|
||||
v = sd.at(j).speed();
|
||||
else if (!std::isnan(seg.speed.at(j)) && !seg.outliers.contains(j))
|
||||
v = seg.speed.at(j);
|
||||
|
39
src/map/IMG/bitmapline.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
#include "bitmapline.h"
|
||||
|
||||
static QImage img2line(const QImage &img, int width)
|
||||
{
|
||||
Q_ASSERT(img.format() == QImage::Format_ARGB32_Premultiplied);
|
||||
QImage res(width, img.height(), QImage::Format_ARGB32_Premultiplied);
|
||||
const int srcBpl = img.bytesPerLine();
|
||||
const int dstBpl = res.bytesPerLine();
|
||||
const uchar *srcBits = img.bits();
|
||||
uchar *dstBits = res.bits();
|
||||
|
||||
for (int i = 0; i < img.height(); i++) {
|
||||
const uchar *srcLine = srcBits + srcBpl * i;
|
||||
uchar *dstLine = dstBits + dstBpl * i;
|
||||
|
||||
for (int j = dstBpl; j > 0; j -= srcBpl, dstLine += srcBpl)
|
||||
memcpy(dstLine, srcLine, qMin(j, srcBpl));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void BitmapLine::draw(QPainter *painter, const QPolygonF &line,
|
||||
const QImage &img)
|
||||
{
|
||||
for (int i = 1; i < line.size(); i++) {
|
||||
QLineF segment(line.at(i-1).x(), line.at(i-1).y(), line.at(i).x(),
|
||||
line.at(i).y());
|
||||
|
||||
painter->save();
|
||||
painter->translate(segment.p1());
|
||||
painter->rotate(-segment.angle());
|
||||
painter->drawImage(0, -img.height()/2, img2line(img, segment.length()));
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
13
src/map/IMG/bitmapline.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef BITMAPLINE_H
|
||||
#define BITMAPLINE_H
|
||||
|
||||
class QPainter;
|
||||
class QImage;
|
||||
class QPolygonF;
|
||||
|
||||
namespace BitmapLine
|
||||
{
|
||||
void draw(QPainter *painter, const QPolygonF &line, const QImage &img);
|
||||
}
|
||||
|
||||
#endif // BITMAPLINE_H
|
257
src/map/IMG/img.cpp
Normal file
@ -0,0 +1,257 @@
|
||||
#include <QSet>
|
||||
#include <QtEndian>
|
||||
#include "common/programpaths.h"
|
||||
#include "vectortile.h"
|
||||
#include "img.h"
|
||||
|
||||
|
||||
#define CHECK(condition) \
|
||||
if (!(condition)) { \
|
||||
_errorString = "Invalid/corrupted IMG file"; \
|
||||
return; \
|
||||
}
|
||||
|
||||
struct CTX
|
||||
{
|
||||
CTX(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
|
||||
QList<IMG::Poly> *lines, QList<IMG::Point> *points)
|
||||
: rect(rect), bits(bits), polygons(polygons), lines(lines),
|
||||
points(points) {}
|
||||
|
||||
const RectC ▭
|
||||
int bits;
|
||||
QList<IMG::Poly> *polygons;
|
||||
QList<IMG::Poly> *lines;
|
||||
QList<IMG::Point> *points;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
static QDebug operator<<(QDebug dbg, const QMap<QString, VectorTile*> &map)
|
||||
{
|
||||
dbg.nospace() << "TileMap(";
|
||||
for (QMap<QString, VectorTile*>::const_iterator it = map.constBegin();
|
||||
it != map.constEnd(); ++it)
|
||||
dbg << "(" << it.key() << ", " << *(*it) << ")";
|
||||
dbg << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
IMG::IMG(const QString &fileName) : _file(fileName), _valid(false)
|
||||
{
|
||||
if (!_file.open(QFile::ReadOnly)) {
|
||||
_errorString = _file.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read IMG header
|
||||
char signature[7], identifier[7];
|
||||
_file.read((char*)&_key, 1) && _file.seek(0x10)
|
||||
&& read(signature, sizeof(signature)) && _file.seek(0x41)
|
||||
&& read(identifier, sizeof(identifier));
|
||||
if (memcmp(signature, "DSKIMG", sizeof(signature))
|
||||
|| memcmp(identifier, "GARMIN", sizeof(identifier))) {
|
||||
_errorString = "Not a Garmin IMG file";
|
||||
return;
|
||||
}
|
||||
char d1[20], d2[31];
|
||||
quint8 e1, e2;
|
||||
CHECK(_file.seek(0x49) && read(d1, sizeof(d1)) && _file.seek(0x61)
|
||||
&& readValue(e1) && readValue(e2) && _file.seek(0x65)
|
||||
&& read(d2, sizeof(d2)));
|
||||
QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2)));
|
||||
_name = QString(nba).trimmed();
|
||||
_blockSize = 1 << (e1 + e2);
|
||||
|
||||
// Read the FAT table
|
||||
quint8 flag;
|
||||
quint64 offset = 0x200;
|
||||
// Skip unused FAT blocks if any
|
||||
while (true) {
|
||||
CHECK(_file.seek(offset) && readValue(flag));
|
||||
if (flag)
|
||||
break;
|
||||
offset += 512;
|
||||
}
|
||||
|
||||
// Read first FAT block with FAT table size
|
||||
char name[8], type[3];
|
||||
quint32 size;
|
||||
quint16 part;
|
||||
CHECK(_file.seek(offset + 12) && readValue(size));
|
||||
offset += 512;
|
||||
int cnt = (size - offset) / 512;
|
||||
|
||||
|
||||
QMap<QString, VectorTile*> tileMap;
|
||||
QMap<QString, SubFile*> TYPMap;
|
||||
|
||||
// Read FAT blocks describing the IMG sub-files
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
quint16 block;
|
||||
CHECK(_file.seek(offset) && readValue(flag) && read(name, sizeof(name))
|
||||
&& read(type, sizeof(type)) && readValue(size) && readValue(part));
|
||||
SubFile::Type tt = SubFile::type(type);
|
||||
|
||||
if (tt == SubFile::GMP) {
|
||||
_errorString = "NT maps not supported";
|
||||
return;
|
||||
}
|
||||
|
||||
QString fn(QByteArray(name, sizeof(name)));
|
||||
if (VectorTile::isTileFile(tt)) {
|
||||
VectorTile *tile;
|
||||
QMap<QString, VectorTile*>::iterator it = tileMap.find(fn);
|
||||
if (it == tileMap.end()) {
|
||||
tile = new VectorTile();
|
||||
tileMap.insert(fn, tile);
|
||||
} else
|
||||
tile = *it;
|
||||
|
||||
SubFile *file = part ? tile->file(tt)
|
||||
: tile->addFile(this, tt, size);
|
||||
CHECK(file);
|
||||
|
||||
_file.seek(offset + 0x20);
|
||||
for (int i = 0; i < 240; i++) {
|
||||
CHECK(readValue(block));
|
||||
if (block == 0xFFFF)
|
||||
break;
|
||||
file->addBlock(block);
|
||||
}
|
||||
} else if (tt == SubFile::TYP) {
|
||||
SubFile *typ;
|
||||
QMap<QString, SubFile*>::iterator it = TYPMap.find(fn);
|
||||
if (it == TYPMap.end()) {
|
||||
typ = new SubFile(this, size);
|
||||
TYPMap.insert(fn, typ);
|
||||
} else
|
||||
typ = *it;
|
||||
|
||||
_file.seek(offset + 0x20);
|
||||
for (int i = 0; i < 240; i++) {
|
||||
CHECK(readValue(block));
|
||||
if (block == 0xFFFF)
|
||||
break;
|
||||
typ->addBlock(block);
|
||||
}
|
||||
}
|
||||
|
||||
offset += 512;
|
||||
}
|
||||
|
||||
// Create tile tree
|
||||
QSet<int> bits;
|
||||
for (QMap<QString, VectorTile*>::iterator it = tileMap.begin();
|
||||
it != tileMap.end(); ++it) {
|
||||
CHECK((*it)->init());
|
||||
|
||||
double min[2], max[2];
|
||||
min[0] = (*it)->bounds().left();
|
||||
min[1] = (*it)->bounds().bottom();
|
||||
max[0] = (*it)->bounds().right();
|
||||
max[1] = (*it)->bounds().top();
|
||||
_tileTree.Insert(min, max, *it);
|
||||
|
||||
_bounds |= (*it)->bounds();
|
||||
|
||||
for (int i = 0; i < (*it)->bits().count(); i++)
|
||||
bits.insert((*it)->bits().at(i));
|
||||
}
|
||||
_bits = bits.toList();
|
||||
qSort(_bits);
|
||||
|
||||
// Read TYP file if any
|
||||
if (!TYPMap.isEmpty()) {
|
||||
if (TYPMap.size() > 1)
|
||||
qWarning("%s: Multiple TYP files, using %s",
|
||||
qPrintable(_file.fileName()), qPrintable(TYPMap.keys().first()));
|
||||
SubFile *typ = TYPMap.values().first();
|
||||
_style = Style(typ);
|
||||
qDeleteAll(TYPMap);
|
||||
} else {
|
||||
QFile typFile(ProgramPaths::typFile());
|
||||
if (typFile.exists()) {
|
||||
SubFile typ(&typFile);
|
||||
_style = Style(&typ);
|
||||
}
|
||||
}
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
IMG::~IMG()
|
||||
{
|
||||
TileTree::Iterator it;
|
||||
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it))
|
||||
delete _tileTree.GetAt(it);
|
||||
}
|
||||
|
||||
static bool cb(VectorTile *tile, void *context)
|
||||
{
|
||||
CTX *ctx = (CTX*)context;
|
||||
tile->objects(ctx->rect, ctx->bits, ctx->polygons, ctx->lines, ctx->points);
|
||||
return true;
|
||||
}
|
||||
|
||||
void IMG::objects(const RectC &rect, int bits, QList<Poly> *polygons,
|
||||
QList<Poly> *lines, QList<Point> *points) const
|
||||
{
|
||||
int mb = _bits.first();
|
||||
for (int i = 0; i < _bits.size(); i++) {
|
||||
if (_bits.at(i) > bits)
|
||||
break;
|
||||
else
|
||||
mb = _bits.at(i);
|
||||
}
|
||||
|
||||
CTX ctx(rect, mb, polygons, lines, points);
|
||||
double min[2], max[2];
|
||||
|
||||
min[0] = rect.left();
|
||||
min[1] = rect.bottom();
|
||||
max[0] = rect.right();
|
||||
max[1] = rect.top();
|
||||
|
||||
_tileTree.Search(min, max, cb, &ctx);
|
||||
}
|
||||
|
||||
qint64 IMG::read(char *data, qint64 maxSize)
|
||||
{
|
||||
qint64 ret = _file.read(data, maxSize);
|
||||
if (_key)
|
||||
for (int i = 0; i < ret; i++)
|
||||
data[i] ^= _key;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T> bool IMG::readValue(T &val)
|
||||
{
|
||||
T data;
|
||||
|
||||
if (read((char*)&data, sizeof(T)) < (qint64)sizeof(T))
|
||||
return false;
|
||||
|
||||
if (sizeof(T) > 1)
|
||||
val = qFromLittleEndian(data);
|
||||
else
|
||||
val = data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IMG::readBlock(int blockNum, QByteArray &data)
|
||||
{
|
||||
QByteArray *block = _blockCache[blockNum];
|
||||
if (!block) {
|
||||
if (!_file.seek((qint64)blockNum * (qint64)_blockSize))
|
||||
return false;
|
||||
data.resize(_blockSize);
|
||||
if (read(data.data(), _blockSize) < _blockSize)
|
||||
return false;
|
||||
_blockCache.insert(blockNum, new QByteArray(data));
|
||||
} else
|
||||
data = *block;
|
||||
|
||||
return true;
|
||||
}
|
87
src/map/IMG/img.h
Normal file
@ -0,0 +1,87 @@
|
||||
#ifndef IMG_H
|
||||
#define IMG_H
|
||||
|
||||
#include <QRect>
|
||||
#include <QFile>
|
||||
#include <QByteArray>
|
||||
#include <QCache>
|
||||
#include <QDebug>
|
||||
#include "common/rtree.h"
|
||||
#include "common/rectc.h"
|
||||
#include "common/range.h"
|
||||
#include "style.h"
|
||||
|
||||
class VectorTile;
|
||||
class SubFile;
|
||||
|
||||
class IMG
|
||||
{
|
||||
public:
|
||||
struct Poly {
|
||||
/* QPointF insted of Coordinates for performance reasons (no need to
|
||||
duplicate all the vectors for drawing). Note, that we do not want to
|
||||
ll2xy() the points in the IMG class as this can not be done in
|
||||
parallel. */
|
||||
QVector<QPointF> points;
|
||||
QString label;
|
||||
quint32 type;
|
||||
|
||||
bool operator<(const Poly &other) const
|
||||
{return type > other.type;}
|
||||
};
|
||||
|
||||
struct Point {
|
||||
Point() : id(0) {}
|
||||
|
||||
Coordinates coordinates;
|
||||
QString label;
|
||||
quint32 type;
|
||||
bool poi;
|
||||
quint64 id;
|
||||
|
||||
bool operator<(const Point &other) const
|
||||
{return id < other.id;}
|
||||
};
|
||||
|
||||
|
||||
IMG(const QString &fileName);
|
||||
~IMG();
|
||||
|
||||
const QString &name() const {return _name;}
|
||||
const RectC &bounds() const {return _bounds;}
|
||||
Range zooms() const {return Range(_bits.first(), _bits.last());}
|
||||
void objects(const RectC &rect, int bits, QList<Poly> *polygons,
|
||||
QList<Poly> *lines, QList<Point> *points) const;
|
||||
const Style &style() const {return _style;}
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
const QString &errorString() const {return _errorString;}
|
||||
|
||||
private:
|
||||
friend class SubFile;
|
||||
|
||||
typedef RTree<VectorTile*, double, 2> TileTree;
|
||||
|
||||
QString fileName() const {return _file.fileName();}
|
||||
int blockSize() const {return _blockSize;}
|
||||
bool readBlock(int blockNum, QByteArray &data);
|
||||
qint64 read(char *data, qint64 maxSize);
|
||||
template<class T> bool readValue(T &val);
|
||||
|
||||
QFile _file;
|
||||
quint8 _key;
|
||||
int _blockSize;
|
||||
QCache<int, QByteArray> _blockCache;
|
||||
|
||||
TileTree _tileTree;
|
||||
|
||||
QString _name;
|
||||
RectC _bounds;
|
||||
QList<int> _bits;
|
||||
Style _style;
|
||||
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#endif // IMG_H
|
173
src/map/IMG/lblfile.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
#include <QTextCodec>
|
||||
#include "lblfile.h"
|
||||
|
||||
enum Charset {Normal, Symbol, Special};
|
||||
|
||||
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', '~', '~', '~', '~', '~',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', '~', '~', '~', '~', '~', '~'
|
||||
};
|
||||
|
||||
static quint8 SYMBOL_CHARS[] = {
|
||||
'@', '!', '"', '#', '$', '%', '&', '\'',
|
||||
'(', ')', '*', '+', ',', '-', '.', '/',
|
||||
'~', '~', '~', '~', '~', '~', '~', '~',
|
||||
'~', '~', ':', ';', '<', '=', '>', '?',
|
||||
'~', '~', '~', '~', '~', '~', '~', '~',
|
||||
'~', '~', '~', '[', '\\', ']', '^', '_'
|
||||
};
|
||||
|
||||
static quint8 SPECIAL_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', '~', '~', '~', '~', '~',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', '~', '~', '~', '~', '~', '~'
|
||||
};
|
||||
|
||||
static QString capitalize(const QString &str)
|
||||
{
|
||||
if (str.isEmpty())
|
||||
return str;
|
||||
for (int i = 0; i < str.size(); i++)
|
||||
if (str.at(i).isLetter() && !str.at(i).isUpper())
|
||||
return str;
|
||||
|
||||
QString ret(str);
|
||||
for (int i = 0; i < str.size(); i++)
|
||||
if (i && !str.at(i-1).isSpace())
|
||||
ret[i] = str.at(i).toLower();
|
||||
else
|
||||
ret[i] = str.at(i);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LBLFile::init()
|
||||
{
|
||||
Handle hdl;
|
||||
quint16 codepage;
|
||||
|
||||
if (!(seek(hdl, 0x15) && readUInt32(hdl, _offset)
|
||||
&& readUInt32(hdl, _size) && readByte(hdl, _multiplier)
|
||||
&& readByte(hdl, _encoding) && seek(hdl, 0x57)
|
||||
&& readUInt32(hdl, _poiOffset) && readUInt32(hdl, _poiSize)
|
||||
&& seek(hdl, 0xAA) && readUInt16(hdl, codepage)))
|
||||
return false;
|
||||
|
||||
_multiplier = 1<<_multiplier;
|
||||
|
||||
if (codepage == 65001)
|
||||
_codec = QTextCodec::codecForName("UTF-8");
|
||||
else if (codepage == 0)
|
||||
_codec = 0;
|
||||
else
|
||||
_codec = QTextCodec::codecForName(QString("CP%1").arg(codepage)
|
||||
.toLatin1());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString LBLFile::label6b(Handle &hdl, quint32 offset) const
|
||||
{
|
||||
QByteArray result;
|
||||
Charset curCharSet = Normal;
|
||||
quint8 b1, b2, b3;
|
||||
|
||||
if (!seek(hdl, offset))
|
||||
return QString();
|
||||
|
||||
while (true) {
|
||||
if (!(readByte(hdl, b1) && readByte(hdl, b2) && readByte(hdl, b3)))
|
||||
return QString();
|
||||
|
||||
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);
|
||||
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
|
||||
result.append(NORMAL_CHARS[c[cpt]]);
|
||||
break;
|
||||
case Symbol:
|
||||
result.append(SYMBOL_CHARS[c[cpt]]);
|
||||
curCharSet = Normal;
|
||||
break;
|
||||
case Special:
|
||||
result.append(SPECIAL_CHARS[c[cpt]]);
|
||||
curCharSet = Normal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString LBLFile::label8b(Handle &hdl, quint32 offset) const
|
||||
{
|
||||
QByteArray result;
|
||||
quint8 c;
|
||||
|
||||
if (!seek(hdl, offset))
|
||||
return QString();
|
||||
|
||||
while (true) {
|
||||
if (!readByte(hdl, c))
|
||||
return QString();
|
||||
if (!c)
|
||||
break;
|
||||
|
||||
if (c >= 0x1B && c <= 0x1F)
|
||||
result.append(' ');
|
||||
else if (c > 0x07)
|
||||
result.append(c);
|
||||
}
|
||||
|
||||
return _codec ? _codec->toUnicode(result) : QString::fromLatin1(result);
|
||||
}
|
||||
|
||||
QString LBLFile::label(Handle &hdl, quint32 offset, bool poi)
|
||||
{
|
||||
if (!_init) {
|
||||
if (!(_init = init()))
|
||||
return QString();
|
||||
}
|
||||
|
||||
quint32 labelOffset;
|
||||
if (poi) {
|
||||
quint32 poiOffset;
|
||||
if (!(seek(hdl, _poiOffset + offset) && readUInt24(hdl, poiOffset)))
|
||||
return QString();
|
||||
labelOffset = _offset + (poiOffset & 0x3FFFFF) * _multiplier;
|
||||
} else
|
||||
labelOffset = _offset + offset * _multiplier;
|
||||
|
||||
if (labelOffset > _offset + _size)
|
||||
return QString();
|
||||
|
||||
switch (_encoding) {
|
||||
case 6:
|
||||
return capitalize(label6b(hdl, labelOffset));
|
||||
case 9:
|
||||
case 10:
|
||||
return capitalize(label8b(hdl, labelOffset));
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
32
src/map/IMG/lblfile.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef LBLFILE_H
|
||||
#define LBLFILE_H
|
||||
|
||||
#include "subfile.h"
|
||||
|
||||
class QTextCodec;
|
||||
|
||||
class LBLFile : public SubFile
|
||||
{
|
||||
public:
|
||||
LBLFile(IMG *img, quint32 size) : SubFile(img, size), _init(false) {}
|
||||
|
||||
QString 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;
|
||||
|
||||
quint32 _offset;
|
||||
quint32 _size;
|
||||
quint32 _poiOffset;
|
||||
quint32 _poiSize;
|
||||
quint8 _multiplier;
|
||||
quint8 _encoding;
|
||||
QTextCodec *_codec;
|
||||
|
||||
bool _init;
|
||||
};
|
||||
|
||||
#endif // LBLFILE_H
|
30
src/map/IMG/netfile.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "netfile.h"
|
||||
|
||||
bool NETFile::init()
|
||||
{
|
||||
Handle hdl;
|
||||
|
||||
if (!(seek(hdl, 0x15) && readUInt32(hdl, _offset)
|
||||
&& readUInt32(hdl, _size) && readByte(hdl, _multiplier)))
|
||||
return false;
|
||||
|
||||
_multiplier = 1<<_multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NETFile::lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset)
|
||||
{
|
||||
if (!_init) {
|
||||
if (!(_init = init()))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(seek(hdl, _offset + netOffset * _multiplier)
|
||||
&& readUInt24(hdl, lblOffset)))
|
||||
return false;
|
||||
|
||||
lblOffset &= 0x3FFFFF;
|
||||
|
||||
return true;
|
||||
}
|
23
src/map/IMG/netfile.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef NETFILE_H
|
||||
#define NETFILE_H
|
||||
|
||||
#include "subfile.h"
|
||||
|
||||
class NETFile : public SubFile
|
||||
{
|
||||
public:
|
||||
NETFile(IMG *img, quint32 size) : SubFile(img, size), _init(false) {}
|
||||
|
||||
bool lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset);
|
||||
|
||||
private:
|
||||
bool init();
|
||||
|
||||
quint32 _offset;
|
||||
quint32 _size;
|
||||
quint8 _multiplier;
|
||||
|
||||
bool _init;
|
||||
};
|
||||
|
||||
#endif // NETFILE_H
|
516
src/map/IMG/rgnfile.cpp
Normal file
@ -0,0 +1,516 @@
|
||||
#include "trefile.h"
|
||||
#include "units.h"
|
||||
#include "lblfile.h"
|
||||
#include "netfile.h"
|
||||
#include "rgnfile.h"
|
||||
|
||||
|
||||
bool RGNFile::BitStream::read(int bits, quint32 &val)
|
||||
{
|
||||
val = 0;
|
||||
|
||||
for (int pos = 0; pos < bits; ) {
|
||||
if (!_remaining) {
|
||||
if (!_length || !_file.readByte(_hdl, _data))
|
||||
return false;
|
||||
_remaining = 8;
|
||||
_length--;
|
||||
}
|
||||
|
||||
quint32 get = bits - pos;
|
||||
if (get >= _remaining) {
|
||||
val |= _data << pos;
|
||||
pos += _remaining;
|
||||
_remaining = 0;
|
||||
} else {
|
||||
quint32 mask = (1<<get) - 1;
|
||||
val |= (_data & mask)<<pos;
|
||||
_data >>= get;
|
||||
_remaining -= get;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RGNFile::BitStream::readDelta(int bits, int sign, bool extraBit,
|
||||
qint32 &delta)
|
||||
{
|
||||
quint32 value;
|
||||
int bo = 0;
|
||||
|
||||
if (!read(bits, value))
|
||||
return false;
|
||||
|
||||
if (extraBit) {
|
||||
value>>=1;
|
||||
bo = 1;
|
||||
}
|
||||
|
||||
if (!sign) {
|
||||
qint32 signMask = 1 << (bits - bo - 1);
|
||||
if (value & signMask) {
|
||||
qint32 comp = value ^ signMask;
|
||||
if (comp)
|
||||
delta = comp - signMask;
|
||||
else {
|
||||
qint32 other;
|
||||
if (!readDelta(bits - bo, sign, false, other))
|
||||
return false;
|
||||
if (other < 0)
|
||||
delta = 1 - signMask + other;
|
||||
else
|
||||
delta = signMask - 1 + other;
|
||||
}
|
||||
} else {
|
||||
delta = value;
|
||||
}
|
||||
} else {
|
||||
delta = value * sign;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RGNFile::BitStream::finish()
|
||||
{
|
||||
while (_length--)
|
||||
if (!_file.readByte(_hdl, _data))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool RGNFile::init()
|
||||
{
|
||||
Handle hdl;
|
||||
|
||||
if (!(seek(hdl, 0x15) && readUInt32(hdl, _offset)
|
||||
&& readUInt32(hdl, _size) && readUInt32(hdl, _polygonsOffset)
|
||||
&& readUInt32(hdl, _polygonsSize) && seek(hdl, 0x39)
|
||||
&& readUInt32(hdl, _linesOffset) && readUInt32(hdl, _linesSize)
|
||||
&& seek(hdl, 0x55) && readUInt32(hdl, _pointsOffset)
|
||||
&& readUInt32(hdl, _pointsSize)))
|
||||
return false;
|
||||
|
||||
if (_offset + _size > size())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RGNFile::sign(BitStream &bs, int &val)
|
||||
{
|
||||
quint32 bit;
|
||||
val = 0;
|
||||
|
||||
if (!bs.read(1, bit))
|
||||
return false;
|
||||
if (bit) {
|
||||
if (!bs.read(1, bit))
|
||||
return false;
|
||||
val = bit ? -1 : 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int RGNFile::bitSize(quint8 baseSize, bool variableSign, bool extraBit)
|
||||
{
|
||||
int bits = 2;
|
||||
if (baseSize <= 9)
|
||||
bits += baseSize;
|
||||
else
|
||||
bits += 2 * baseSize - 9;
|
||||
|
||||
if (variableSign)
|
||||
bits++;
|
||||
if (extraBit)
|
||||
bits++;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net,
|
||||
Handle &netHdl, QList<IMG::Poly> *polys) const
|
||||
{
|
||||
if (segment.start() == segment.end())
|
||||
return true;
|
||||
|
||||
if (!seek(hdl, segment.start()))
|
||||
return false;
|
||||
|
||||
quint32 labelPtr;
|
||||
quint8 type, len8, bitstreamInfo;
|
||||
qint16 lon, lat;
|
||||
quint16 len;
|
||||
|
||||
while (hdl.pos < (int)segment.end()) {
|
||||
IMG::Poly poly;
|
||||
|
||||
if (!(readByte(hdl, type) && readUInt24(hdl, labelPtr)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
|
||||
return false;
|
||||
if (type & 0x80) {
|
||||
if (!readUInt16(hdl, len))
|
||||
return false;
|
||||
} else {
|
||||
if (!readByte(hdl, len8))
|
||||
return false;
|
||||
len = len8;
|
||||
}
|
||||
if (!readByte(hdl, bitstreamInfo))
|
||||
return false;
|
||||
|
||||
poly.type = (segment.type() == Segment::Polygon)
|
||||
? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8;
|
||||
|
||||
RectC br;
|
||||
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
||||
br = br.united(c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
|
||||
BitStream bs(*this, hdl, len);
|
||||
int lonSign, latSign;
|
||||
if (!sign(bs, lonSign) || !sign(bs, latSign))
|
||||
return false;
|
||||
bool extraBit = labelPtr & 0x400000;
|
||||
int lonBits = bitSize(bitstreamInfo & 0x0F, !lonSign, extraBit);
|
||||
int latBits = bitSize(bitstreamInfo >> 4, !latSign, false);
|
||||
|
||||
while (bs.hasNext(lonBits + latBits)) {
|
||||
qint32 lonDelta, latDelta;
|
||||
|
||||
if (!(bs.readDelta(lonBits, lonSign, extraBit, lonDelta)
|
||||
&& bs.readDelta(latBits, latSign, false, latDelta)))
|
||||
return false;
|
||||
|
||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||
|
||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
br = br.united(c);
|
||||
}
|
||||
if (!bs.finish())
|
||||
return false;
|
||||
|
||||
if (!rect.intersects(br))
|
||||
continue;
|
||||
|
||||
if (lbl && (labelPtr & 0x3FFFFF)) {
|
||||
if (labelPtr & 0x800000) {
|
||||
quint32 lblOff;
|
||||
if (net && net->lblOffset(netHdl, labelPtr & 0x3FFFFF, lblOff))
|
||||
poly.label = lbl->label(lblHdl, lblOff);
|
||||
} else
|
||||
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
|
||||
}
|
||||
|
||||
polys->append(poly);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
||||
const SubDiv *subdiv, const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Poly> *polys) const
|
||||
{
|
||||
quint32 labelPtr;
|
||||
quint8 type, subtype, len8, len82, bitstreamInfo;
|
||||
qint16 lon, lat;
|
||||
quint16 len;
|
||||
|
||||
|
||||
if (!seek(hdl, segment.start()))
|
||||
return false;
|
||||
|
||||
while (hdl.pos < (int)segment.end()) {
|
||||
IMG::Poly poly;
|
||||
|
||||
if (!(readByte(hdl, type) && readByte(hdl, subtype)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat) && readByte(hdl, len8)))
|
||||
return false;
|
||||
|
||||
if (subtype & 0x80) {
|
||||
qWarning("Polygons/lines with extra bytes not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len8 & 0x01)
|
||||
len = (len8>>1) - 1;
|
||||
else {
|
||||
if (!readByte(hdl, len82))
|
||||
return false;
|
||||
len = ((len8 | ((quint16)len82<<8))>>2) - 1;
|
||||
}
|
||||
if (!readByte(hdl, bitstreamInfo))
|
||||
return false;
|
||||
poly.type = 0x10000 + (quint16(type) << 8) + (subtype & 0x1F);
|
||||
|
||||
RectC br;
|
||||
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
||||
br = br.united(c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
|
||||
BitStream bs(*this, hdl, len);
|
||||
int lonSign, latSign;
|
||||
if (!sign(bs, lonSign) || !sign(bs, latSign))
|
||||
return false;
|
||||
quint32 extraBit;
|
||||
bs.read(1, extraBit);
|
||||
int lonBits = bitSize(bitstreamInfo & 0x0F, !lonSign, extraBit);
|
||||
int latBits = bitSize(bitstreamInfo >> 4, !latSign, extraBit);
|
||||
|
||||
while (bs.hasNext(lonBits + latBits)) {
|
||||
qint32 lonDelta, latDelta;
|
||||
|
||||
if (!(bs.readDelta(lonBits, lonSign, false, lonDelta)
|
||||
&& bs.readDelta(latBits, latSign, false, latDelta)))
|
||||
return false;
|
||||
|
||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||
|
||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
br = br.united(c);
|
||||
}
|
||||
if (!bs.finish())
|
||||
return false;
|
||||
|
||||
if (subtype & 0x20) {
|
||||
if (!readUInt24(hdl, labelPtr))
|
||||
return false;
|
||||
if (lbl)
|
||||
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
|
||||
}
|
||||
|
||||
if (!rect.intersects(br))
|
||||
continue;
|
||||
|
||||
polys->append(poly);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Point> *points) const
|
||||
{
|
||||
quint8 type, subtype;
|
||||
qint16 lon, lat;
|
||||
quint32 labelPtr;
|
||||
|
||||
if (!seek(hdl, segment.start()))
|
||||
return false;
|
||||
|
||||
while (hdl.pos < (int)segment.end()) {
|
||||
IMG::Point point;
|
||||
|
||||
if (!(readByte(hdl, type) && readUInt24(hdl, labelPtr)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
|
||||
return false;
|
||||
if (labelPtr & 0x800000) {
|
||||
if (!readByte(hdl, subtype))
|
||||
return false;
|
||||
} else
|
||||
subtype = 0;
|
||||
|
||||
point.type = (quint16)type<<8 | subtype;
|
||||
|
||||
qint16 lonOffset = lon<<(24-subdiv->bits());
|
||||
qint16 latOffset = lat<<(24-subdiv->bits());
|
||||
point.coordinates = Coordinates(toWGS84(subdiv->lon() + lonOffset),
|
||||
toWGS84(subdiv->lat() + latOffset));
|
||||
|
||||
if (!rect.contains(point.coordinates))
|
||||
continue;
|
||||
|
||||
point.poi = labelPtr & 0x400000;
|
||||
if (lbl && (labelPtr & 0x3FFFFF)) {
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
||||
point.id = ((quint64)lbl->offset())<<24 | (labelPtr & 0x3FFFFF);
|
||||
}
|
||||
|
||||
points->append(point);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
|
||||
const SubDiv *subdiv, const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Point> *points) const
|
||||
{
|
||||
quint8 type, subtype;
|
||||
qint16 lon, lat;
|
||||
quint32 labelPtr;
|
||||
|
||||
if (!seek(hdl, segment.start()))
|
||||
return false;
|
||||
|
||||
while (hdl.pos < (int)segment.end()) {
|
||||
IMG::Point point;
|
||||
|
||||
if (!(readByte(hdl, type) && readByte(hdl, subtype)
|
||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
|
||||
return false;
|
||||
|
||||
if (subtype & 0x80) {
|
||||
qWarning("Points with extra bytes not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F);
|
||||
|
||||
qint16 lonOffset = lon<<(24-subdiv->bits());
|
||||
qint16 latOffset = lat<<(24-subdiv->bits());
|
||||
point.coordinates = Coordinates(toWGS84(subdiv->lon() + lonOffset),
|
||||
toWGS84(subdiv->lat() + latOffset));
|
||||
|
||||
if (subtype & 0x20) {
|
||||
if (!readUInt24(hdl, labelPtr))
|
||||
return false;
|
||||
point.poi = labelPtr & 0x400000;
|
||||
if (lbl && (labelPtr & 0x3FFFFF)) {
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
||||
point.id = ((quint64)lbl->offset())<<24 | (labelPtr & 0x3FFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
if (rect.contains(point.coordinates))
|
||||
points->append(point);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void RGNFile::objects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
|
||||
NETFile *net, QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
||||
QList<IMG::Point> *points)
|
||||
{
|
||||
Handle rgnHdl, lblHdl, netHdl;
|
||||
|
||||
if (!_init) {
|
||||
if (!(_init = init()))
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<RGNFile::Segment> seg(segments(rgnHdl, subdiv));
|
||||
for (int i = 0; i < seg.size(); i++) {
|
||||
switch (seg.at(i).type()) {
|
||||
case Segment::Point:
|
||||
case Segment::IndexedPoint:
|
||||
if (points)
|
||||
pointObjects(rect, rgnHdl, subdiv, seg.at(i), lbl, lblHdl,
|
||||
points);
|
||||
break;
|
||||
case Segment::Line:
|
||||
if (lines)
|
||||
polyObjects(rect, rgnHdl, subdiv, seg.at(i), lbl, lblHdl,
|
||||
net, netHdl, lines);
|
||||
break;
|
||||
case Segment::Polygon:
|
||||
if (polygons)
|
||||
polyObjects(rect, rgnHdl, subdiv, seg.at(i), lbl, lblHdl,
|
||||
net, netHdl, polygons);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RGNFile::extObjects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
|
||||
QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
||||
QList<IMG::Point> *points)
|
||||
{
|
||||
Handle rgnHdl, lblHdl;
|
||||
|
||||
if (!_init) {
|
||||
if (!(_init = init()))
|
||||
return;
|
||||
}
|
||||
|
||||
if (polygons && subdiv->polygonsOffset() != subdiv->polygonsEnd()) {
|
||||
quint32 start = _polygonsOffset + subdiv->polygonsOffset();
|
||||
quint32 end = subdiv->polygonsEnd()
|
||||
? _polygonsOffset + subdiv->polygonsEnd()
|
||||
: _polygonsOffset + _polygonsSize;
|
||||
extPolyObjects(rect, rgnHdl, subdiv, Segment(start, end,
|
||||
Segment::Polygon), lbl, lblHdl, polygons);
|
||||
}
|
||||
if (lines && subdiv->linesOffset() != subdiv->linesEnd()) {
|
||||
quint32 start = _linesOffset + subdiv->linesOffset();
|
||||
quint32 end = subdiv->linesEnd()
|
||||
? _linesOffset + subdiv->linesEnd()
|
||||
: _linesOffset + _linesSize;
|
||||
extPolyObjects(rect, rgnHdl, subdiv, Segment(start, end, Segment::Line),
|
||||
lbl, lblHdl, lines);
|
||||
}
|
||||
if (points && subdiv->pointsOffset() != subdiv->pointsEnd()) {
|
||||
quint32 start = _pointsOffset + subdiv->pointsOffset();
|
||||
quint32 end = subdiv->pointsEnd()
|
||||
? _pointsOffset + subdiv->pointsEnd()
|
||||
: _pointsOffset + _linesSize;
|
||||
extPointObjects(rect, rgnHdl, subdiv, Segment(start, end,
|
||||
Segment::Point), lbl, lblHdl, points);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<RGNFile::Segment> RGNFile::segments(Handle &hdl, const SubDiv *subdiv)
|
||||
const
|
||||
{
|
||||
if (subdiv->offset() == subdiv->end() || !(subdiv->objects() & 0xF0))
|
||||
return QVector<Segment>();
|
||||
|
||||
quint32 offset = _offset + subdiv->offset();
|
||||
|
||||
int no = 0;
|
||||
for (quint8 mask = 0x10; mask; mask <<= 1)
|
||||
if (subdiv->objects() & mask)
|
||||
no++;
|
||||
|
||||
if (!seek(hdl, offset))
|
||||
return QVector<Segment>();
|
||||
|
||||
QVector<Segment> ret;
|
||||
quint32 start = offset + 2 * (no - 1);
|
||||
quint16 po;
|
||||
int cnt = 0;
|
||||
|
||||
for (quint8 mask = 0x10; mask; mask <<= 1) {
|
||||
if (subdiv->objects() & mask) {
|
||||
if (cnt) {
|
||||
if (!readUInt16(hdl, po))
|
||||
return QVector<Segment>();
|
||||
start = offset + po;
|
||||
}
|
||||
if (!ret.isEmpty())
|
||||
ret.last().setEnd(start);
|
||||
ret.append(Segment(start, (Segment::Type)mask));
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
ret.last().setEnd(subdiv->end() ? _offset + subdiv->end() : _offset + _size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment)
|
||||
{
|
||||
dbg.nospace() << "Segment(" << segment.start() << ", " << segment.end()
|
||||
<< ", " << segment.type() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
107
src/map/IMG/rgnfile.h
Normal file
@ -0,0 +1,107 @@
|
||||
#ifndef RGNFILE_H
|
||||
#define RGNFILE_H
|
||||
|
||||
#include "img.h"
|
||||
#include "subfile.h"
|
||||
#include "subdiv.h"
|
||||
|
||||
class LBLFile;
|
||||
class NETFile;
|
||||
|
||||
class RGNFile : public SubFile
|
||||
{
|
||||
public:
|
||||
RGNFile(IMG *img, quint32 size) : SubFile(img, size), _init(false) {}
|
||||
|
||||
void objects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
|
||||
NETFile *net, QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
||||
QList<IMG::Point> *points);
|
||||
void extObjects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
|
||||
QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
||||
QList<IMG::Point> *points);
|
||||
|
||||
private:
|
||||
class Segment {
|
||||
public:
|
||||
enum Type {
|
||||
Point = 0x10,
|
||||
IndexedPoint = 0x20,
|
||||
Line = 0x40,
|
||||
Polygon = 0x80
|
||||
};
|
||||
|
||||
Segment() : _start(0), _end(0), _type(Point) {}
|
||||
Segment(quint32 start, Type type)
|
||||
: _start(start), _end(0), _type(type) {}
|
||||
Segment(quint32 start, quint32 end, Type type)
|
||||
: _start(start), _end(end), _type(type) {}
|
||||
|
||||
void setEnd(quint32 end) {_end = end;}
|
||||
|
||||
quint32 start() const {return _start;}
|
||||
quint32 end() const {return _end;}
|
||||
Type type() const {return _type;}
|
||||
|
||||
private:
|
||||
quint32 _start;
|
||||
quint32 _end;
|
||||
Type _type;
|
||||
};
|
||||
|
||||
class BitStream {
|
||||
public:
|
||||
BitStream(const SubFile &file, Handle &hdl, quint16 length)
|
||||
: _file(file), _hdl(hdl), _length(length), _remaining(0) {}
|
||||
|
||||
bool read(int bits, quint32 &val);
|
||||
bool readDelta(int bits, int sign, bool extraBit, qint32 &delta);
|
||||
bool hasNext(int bits) const
|
||||
{return _length * 8 + _remaining >= (quint32)bits;}
|
||||
bool finish();
|
||||
|
||||
private:
|
||||
const SubFile &_file;
|
||||
Handle &_hdl;
|
||||
quint16 _length;
|
||||
quint32 _remaining;
|
||||
quint8 _data;
|
||||
};
|
||||
|
||||
static bool sign(BitStream &bs, int &val);
|
||||
static int bitSize(quint8 baseSize, bool variableSign, bool extraBit);
|
||||
|
||||
bool init();
|
||||
QVector<Segment> segments(Handle &hdl, const SubDiv *subdiv) const;
|
||||
bool polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net,
|
||||
Handle &netHdl, QList<IMG::Poly> *polys) const;
|
||||
bool pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Point> *points) const;
|
||||
bool extPolyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Poly> *polys) const;
|
||||
bool extPointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
||||
QList<IMG::Point> *points) const;
|
||||
|
||||
friend QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment);
|
||||
|
||||
quint32 _offset;
|
||||
quint32 _size;
|
||||
|
||||
quint32 _polygonsOffset;
|
||||
quint32 _polygonsSize;
|
||||
quint32 _linesOffset;
|
||||
quint32 _linesSize;
|
||||
quint32 _pointsOffset;
|
||||
quint32 _pointsSize;
|
||||
|
||||
bool _init;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // RGNFILE_H
|
857
src/map/IMG/style.cpp
Normal file
@ -0,0 +1,857 @@
|
||||
#include <QImage>
|
||||
#include "style.h"
|
||||
|
||||
#define TYPE(t) ((t)<<8)
|
||||
|
||||
void Style::defaultPolygonStyle()
|
||||
{
|
||||
_polygons[TYPE(0x01)] = Style::Polygon(QBrush("#dfd3b5"));
|
||||
_polygons[TYPE(0x02)] = Style::Polygon(QBrush("#dfd3b5"));
|
||||
_polygons[TYPE(0x03)] = Style::Polygon(QBrush("#dfd3b5"));
|
||||
_polygons[TYPE(0x04)] = Style::Polygon(QBrush("#ff4040", Qt::BDiagPattern));
|
||||
_polygons[TYPE(0x05)] = Style::Polygon(QBrush("#d6d4ce"));
|
||||
_polygons[TYPE(0x06)] = Style::Polygon(QBrush("#d6d4ce"));
|
||||
_polygons[TYPE(0x07)] = Style::Polygon(QBrush("#d6d4ce"));
|
||||
_polygons[TYPE(0x08)] = Style::Polygon(QBrush("#d6d4ce"));
|
||||
_polygons[TYPE(0x09)] = Style::Polygon(QBrush("#d6d4ce"));
|
||||
_polygons[TYPE(0x0a)] = Style::Polygon(QBrush("#d6d4ce"));
|
||||
_polygons[TYPE(0x0b)] = Style::Polygon(QBrush("#d6d4ce"));
|
||||
_polygons[TYPE(0x0c)] = Style::Polygon(QBrush("#d6d4ce"));
|
||||
_polygons[TYPE(0x0d)] = Style::Polygon(QBrush("#f8e3be"));
|
||||
_polygons[TYPE(0x0e)] = Style::Polygon(QBrush("#ffffff"));
|
||||
_polygons[TYPE(0x0f)] = Style::Polygon(QBrush("#e6e2d9"));
|
||||
_polygons[TYPE(0x10)] = Style::Polygon(QBrush("#e6e2d9"));
|
||||
_polygons[TYPE(0x11)] = Style::Polygon(QBrush("#e6e2d9"));
|
||||
_polygons[TYPE(0x12)] = Style::Polygon(QBrush("#e6e2d9"));
|
||||
_polygons[TYPE(0x13)] = Style::Polygon(QBrush("#dbd0b6"),
|
||||
QPen(QColor("#cdccc4"), 1));
|
||||
_polygons[TYPE(0x14)] = Style::Polygon(QBrush(QColor("#9ac269"),
|
||||
Qt::BDiagPattern));
|
||||
_polygons[TYPE(0x15)] = Style::Polygon(QBrush(QColor("#9ac269"),
|
||||
Qt::BDiagPattern));
|
||||
_polygons[TYPE(0x16)] = Style::Polygon(QBrush(QColor("#9ac269"),
|
||||
Qt::BDiagPattern));
|
||||
_polygons[TYPE(0x17)] = Style::Polygon(QBrush("#d4ebb8"));
|
||||
_polygons[TYPE(0x18)] = Style::Polygon(QBrush("#d4ebb8"));
|
||||
_polygons[TYPE(0x19)] = Style::Polygon(QBrush("#d6d4ce"));
|
||||
_polygons[TYPE(0x1a)] = Style::Polygon(QBrush("#000000", Qt::Dense6Pattern),
|
||||
QPen(QColor("#cdccc4"), 1));
|
||||
_polygons[TYPE(0x1e)] = Style::Polygon(QBrush(QColor("#9ac269"),
|
||||
Qt::BDiagPattern));
|
||||
_polygons[TYPE(0x1f)] = Style::Polygon(QBrush(QColor("#9ac269"),
|
||||
Qt::BDiagPattern));
|
||||
_polygons[TYPE(0x28)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x29)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x32)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x3b)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x3c)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x3d)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x3e)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x3f)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x40)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x41)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x42)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x43)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x44)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x45)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x46)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x47)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x48)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x49)] = Style::Polygon(QBrush("#9fc4e1"));
|
||||
_polygons[TYPE(0x4b)] = Style::Polygon(QBrush("#f1f0e5"), QPen("#f1f0e5"));
|
||||
_polygons[TYPE(0x4a)] = Style::Polygon(QBrush("#f1f0e5"), QPen("#f1f0e5"));
|
||||
_polygons[TYPE(0x4c)] = Style::Polygon(QBrush("#9fc4e1", Qt::Dense6Pattern));
|
||||
_polygons[TYPE(0x4d)] = Style::Polygon(QBrush("#ddf1fd"));
|
||||
_polygons[TYPE(0x4e)] = Style::Polygon(QBrush("#e3edc1"));
|
||||
_polygons[TYPE(0x4f)] = Style::Polygon(QBrush("#d4ebb8"));
|
||||
_polygons[TYPE(0x50)] = Style::Polygon(QBrush("#d4ebb8"));
|
||||
_polygons[TYPE(0x51)] = Style::Polygon(QBrush("#9fc4e1", Qt::Dense4Pattern));
|
||||
_polygons[TYPE(0x52)] = Style::Polygon(QBrush("#d4ebb8"));
|
||||
|
||||
_drawOrder << TYPE(0x4b) << TYPE(0x4a) << TYPE(0x01) << TYPE(0x02)
|
||||
<< TYPE(0x03) << TYPE(0x17) << TYPE(0x18) << TYPE(0x19) << TYPE(0x1a)
|
||||
<< TYPE(0x28) << TYPE(0x29) << TYPE(0x32) << TYPE(0x3b) << TYPE(0x3c)
|
||||
<< TYPE(0x3d) << TYPE(0x3e) << TYPE(0x3f) << TYPE(0x40) << TYPE(0x41)
|
||||
<< TYPE(0x42) << TYPE(0x43) << TYPE(0x44) << TYPE(0x45) << TYPE(0x46)
|
||||
<< TYPE(0x47) << TYPE(0x48) << TYPE(0x49) << TYPE(0x4c) << TYPE(0x4d)
|
||||
<< TYPE(0x4e) << TYPE(0x4f) << TYPE(0x50) << TYPE(0x51) << TYPE(0x52)
|
||||
<< TYPE(0x14) << TYPE(0x15) << TYPE(0x1e) << TYPE(0x1f) << TYPE(0x04)
|
||||
<< TYPE(0x05) << TYPE(0x06) << TYPE(0x07) << TYPE(0x08) << TYPE(0x09)
|
||||
<< TYPE(0x0a) << TYPE(0x0b) << TYPE(0x0c) << TYPE(0x0d) << TYPE(0x0e)
|
||||
<< TYPE(0x0f) << TYPE(0x10) << TYPE(0x11) << TYPE(0x12) << TYPE(0x13);
|
||||
}
|
||||
|
||||
void Style::defaultLineStyle()
|
||||
{
|
||||
QVector<qreal> pattern;
|
||||
pattern << 4 << 4;
|
||||
QPen rr(QColor("#717171"), 3, Qt::CustomDashLine);
|
||||
rr.setDashPattern(pattern);
|
||||
|
||||
_lines[TYPE(0x01)] = Style::Line(QPen(QColor("#9bd772"), 2, Qt::SolidLine),
|
||||
QPen(QColor("#72a35a"), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x02)] = Style::Line(QPen(QColor("#ffcc78"), 2, Qt::SolidLine),
|
||||
QPen(QColor("#e8a541"), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x03)] = Style::Line(QPen(QColor("#ffcc78"), 2, Qt::SolidLine),
|
||||
QPen(QColor("#e8a541"), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x04)] = Style::Line(QPen(QColor("#faef75"), 3, Qt::SolidLine),
|
||||
QPen(QColor("#dbd27b"), 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x05)] = Style::Line(QPen(QColor("#ffffff"), 3, Qt::SolidLine),
|
||||
QPen(QColor("#d5cdc0"), 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x06)] = Style::Line(QPen(QColor("#ffffff"), 3, Qt::SolidLine),
|
||||
QPen(QColor("#d5cdc0"), 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x07)] = Style::Line(QPen(QColor("#ffffff"), 2, Qt::SolidLine),
|
||||
QPen(QColor("#d5cdc0"), 4, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x08)] = Style::Line(QPen(QColor("#ffcc78"), 2, Qt::SolidLine),
|
||||
QPen(QColor("#e8a541"), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x09)] = Style::Line(QPen(QColor("#9bd772"), 2, Qt::SolidLine),
|
||||
QPen(QColor("#72a35a"), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x0a)] = Style::Line(QPen(QColor("#aba083"), 1, Qt::DashLine));
|
||||
_lines[TYPE(0x0b)] = Style::Line(QPen(QColor("#ffcc78"), 2, Qt::SolidLine),
|
||||
QPen(QColor("#e8a541"), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x0c)] = Style::Line(QPen(QColor("#ffffff"), 3, Qt::SolidLine),
|
||||
QPen(QColor("#d5cdc0"), 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x14)] = Style::Line(rr, QPen(Qt::white, 3, Qt::SolidLine,
|
||||
Qt::RoundCap, Qt::RoundJoin));
|
||||
_lines[TYPE(0x16)] = Style::Line(QPen(QColor("#aba083"), 1, Qt::DotLine));
|
||||
_lines[TYPE(0x18)] = Style::Line(QPen(QColor("#9fc4e1"), 2, Qt::SolidLine));
|
||||
_lines[TYPE(0x18)].setTextColor(QColor("#9fc4e1"));
|
||||
//_lines[TYPE(0x1a)] = Style::Line(QPen(QColor("#7697b7"), 1, Qt::DashLine));
|
||||
_lines[TYPE(0x1b)] = Style::Line(QPen(QColor("#7697b7"), 1, Qt::DashLine));
|
||||
_lines[TYPE(0x1e)] = Style::Line(QPen(QColor("#505145"), 2, Qt::DashDotLine));
|
||||
_lines[TYPE(0x1f)] = Style::Line(QPen(QColor("#9fc4e1"), 3, Qt::SolidLine));
|
||||
_lines[TYPE(0x1f)].setTextColor(QColor("#9fc4e1"));
|
||||
_lines[TYPE(0x20)] = Style::Line(QPen(QColor("#cacfc0"), 1, Qt::SolidLine));
|
||||
_lines[TYPE(0x20)].setTextColor(QColor("#62695a"));
|
||||
_lines[TYPE(0x20)].setTextFontSize(Style::Small);
|
||||
_lines[TYPE(0x21)] = Style::Line(QPen(QColor("#cacfc0"), 1.5, Qt::SolidLine));
|
||||
_lines[TYPE(0x21)].setTextColor(QColor("#62695a"));
|
||||
_lines[TYPE(0x21)].setTextFontSize(Style::Small);
|
||||
_lines[TYPE(0x22)] = Style::Line(QPen(QColor("#cacfc0"), 2, Qt::SolidLine));
|
||||
_lines[TYPE(0x22)].setTextColor(QColor("#62695a"));
|
||||
_lines[TYPE(0x22)].setTextFontSize(Style::Small);
|
||||
_lines[TYPE(0x23)] = Style::Line(QPen(QColor("#55aaff"), 1, Qt::SolidLine));
|
||||
_lines[TYPE(0x23)].setTextColor(QColor("#55aaff"));
|
||||
_lines[TYPE(0x23)].setTextFontSize(Style::Small);
|
||||
_lines[TYPE(0x24)] = Style::Line(QPen(QColor("#55aaff"), 1.5, Qt::SolidLine));
|
||||
_lines[TYPE(0x24)].setTextColor(QColor("#55aaff"));
|
||||
_lines[TYPE(0x24)].setTextFontSize(Style::Small);
|
||||
_lines[TYPE(0x25)] = Style::Line(QPen(QColor("#55aaff"), 2, Qt::SolidLine));
|
||||
_lines[TYPE(0x25)].setTextColor(QColor("#55aaff"));
|
||||
_lines[TYPE(0x25)].setTextFontSize(Style::Small);
|
||||
_lines[TYPE(0x26)] = Style::Line(QPen(QColor("#9fc4e1"), 2, Qt::DotLine));
|
||||
_lines[TYPE(0x27)] = Style::Line(QPen(QColor("#ffffff"), 4, Qt::SolidLine),
|
||||
QPen(QColor("#d5cdc0"), 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
|
||||
//_lines[TYPE(0x28)] = Style::Line(QPen(QColor("#5a5a5a"), 1, Qt::SolidLine));
|
||||
_lines[TYPE(0x29)] = Style::Line(QPen(QColor("#5a5a5a"), 1, Qt::SolidLine));
|
||||
_lines[TYPE(0x29)].setTextFontSize(Style::None);
|
||||
}
|
||||
|
||||
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 skipLocalization(SubFile *file, SubFile::Handle &hdl)
|
||||
{
|
||||
quint8 t8;
|
||||
quint16 len;
|
||||
|
||||
if (!file->readByte(hdl, t8))
|
||||
return false;
|
||||
len = t8;
|
||||
|
||||
if (len & 0x01)
|
||||
len = len >> 1;
|
||||
else {
|
||||
if (!file->readByte(hdl, t8))
|
||||
return false;
|
||||
len = (((quint16)t8) << 8) | len;
|
||||
len = len >> 2;
|
||||
}
|
||||
|
||||
if (!file->seek(hdl, hdl.pos + len))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Style::itemInfo(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion, ItemInfo &info)
|
||||
{
|
||||
quint16 t16_1, t16_2;
|
||||
quint8 t8;
|
||||
|
||||
if (section.arrayItemSize == 5) {
|
||||
if (!(file->readUInt16(hdl, t16_1) && file->readUInt16(hdl, t16_2)
|
||||
&& file->readByte(hdl, t8)))
|
||||
return false;
|
||||
info.offset = t16_2 | (t8<<16);
|
||||
} else if (section.arrayItemSize == 4) {
|
||||
if (!(file->readUInt16(hdl, t16_1) && file->readUInt16(hdl, t16_2)))
|
||||
return false;
|
||||
info.offset = t16_2;
|
||||
} else if (section.arrayItemSize == 3) {
|
||||
if (!(file->readUInt16(hdl, t16_1) && file->readByte(hdl, t8)))
|
||||
return false;
|
||||
info.offset = t8;
|
||||
} else
|
||||
return false;
|
||||
|
||||
t16_2 = (t16_1 >> 5) | (( t16_1 & 0x1f) << 11);
|
||||
info.type = t16_2 & 0x7F;
|
||||
info.subtype = t16_1 & 0x1F;
|
||||
info.extended = t16_1 & 0x2000;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::parsePolygons(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion)
|
||||
{
|
||||
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)))
|
||||
return false;
|
||||
flags = t8 & 0x0F;
|
||||
|
||||
QColor c1, c2, c3, c4;
|
||||
QImage img(32, 32, QImage::Format_Indexed8);
|
||||
|
||||
switch (flags) {
|
||||
case 0x01:
|
||||
if (!(readColor(file, hdl, c1) && readColor(file, hdl, c2)
|
||||
&& readColor(file, hdl, c3) && readColor(file, hdl, c4)))
|
||||
return false;
|
||||
_polygons[type] = Style::Polygon(QBrush(c1), QPen(c3, 2));
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
if (!readColor(file, hdl, c1))
|
||||
return false;
|
||||
_polygons[type] = Style::Polygon(QBrush(c1));
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
if (!(readColor(file, hdl, c1) && readColor(file, hdl, c2)))
|
||||
return false;
|
||||
|
||||
img.setColorCount(2);
|
||||
img.setColor(0, c2.rgb());
|
||||
img.setColor(1, c1.rgb());
|
||||
if (!readBitmap(file, hdl, img, 1))
|
||||
return false;
|
||||
|
||||
_polygons[type] = Style::Polygon(QBrush(img));
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
if (!(readColor(file, hdl, c1) && readColor(file, hdl, c2)
|
||||
&& readColor(file, hdl, c3) && readColor(file, hdl, c4)))
|
||||
return false;
|
||||
|
||||
img.setColorCount(2);
|
||||
img.setColor(0, c2.rgb());
|
||||
img.setColor(1, c1.rgb());
|
||||
if (!readBitmap(file, hdl, img, 1))
|
||||
return false;
|
||||
|
||||
_polygons[type] = Style::Polygon(QBrush(img));
|
||||
break;
|
||||
|
||||
case 0x0B:
|
||||
case 0x0D:
|
||||
if (!(readColor(file, hdl, c1) && readColor(file, hdl, c2)
|
||||
&& readColor(file, hdl, c3)))
|
||||
return false;
|
||||
|
||||
img.setColorCount(2);
|
||||
img.setColor(0, (flags == 0x0B) ? qRgba(255, 255, 255, 0)
|
||||
: c2.rgb());
|
||||
img.setColor(1, c1.rgb());
|
||||
if (!readBitmap(file, hdl, img, 1))
|
||||
return false;
|
||||
|
||||
_polygons[type] = Style::Polygon(QBrush(img));
|
||||
break;
|
||||
|
||||
case 0x0E:
|
||||
if (!readColor(file, hdl, c1))
|
||||
return false;
|
||||
|
||||
img.setColorCount(2);
|
||||
img.setColor(0, qRgba(255, 255, 255, 0));
|
||||
img.setColor(1, c1.rgb());
|
||||
if (!readBitmap(file, hdl, img, 1))
|
||||
return false;
|
||||
|
||||
_polygons[type] = Style::Polygon(QBrush(img));
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
if (!(readColor(file, hdl, c1) && readColor(file, hdl, c2)))
|
||||
return false;
|
||||
|
||||
img.setColorCount(2);
|
||||
img.setColor(0, qRgba(255, 255, 255, 0));
|
||||
img.setColor(1, c1.rgb());
|
||||
if (!readBitmap(file, hdl, img, 1))
|
||||
return false;
|
||||
|
||||
_polygons[type] = Style::Polygon(QBrush(img));
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion)
|
||||
{
|
||||
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)))
|
||||
return false;
|
||||
flags = t8_1 & 0x07;
|
||||
rows = t8_1 >> 3;
|
||||
bool localization = t8_2 & 0x01;
|
||||
bool textColor = t8_2 & 0x04;
|
||||
|
||||
QColor c1, c2, c3, c4;
|
||||
quint8 w1, w2;
|
||||
|
||||
switch (flags) {
|
||||
case 0x00:
|
||||
if (!(readColor(file, hdl, c1) && readColor(file, hdl, c2)))
|
||||
return false;
|
||||
|
||||
if (rows) {
|
||||
QImage img(32, rows, QImage::Format_Indexed8);
|
||||
img.setColorCount(2);
|
||||
img.setColor(0, c2.rgb());
|
||||
img.setColor(1, c1.rgb());
|
||||
if (!readBitmap(file, hdl, img, 1))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!(file->readByte(hdl, w1) && file->readByte(hdl, w2)))
|
||||
return false;
|
||||
|
||||
_lines[type] = (w2 > w1)
|
||||
? Style::Line(QPen(c1, w1, Qt::SolidLine, Qt::RoundCap,
|
||||
Qt::RoundJoin), QPen(c2, w2, Qt::SolidLine, Qt::RoundCap,
|
||||
Qt::RoundJoin))
|
||||
: Style::Line(QPen(c1, w1, Qt::SolidLine, Qt::RoundCap,
|
||||
Qt::RoundJoin));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
if (!(readColor(file, hdl, c1) && readColor(file, hdl, c2)
|
||||
&& readColor(file, hdl, c3) && readColor(file, hdl, c4)))
|
||||
return false;
|
||||
|
||||
if (rows) {
|
||||
QImage img(32, rows, QImage::Format_Indexed8);
|
||||
img.setColorCount(2);
|
||||
img.setColor(0, c2.rgb());
|
||||
img.setColor(1, c1.rgb());
|
||||
if (!readBitmap(file, hdl, img, 1))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!(file->readByte(hdl, w1) && file->readByte(hdl, w2)))
|
||||
return false;
|
||||
|
||||
_lines[type] = (w2 > w1)
|
||||
? Style::Line(QPen(c1, w1, Qt::SolidLine, Qt::RoundCap,
|
||||
Qt::RoundJoin), QPen(c2, w2, Qt::SolidLine, Qt::RoundCap,
|
||||
Qt::RoundJoin))
|
||||
: Style::Line(QPen(c1, w1, Qt::SolidLine, Qt::RoundCap,
|
||||
Qt::RoundJoin));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
if (!(readColor(file, hdl, c1) && readColor(file, hdl, c2)
|
||||
&& readColor(file, hdl, c3)))
|
||||
return false;
|
||||
|
||||
if (rows) {
|
||||
QImage img(32, rows, QImage::Format_Indexed8);
|
||||
img.setColorCount(2);
|
||||
img.setColor(0, qRgba(255, 255, 255, 0));
|
||||
img.setColor(1, c1.rgb());
|
||||
if (!readBitmap(file, hdl, img, 1))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!(file->readByte(hdl, w1) && file->readByte(hdl, w2)))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(QPen(c1, w1, Qt::SolidLine,
|
||||
Qt::RoundCap, Qt::RoundJoin));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
if (!(readColor(file, hdl, c1) && readColor(file, hdl, c2)
|
||||
&& readColor(file, hdl, c3)))
|
||||
return false;
|
||||
|
||||
if (rows) {
|
||||
QImage img(32, rows, QImage::Format_Indexed8);
|
||||
img.setColorCount(2);
|
||||
img.setColor(0, c2.rgb());
|
||||
img.setColor(1, c1.rgb());
|
||||
if (!readBitmap(file, hdl, img, 1))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!(file->readByte(hdl, w1) && file->readByte(hdl, w2)))
|
||||
return false;
|
||||
|
||||
_lines[type] = (w2 > w1)
|
||||
? Style::Line(QPen(c1, w1, Qt::SolidLine, Qt::RoundCap,
|
||||
Qt::RoundJoin), QPen(c2, w2, Qt::SolidLine, Qt::RoundCap,
|
||||
Qt::RoundJoin))
|
||||
: Style::Line(QPen(c1, w1, Qt::SolidLine, Qt::RoundCap,
|
||||
Qt::RoundJoin));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
if (!readColor(file, hdl, c1))
|
||||
return false;
|
||||
|
||||
if (rows) {
|
||||
QImage img(32, rows, QImage::Format_Indexed8);
|
||||
img.setColorCount(2);
|
||||
img.setColor(0, qRgba(255, 255, 255, 0));
|
||||
img.setColor(1, c1.rgb());
|
||||
if (!readBitmap(file, hdl, img, 1))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!file->readByte(hdl, w1))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(QPen(c1, w1, Qt::SolidLine,
|
||||
Qt::RoundCap, Qt::RoundJoin));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
if (!(readColor(file, hdl, c1) && readColor(file, hdl, c2)))
|
||||
return false;
|
||||
|
||||
if (rows) {
|
||||
QImage img(32, rows, QImage::Format_Indexed8);
|
||||
img.setColorCount(2);
|
||||
img.setColor(0, qRgba(255,255,255,0));
|
||||
img.setColor(1, c1.rgb());
|
||||
if (!readBitmap(file, hdl, img, 1))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(img);
|
||||
} else {
|
||||
if (!file->readByte(hdl, w1))
|
||||
return false;
|
||||
|
||||
_lines[type] = Style::Line(QPen(c1, w1, Qt::SolidLine,
|
||||
Qt::RoundCap, Qt::RoundJoin));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isContourLine(type)) {
|
||||
Line &l = _lines[type];
|
||||
l.setTextColor(l.foreground().color());
|
||||
l.setTextFontSize(Small);
|
||||
}
|
||||
|
||||
if (localization && !skipLocalization(file, hdl))
|
||||
return false;
|
||||
|
||||
if (textColor) {
|
||||
quint8 labelFlags;
|
||||
if (!file->readByte(hdl, labelFlags))
|
||||
return false;
|
||||
if (labelFlags & 0x08) {
|
||||
if (!readColor(file, hdl, c1))
|
||||
return false;
|
||||
_lines[type].setTextColor(c1);
|
||||
}
|
||||
_lines[type].setTextFontSize((FontSize)(labelFlags & 0x07));
|
||||
}
|
||||
}
|
||||
|
||||
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 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)
|
||||
{
|
||||
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)
|
||||
&& file->readByte(hdl, imgType)))
|
||||
return false;
|
||||
|
||||
bool localization = t8_1 & 0x04;
|
||||
bool textColor = t8_1 & 0x08;
|
||||
|
||||
int bpp = colors2bpp(numColors, imgType);
|
||||
if (bpp <= 0)
|
||||
continue;
|
||||
QImage img(width, height, QImage::Format_Indexed8);
|
||||
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
|
||||
return false;
|
||||
if (!readBitmap(file, hdl, img, bpp))
|
||||
return false;
|
||||
_points[type] = Point(img);
|
||||
|
||||
if (t8_1 == 0x03) {
|
||||
if (!(file->readByte(hdl, numColors)
|
||||
&& file->readByte(hdl, imgType)))
|
||||
return false;
|
||||
if ((bpp = colors2bpp(numColors, imgType)) < 0)
|
||||
continue;
|
||||
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
|
||||
return false;
|
||||
if (!readBitmap(file, hdl, img, bpp))
|
||||
return false;
|
||||
} else if (t8_1 == 0x02) {
|
||||
if (!(file->readByte(hdl, numColors)
|
||||
&& file->readByte(hdl, imgType)))
|
||||
return false;
|
||||
if ((bpp = colors2bpp(numColors, imgType)) < 0)
|
||||
continue;
|
||||
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (localization && !skipLocalization(file, hdl))
|
||||
return false;
|
||||
|
||||
if (textColor) {
|
||||
quint8 labelFlags;
|
||||
QColor color;
|
||||
if (!file->readByte(hdl, labelFlags))
|
||||
return false;
|
||||
if (labelFlags & 0x08) {
|
||||
if (!readColor(file, hdl, color))
|
||||
return false;
|
||||
_points[type].setTextColor(color);
|
||||
}
|
||||
_points[type].setTextFontSize((FontSize)(labelFlags & 0x07));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::parseDrawOrder(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section &order)
|
||||
{
|
||||
QList<quint32> drawOrder;
|
||||
|
||||
if (!file->seek(hdl, order.arrayOffset))
|
||||
return false;
|
||||
|
||||
for (quint32 i = 0; i < order.arraySize / order.arrayItemSize; i++) {
|
||||
quint8 type;
|
||||
quint32 subtype;
|
||||
|
||||
if (!(file->readByte(hdl, type) && file->readUInt32(hdl, subtype)))
|
||||
return false;
|
||||
|
||||
if (!subtype)
|
||||
drawOrder.append(((quint32)type) << 8);
|
||||
else {
|
||||
for (int j = 0; j < 32; j++) {
|
||||
quint32 mask = 1 << j;
|
||||
if (subtype & mask)
|
||||
drawOrder.append(0x010000 | (((quint32)type) << 8) | j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_drawOrder = drawOrder;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::parseTYPFile(SubFile *file)
|
||||
{
|
||||
SubFile::Handle hdl;
|
||||
Section points, lines, polygons, order;
|
||||
quint16 tmp16, codepage;
|
||||
|
||||
if (!(file->seek(hdl, 0x15) && file->readUInt16(hdl, codepage)
|
||||
&& file->readUInt32(hdl, points.offset)
|
||||
&& file->readUInt32(hdl, points.size)
|
||||
&& file->readUInt32(hdl, lines.offset)
|
||||
&& file->readUInt32(hdl, lines.size)
|
||||
&& file->readUInt32(hdl, polygons.offset)
|
||||
&& file->readUInt32(hdl, polygons.size)))
|
||||
return false;
|
||||
|
||||
if (!(file->readUInt16(hdl, tmp16) && file->readUInt16(hdl, tmp16)))
|
||||
return false;
|
||||
|
||||
if (!(file->readUInt32(hdl, points.arrayOffset)
|
||||
&& file->readUInt16(hdl, points.arrayItemSize)
|
||||
&& file->readUInt32(hdl, points.arraySize)
|
||||
&& file->readUInt32(hdl, lines.arrayOffset)
|
||||
&& file->readUInt16(hdl, lines.arrayItemSize)
|
||||
&& file->readUInt32(hdl, lines.arraySize)
|
||||
&& file->readUInt32(hdl, polygons.arrayOffset)
|
||||
&& file->readUInt16(hdl, polygons.arrayItemSize)
|
||||
&& file->readUInt32(hdl, polygons.arraySize)
|
||||
&& file->readUInt32(hdl, order.arrayOffset)
|
||||
&& file->readUInt16(hdl, order.arrayItemSize)
|
||||
&& file->readUInt32(hdl, order.arraySize)))
|
||||
return false;
|
||||
|
||||
if (!(parsePoints(file, hdl, points) && parseLines(file, hdl, lines)
|
||||
&& parsePolygons(file, hdl, polygons)
|
||||
&& parseDrawOrder(file, hdl, order))) {
|
||||
qWarning("%s: Invalid TYP file, using default style",
|
||||
qPrintable(file->fileName()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Style::Style(SubFile *typ)
|
||||
{
|
||||
defaultLineStyle();
|
||||
defaultPolygonStyle();
|
||||
|
||||
if (typ && typ->isValid())
|
||||
parseTYPFile(typ);
|
||||
}
|
||||
|
||||
const Style::Line &Style::line(quint32 type) const
|
||||
{
|
||||
static Line null;
|
||||
|
||||
QMap<quint32, Line>::const_iterator it = _lines.find(type);
|
||||
return (it == _lines.constEnd()) ? null : *it;
|
||||
}
|
||||
|
||||
const Style::Polygon &Style::polygon(quint32 type) const
|
||||
{
|
||||
static Polygon null;
|
||||
|
||||
QMap<quint32, Polygon>::const_iterator it = _polygons.find(type);
|
||||
return (it == _polygons.constEnd()) ? null : *it;
|
||||
}
|
||||
|
||||
const Style::Point &Style::point(quint32 type) const
|
||||
{
|
||||
static Point null;
|
||||
|
||||
QMap<quint16, Point>::const_iterator it = _points.find(type);
|
||||
return (it == _points.constEnd()) ? null : *it;
|
||||
}
|
||||
|
||||
bool Style::isContourLine(quint32 type)
|
||||
{
|
||||
return (type == TYPE(0x20) || type == TYPE(0x21) || type == TYPE(0x22)
|
||||
|| type == TYPE(0x23) || type == TYPE(0x24) || type == TYPE(0x25));
|
||||
}
|
||||
|
||||
bool Style::isSpot(quint32 type)
|
||||
{
|
||||
return (type == TYPE(0x62) || type == TYPE(0x63));
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
static QString penColor(const QPen &pen)
|
||||
{
|
||||
return (pen == Qt::NoPen) ? "None" : pen.color().name();
|
||||
}
|
||||
|
||||
static QString brushColor(const QBrush &brush)
|
||||
{
|
||||
return (brush == Qt::NoBrush) ? "None" : brush.color().name();
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const Style::Polygon &polygon)
|
||||
{
|
||||
dbg.nospace() << "Polygon(" << brushColor(polygon.brush()) << ", "
|
||||
<< penColor(polygon.pen()) << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const Style::Line &line)
|
||||
{
|
||||
dbg.nospace() << "Line(" << penColor(line.foreground()) << ", "
|
||||
<< penColor(line.background()) << ", " << !line.img().isNull() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
136
src/map/IMG/style.h
Normal file
@ -0,0 +1,136 @@
|
||||
#ifndef STYLE_H
|
||||
#define STYLE_H
|
||||
|
||||
#include <QPen>
|
||||
#include <QBrush>
|
||||
#include <QDebug>
|
||||
#include "subfile.h"
|
||||
|
||||
|
||||
class Style
|
||||
{
|
||||
public:
|
||||
enum FontSize {
|
||||
NotSet = 0,
|
||||
None = 1,
|
||||
Small = 2,
|
||||
Normal = 3,
|
||||
Large = 4
|
||||
};
|
||||
|
||||
class Polygon {
|
||||
public:
|
||||
Polygon() : _brush(Qt::NoBrush), _pen(Qt::NoPen) {}
|
||||
Polygon(const QBrush &brush, const QPen &pen = Qt::NoPen)
|
||||
: _brush(brush)
|
||||
{
|
||||
_pen = (pen == Qt::NoPen) ? QPen(_brush, 0) : pen;
|
||||
}
|
||||
|
||||
const QPen &pen() const {return _pen;}
|
||||
const QBrush &brush() const {return _brush;}
|
||||
|
||||
private:
|
||||
QBrush _brush;
|
||||
QPen _pen;
|
||||
};
|
||||
|
||||
class Line {
|
||||
public:
|
||||
Line() : _foreground(Qt::NoPen), _background(Qt::NoPen),
|
||||
_textFontSize(NotSet) {}
|
||||
Line(const QPen &foreground, const QPen &background = Qt::NoPen)
|
||||
: _foreground(foreground), _background(background),
|
||||
_textFontSize(NotSet) {}
|
||||
Line(const QImage &img)
|
||||
: _foreground(Qt::NoPen), _background(Qt::NoPen),
|
||||
_textFontSize(NotSet), _img(img.convertToFormat(
|
||||
QImage::Format_ARGB32_Premultiplied)) {}
|
||||
|
||||
void setTextColor(const QColor &color) {_textColor = color;}
|
||||
void setTextFontSize(FontSize size) {_textFontSize = size;}
|
||||
|
||||
const QPen &foreground() const {return _foreground;}
|
||||
const QPen &background() const {return _background;}
|
||||
const QColor &textColor() const {return _textColor;}
|
||||
FontSize textFontSize() const {return _textFontSize;}
|
||||
const QImage &img() const {return _img;}
|
||||
|
||||
private:
|
||||
QPen _foreground, _background;
|
||||
QColor _textColor;
|
||||
FontSize _textFontSize;
|
||||
QImage _img;
|
||||
};
|
||||
|
||||
class Point {
|
||||
public:
|
||||
Point() : _textFontSize(NotSet) {}
|
||||
Point(const QImage &img) : _textFontSize(NotSet), _img(img) {}
|
||||
|
||||
void setTextColor(const QColor &color) {_textColor = color;}
|
||||
void setTextFontSize(FontSize size) {_textFontSize = size;}
|
||||
|
||||
const QColor &textColor() const {return _textColor;}
|
||||
FontSize textFontSize() const {return _textFontSize;}
|
||||
const QImage &img() const {return _img;}
|
||||
|
||||
private:
|
||||
QColor _textColor;
|
||||
FontSize _textFontSize;
|
||||
QImage _img;
|
||||
};
|
||||
|
||||
|
||||
Style(SubFile *typ = 0);
|
||||
|
||||
const Line &line(quint32 type) const;
|
||||
const Polygon &polygon(quint32 type) const;
|
||||
const Point &point(quint32 type) const;
|
||||
const QList<quint32> &drawOrder() const {return _drawOrder;}
|
||||
|
||||
static bool isContourLine(quint32 type);
|
||||
static bool isSpot(quint32 type);
|
||||
|
||||
private:
|
||||
struct Section {
|
||||
quint32 offset;
|
||||
quint32 size;
|
||||
quint32 arrayOffset;
|
||||
quint32 arraySize;
|
||||
quint16 arrayItemSize;
|
||||
};
|
||||
|
||||
struct ItemInfo {
|
||||
quint32 offset;
|
||||
quint8 type;
|
||||
quint8 subtype;
|
||||
bool extended;
|
||||
};
|
||||
|
||||
bool parseTYPFile(SubFile *file);
|
||||
bool parsePoints(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion);
|
||||
bool parseLines(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion);
|
||||
bool parsePolygons(SubFile *file, SubFile::Handle &hdl,
|
||||
const Section §ion);
|
||||
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();
|
||||
|
||||
QMap<quint32, Line> _lines;
|
||||
QMap<quint32, Polygon> _polygons;
|
||||
QMap<quint16, Point> _points;
|
||||
QList<quint32> _drawOrder;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Style::Polygon &polygon);
|
||||
QDebug operator<<(QDebug dbg, const Style::Line &line);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // STYLE_H
|
61
src/map/IMG/subdiv.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef SUBDIV_H
|
||||
#define SUBDIV_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include "common/coordinates.h"
|
||||
#include "units.h"
|
||||
|
||||
class SubDiv {
|
||||
public:
|
||||
SubDiv(quint32 offset, qint32 lon, qint32 lat, int bits, quint8 objects)
|
||||
: _offset(offset), _end(0), _lon(lon), _lat(lat), _bits(bits),
|
||||
_objects(objects), _polygonsOffset(0), _polygonsEnd(0), _linesOffset(0),
|
||||
_linesEnd(0), _pointsOffset(0), _pointsEnd(0) {}
|
||||
void setEnd(quint32 end) {_end = end;}
|
||||
|
||||
quint32 offset() const {return _offset;}
|
||||
quint32 end() const {return _end;}
|
||||
qint32 lon() const {return _lon;}
|
||||
qint32 lat() const {return _lat;}
|
||||
quint8 bits() const {return _bits;}
|
||||
quint8 objects() const {return _objects;}
|
||||
|
||||
// Extended types objects (TRE7)
|
||||
void setExtOffsets(quint32 polygon, quint32 line, quint32 point)
|
||||
{_polygonsOffset = polygon; _linesOffset = line; _pointsOffset = point;}
|
||||
void setExtEnds(quint32 polygon, quint32 line, quint32 point)
|
||||
{_polygonsEnd = polygon; _linesEnd = line; _pointsEnd = point;}
|
||||
|
||||
quint32 polygonsOffset() const {return _polygonsOffset;}
|
||||
quint32 polygonsEnd() const {return _polygonsEnd;}
|
||||
quint32 linesOffset() const {return _linesOffset;}
|
||||
quint32 linesEnd() const {return _linesEnd;}
|
||||
quint32 pointsOffset() const {return _pointsOffset;}
|
||||
quint32 pointsEnd() const {return _pointsEnd;}
|
||||
|
||||
private:
|
||||
quint32 _offset;
|
||||
quint32 _end;
|
||||
qint32 _lon, _lat;
|
||||
quint8 _bits;
|
||||
quint8 _objects;
|
||||
|
||||
quint32 _polygonsOffset;
|
||||
quint32 _polygonsEnd;
|
||||
quint32 _linesOffset;
|
||||
quint32 _linesEnd;
|
||||
quint32 _pointsOffset;
|
||||
quint32 _pointsEnd;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const SubDiv &subdiv)
|
||||
{
|
||||
Coordinates c(toWGS84(subdiv.lon()), toWGS84(subdiv.lat()));
|
||||
dbg.nospace() << "SubDiv(" << c << ", " << subdiv.offset()
|
||||
<< ", " << subdiv.end() << ", " << subdiv.objects() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // SUBDIV_H
|
102
src/map/IMG/subfile.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include <QFile>
|
||||
#include "img.h"
|
||||
#include "subfile.h"
|
||||
|
||||
SubFile::Type SubFile::type(const char str[3])
|
||||
{
|
||||
if (!memcmp(str, "TRE", 3))
|
||||
return TRE;
|
||||
else if (!memcmp(str, "RGN", 3))
|
||||
return RGN;
|
||||
else if (!memcmp(str, "LBL", 3))
|
||||
return LBL;
|
||||
else if (!memcmp(str, "TYP", 3))
|
||||
return TYP;
|
||||
else if (!memcmp(str, "GMP", 3))
|
||||
return GMP;
|
||||
else if (!memcmp(str, "NET", 3))
|
||||
return NET;
|
||||
else
|
||||
return Unknown;
|
||||
}
|
||||
|
||||
SubFile::SubFile(QFile *file) : _img(0), _file(file), _size(0)
|
||||
{
|
||||
if (!_file->open(QIODevice::ReadOnly))
|
||||
qWarning("Error opening %s: %s", qPrintable(_file->fileName()),
|
||||
qPrintable(_file->errorString()));
|
||||
}
|
||||
|
||||
bool SubFile::isValid() const
|
||||
{
|
||||
return _file
|
||||
? _file->isOpen()
|
||||
: ((quint32)_img->blockSize() * (quint32)_blocks.size() - _size
|
||||
< (quint32)_img->blockSize());
|
||||
}
|
||||
|
||||
bool SubFile::seek(Handle &handle, quint32 pos) const
|
||||
{
|
||||
Q_ASSERT(_img || _file);
|
||||
|
||||
if (_file)
|
||||
return _file->seek(pos);
|
||||
else {
|
||||
quint32 blockSize = _img->blockSize();
|
||||
int blockNum = pos / blockSize;
|
||||
|
||||
if (handle.blockNum != blockNum) {
|
||||
if (blockNum >= _blocks.size())
|
||||
return false;
|
||||
if (!_img->readBlock(_blocks.at(blockNum), handle.data))
|
||||
return false;
|
||||
handle.blockNum = blockNum;
|
||||
}
|
||||
|
||||
handle.blockPos = pos % blockSize;
|
||||
handle.pos = pos;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool SubFile::readByte(Handle &handle, quint8 &val) const
|
||||
{
|
||||
Q_ASSERT(_img || _file);
|
||||
|
||||
if (_file)
|
||||
return _file->getChar((char*)&val);
|
||||
else {
|
||||
val = handle.data.at(handle.blockPos++);
|
||||
handle.pos++;
|
||||
return (handle.blockPos >= _img->blockSize())
|
||||
? seek(handle, handle.pos) : true;
|
||||
}
|
||||
}
|
||||
|
||||
quint32 SubFile::size() const
|
||||
{
|
||||
return _img ? _size : (quint32)_file->size();
|
||||
}
|
||||
|
||||
QString SubFile::fileName() const
|
||||
{
|
||||
return _img ? _img->fileName() : _file->fileName();
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const SubFile &file)
|
||||
{
|
||||
bool continuous = true;
|
||||
for (int i = 1; i < file._blocks.size(); i++) {
|
||||
if (file._blocks.at(i) != file._blocks.at(i-1) + 1) {
|
||||
continuous = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dbg.nospace() << "SubFile(" << file._size << ", " << file._blocks.size()
|
||||
<< ", " << continuous << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|