diff options
121 files changed, 2781 insertions, 349 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index f1c2c6f30..e643305e6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ defaults: &defaults jobs: sanity_check: docker: - - image: navit/sanity_check:latest + - image: circleci/android:api-29-ndk steps: - checkout - run: @@ -107,19 +107,19 @@ jobs: command: ./gradlew generateDebugJavadoc - store_artifacts: name: Store APK - path: navit/android/build/outputs/apk + path: build/outputs/apk destination: apk - store_artifacts: name: Store logs - path: navit/android/build/outputs/logs + path: build/outputs/logs destination: logs - store_artifacts: name: Store Javadoc - path: navit/android/build/outputs/docs/javadoc + path: build/outputs/docs/javadoc destination: doc - store_artifacts: name: Store Lint reports - path: navit/android/build/reports + path: build/reports destination: reports - store_test_results: path: test-results @@ -127,6 +127,40 @@ jobs: name: Update Navit-Download-Center command: | bash scripts/update_download_center.sh + build_fdroid: + docker: + - image: registry.gitlab.com/fdroid/ci-images-client:latest + steps: + - checkout + - run: + name: Build with F-Droid + command: | + test -d build || mkdir build + test -d fdroidserver || mkdir fdroidserver + git ls-remote https://gitlab.com/fdroid/fdroidserver.git master + curl --silent https://gitlab.com/fdroid/fdroidserver/-/archive/master/fdroidserver-master.tar.gz | tar -xz --directory=fdroidserver --strip-components=1 + export PATH="`pwd`/fdroidserver:$PATH" + export PYTHONPATH="$CI_PROJECT_DIR/fdroidserver:$CI_PROJECT_DIR/fdroidserver/examples" + export PYTHONUNBUFFERED=true + bash fdroidserver/buildserver/setup-env-vars $ANDROID_HOME + adduser --disabled-password --gecos "" vagrant + ln -s $CI_PROJECT_DIR/fdroidserver /home/vagrant/fdroidserver + mkdir -p /vagrant/cache + wget -q https://services.gradle.org/distributions/gradle-5.6.2-bin.zip --output-document=/vagrant/cache/gradle-5.6.2-bin.zip + bash fdroidserver/buildserver/provision-gradle + bash fdroidserver/buildserver/provision-apt-get-install http://deb.debian.org/debian + source /etc/profile.d/bsenv.sh + apt-get dist-upgrade + apt-get install -t stretch-backports fdroidserver python3-asn1crypto python3-ruamel.yaml yamllint + apt-get purge fdroidserver + export GRADLE_USER_HOME=$PWD/.gradle + set -x + apt-get install sudo + fdroid build --verbose --on-server --no-tarball + - store_artifacts: + name: Store APK + path: unsigned + destination: apk build_win32: docker: - image: ubuntu:14.04 @@ -219,13 +253,11 @@ jobs: command: | bash scripts/update_download_center.sh merge_trunk_in_master: - <<: *defaults + docker: + - image: cimg/base:2020.01 steps: - checkout - run: - name: Install git - command: apt-get update && apt-get -y install ca-certificates git - - run: name: configure ssh git command: mkdir -p ~/.ssh/ && ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts - add_ssh_keys: @@ -268,6 +300,9 @@ workflows: - build_android: requires: - sanity_check + - build_fdroid: + requires: + - sanity_check - build_sailfish: requires: - sanity_check diff --git a/.fdroid.yml b/.fdroid.yml new file mode 100644 index 000000000..1e314c64b --- /dev/null +++ b/.fdroid.yml @@ -0,0 +1,53 @@ +Categories: + - Navigation +License: GPL-2.0-only +WebSite: https://www.navit-project.org/ +SourceCode: https://github.com/navit-gps/navit +IssueTracker: http://trac.navit-project.org +Translation: https://translations.launchpad.net/navit/trunk/+pots/navit +Changelog: https://github.com/navit-gps/navit/blob/HEAD/CHANGELOG.md#changelog + +AutoName: Navit +Description: |- + Its modular design is capable of using vector maps of various formats for + routing and rendering of the displayed map. It’s even possible to use multiple + maps at a time. While Navit supports all major platforms, there is a fork + specializing on an easy-to-use, Android-only solution: + https://f-droid.org/packages/com.zoffcc.applications.zanavi. + + The routing engine not only calculates an optimal route to your destination, but + also generates directions and even speaks to you. + + Navit currently speaks 27 languages. You can help translating via the web-based + <a href="http://translations.launchpad.net/navit/trunk/+pots/navit">translation page</a>. + +RepoType: git +Repo: https://github.com/navit-gps/navit + +Builds: + - versionName: generated_at_build_time + versionCode: 42 + # since we generate version codes on the fly, we never know them at commit time + # therefore we use dummy values and skip the version check + novcheck: yes + commit: HEAD + gradle: + - yes + output: build/outputs/apk/release/navit-release.apk + rm: + - navit/support/espeak/espeak-data/* + prebuild: + # ndk is needed because of CI limitations and can be removed once the CI image comes with NDK 20 + - $$SDK$$/tools/bin/sdkmanager "cmake;3.6.4111459" "ndk;20.0.5594570" > /dev/null + - sed -i -e '/gradlew/d' scripts/build_android.sh + build: scripts/build_android.sh + # disable for now because of CI limitations + #ndk: r20b + +MaintainerNotes: |- + Found JAR file at navit/android/libs/TTS_library_stub.jar, removed as of v0.5.3-442-g96d9c41. + NDK r12b is the minimum required as of v0.5.3, later versions may work but are untested. + +AutoUpdateMode: Version %v +UpdateCheckMode: HTTP +UpdateCheckData: https://download.navit-project.org/api/version.json|"version_code":.*"(.*)"|.|"version_name":.*\"(.*)\", diff --git a/.gitchangelog.tpl b/.gitchangelog.tpl index 59bc8a299..b89a83815 100644 --- a/.gitchangelog.tpl +++ b/.gitchangelog.tpl @@ -29,7 +29,7 @@ Navit follows the semantic versioning: <% title = "## [%s] - %s" % (version["tag"], version["date"]) if version["tag"] else "## %s" % opts["unreleased_version_label"] %>${title} % for section in version["sections"]: -<% lbl = "## %s" % section["label"] %>${lbl} +<% lbl = "### %s" % section["label"] %>${lbl} % for commit in section["commits"]: <% @@ -1,10 +1,11 @@ # Active contributors: +barbeque-squared Benjamin Davies Bignaux Ronan -Charles Curley David Heidelberg emaiannone gefin +James Hilliard jandegr jkoan Johan Fitié @@ -16,8 +17,8 @@ mvglasow OLFDB Patrick Höhn Pierre Grandin -Robert Pohlink Stefan Wildemann +Tim Gates # Retired contributors: afaber @@ -29,6 +30,7 @@ bodenseepingu bustersnyvel carcinoma Cedric Paille +Charles Curley christeck eiten gauthier60 @@ -56,6 +58,7 @@ OmegA_MRS pavel plum_ Rikky +Robert Pohlink Robotaxi rphlx sanderd17 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ec7e02e4..f73c456ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,16 +23,94 @@ Navit follows the semantic versioning: usually tends to occur along with larger changes which would warrant a new major version anyway - -## [Unreleased] +## [Unreleased](https://github.com/navit-gps/navit/compare/v0.5.6...HEAD) To get the list of all the unreleased commits, see: -[Full Changelog](https://github.com/navit-gps/navit/compare/v0.5.4...HEAD) +[Full Changelog](https://github.com/navit-gps/navit/compare/v0.5.6...HEAD) + +## [v0.5.6](https://github.com/navit-gps/navit/compare/v0.5.5...v0.5.6) - 2021-03-06 +### Added -## [0.5.5] - 2020-08-08 +* Add:traffic:Log class/type of unrecognized events during XML parsing. [mvglasow] +* Add:traffic:Log ID for messages discarded as invalid. [mvglasow] +* Add:graphics:svg\_debug:Add svg\_debugging plugin (#1061) [jkoan] +* Add:vehicle:Add first Prototype of the geoclue Plugin. [jkoan] +* Add:port/android:Adaptive app icon. [mvglasow] +* Added license information to fix #1048 (#1060) [Patrick Höhn] +* Add:traffic/traff\_android:Process heartbeat requests. [mvglasow] +* Add:traffic/traff\_android:Log subscription operations in detail. [mvglasow] +* Add:port/android:Adaptive app icon. [mvglasow] +* Add:traffic:Complete TraFF 0.8 subscription suport. [mvglasow] +* Add:traffic:Add basic TraFF 0.8 support. [mvglasow] + +### Changed -## Added +* Update macos\_development.rst. [Patrick Höhn] +* Change:android:Remove map download size limit on modern Android versions (#1029) [Johan Fitié] + +### Fixed + +* Build:Use NDK libraries when building for Android. [mvglasow] +* Build:Keep generated Android resource files in build dir. [mvglasow] +* Build:Reduce source tree pollution by Android build CMake output now moved to android-builddir Generated XML, PNG and translations still get written to source tree. [mvglasow] +* Vehicle:gpsd:Fix #1090, plugin\_init not found. [jkoan] +* Fixed:android:build:Fixed the apk outputname and the corresponding locations within the scripts. [jkoan] +* Build:do not request CXX if explicitly disabled. [mvglasow] +* Build/android:do not double-define getcwd on recent NDK versions. [mvglasow] +* Build:android: Fix VersionCode after 31.12.2020 (#1082) [jkoan] +* Fix Link to full Changelog. [jkoan] +* Build:Remove install of git as the baseimage already has it. [jkoan] +* Builds:Revert baseimage back and oly set merge\_trunk\_in\_master to cimg/base. [jkoan] +* Core:Prevent crash if destination is set before acquiring a location. [mvglasow] +* Vehicle\_geoclue:Fix speed and direction and do some cleanup. [jkoan] +* Vehicle:Fix codestyle. [jkoan] +* Android:Add possibility to use background position usage. [jkoan] +* Build:Prevent try\_compile() from choking on CXX. [mvglasow] +* Plugin/j1850: Replace graphic\_fg\_white with graphic\_fg. [James Hilliard] +* Build:core:Fix two issues where the wrong enum type is used, but both have the same value of 0. [jkoan] +* Core:osd:Altitude in metric with imperial defined. [Patrick Höhn] +* Build:android:Add extra security check for gradle. [jkoan] +* Android:Add possibility to use background position usage. [jkoan] +* Vehicle:gpsd:minor comment fix. [jkoan] +* Fix:graphics:win32:Fix build with newer libpng versions. Thx @bignaux fixes #984. [jkoan] +* Build:Fix usage of inkscape 1.0 commandline usage. [jkoan] +* Build:Fix Codesigning with newer ndk image versions. [jkoan] +* Maptool:Add missing external, fixes #1045. [barbeque-squared] +* Graphics/qt5:Add missing include. [barbeque-squared] +* Vehicle:gpsd:Add Support for Gpsd 3.21. [jkoan] +* Core:Optimize log message for required vehicle attributes. [jkoan] +* Traffic/traff\_android:Get subscription ID from request where applicable. [mvglasow] +* Traffic/traff\_android:Fix log messages when subscription ID is missing. [mvglasow] +* Traffic/traff\_android:Fix log messages when content URI is missing. [mvglasow] +* Traffic/traff\_android:Fix subscription lookup. [mvglasow] +* Core:Prevent crash if destination is set before acquiring a location. [mvglasow] +* Core:Fix invalid pointer which would cause unpredictable crashes. [mvglasow] +* Core:set destination before firing callbacks. [mvglasow] +* Build:Prevent try\_compile() from choking on CXX. [mvglasow] + +### Other + +* Refactor:fdroid:Remove build.xml generation. [mvglasow] +* Refactor:core:Documentation update (#1095) [mvglasow] +* Refactor:build:merge into one single build.gradle. [mvglasow] +* Refactor:traffic/traff\_android:remove TODO comment. [mvglasow] +* Refactor:traffic:Make sanity check happy. [mvglasow] +* Docs: fix simple typo, useage -\> usage. [Tim Gates] +* Refactor:core:Fix documentation for route\_graph\_build() [mvglasow] +* Refactor:core:make sanity\_check happy (sort of, see #1041) [mvglasow] +* Refactor:core:Fix documentation for route\_graph\_build() [mvglasow] +* Refactor:traffic/traff\_android:Fix checkstyle issues. [mvglasow] +* Refactor:traffic/traff\_android:Fix Javadoc formatting. [mvglasow] +* Refactor:traffic/traff\_android:More sanity check fixes. [mvglasow] +* Refactor:traffic:Make sanity check happy. [mvglasow] +* Refactor:core:Add documentation. [mvglasow] +* Refactor:core:Add documentation. [mvglasow] + + +## [v0.5.5](https://github.com/navit-gps/navit/compare/v0.5.4...v0.5.5) - 2020-08-08 + +### Added * Add poly\_swimming\_pool. [Stefan Wildemann] * Add:maptool:enhance leisure=track handling and add poi\_archeaological\_site (#1005) [Stefan Wildemann] @@ -44,7 +122,7 @@ To get the list of all the unreleased commits, see: * Add:build:Android build and signing. Also add fastlane for metadata. Set execute on scripts/\*.sh. [jkoan] * Add:cmake: add compilation flags to harden the security of navit (#969) [Joseph Herlant] -## Changed +### Changed * Change:core:Remove unused argument from attr\_search. [jkoan] * Change\_layout:Make sure park, meadow, scrub, and wood render in correct order (#1017) [Johan Fitié] @@ -54,7 +132,7 @@ To get the list of all the unreleased commits, see: * Change:android:build:Fix empty Variable handling. [jkoan] * Change:metadata:Rename Title to "Navit" only because everybody knows that its for Android when found within F-Droid or Google Play store. [jkoan] -## Fixed +### Fixed * Android:Remove old, confusing AndroidManifest.xml. [jkoan] * Android:Readd android:sharedUserId to allow for Updates. [jkoan] @@ -79,7 +157,7 @@ To get the list of all the unreleased commits, see: * Plugins: too few arguments to functions navit\_attr\_iter\_new and config\_attr\_iter\_new (#966) [Joseph Herlant] * Port/android:Use new icon for notification (#963) [mvglasow] -## Other +### Other * Android: Activate downloaded maps automatically (#1027) [Johan Fitié] * Improvement:layout:car-dark Improve Car-Dark layout colors (#1028) [Johan Fitié] @@ -94,7 +172,7 @@ To get the list of all the unreleased commits, see: * Improve layout (#1002) [Johan Fitié] * Use debian:latest in the CI to get more up-to-date tools (#971) [Joseph Herlant] -## [0.5.4] - 2020-01-18 +## [v0.5.4](https://github.com/navit-gps/navit/compare/v0.5.3...v0.5.4) - 2020-01-18 ### Added @@ -191,7 +269,7 @@ To get the list of all the unreleased commits, see: - Refactoring:mingw:simplify toolchain [\#659](https://github.com/navit-gps/navit/pull/659) ([bignaux](https://github.com/bignaux)) - Refactoring:cmake:from 2.6 to 3.2 [\#651](https://github.com/navit-gps/navit/pull/651) ([bignaux](https://github.com/bignaux)) -## [v0.5.3] - 2018-08-31 +## [v0.5.3](https://github.com/navit-gps/navit/compare/v0.5.2...v0.5.3) - 2018-08-31 Release 0.5.2 had issues with the version not properly updated in the `CMakeLists.txt`. This release fixes that issue. @@ -200,7 +278,7 @@ Release 0.5.2 had issues with the version not properly updated in the `CMakeList * Update Sailfish spec for release 0.5.3. [Joseph Herlant] * Update Patch version for release 0.5.3. [Joseph Herlant] -## [v0.5.2] - 2018-08-30 +## [v0.5.2](https://github.com/navit-gps/navit/compare/v0.5.1...v0.5.2) - 2018-08-30 ### Added @@ -300,7 +378,7 @@ Release 0.5.2 had issues with the version not properly updated in the `CMakeList * Android:Fix:remove unused dependency libpng (#592) [jandegr] -## [v0.5.1] - 2018-04-19 +## [v0.5.1](https://github.com/navit-gps/navit/compare/v0.5.0...v0.5.1) - 2018-04-19 ### Added @@ -751,7 +829,7 @@ Release 0.5.2 had issues with the version not properly updated in the `CMakeList * We always want the failed code from bash not from tee. [jkoan] * Little quick change to make it working fast. [jkoan] * Auto pitch and orientation (#306) [Johan Fitié] -* #1352 workaround. [mdankov] +* \#1352 workaround. [mdankov] * Smaller Android screenshot for README.md. [Johan Fitié] * Pitch correction (#303) [Johan Fitié] * [POI] Resize SVG icons to 22x22 (#304) [Johan Fitié] @@ -899,29 +977,20 @@ Release 0.5.2 had issues with the version not properly updated in the `CMakeList * Trac-1064 render OSM shop=mall as poi\_mall. [Pierre GRANDIN] * Bumping the trunk to 0.5.1. [Pierre GRANDIN] -## [v0.5.0] - 2015-12-31 +## [v0.5.0](https://github.com/navit-gps/navit/compare/v0.5.0-rc.2...v0.5.0) - 2015-12-31 This release was done before the adoption of this changelog format. Use [this v0.5.0-rc.2 to v0.5.0 comparison link](https://github.com/navit-gps/navit/compare/v0.5.0-rc.2...v0.5.0) to view the corresponding changes. -## [v0.5.0-rc2] - 2015-09-02 +## [v0.5.0-rc2](https://github.com/navit-gps/navit/compare/v0.5.0-rc.1...v0.5.0-rc.2) - 2015-09-02 This release was done before the adoption of this changelog format. Use [this v0.5.0-rc.1 to v0.5.0-rc.2 comparison link](https://github.com/navit-gps/navit/compare/v0.5.0-rc.1...v0.5.0-rc.2) to view the corresponding changes. -## [v0.5.0-rc1] - 2015-08-08 +## [v0.5.0-rc1](https://github.com/navit-gps/navit/compare/v0.5.0-beta.1...v0.5.0-rc.1) - 2015-08-08 This release was done before the adoption of this changelog format. Use [this v0.5.0-beta.1 to v0.5.0-rc.1 comparison link](https://github.com/navit-gps/navit/compare/v0.5.0-beta.1...v0.5.0-rc.1) to view the corresponding changes. - -[Unreleased]: https://github.com/navit-gps/navit/compare/v0.5.4...HEAD -[v0.5.4]: https://github.com/navit-gps/navit/compare/v0.5.3...v0.5.4 -[v0.5.3]: https://github.com/navit-gps/navit/compare/v0.5.2...v0.5.3 -[v0.5.2]: https://github.com/navit-gps/navit/compare/v0.5.1...v0.5.2 -[v0.5.1]: https://github.com/navit-gps/navit/compare/v0.5.0...v0.5.1 -[v0.5.0]: https://github.com/navit-gps/navit/compare/v0.5.0-rc.2...v0.5.0 -[v0.5.0-rc.2]: https://github.com/navit-gps/navit/compare/v0.5.0-rc.1...v0.5.0-rc.2 -[v0.5.0-rc.1]: https://github.com/navit-gps/navit/compare/v0.5.0-beta.1...v0.5.0-rc.1 diff --git a/CMakeLists.txt b/CMakeLists.txt index f392e1f92..9b4bf0f37 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,11 @@ cmake_minimum_required(VERSION 3.2) set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.navitproject.navit") set(MACOSX_BUNDLE_BUNDLE_NAME "Navit") message(STATUS "Building with CMake V${CMAKE_VERSION}") -project(navit C) +if (DISABLE_CXX) + project(navit C) +else(DISABLE_CXX) + project(navit C CXX) +endif(DISABLE_CXX) # Workaround for CMake issue 8345 / 9220, see http://trac.navit-project.org/ticket/1041 if(DEFINED CMAKE_CXX_COMPILER AND CMAKE_CXX_COMPILER MATCHES "^$") @@ -15,7 +19,7 @@ endif(NOT DISABLE_CXX) set(NAVIT_VERSION_MAJOR "0") set(NAVIT_VERSION_MINOR "5") -set(NAVIT_VERSION_PATCH "5") +set(NAVIT_VERSION_PATCH "6") if(ANDROID) set(PACKAGE_VERSION "${NAVIT_VERSION_MAJOR}.${NAVIT_VERSION_MINOR}.${NAVIT_VERSION_PATCH}.${ANDROID_ABI}") else(ANDROID) @@ -103,9 +107,11 @@ add_module(graphics/sdl "Required library not found" FALSE) add_module(graphics/egl "Required library not found" FALSE) add_module(graphics/qt_qpainter "Qt libraries not found" FALSE) add_module(graphics/qt5 "Qt5 libraries not found" FALSE) +add_module(graphics/svg_debug "native Glib not found" FALSE) add_module(gui/qml "Qt Declarative not found" FALSE) add_module(gui/qt5_qml "Qt5 Declarative not found" FALSE) add_module(gui/gtk "GTK libs not found" FALSE) +add_module(vehicle/geoclue "geoclue lib not found" FALSE) add_module(vehicle/gpsd "gpsd lib not found" FALSE) add_module(vehicle/gypsy "gypsy lib not found" FALSE) add_module(vehicle/maemo "Default" FALSE) @@ -153,6 +159,12 @@ INCLUDE (CheckLibraryExists) INCLUDE (CheckFunctionExists) INCLUDE (CheckSymbolExists) +if(ANDROID) + set(ENV{PKG_CONFIG_DIR} "") + set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig") + set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT}) +endif(ANDROID) + ################################ # pkg-config based detection # ################################ @@ -197,6 +209,14 @@ if(PKG_CONFIG_FOUND) if(IMLIB2_FOUND) set(HAVE_IMLIB2 1) endif(IMLIB2_FOUND) + + # Geoclue + pkg_check_modules ( GeoClue libgeoclue-2.0 ) + if(GeoClue_FOUND) + include_directories(${GeoClue_INCLUDE_DIRS}) + set_with_reason(vehicle/geoclue "libgeoclue found" TRUE + ${GeoClue_LIBRARIES}) + endif(GeoClue_FOUND) else(PKG_CONFIG_FOUND) set_with_reason(support/glib "Glib not found" TRUE ${INTL_LIBS}) endif(PKG_CONFIG_FOUND) @@ -317,7 +337,10 @@ if (NOT HAVE_WORDEXP) endif() if (NOT GLIB2_FOUND) set_with_reason(support/ezxml "Glib not found" TRUE) -endif() +else(NOT GLIB2_FOUND) + set_with_reason(graphics/svg_debug "Glib found" TRUE) +endif(NOT GLIB2_FOUND) + if(FREETYPE_FOUND) pkg_check_modules(FRIBIDI fribidi) diff --git a/build.gradle b/build.gradle index b9db6a857..d284d54a0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,6 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.android.application' +apply from: "$project.rootDir/gradle/scripts/git-scm-version.gradle" +apply plugin: 'checkstyle' buildscript { repositories { @@ -28,6 +30,115 @@ allprojects { } } +/* task clean(type: Delete) { delete rootProject.buildDir } +*/ +android { + compileSdkVersion 29 + buildToolsVersion "29.0.2" + signingConfigs { + release { + // We can leave these in environment variables + storeFile file(System.getenv("KEYSTORE") ?: "/store") + keyAlias System.getenv("KEY_ALIAS") + storePassword System.getenv("STORE_PASS") + keyPassword System.getenv("STORE_PASS") + } + } + defaultConfig { + applicationId "org.navitproject.navit" + minSdkVersion 10 + targetSdkVersion 29 + versionCode gitVersionCode + versionName gitVersionName + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + ndk { + abiFilters 'x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a' + } + externalNativeBuild { + cmake { + arguments '-DDISABLE_CXX=y', '-DUSE_PLUGINS=n', '-DBUILD_MAPTOOL=n', '-DXSL_PROCESSING=n', '-DSAMPLE_MAP=n', '-DCMAKE_SYSROOT='+android.ndkDirectory+'/sysroot' + } + } + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + if(file(System.getenv("KEYSTORE") ?: "/store").exists()){ + signingConfig signingConfigs.release + } + } + } + lintOptions { + disable 'UnusedResources' + abortOnError true + } + sourceSets { + main { + manifest.srcFile "navit/android/AndroidManifest.xml" + java.srcDirs = ["navit/android/src"] + resources.srcDirs = ["navit/android/src"] + renderscript.srcDirs = ["navit/android/src"] + res.srcDirs = ["navit/android/res", "android-builddir/android/res"] + assets.srcDirs = ["navit/android/assets", "android-builddir/android/assets"] + } + } + externalNativeBuild { + cmake { + buildStagingDirectory "./android-builddir" + path 'CMakeLists.txt' + } + } + + task checkstyleMain(type: Checkstyle){ + source 'navit/android/src' + include '**/*.java' + configFile = rootProject.file('checkstyle.xml') + ignoreFailures = false + showViolations = true + // empty classpath + classpath = files() + reports { + include ('**/*.java') + xml.enabled = true + html.enabled = true + xml { + destination file("checkstyle/checkstyleMain.xml") + } + html { + destination file("checkstyle/checkstyleMain.html") + } + } + + checkstyle { + toolVersion = '8.26' + } + } + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = "navit-${variant.buildType.name}.apk" + } + // create tasks to generate Javadocs + task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) { + source = android.sourceSets.main.java.srcDirs + destinationDir = file("navit/android/build/outputs/docs/javadoc/") + title = rootProject.name + options.memberLevel = JavadocMemberLevel.PACKAGE + verbose = true + failOnError false + } + } + +} +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'navit/android/libs') + androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + testImplementation 'junit:junit:4.12' + implementation 'ch.acra:acra:4.9.2' +// implementation 'com.android.support:support-v4:28.0.0' +} diff --git a/checkstyle.xml b/checkstyle.xml index 8a19f6944..96f871666 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -59,9 +59,6 @@ <property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/> </module> - <module name="NeedBraces"> - <property name="severity" value="error"/> - </module> <module name="LeftCurly"/> <module name="RightCurly"> <property name="id" value="RightCurlySame"/> @@ -141,7 +138,7 @@ <property name="severity" value="error"/> </module> <module name="MemberName"> - <property name="format" value="^m[A-Z][a-zA-Z0-9]*$"/> + <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> <message key="name.invalidPattern" value="Member name ''{0}'' must match pattern ''{1}''."/> <property name="severity" value="error"/> @@ -211,7 +208,6 @@ <property name="allowedAbbreviationLength" value="3"/> </module> <module name="OverloadMethodsDeclarationOrder"/> - <module name="VariableDeclarationUsageDistance"/> <module name="CustomImportOrder"> <property name="sortImportsInGroupAlphabetically" value="true"/> <property name="separateLineBetweenGroups" value="true"/> diff --git a/contrib/sailfish/navit-sailfish.spec b/contrib/sailfish/navit-sailfish.spec index e2b49aea2..bbc0c75d4 100755 --- a/contrib/sailfish/navit-sailfish.spec +++ b/contrib/sailfish/navit-sailfish.spec @@ -9,7 +9,7 @@ Name: harbour-navit Summary: Open Source car navigation system #Version: %{navit_version}_%{git_version} -Version: 0.5.5 +Version: 0.5.6 Release: 1 License: GPL Group: Applications/Productivity diff --git a/docs/development/linux_development.rst b/docs/development/linux_development.rst index e9802ea31..10ed64dec 100644 --- a/docs/development/linux_development.rst +++ b/docs/development/linux_development.rst @@ -86,6 +86,15 @@ Everything in one command: g++ gpsd gpsd-clients libgps-dev libdbus-glib-1-dev freeglut3-dev libxft-dev \ libglib2.0-dev libfreeimage-dev gettext protobuf-c-compiler libprotobuf-c-dev +For Raspberry Pi OS: + +.. code-block:: bash + + sudo apt-get install cmake zlib1g-dev libpng-dev libgtk2.0-dev librsvg2-bin \ + g++ gpsd gpsd-clients libgps-dev libdbus-glib-1-dev freeglut3-dev libxft-dev \ + libglib2.0-dev libfreeimage-dev gettext protobuf-c-compiler libprotobuf-c-dev + + Fedora dependencies ------------------- diff --git a/docs/development/macos_development.rst b/docs/development/macos_development.rst index b1559c0a5..bfc2b2b43 100644 --- a/docs/development/macos_development.rst +++ b/docs/development/macos_development.rst @@ -4,6 +4,10 @@ MacOS Development Here are some notes about running navit under Apple Mac OSX. +================================================================================================================================ +WARNING: These instructions are currently unmaintained. Please feel free to submit a PR if you manage to build navit on Mac OSX. +================================================================================================================================ + What you will need ================== diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 5d8e2d734..edb4fd4f7 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -40,7 +40,7 @@ platform :android do if isOnMasterBranch upload_to_play_store( track: 'beta', json_key: 'key.json', - apk: 'navit/android/build/outputs/apk/release/android-release.apk', + apk: 'build/outputs/apk/release/navit-release.apk', package_name: 'org.navitproject.navit' ) else diff --git a/fastlane/metadata/android/de_DE/full_description.txt b/fastlane/metadata/android/de-DE/full_description.txt index 3c3efd6a3..3c3efd6a3 100644 --- a/fastlane/metadata/android/de_DE/full_description.txt +++ b/fastlane/metadata/android/de-DE/full_description.txt diff --git a/fastlane/metadata/android/de_DE/images/phoneScreenshots/1_de-DE.jpeg b/fastlane/metadata/android/de-DE/images/phoneScreenshots/1_de-DE.jpeg Binary files differindex 6792d911b..6792d911b 100644 --- a/fastlane/metadata/android/de_DE/images/phoneScreenshots/1_de-DE.jpeg +++ b/fastlane/metadata/android/de-DE/images/phoneScreenshots/1_de-DE.jpeg diff --git a/fastlane/metadata/android/de_DE/images/phoneScreenshots/2_de-DE.jpeg b/fastlane/metadata/android/de-DE/images/phoneScreenshots/2_de-DE.jpeg Binary files differindex 72a609cd2..72a609cd2 100644 --- a/fastlane/metadata/android/de_DE/images/phoneScreenshots/2_de-DE.jpeg +++ b/fastlane/metadata/android/de-DE/images/phoneScreenshots/2_de-DE.jpeg diff --git a/fastlane/metadata/android/de_DE/short_description.txt b/fastlane/metadata/android/de-DE/short_description.txt index f5b38ca77..f5b38ca77 100644 --- a/fastlane/metadata/android/de_DE/short_description.txt +++ b/fastlane/metadata/android/de-DE/short_description.txt diff --git a/fastlane/metadata/android/de_DE/title.txt b/fastlane/metadata/android/de-DE/title.txt index c0fbba6e0..c0fbba6e0 100644 --- a/fastlane/metadata/android/de_DE/title.txt +++ b/fastlane/metadata/android/de-DE/title.txt diff --git a/fastlane/metadata/android/de_DE/video.txt b/fastlane/metadata/android/de-DE/video.txt index e69de29bb..e69de29bb 100644 --- a/fastlane/metadata/android/de_DE/video.txt +++ b/fastlane/metadata/android/de-DE/video.txt diff --git a/fastlane/metadata/android/en_US/changelogs/navit 0.5.1-1804161521.txt b/fastlane/metadata/android/en-US/changelogs/navit 0.5.1-1804161521.txt index 4f3d19e29..4f3d19e29 100644 --- a/fastlane/metadata/android/en_US/changelogs/navit 0.5.1-1804161521.txt +++ b/fastlane/metadata/android/en-US/changelogs/navit 0.5.1-1804161521.txt diff --git a/fastlane/metadata/android/en_US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index c1707e0f2..c1707e0f2 100644 --- a/fastlane/metadata/android/en_US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt diff --git a/fastlane/metadata/android/en_US/images/featureGraphic.png b/fastlane/metadata/android/en-US/images/featureGraphic.png Binary files differindex 5c766c722..5c766c722 100644 --- a/fastlane/metadata/android/en_US/images/featureGraphic.png +++ b/fastlane/metadata/android/en-US/images/featureGraphic.png diff --git a/fastlane/metadata/android/en_US/images/icon.png b/fastlane/metadata/android/en-US/images/icon.png Binary files differindex b25e9f8d6..b25e9f8d6 100644 --- a/fastlane/metadata/android/en_US/images/icon.png +++ b/fastlane/metadata/android/en-US/images/icon.png diff --git a/fastlane/metadata/android/en_US/images/phoneScreenshots/3_en-US.jpeg b/fastlane/metadata/android/en-US/images/phoneScreenshots/3_en-US.jpeg Binary files differindex 91e3890fa..91e3890fa 100644 --- a/fastlane/metadata/android/en_US/images/phoneScreenshots/3_en-US.jpeg +++ b/fastlane/metadata/android/en-US/images/phoneScreenshots/3_en-US.jpeg diff --git a/fastlane/metadata/android/en_US/images/phoneScreenshots/4_en-US.jpeg b/fastlane/metadata/android/en-US/images/phoneScreenshots/4_en-US.jpeg Binary files differindex b27c020bc..b27c020bc 100644 --- a/fastlane/metadata/android/en_US/images/phoneScreenshots/4_en-US.jpeg +++ b/fastlane/metadata/android/en-US/images/phoneScreenshots/4_en-US.jpeg diff --git a/fastlane/metadata/android/en_US/images/phoneScreenshots/5_en-US.jpeg b/fastlane/metadata/android/en-US/images/phoneScreenshots/5_en-US.jpeg Binary files differindex d2ea0637c..d2ea0637c 100644 --- a/fastlane/metadata/android/en_US/images/phoneScreenshots/5_en-US.jpeg +++ b/fastlane/metadata/android/en-US/images/phoneScreenshots/5_en-US.jpeg diff --git a/fastlane/metadata/android/en_US/images/sevenInchScreenshots/1_en-US.png b/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png Binary files differindex 9eb7bda89..9eb7bda89 100644 --- a/fastlane/metadata/android/en_US/images/sevenInchScreenshots/1_en-US.png +++ b/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png diff --git a/fastlane/metadata/android/en_US/short_description.txt b/fastlane/metadata/android/en-US/short_description.txt index 01629f09c..01629f09c 100644 --- a/fastlane/metadata/android/en_US/short_description.txt +++ b/fastlane/metadata/android/en-US/short_description.txt diff --git a/fastlane/metadata/android/en_US/title.txt b/fastlane/metadata/android/en-US/title.txt index c0fbba6e0..c0fbba6e0 100644 --- a/fastlane/metadata/android/en_US/title.txt +++ b/fastlane/metadata/android/en-US/title.txt diff --git a/fastlane/metadata/android/en_US/video.txt b/fastlane/metadata/android/en-US/video.txt index e69de29bb..e69de29bb 100644 --- a/fastlane/metadata/android/en_US/video.txt +++ b/fastlane/metadata/android/en-US/video.txt diff --git a/fastlane/metadata/android/fr_FR/full_description.txt b/fastlane/metadata/android/fr-FR/full_description.txt index 6ce04465b..6ce04465b 100644 --- a/fastlane/metadata/android/fr_FR/full_description.txt +++ b/fastlane/metadata/android/fr-FR/full_description.txt diff --git a/fastlane/metadata/android/fr_FR/short_description.txt b/fastlane/metadata/android/fr-FR/short_description.txt index 68c88d343..68c88d343 100644 --- a/fastlane/metadata/android/fr_FR/short_description.txt +++ b/fastlane/metadata/android/fr-FR/short_description.txt diff --git a/fastlane/metadata/android/fr_FR/title.txt b/fastlane/metadata/android/fr-FR/title.txt index c0fbba6e0..c0fbba6e0 100644 --- a/fastlane/metadata/android/fr_FR/title.txt +++ b/fastlane/metadata/android/fr-FR/title.txt diff --git a/fastlane/metadata/android/fr_FR/video.txt b/fastlane/metadata/android/fr-FR/video.txt index e69de29bb..e69de29bb 100644 --- a/fastlane/metadata/android/fr_FR/video.txt +++ b/fastlane/metadata/android/fr-FR/video.txt diff --git a/fastlane/metadata/android/nl_NL/full_description.txt b/fastlane/metadata/android/nl-NL/full_description.txt index 992b3b550..992b3b550 100644 --- a/fastlane/metadata/android/nl_NL/full_description.txt +++ b/fastlane/metadata/android/nl-NL/full_description.txt diff --git a/fastlane/metadata/android/nl_NL/short_description.txt b/fastlane/metadata/android/nl-NL/short_description.txt index b91ee980c..b91ee980c 100644 --- a/fastlane/metadata/android/nl_NL/short_description.txt +++ b/fastlane/metadata/android/nl-NL/short_description.txt diff --git a/fastlane/metadata/android/nl_NL/title.txt b/fastlane/metadata/android/nl-NL/title.txt index c0fbba6e0..c0fbba6e0 100644 --- a/fastlane/metadata/android/nl_NL/title.txt +++ b/fastlane/metadata/android/nl-NL/title.txt diff --git a/fastlane/metadata/android/nl_NL/video.txt b/fastlane/metadata/android/nl-NL/video.txt index e69de29bb..e69de29bb 100644 --- a/fastlane/metadata/android/nl_NL/video.txt +++ b/fastlane/metadata/android/nl-NL/video.txt diff --git a/fastlane/metadata/android/pl_PL/full_description.txt b/fastlane/metadata/android/pl-PL/full_description.txt index c1eab69e0..c1eab69e0 100644 --- a/fastlane/metadata/android/pl_PL/full_description.txt +++ b/fastlane/metadata/android/pl-PL/full_description.txt diff --git a/fastlane/metadata/android/pl_PL/short_description.txt b/fastlane/metadata/android/pl-PL/short_description.txt index 043324ca3..043324ca3 100644 --- a/fastlane/metadata/android/pl_PL/short_description.txt +++ b/fastlane/metadata/android/pl-PL/short_description.txt diff --git a/fastlane/metadata/android/pl_PL/title.txt b/fastlane/metadata/android/pl-PL/title.txt index c0fbba6e0..c0fbba6e0 100644 --- a/fastlane/metadata/android/pl_PL/title.txt +++ b/fastlane/metadata/android/pl-PL/title.txt diff --git a/fastlane/metadata/android/pl_PL/video.txt b/fastlane/metadata/android/pl-PL/video.txt index e69de29bb..e69de29bb 100644 --- a/fastlane/metadata/android/pl_PL/video.txt +++ b/fastlane/metadata/android/pl-PL/video.txt diff --git a/fastlane/metadata/android/ru_RU/full_description.txt b/fastlane/metadata/android/ru-RU/full_description.txt index 008118d5f..008118d5f 100644 --- a/fastlane/metadata/android/ru_RU/full_description.txt +++ b/fastlane/metadata/android/ru-RU/full_description.txt diff --git a/fastlane/metadata/android/ru_RU/short_description.txt b/fastlane/metadata/android/ru-RU/short_description.txt index f662bffd1..f662bffd1 100644 --- a/fastlane/metadata/android/ru_RU/short_description.txt +++ b/fastlane/metadata/android/ru-RU/short_description.txt diff --git a/fastlane/metadata/android/ru_RU/title.txt b/fastlane/metadata/android/ru-RU/title.txt index c0fbba6e0..c0fbba6e0 100644 --- a/fastlane/metadata/android/ru_RU/title.txt +++ b/fastlane/metadata/android/ru-RU/title.txt diff --git a/fastlane/metadata/android/ru_RU/video.txt b/fastlane/metadata/android/ru-RU/video.txt index e69de29bb..e69de29bb 100644 --- a/fastlane/metadata/android/ru_RU/video.txt +++ b/fastlane/metadata/android/ru-RU/video.txt diff --git a/gradle/scripts/git-scm-version.gradle b/gradle/scripts/git-scm-version.gradle index 685c95ed8..c6a7cfa09 100644 --- a/gradle/scripts/git-scm-version.gradle +++ b/gradle/scripts/git-scm-version.gradle @@ -15,7 +15,11 @@ import java.time.format.DateTimeFormatter ext { git = Grgit.open(currentDir: projectDir) gitVersionName = git.describe(match: ["v[0-9.rc]*"]) - gitVersionCode = Integer.parseInt(DateTimeFormatter.ofPattern("yyMMddHHmm").format(git.head().dateTime)) + hh = Integer.parseInt(DateTimeFormatter.ofPattern("HH").format(git.head().dateTime)) + mm = Integer.parseInt(DateTimeFormatter.ofPattern("mm").format(git.head().dateTime)) + hhmm = Math.round((hh*4)+(mm/15)).toString() + yyyyMMdd = DateTimeFormatter.ofPattern("yyyyMMdd").format(git.head().dateTime) + gitVersionCode = Integer.parseInt(yyyyMMdd + hhmm) } task printVersion() { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 25f587d12..7292aa85e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,3 +3,4 @@ distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-5.6-all.zip +distributionSha256Sum=33214524e686838c88a88e14e8b30e2323589cc9698186bc8e0594758b132b31 diff --git a/navit/android/AndroidManifest.xml b/navit/android/AndroidManifest.xml index 27c7c3359..b9e646097 100644 --- a/navit/android/AndroidManifest.xml +++ b/navit/android/AndroidManifest.xml @@ -8,6 +8,7 @@ <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:resizeable="true" android:anyDensity="true"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> @@ -16,7 +17,7 @@ android:usesCleartextTraffic="true" android:allowBackup="true" android:fullBackupContent="@xml/navit_backup_rules" - android:icon="@drawable/icon" + android:icon="@mipmap/ic_launcher" android:name=".NavitAppConfig"> <activity android:name="Navit" android:label="@string/app_name" diff --git a/navit/android/build.gradle b/navit/android/build.gradle deleted file mode 100644 index dc19f4f5d..000000000 --- a/navit/android/build.gradle +++ /dev/null @@ -1,107 +0,0 @@ -apply plugin: 'com.android.application' -apply from: "$project.rootDir/gradle/scripts/git-scm-version.gradle" -apply plugin: 'checkstyle' - -android { - compileSdkVersion 29 - buildToolsVersion "29.0.2" - signingConfigs { - release { - // We can leave these in environment variables - storeFile file(System.getenv("KEYSTORE") ?: "/store") - keyAlias System.getenv("KEY_ALIAS") - storePassword System.getenv("STORE_PASS") - keyPassword System.getenv("KEY_PASS") - } - } - defaultConfig { - applicationId "org.navitproject.navit" - minSdkVersion 10 - targetSdkVersion 29 - versionCode gitVersionCode - versionName gitVersionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - ndk { - abiFilters 'x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a' - } - externalNativeBuild { - cmake { - arguments '-DDISABLE_CXX=y', '-DUSE_PLUGINS=n', '-DBUILD_MAPTOOL=n', '-DXSL_PROCESSING=n', '-DSAMPLE_MAP=n' - } - } - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - if(file(System.getenv("KEYSTORE") ?: "/store").exists()){ - signingConfig signingConfigs.release - } - } - } - lintOptions { - disable 'UnusedResources' - abortOnError true - } - sourceSets { - main { - manifest.srcFile "AndroidManifest.xml" - java.srcDirs = ["src"] - resources.srcDirs = ["src"] - renderscript.srcDirs = ["src"] - res.srcDirs = ["res"] - assets.srcDirs = ["assets"] - } - } - externalNativeBuild { - cmake { - path '../../CMakeLists.txt' - } - } - - task checkstyleMain(type: Checkstyle){ - source 'src' - include '**/*.java' - configFile = rootProject.file('checkstyle.xml') - ignoreFailures = false - showViolations = true - // empty classpath - classpath = files() - reports { - include ('**/*.java') - xml.enabled = true - html.enabled = true - xml { - destination file("checkstyle/checkstyleMain.xml") - } - html { - destination file("checkstyle/checkstyleMain.html") - } - } - - checkstyle { - toolVersion = '8.26' - } - } - applicationVariants.all { variant -> - // create tasks to generate Javadocs - task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) { - source = android.sourceSets.main.java.srcDirs - destinationDir = file("build/outputs/docs/javadoc/") - title = rootProject.name - options.memberLevel = JavadocMemberLevel.PACKAGE - verbose = true - failOnError false - } - } - -} -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { - exclude group: 'com.android.support', module: 'support-annotations' - }) - testImplementation 'junit:junit:4.12' - implementation 'ch.acra:acra:4.9.2' -// implementation 'com.android.support:support-v4:28.0.0' -} diff --git a/navit/android/res/drawable-hdpi/ic_launcher_background.png b/navit/android/res/drawable-hdpi/ic_launcher_background.png Binary files differnew file mode 100644 index 000000000..4d8e2e760 --- /dev/null +++ b/navit/android/res/drawable-hdpi/ic_launcher_background.png diff --git a/navit/android/res/drawable-hdpi/ic_launcher_foreground.png b/navit/android/res/drawable-hdpi/ic_launcher_foreground.png Binary files differnew file mode 100644 index 000000000..316279d11 --- /dev/null +++ b/navit/android/res/drawable-hdpi/ic_launcher_foreground.png diff --git a/navit/android/res/drawable-ldpi/ic_launcher_background.png b/navit/android/res/drawable-ldpi/ic_launcher_background.png Binary files differnew file mode 100644 index 000000000..8999f7aa1 --- /dev/null +++ b/navit/android/res/drawable-ldpi/ic_launcher_background.png diff --git a/navit/android/res/drawable-ldpi/ic_launcher_foreground.png b/navit/android/res/drawable-ldpi/ic_launcher_foreground.png Binary files differnew file mode 100644 index 000000000..e06e327bb --- /dev/null +++ b/navit/android/res/drawable-ldpi/ic_launcher_foreground.png diff --git a/navit/android/res/drawable-mdpi/ic_launcher_background.png b/navit/android/res/drawable-mdpi/ic_launcher_background.png Binary files differnew file mode 100644 index 000000000..f2e553f55 --- /dev/null +++ b/navit/android/res/drawable-mdpi/ic_launcher_background.png diff --git a/navit/android/res/drawable-mdpi/ic_launcher_foreground.png b/navit/android/res/drawable-mdpi/ic_launcher_foreground.png Binary files differnew file mode 100644 index 000000000..0196097fb --- /dev/null +++ b/navit/android/res/drawable-mdpi/ic_launcher_foreground.png diff --git a/navit/android/res/drawable-xhdpi/ic_launcher_background.png b/navit/android/res/drawable-xhdpi/ic_launcher_background.png Binary files differnew file mode 100644 index 000000000..58c6beb60 --- /dev/null +++ b/navit/android/res/drawable-xhdpi/ic_launcher_background.png diff --git a/navit/android/res/drawable-xhdpi/ic_launcher_foreground.png b/navit/android/res/drawable-xhdpi/ic_launcher_foreground.png Binary files differnew file mode 100644 index 000000000..70148579d --- /dev/null +++ b/navit/android/res/drawable-xhdpi/ic_launcher_foreground.png diff --git a/navit/android/res/drawable-xxhdpi/ic_launcher_background.png b/navit/android/res/drawable-xxhdpi/ic_launcher_background.png Binary files differnew file mode 100644 index 000000000..df2ea36fb --- /dev/null +++ b/navit/android/res/drawable-xxhdpi/ic_launcher_background.png diff --git a/navit/android/res/drawable-xxhdpi/ic_launcher_foreground.png b/navit/android/res/drawable-xxhdpi/ic_launcher_foreground.png Binary files differnew file mode 100644 index 000000000..ce3ccbc22 --- /dev/null +++ b/navit/android/res/drawable-xxhdpi/ic_launcher_foreground.png diff --git a/navit/android/res/mipmap-anydpi-v26/ic_launcher.xml b/navit/android/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 000000000..6b78462d6 --- /dev/null +++ b/navit/android/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/ic_launcher_background" /> + <foreground android:drawable="@drawable/ic_launcher_foreground" /> +</adaptive-icon> diff --git a/navit/android/res/mipmap-hdpi/ic_launcher.png b/navit/android/res/mipmap-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..ce18b5780 --- /dev/null +++ b/navit/android/res/mipmap-hdpi/ic_launcher.png diff --git a/navit/android/res/mipmap-ldpi/ic_launcher.png b/navit/android/res/mipmap-ldpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..183e2f829 --- /dev/null +++ b/navit/android/res/mipmap-ldpi/ic_launcher.png diff --git a/navit/android/res/mipmap-mdpi/ic_launcher.png b/navit/android/res/mipmap-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..1bde1888e --- /dev/null +++ b/navit/android/res/mipmap-mdpi/ic_launcher.png diff --git a/navit/android/res/mipmap-xhdpi/ic_launcher.png b/navit/android/res/mipmap-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..041c61c03 --- /dev/null +++ b/navit/android/res/mipmap-xhdpi/ic_launcher.png diff --git a/navit/android/res/mipmap-xxhdpi/ic_launcher.png b/navit/android/res/mipmap-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..ad89bd0b5 --- /dev/null +++ b/navit/android/res/mipmap-xxhdpi/ic_launcher.png diff --git a/navit/android/src/org/navitproject/navit/Navit.java b/navit/android/src/org/navitproject/navit/Navit.java index bacc15213..011acd9fe 100644 --- a/navit/android/src/org/navitproject/navit/Navit.java +++ b/navit/android/src/org/navitproject/navit/Navit.java @@ -248,10 +248,15 @@ public class Navit extends Activity { private void verifyPermissions() { if (ContextCompat.checkSelfPermission(this, - Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + return; + } else if (ContextCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) { + return; + } else { Log.d(TAG,"ask for permission(s)"); ActivityCompat.requestPermissions(this, new String[] { - Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQ_FINE_LOC); + Manifest.permission.ACCESS_BACKGROUND_LOCATION}, MY_PERMISSIONS_REQ_FINE_LOC); } } @@ -728,7 +733,7 @@ public class Navit extends Activity { if (resultCode == RESULT_OK) { String newDir = data.getStringExtra(FileBrowserActivity.returnDirectoryParameter); Log.d(TAG, "selected path= " + newDir); - if (!newDir.contains("/navit")) { + if (!(newDir.contains("/navit") || newDir.contains("/org.navitproject.navit"))) { newDir = newDir + "/navit/"; } else { newDir = newDir + "/"; @@ -774,7 +779,8 @@ public class Navit extends Activity { private void setMapLocation() { Intent fileExploreIntent = new Intent(this,FileBrowserActivity.class); fileExploreIntent - .putExtra(FileBrowserActivity.startDirectoryParameter, "/mnt") + .putExtra(FileBrowserActivity.startDirectoryParameter, + getApplicationContext().getExternalFilesDir(null).toString()) .setAction(FileBrowserActivity.INTENT_ACTION_SELECT_DIR); startActivityForResult(fileExploreIntent,NavitSelectStorage_id); } diff --git a/navit/android/src/org/navitproject/navit/NavitTraff.java b/navit/android/src/org/navitproject/navit/NavitTraff.java index c82d7d293..fd499b70b 100644 --- a/navit/android/src/org/navitproject/navit/NavitTraff.java +++ b/navit/android/src/org/navitproject/navit/NavitTraff.java @@ -25,11 +25,18 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.IntentFilter.MalformedMimeTypeException; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; import android.util.Log; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; /** * The TraFF receiver implementation. @@ -39,11 +46,46 @@ import java.util.List; */ public class NavitTraff extends BroadcastReceiver { + private static final String ACTION_TRAFF_GET_CAPABILITIES = "org.traffxml.traff.GET_CAPABILITIES"; + private static final String ACTION_TRAFF_HEARTBEAT = "org.traffxml.traff.HEARTBEAT"; private static final String ACTION_TRAFF_FEED = "org.traffxml.traff.FEED"; private static final String ACTION_TRAFF_POLL = "org.traffxml.traff.POLL"; + private static final String ACTION_TRAFF_SUBSCRIBE = "org.traffxml.traff.SUBSCRIBE"; + private static final String ACTION_TRAFF_SUBSCRIPTION_CHANGE = "org.traffxml.traff.SUBSCRIPTION_CHANGE"; + private static final String ACTION_TRAFF_UNSUBSCRIBE = "org.traffxml.traff.UNSUBSCRIBE"; + private static final String COLUMN_DATA = "data"; + private static final String CONTENT_SCHEMA = "content"; + private static final String[] ERROR_STRINGS = { + "unknown (0)", + "invalid request (1)", + "subscription rejected by the source (2)", + "requested area not covered (3)", + "requested area partially covered (4)", + "subscription ID not recognized by the source (5)", + "unknown (6)", + "source reported an internal error (7)" + }; + private static final String EXTRA_CAPABILITIES = "capabilities"; private static final String EXTRA_FEED = "feed"; + private static final String EXTRA_FILTER_LIST = "filter_list"; + private static final String EXTRA_PACKAGE = "package"; + private static final String EXTRA_SUBSCRIPTION_ID = "subscription_id"; + private static final String MIME_TYPE_TRAFF = "vnd.android.cursor.dir/org.traffxml.message"; + private static final int RESULT_OK = -1; + private static final int RESULT_INTERNAL_ERROR = 7; + private static final int RESULT_INVALID = 1; + private static final int RESULT_SUBSCRIPTION_REJECTED = 2; + private static final int RESULT_NOT_COVERED = 3; + private static final int RESULT_PARTIALLY_COVERED = 4; + private static final int RESULT_SUBSCRIPTION_UNKNOWN = 5; + private static final String TAG = "NavitTraff"; private final long mCbid; + private final Context context; + + /** Active subscriptions (key is the subscription ID, value is the package ID). */ + private Map<String, String> subscriptions = new HashMap<String, String>(); + /** * Forwards a newly received TraFF feed to the traffic module for processing. * @@ -65,39 +107,322 @@ public class NavitTraff extends BroadcastReceiver { */ NavitTraff(Context context, long cbid) { this.mCbid = cbid; + this.context = context.getApplicationContext(); + + /* An intent filter for TraFF 0.7 events. */ + IntentFilter traffFilter07 = new IntentFilter(); + traffFilter07.addAction(ACTION_TRAFF_FEED); - /* An intent filter for TraFF events. */ - IntentFilter traffFilter = new IntentFilter(); - traffFilter.addAction(ACTION_TRAFF_FEED); - traffFilter.addAction(ACTION_TRAFF_POLL); + /* An intent filter for TraFF 0.8 events. */ + IntentFilter traffFilter08 = new IntentFilter(); + traffFilter08.addAction(ACTION_TRAFF_FEED); + traffFilter08.addDataScheme(CONTENT_SCHEMA); + try { + traffFilter08.addDataType(MIME_TYPE_TRAFF); + } catch (MalformedMimeTypeException e) { + // as long as the constant is a well-formed MIME type, this exception never gets thrown + e.printStackTrace(); + } - context.registerReceiver(this, traffFilter); - /* TODO unregister receiver on exit */ + this.context.registerReceiver(this, traffFilter07); + this.context.registerReceiver(this, traffFilter08); - /* Broadcast a poll intent */ + /* Broadcast a poll intent to all TraFF 0.7-only receivers */ Intent outIntent = new Intent(ACTION_TRAFF_POLL); - PackageManager pm = context.getPackageManager(); - List<ResolveInfo> receivers = pm.queryBroadcastReceivers(outIntent, 0); - if (receivers != null) { - for (ResolveInfo receiver : receivers) { + PackageManager pm = this.context.getPackageManager(); + List<ResolveInfo> receivers07 = pm.queryBroadcastReceivers(outIntent, 0); + List<ResolveInfo> receivers08 = pm.queryBroadcastReceivers(new Intent(ACTION_TRAFF_GET_CAPABILITIES), 0); + if (receivers07 != null) { + /* get receivers which support only TraFF 0.7 and poll them */ + if (receivers08 != null) + receivers07.removeAll(receivers08); + for (ResolveInfo receiver : receivers07) { ComponentName cn = new ComponentName(receiver.activityInfo.applicationInfo.packageName, receiver.activityInfo.name); outIntent = new Intent(ACTION_TRAFF_POLL); outIntent.setComponent(cn); - context.sendBroadcast(outIntent, Manifest.permission.ACCESS_COARSE_LOCATION); + this.context.sendBroadcast(outIntent, Manifest.permission.ACCESS_COARSE_LOCATION); + } + } + } + + void close() { + for (Map.Entry<String, String> subscription : subscriptions.entrySet()) { + Bundle extras = new Bundle(); + extras.putString(EXTRA_SUBSCRIPTION_ID, subscription.getKey()); + sendTraffIntent(this.context, ACTION_TRAFF_UNSUBSCRIBE, null, extras, subscription.getValue(), + Manifest.permission.ACCESS_COARSE_LOCATION, this); + } + this.context.unregisterReceiver(this); + } + + void onFilterUpdate(String filterList) { + /* change existing subscriptions */ + for (Map.Entry<String, String> entry : subscriptions.entrySet()) { + Log.d(TAG, String.format("changing subscription %s (%s)", entry.getKey(), entry.getValue())); + Bundle extras = new Bundle(); + extras.putString(EXTRA_SUBSCRIPTION_ID, entry.getKey()); + extras.putString(EXTRA_FILTER_LIST, filterList); + sendTraffIntent(context, ACTION_TRAFF_SUBSCRIPTION_CHANGE, null, extras, + entry.getValue(), + Manifest.permission.ACCESS_COARSE_LOCATION, this); + } + + /* set up missing subscriptions */ + PackageManager pm = this.context.getPackageManager(); + List<ResolveInfo> receivers = pm.queryBroadcastReceivers(new Intent(ACTION_TRAFF_GET_CAPABILITIES), 0); + if (receivers != null) { + /* filter out receivers to which we are already subscribed */ + Iterator<ResolveInfo> iter = receivers.iterator(); + while (iter.hasNext()) { + ResolveInfo receiver = iter.next(); + if (subscriptions.containsValue(receiver.activityInfo.applicationInfo.packageName)) + iter.remove(); + } + + for (ResolveInfo receiver : receivers) { + Log.d(TAG, "subscribing to " + receiver.activityInfo.applicationInfo.packageName); + Bundle extras = new Bundle(); + extras.putString(EXTRA_PACKAGE, context.getPackageName()); + extras.putString(EXTRA_FILTER_LIST, filterList); + sendTraffIntent(context, ACTION_TRAFF_SUBSCRIBE, null, extras, + receiver.activityInfo.applicationInfo.packageName, + Manifest.permission.ACCESS_COARSE_LOCATION, this); } } } @Override public void onReceive(Context context, Intent intent) { - if ((intent != null) && (intent.getAction().equals(ACTION_TRAFF_FEED))) { - String feed = intent.getStringExtra(EXTRA_FEED); - if (feed == null) { - Log.w(this.getClass().getSimpleName(), "empty feed, ignoring"); - } else { - onFeedReceived(mCbid, feed); + if (intent != null) { + if (intent.getAction().equals(ACTION_TRAFF_FEED)) { + Uri uri = intent.getData(); + if (uri != null) { + /* 0.8 feed */ + String subscriptionId = intent.getStringExtra(EXTRA_SUBSCRIPTION_ID); + if (subscriptions.containsKey(subscriptionId)) + fetchMessages(context, uri); + else { + /* + * If we don’t recognize the subscription, skip processing and unsubscribe. + * Note: if EXTRA_PACKAGE is not set, sendTraffIntent() sends the request to every + * manifest-declared receiver which handles the request. + */ + Log.d(TAG, + String.format("got a feed from %s for unknown subscription %s, URI %s; unsubscribing", + intent.getStringExtra(EXTRA_PACKAGE), subscriptionId, uri)); + Bundle extras = new Bundle(); + extras.putString(EXTRA_SUBSCRIPTION_ID, subscriptionId); + sendTraffIntent(context, ACTION_TRAFF_UNSUBSCRIBE, null, extras, + intent.getStringExtra(EXTRA_PACKAGE), + Manifest.permission.ACCESS_COARSE_LOCATION, this); + } + } else { + /* 0.7 feed */ + String packageName = intent.getStringExtra(EXTRA_PACKAGE); + /* + * If the feed comes from a TraFF 0.8+ source and we are subscribed, skip it. + * As a side effect of the current implementation, if a “bilingual” TraFF 0.7/0.8 + * source sends a broadcast feed before we have subscribed to it, we would process + * the whole feed first, and then subscribe to a subset of that data. + * If that turns out to be an issue, we would need to detect TraFF 0.8-capable + * sources and discard broadcast feeds from them. + */ + if ((packageName != null) && subscriptions.containsValue(packageName)) + return; + String feed = intent.getStringExtra(EXTRA_FEED); + if (feed == null) { + Log.w(this.getClass().getSimpleName(), "empty feed, ignoring"); + } else { + onFeedReceived(mCbid, feed); + } + } // uri != null + } else if (intent.getAction().equals(ACTION_TRAFF_SUBSCRIBE)) { + if (this.getResultCode() != RESULT_OK) { + Bundle extras = this.getResultExtras(true); + if (extras != null) + Log.e(this.getClass().getSimpleName(), String.format("subscription to %s failed, %s", + extras.getString(EXTRA_PACKAGE), formatTraffError(this.getResultCode()))); + else + Log.e(this.getClass().getSimpleName(), String.format("subscription failed, %s", + formatTraffError(this.getResultCode()))); + return; + } + Bundle extras = this.getResultExtras(true); + String data = this.getResultData(); + String packageName = extras.getString(EXTRA_PACKAGE); + String subscriptionId = extras.getString(EXTRA_SUBSCRIPTION_ID); + if (subscriptionId == null) { + Log.e(this.getClass().getSimpleName(), + String.format("subscription to %s failed: no subscription ID returned", packageName)); + return; + } else if (packageName == null) { + Log.e(this.getClass().getSimpleName(), "subscription failed: no package name"); + return; + } else if (data == null) { + Log.w(this.getClass().getSimpleName(), + String.format("subscription to %s successful (ID: %s) but no content URI was supplied. " + + "This is an issue with the source and may result in delayed message retrieval.", + packageName, subscriptionId)); + subscriptions.put(subscriptionId, packageName); + return; + } + Log.d(TAG, "subscription to " + packageName + " successful, ID: " + subscriptionId); + subscriptions.put(subscriptionId, packageName); + fetchMessages(context, Uri.parse(data)); + } else if (intent.getAction().equals(ACTION_TRAFF_SUBSCRIPTION_CHANGE)) { + if (this.getResultCode() != RESULT_OK) { + Bundle extras = this.getResultExtras(true); + if (extras != null) + Log.e(this.getClass().getSimpleName(), + String.format("subscription change for %s failed: %s", + extras.getString(EXTRA_SUBSCRIPTION_ID), + formatTraffError(this.getResultCode()))); + else + Log.e(this.getClass().getSimpleName(), + String.format("subscription change failed: %s", + formatTraffError(this.getResultCode()))); + return; + } + Bundle extras = intent.getExtras(); + String data = this.getResultData(); + String subscriptionId = extras.getString(EXTRA_SUBSCRIPTION_ID); + if (subscriptionId == null) { + Log.w(this.getClass().getSimpleName(), + "subscription change successful but the source did not specify the subscription ID. " + + "This is an issue with the source and may result in delayed message retrieval. " + + "URI: " + data); + return; + } else if (data == null) { + Log.w(this.getClass().getSimpleName(), + String.format("subscription change for %s successful but no content URI was supplied. " + + "This is an issue with the source and may result in delayed message retrieval.", + subscriptionId)); + return; + } else if (!subscriptions.containsKey(subscriptionId)) { + Log.e(this.getClass().getSimpleName(), + "subscription change failed: unknown subscription ID " + subscriptionId); + return; + } + Log.d(TAG, "subscription change for " + subscriptionId + " successful"); + fetchMessages(context, Uri.parse(data)); + } else if (intent.getAction().equals(ACTION_TRAFF_UNSUBSCRIBE)) { + /* + * If we ever unsubscribe for reasons other than that we are shutting down or got a feed for + * a subscription we don’t recognize, or if we start keeping a persistent list of + * subscriptions, we need to delete the subscription from our list. Until then, there is + * nothing to do here: either the subscription isn’t in the list, or we are about to shut + * down and the whole list is about to get discarded. + */ + } else if (intent.getAction().equals(ACTION_TRAFF_HEARTBEAT)) { + String subscriptionId = intent.getStringExtra(EXTRA_SUBSCRIPTION_ID); + if (subscriptions.containsKey(subscriptionId)) { + Log.d(TAG, + String.format("got a heartbeat from %s for subscription %s; sending result", + intent.getStringExtra(EXTRA_PACKAGE), subscriptionId)); + this.setResult(RESULT_OK, null, null); + } else { + /* + * If we don’t recognize the subscription, skip reply and unsubscribe. + * Note: if EXTRA_PACKAGE is not set, sendTraffIntent() sends the request to every + * manifest-declared receiver which handles the request. + */ + Log.d(TAG, + String.format("got a heartbeat from %s for unknown subscription %s; unsubscribing", + intent.getStringExtra(EXTRA_PACKAGE), subscriptionId)); + Bundle extras = new Bundle(); + extras.putString(EXTRA_SUBSCRIPTION_ID, subscriptionId); + sendTraffIntent(context, ACTION_TRAFF_UNSUBSCRIBE, null, extras, + intent.getStringExtra(EXTRA_PACKAGE), + Manifest.permission.ACCESS_COARSE_LOCATION, this); + } + } // intent.getAction() + } // intent != null + } + + /** + * Fetches messages from a content provider. + * + * @param context The context to use for the content resolver + * @param uri The content provider URI + */ + private void fetchMessages(Context context, Uri uri) { + try { + Cursor cursor = context.getContentResolver().query(uri, new String[] {COLUMN_DATA}, null, null, null); + if (cursor == null) + return; + if (cursor.getCount() < 1) { + cursor.close(); + return; } + StringBuilder builder = new StringBuilder("<feed>\n"); + while (cursor.moveToNext()) + builder.append(cursor.getString(cursor.getColumnIndex(COLUMN_DATA))).append("\n"); + builder.append("</feed>"); + cursor.close(); + onFeedReceived(mCbid, builder.toString()); + } catch (Exception e) { + Log.w(TAG, String.format("Unable to fetch messages from %s", uri.toString()), e); + e.printStackTrace(); } } + + /** + * Sends a TraFF intent to a source. This encapsulates most of the low-level Android handling. + * + * <p>If the recipient specified in {@code packageName} declares multiple receivers for the intent in its + * manifest, a separate intent will be delivered to each of them. The intent will not be delivered to + * receivers registered at runtime. + * + * <p>All intents are sent as explicit ordered broadcasts. This means two things: + * + * <p>Any app which declares a matching receiver in its manifest will be woken up to process the intent. + * This works even with certain Android 7 builds which restrict intent delivery to apps which are not + * currently running. + * + * <p>It is safe for the recipient to unconditionally set result data. If the recipient does not set result + * data, the result will have a result code of {@link #RESULT_INTERNAL_ERROR}, no data and no extras. + * + * @param context The context + * @param action The intent action. + * @param data The intent data (for TraFF, this is the content provider URI), or null + * @param extras The extras for the intent + * @param packageName The package name for the recipient, or null to deliver the intent to all matching receivers + * @param receiverPermission A permission which the recipient must hold, or null if not required + * @param resultReceiver A BroadcastReceiver which will receive the result for the intent + */ + /* From traff-consumer-android, by the same author and re-licensed under GPL2 for Navit */ + public static void sendTraffIntent(Context context, String action, Uri data, Bundle extras, String packageName, + String receiverPermission, BroadcastReceiver resultReceiver) { + Intent outIntent = new Intent(action); + PackageManager pm = context.getPackageManager(); + List<ResolveInfo> receivers = pm.queryBroadcastReceivers(outIntent, 0); + if (receivers != null) + for (ResolveInfo receiver : receivers) { + if ((packageName != null) && !packageName.equals(receiver.activityInfo.applicationInfo.packageName)) + continue; + ComponentName cn = new ComponentName(receiver.activityInfo.applicationInfo.packageName, + receiver.activityInfo.name); + outIntent = new Intent(action); + if (data != null) + outIntent.setData(data); + if (extras != null) + outIntent.putExtras(extras); + outIntent.setComponent(cn); + context.sendOrderedBroadcast(outIntent, + receiverPermission, + resultReceiver, + null, // scheduler, + RESULT_INTERNAL_ERROR, // initialCode, + null, // initialData, + null); + } + } + + private static String formatTraffError(int code) { + if ((code < 0) || (code >= ERROR_STRINGS.length)) + return String.format("unknown (%d)", code); + else + return ERROR_STRINGS[code]; + } } diff --git a/navit/attr.c b/navit/attr.c index de2a508f0..b9d54899f 100644 --- a/navit/attr.c +++ b/navit/attr.c @@ -680,6 +680,10 @@ attr_generic_prepend_attr(struct attr **attrs, struct attr *attr) { * * If `attrs` does not contain `attr`, this function is a no-op. * + * Attributes are matched based on their `type` and `u.data` members, thus `attr` can be a shallow copy + * of the attribute, and can match multiple attributes in the list. The `attr` argument itself is not + * changed. + * * @param attrs The attribute list * @param attr The attribute to remove from the list * diff --git a/navit/attr_def.h b/navit/attr_def.h index 45764ebb2..e5f3033ff 100644 --- a/navit/attr_def.h +++ b/navit/attr_def.h @@ -203,6 +203,7 @@ ATTR(nav_status) ATTR(virtual_dpi) ATTR(real_dpi) ATTR(underground_alpha) +ATTR(sunrise_degrees) ATTR2(0x00027500,type_rel_abs_begin) /* These attributes are int that can either hold relative or absolute values. See the * documentation of ATTR_REL_RELSHIFT for details. @@ -264,6 +265,8 @@ ATTR(no_warning_if_map_file_missing) ATTR(duplicate) ATTR(has_menu_button) ATTR(oneway) +ATTR(tunnel_nightlayout) +ATTR(layout_daynightauto) ATTR2(0x0002ffff,type_int_end) ATTR2(0x00030000,type_string_begin) ATTR(type) @@ -404,6 +407,7 @@ ATTR(street_destination) ATTR(exit_to) ATTR(street_destination_forward) ATTR(street_destination_backward) +ATTR(outputdir) ATTR2(0x0003ffff,type_string_end) ATTR2(0x00040000,type_special_begin) ATTR(order) diff --git a/navit/command.c b/navit/command.c index cc498b1a7..f2c6c0bb0 100644 --- a/navit/command.c +++ b/navit/command.c @@ -158,7 +158,7 @@ static void result_free(struct result *res) { attr_free_content(&res->attr); res->allocated=0; } else { - res->attr.type=type_none; + res->attr.type=attr_none; res->attr.u.data=NULL; } } diff --git a/navit/graphics/qt5/graphics_qt5.cpp b/navit/graphics/qt5/graphics_qt5.cpp index 11f480c0a..e2747ff78 100644 --- a/navit/graphics/qt5/graphics_qt5.cpp +++ b/navit/graphics/qt5/graphics_qt5.cpp @@ -45,6 +45,7 @@ extern "C" { #include <QFont> #include <QGuiApplication> #include <QPainter> +#include <QPainterPath> #include <QPixmap> #include <QScreen> #include <QSvgRenderer> diff --git a/navit/graphics/svg_debug/CMakeLists.txt b/navit/graphics/svg_debug/CMakeLists.txt new file mode 100644 index 000000000..2bc202c1e --- /dev/null +++ b/navit/graphics/svg_debug/CMakeLists.txt @@ -0,0 +1,2 @@ +module_add_library(graphics_svg_debug graphics_svg_debug.c) + diff --git a/navit/graphics/svg_debug/graphics_svg_debug.c b/navit/graphics/svg_debug/graphics_svg_debug.c new file mode 100644 index 000000000..348906ad8 --- /dev/null +++ b/navit/graphics/svg_debug/graphics_svg_debug.c @@ -0,0 +1,782 @@ +/* + * Navit, a modular navigation system. + * Copyright (C) 2020 Navit Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * This Plugin can act as a Plugin + * + */ +#include "color.h" +#include <glib.h> +#include "config.h" +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <glib.h> +#include <gio/gio.h> +#include <pthread.h> +#include <poll.h> +#include <signal.h> + +#include "config.h" +#include "debug.h" +#include "point.h" +#include "graphics.h" + +#include "plugin.h" +#include "window.h" +#include "navit.h" +#include "keys.h" +#include "item.h" +#include "attr.h" +#include "item.h" +#include "attr.h" +#include "point.h" +#include "graphics.h" +#include "color.h" +#include "navit.h" +#include "event.h" +#include "debug.h" +#include "callback.h" +#include "util.h" + +struct graphics_priv { + + unsigned int frame; + int width; + int height; + int fullscreen; + struct color bg_color; + FILE *outfile; + const char *outputdir; + void *proxy_priv; + struct graphics_methods *proxy_graphics_methods; + struct navit *nav; + struct callback_list *cbl; +}; + +struct graphics_font_priv { + int size; + char *font; + struct graphics_font graphics_font_proxy; +}; + +struct graphics_gc_priv { + struct graphics_priv *gr; + unsigned int *dashed; + int is_dashed; + struct color fg; + struct color bg; + int linewidth; + struct graphics_image_priv *img; + struct graphics_gc_priv *graphics_gc_priv_proxy; + struct graphics_gc_methods *graphics_gc_methods_proxy; +}; + +struct graphics_image_priv { + int w, h; + char *data; + struct graphics_image_priv *graphics_image_priv_proxy; + struct graphics_image_methods *graphics_image_methods_proxy; +}; + +static void svg_debug_graphics_destroy(struct graphics_priv *gr) { + // TODO +} + +static void svg_debug_font_destroy(struct graphics_font_priv *this); +void svg_debug_get_text_bbox(struct graphics_priv *gr, + struct graphics_font_priv *font, char *text, int dx, int dy, + struct point *ret, int estimate); + +static struct graphics_font_methods font_methods = { .font_destroy = + svg_debug_font_destroy, +}; + +static void resize_callback_do(struct graphics_priv *gr, int w, int h) { + dbg(lvl_debug, "resize_callback w:%i h:%i", w, h) + gr->width = w; + gr->height = h; +} + +static void svg_debug_font_destroy(struct graphics_font_priv *this) { + dbg(lvl_debug, "enter font_destroy"); + if (this->graphics_font_proxy.meth.font_destroy) { + this->graphics_font_proxy.meth.font_destroy( + this->graphics_font_proxy.priv); + } + g_free(this); +} + +static struct graphics_font_priv* svg_debug_font_new(struct graphics_priv *gr, + struct graphics_font_methods *meth, char *font, int size, int flags) { + struct graphics_font_priv *priv = g_new(struct graphics_font_priv, 1); + + *meth = font_methods; + + priv->size = size / 10; + if (gr->proxy_graphics_methods->font_new) { + priv->graphics_font_proxy.priv = gr->proxy_graphics_methods->font_new( + gr->proxy_priv, &priv->graphics_font_proxy.meth, font, size, + flags); + } else { + return priv; + } + if (priv->graphics_font_proxy.priv) { + return priv; + } + return NULL; +} +void svg_debug_get_text_bbox(struct graphics_priv *gr, + struct graphics_font_priv *font, char *text, int dx, int dy, + struct point *ret, int estimate) { + if (gr->proxy_graphics_methods->get_text_bbox) { + gr->proxy_graphics_methods->get_text_bbox(gr->proxy_priv, + font->graphics_font_proxy.priv, text, dx, dy, ret, estimate); + } +} + +static void svg_debug_gc_destroy(struct graphics_gc_priv *gc) { + if (gc->graphics_gc_methods_proxy->gc_destroy) { + gc->graphics_gc_methods_proxy->gc_destroy(gc->graphics_gc_priv_proxy); + } + g_free(gc->graphics_gc_methods_proxy); + g_free(gc); +} + +static void svg_debug_gc_set_linewidth(struct graphics_gc_priv *gc, int w) { + gc->linewidth = w; + if (gc->graphics_gc_methods_proxy->gc_set_linewidth) { + gc->graphics_gc_methods_proxy->gc_set_linewidth( + gc->graphics_gc_priv_proxy, w); + } + +} + +static void svg_debug_gc_set_dashes(struct graphics_gc_priv *gc, int w, + int offset, unsigned char *dash_list, int n) { + gc->dashed = dash_list; + gc->is_dashed = TRUE; + if (gc->graphics_gc_methods_proxy->gc_set_dashes) { + gc->graphics_gc_methods_proxy->gc_set_dashes(gc->graphics_gc_priv_proxy, + w, offset, dash_list, n); + } +} + +static void svg_debug_gc_set_foreground(struct graphics_gc_priv *gc, + struct color *c) { + gc->fg.r = c->r / 256; + gc->fg.g = c->g / 256; + gc->fg.b = c->b / 256; + gc->fg.a = c->a / 256; + if (gc->graphics_gc_methods_proxy->gc_set_foreground) { + gc->graphics_gc_methods_proxy->gc_set_foreground( + gc->graphics_gc_priv_proxy, c); + } +} + +static void svg_debug_gc_set_background(struct graphics_gc_priv *gc, + struct color *c) { + gc->bg.r = c->r / 256; + gc->bg.g = c->g / 256; + gc->bg.b = c->b / 256; + gc->bg.a = c->a / 256; + if (gc->graphics_gc_methods_proxy->gc_set_foreground) { + gc->graphics_gc_methods_proxy->gc_set_foreground( + gc->graphics_gc_priv_proxy, c); + } +} + +static void svg_debug_gc_set_texture(struct graphics_gc_priv *gc, + struct graphics_image_priv *img) { + gc->img = img; +} + +static struct graphics_gc_methods gc_methods = { .gc_destroy = + svg_debug_gc_destroy, .gc_set_linewidth = svg_debug_gc_set_linewidth, + .gc_set_dashes = svg_debug_gc_set_dashes, .gc_set_foreground = + svg_debug_gc_set_foreground, .gc_set_background = + svg_debug_gc_set_background, .gc_set_texture = + svg_debug_gc_set_texture, +}; + +static struct graphics_gc_priv* svg_debug_gc_new(struct graphics_priv *gr, + struct graphics_gc_methods *meth) { + struct graphics_gc_priv *gc = g_new0(struct graphics_gc_priv, 1); + struct graphics_gc_priv *graphics_gc_priv_proxy = g_new0( + struct graphics_gc_priv, 1); + struct graphics_gc_methods *graphics_gc_methods_proxy = g_new0( + struct graphics_gc_methods, 1); + *meth = gc_methods; + gc->gr = gr; + gc->is_dashed = FALSE; + gc->linewidth = 1; + + if (gr->proxy_graphics_methods->gc_new) { + gr->proxy_graphics_methods->gc_new(gr->proxy_priv, + graphics_gc_methods_proxy); + } + gc->graphics_gc_methods_proxy = graphics_gc_methods_proxy; + gc->graphics_gc_priv_proxy = graphics_gc_priv_proxy; + return gc; +} + +void svg_debug_image_destroy(struct graphics_image_priv *img); +void svg_debug_image_destroy(struct graphics_image_priv *img) { + dbg(lvl_debug, "enter image_destroy"); + g_free(img->data); + if (img->graphics_image_methods_proxy->image_destroy) { + img->graphics_image_methods_proxy->image_destroy( + img->graphics_image_priv_proxy); + } + g_free(img->data); + g_free(img->graphics_image_methods_proxy); + g_free(img->graphics_image_priv_proxy); + g_free(img); +} + +static struct graphics_image_methods image_methods = { .image_destroy = + svg_debug_image_destroy, +}; + +static struct graphics_image_priv* svg_debug_image_new(struct graphics_priv *gr, + struct graphics_image_methods *meth, char *path, int *w, int *h, + struct point *hot, int rotation) { + struct graphics_image_priv *image_priv; + struct graphics_image_methods *graphics_image_methods; + char *base64_data_url = NULL; + char *base64_encoded_image = NULL; + char *image_mime_type = NULL; + char *contents = NULL; + char fileext[3] = ""; + gsize img_size; + + image_priv = g_new0(struct graphics_image_priv, 1); + graphics_image_methods = g_new0(struct graphics_image_methods, 1); + *meth = image_methods; + const char *data_url_template = "data:%s;base64,%s"; + + if (g_file_get_contents(path, &contents, &img_size, NULL)) { + dbg(lvl_debug, "image_new loaded %s", path); + + strtolower(fileext, &path[(strlen(path) - 3)]); + if (strcmp(fileext, "png")) { + image_mime_type = "image/png"; + } else if (strcmp(fileext, "jpg")) { + image_mime_type = "image/jpeg"; + } else if (strcmp(fileext, "gif")) { + image_mime_type = "image/gif"; + } else { + image_mime_type = "application/octet-stream"; + } + base64_encoded_image = g_base64_encode((guchar*) contents, img_size); + + base64_data_url = g_malloc0( + strlen(base64_encoded_image) + strlen(data_url_template) + + strlen(image_mime_type) + 1); + sprintf(base64_data_url, data_url_template, image_mime_type, + base64_encoded_image); + g_free(base64_encoded_image); + + image_priv->data = base64_data_url; + g_free(contents); + image_priv->h = *h; + image_priv->w = *w; + } else { + dbg(lvl_error, "image_new failed to load %s", path); + image_priv->data = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="; + image_priv->h = 1; + image_priv->w = 1; + } + if (gr->proxy_graphics_methods->image_new) { + image_priv->graphics_image_priv_proxy = + gr->proxy_graphics_methods->image_new(gr->proxy_priv, + graphics_image_methods, path, w, h, hot, rotation); + image_priv->graphics_image_methods_proxy = graphics_image_methods; + } + if (image_priv->graphics_image_priv_proxy) { + return image_priv; + } + if (base64_data_url != NULL) { + g_free(base64_data_url); + } + g_free(graphics_image_methods); + g_free(image_priv); + return NULL; +} + +static void svg_debug_draw_lines(struct graphics_priv *gr, + struct graphics_gc_priv *gc, struct point *p, int count) { + const char *line_template_start = "<polyline points=\""; + const char *coord_template = "%i,%i "; + const char *dashed_template_start = "\" stroke-dasharray=\""; + const char *dashed_dasharray = "%i "; + const char *dashed_template_end = ""; + const char *line_template_end = + "\" style=\"fill:none;stroke:rgb(%i,%i,%i);stroke-width:%i\" />\n"; + + fprintf(gr->outfile, line_template_start, ""); + int i; + for (i = 0; i < count; i++) { + fprintf(gr->outfile, coord_template, p[i].x, p[i].y); + } + + if (gc->is_dashed) { + fprintf(gr->outfile, dashed_template_start, ""); + int i; + for (i = 0; i < 4; i++) { + fprintf(gr->outfile, dashed_dasharray, gc->dashed[i]); + } + fprintf(gr->outfile, dashed_template_end, ""); + } + + fprintf(gr->outfile, line_template_end, gc->fg.r, gc->fg.g, gc->fg.b, + gc->linewidth); + + if (gr->proxy_graphics_methods->draw_lines) { + gr->proxy_graphics_methods->draw_lines(gr->proxy_priv, + gc->graphics_gc_priv_proxy, p, count); + } + +} + +static void svg_debug_draw_polygon(struct graphics_priv *gr, + struct graphics_gc_priv *gc, struct point *p, int count) { + const char *coord_template = "%i,%i "; + const char *polygon_template_start = "<polygon points=\"%s"; + const char *polygon_template_end = "\" style=\"fill:rgb(%i,%i,%i)\" />\n"; + fprintf(gr->outfile, polygon_template_start, ""); + int i; + for (i = 0; i < count; i++) { + fprintf(gr->outfile, coord_template, p[i].x, p[i].y); + } + fprintf(gr->outfile, polygon_template_end, gc->fg.r, gc->fg.g, gc->fg.b); + + if (gr->proxy_graphics_methods->draw_polygon) { + gr->proxy_graphics_methods->draw_polygon(gr->proxy_priv, + gc->graphics_gc_priv_proxy, p, count); + } + +} + +static void svg_debug_draw_rectangle(struct graphics_priv *gr, + struct graphics_gc_priv *gc, struct point *p, int w, int h) { + const char *rectangle_template = + "<rect x=\"%i\" y=\"%i\" width=\"%i\" height=\"%i\" style=\"fill:rgb(%i,%i,%i)\"></rect>\n"; + fprintf(gr->outfile, rectangle_template, p->x, p->y, w, h, gc->fg.r, + gc->fg.g, gc->fg.b); + + if (gr->proxy_graphics_methods->draw_rectangle) { + gr->proxy_graphics_methods->draw_rectangle(gr->proxy_priv, + gc->graphics_gc_priv_proxy, p, w, h); + } +} + +static void svg_debug_draw_circle(struct graphics_priv *gr, + struct graphics_gc_priv *gc, struct point *p, int r) { + const char *circle_template = + "<circle cx=\"%i\" cy=\"%i\" r=\"%i\" fill=\"rgb(%i,%i,%i)\" />\n"; + fprintf(gr->outfile, circle_template, p->x, p->y, r / 2, gc->fg.r, gc->fg.g, + gc->fg.b); + + if (gr->proxy_graphics_methods->draw_circle) { + gr->proxy_graphics_methods->draw_circle(gr->proxy_priv, + gc->graphics_gc_priv_proxy, p, r); + } + +} + +static void svg_debug_draw_text(struct graphics_priv *gr, + struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, + struct graphics_font_priv *font, char *text, struct point *p, int dx, + int dy) { + const char *image_template = + "<text x=\"%i\" y=\"%i\" fill=\"rgb(%i,%i,%i)\" style=\"font-size: %ipt;\">%s</text>\n"; + if (dx == 0x10000 || dy == 0) { + fprintf(gr->outfile, image_template, p->x, p->y, fg->fg.r, fg->fg.g, + fg->fg.b, font ? font->size : 0, text); + } + if (gr->proxy_graphics_methods->draw_text && font) { + gr->proxy_graphics_methods->draw_text(gr->proxy_priv, + fg->graphics_gc_priv_proxy, bg->graphics_gc_priv_proxy, + font->graphics_font_proxy.priv, text, p, dx, dy); + } +} + +static void svg_debug_draw_image(struct graphics_priv *gr, + struct graphics_gc_priv *fg, struct point *p, + struct graphics_image_priv *img) { + // Write already encoded image to file + const char *image_template = + "<image x=\"%i\" y=\"%i\" width=\"%i\" height=\"%i\" xlink:href=\"%s\"></image>\n"; + fprintf(gr->outfile, image_template, p->x, p->y, img->w, img->h, img->data); + if (gr->proxy_graphics_methods->draw_image) { + gr->proxy_graphics_methods->draw_image(gr->proxy_priv, fg, p, + img->graphics_image_priv_proxy); + } +} + +static void svg_debug_draw_drag(struct graphics_priv *gr, struct point *p) { + if (gr->proxy_graphics_methods->draw_drag) { + gr->proxy_graphics_methods->draw_drag(gr->proxy_priv, p); + } +} + +static void svg_debug_background_gc(struct graphics_priv *gr, + struct graphics_gc_priv *gc) { + if (gr->proxy_graphics_methods->background_gc) { + gr->proxy_graphics_methods->background_gc(gr->proxy_priv, + gc->graphics_gc_priv_proxy); + } +} + +static void svg_debug_draw_mode(struct graphics_priv *gr, + enum draw_mode_num mode) { + const char *svg_start_template = + "<svg height=\"%i\" width=\"%i\" xmlns= \"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n"; + const char *svg_end_template = "</svg>\n"; + char filename[255]; + switch (mode) { + case draw_mode_begin: + if (gr->outfile) { + dbg(lvl_debug, "Finished drawing %s/svg_debug_after_frame_%u.svg", + gr->outputdir, gr->frame) + fprintf(gr->outfile, svg_end_template, ""); + fclose(gr->outfile); + gr->frame += 1; + } + sprintf(filename, "%s/svg_debug_frame_%u.svg", gr->outputdir, + gr->frame); + gr->outfile = fopen(filename, "w"); + fprintf(gr->outfile, svg_start_template, gr->height, gr->width); + break; + case draw_mode_end: + dbg(lvl_debug, "Finished drawing %s/svg_debug_after_frame_%u.svg", + gr->outputdir, gr->frame) + fprintf(gr->outfile, svg_end_template, ""); + fclose(gr->outfile); + gr->frame += 1; + sprintf(filename, "%s/svg_debug_after_frame_%u.svg", gr->outputdir, + gr->frame); + gr->outfile = fopen(filename, "w"); + fprintf(gr->outfile, svg_start_template, gr->height, gr->width); + break; + default: + break; + } + if (gr->proxy_graphics_methods->draw_mode) { + gr->proxy_graphics_methods->draw_mode(gr->proxy_priv, mode); + } +} + +static void graphics_svg_debug_overlay_draw_mode(struct graphics_priv *gr, + enum draw_mode_num mode) { + // TODO + // https://stackoverflow.com/questions/5451135/embed-svg-in-svg + // more or less like in draw_mode but with different format string + // probably overlay_num so main svg can import it +} + +static struct graphics_priv* graphics_svg_debug_overlay_new( + struct graphics_priv *gr, struct graphics_methods *meth, + struct point *p, int w, int h, int wraparound); + +static int graphics_svg_debug_fullscreen(struct window *win, int on) { + struct graphics_priv *graphics_priv = (struct graphics_priv*) win->priv; + struct window *proxy_win; + if (!graphics_priv->proxy_graphics_methods->get_data) { + return 0; + } + proxy_win = graphics_priv->proxy_graphics_methods->get_data( + graphics_priv->proxy_priv, "window"); + if (proxy_win) { + return proxy_win->fullscreen(proxy_win, on); + } + return 0; +} + +static gboolean graphics_svg_debug_idle(void *data) { + struct graphics_priv *gr = (struct graphics_priv*) data; + static int first_run = TRUE; + if (first_run) { + callback_list_call_attr_2(gr->cbl, attr_resize, + GINT_TO_POINTER(gr->width), GINT_TO_POINTER(gr->height)); + first_run = FALSE; + } + return TRUE; +} + +static void graphics_svg_debug_disable_suspend(struct window *w) { + struct graphics_priv *graphics_priv = (struct graphics_priv*) w->priv; + struct window *proxy_win; + if (!graphics_priv->proxy_graphics_methods->get_data) { + return; + } + proxy_win = graphics_priv->proxy_graphics_methods->get_data( + graphics_priv->proxy_priv, "window"); + if (proxy_win) { + proxy_win->disable_suspend(proxy_win); + } + return; +} + +static void* svg_debug_get_data(struct graphics_priv *this, char const *type) { + if (strcmp(type, "window") == 0) { + struct window *win; + win = g_new0(struct window, 1); + win->priv = this; + win->fullscreen = graphics_svg_debug_fullscreen; + win->disable_suspend = graphics_svg_debug_disable_suspend; + return win; + } + if (this->proxy_graphics_methods->get_data) { + // FIXME: This will leak the proxied graphics_priv... But it works for now + return this->proxy_graphics_methods->get_data(this->proxy_priv, type); + } + return NULL; +} + +static void svg_debug_image_free(struct graphics_priv *gr, + struct graphics_image_priv *img) { + dbg(lvl_debug, "enter image_free"); + if (img->graphics_image_methods_proxy->image_destroy) { + img->graphics_image_methods_proxy->image_destroy( + img->graphics_image_priv_proxy); + } + if (gr->proxy_graphics_methods->image_free) { + gr->proxy_graphics_methods->image_free(gr->proxy_priv, + img->graphics_image_priv_proxy); + } + g_free(img->graphics_image_methods_proxy); + g_free(img->data); + g_free(img); +} + +static void graphics_svg_debug_overlay_disable(struct graphics_priv *gr, + int disable) { + // TODO +} + +static void graphics_svg_debug_overlay_resize(struct graphics_priv *gr, + struct point *p, int w, int h, int wraparound) { + // TODO +} + +static struct graphics_methods graphics_methods = { + .graphics_destroy = svg_debug_graphics_destroy, + .draw_mode = svg_debug_draw_mode, + .draw_lines = svg_debug_draw_lines, + .draw_polygon = svg_debug_draw_polygon, + .draw_rectangle = svg_debug_draw_rectangle, + .draw_circle = svg_debug_draw_circle, + .draw_text = svg_debug_draw_text, + // FIXME: Text size calculation is hard, because the svg is + // interpreted by the viewer, so we don't know its size + + .draw_image = svg_debug_draw_image, + .draw_image_warp = NULL, + .draw_drag = svg_debug_draw_drag, + .font_new = svg_debug_font_new, + .gc_new = svg_debug_gc_new, + .background_gc = svg_debug_background_gc, + .overlay_new = NULL, //graphics_svg_debug_overlay_new, // TODO + .image_new = svg_debug_image_new, + .get_data = svg_debug_get_data, + .image_free = svg_debug_image_free, + .get_text_bbox = svg_debug_get_text_bbox, + .overlay_disable = NULL, // graphics_svg_debug_overlay_disable, // TODO + .overlay_resize = NULL, // graphics_svg_debug_overlay_resize, // TODO + .set_attr = NULL, // TODO add proxy + .show_native_keyboard = NULL, // TODO add proxy + .hide_native_keyboard = NULL, // TODO add proxy + .get_dpi = NULL, // TODO add proxy + .draw_polygon_with_holes = NULL, // TODO add proxy + +}; + +static struct graphics_priv* graphics_svg_debug_overlay_new( + struct graphics_priv *gr, struct graphics_methods *meth, + struct point *p, int w, int h, int wraparound) { + struct graphics_priv *this = g_new0(struct graphics_priv, 1); + *meth = graphics_methods; + meth->draw_mode = graphics_svg_debug_overlay_draw_mode; + + // TODO + + return this; +} + +static struct graphics_priv* graphics_svg_debug_new(struct navit *nav, + struct graphics_methods *meth, struct attr **attrs, + struct callback_list *cbl) { + struct graphics_priv *this = g_new0(struct graphics_priv, 1); + struct graphics_methods *proxy_graphics_methods = g_new0( + struct graphics_methods, 1); + struct attr *attr; + void *proxy_priv = NULL; + struct graphics_priv* (*proxy_gra)(struct navit *nav, + struct graphics_methods *meth, struct attr **attrs, + struct callback_list *cbl); + + *meth = graphics_methods; + + // Save Parameters for later + this->nav = nav; + this->cbl = cbl; + + // Read configuration + this->width = 32; + if ((attr = attr_search(attrs, attr_w))) + this->width = attr->u.num; + this->height = 32; + if ((attr = attr_search(attrs, attr_h))) + this->height = attr->u.num; + + this->outputdir = g_get_tmp_dir(); + if ((attr = attr_search(attrs, attr_outputdir))) + this->outputdir = attr->u.str; + + // Get plugin to proxy + proxy_gra = NULL; + if ((attr = attr_search(attrs, attr_name))) { + if (attr->u.str[0] != '\0') { + proxy_gra = plugin_get_category_graphics(attr->u.str); + } + if (proxy_gra) { + // Call proxy plugin + proxy_priv = (*proxy_gra)(nav, proxy_graphics_methods, attrs, cbl); + } else { + dbg(lvl_error, "Failed to load graphics plugin %s.", attr->u.str); + return NULL; + } + } else { + if (!event_request_system("glib", "graphics_sdl_new")) { + dbg(lvl_error, "event_request_system failed"); + g_free(this); + return NULL; + } + } + + // Save proxy to call it later + this->proxy_priv = proxy_priv; + this->proxy_graphics_methods = proxy_graphics_methods; + this->frame = 0; + + // If something tries to write before calling draw_mode with start for the first time + this->outfile = fopen("/dev/null", "w"); + + //callbacks = cbl; + g_timeout_add(G_PRIORITY_DEFAULT + 10, graphics_svg_debug_idle, this); + + if (!proxy_gra) { + dbg(lvl_debug, "No Proxied plugin, so do not set functions to NULL") + // see comment below + callback_list_call_attr_2(cbl, attr_resize, + GINT_TO_POINTER(this->width), GINT_TO_POINTER(this->height)); + return this; + } + + // The rest of this function makes sure that svg_debug only supports what the + // proxied graphics plugin supports as well + // for example some graphics plugins don't support circles, but svg_debug does. + // if navit core sees that we support circles we would see it inside the svg, but not + // in the proxied graphics + // + // get_data and draw_mode may not been set to null because they need to exist + if (!this->proxy_graphics_methods->graphics_destroy) { + meth->graphics_destroy = NULL; + } + if (!this->proxy_graphics_methods->draw_lines) { + meth->draw_lines = NULL; + } + if (!this->proxy_graphics_methods->draw_polygon) { + meth->draw_polygon = NULL; + } + if (!this->proxy_graphics_methods->draw_rectangle) { + meth->draw_rectangle = NULL; + } + if (!this->proxy_graphics_methods->draw_circle) { + meth->draw_circle = NULL; + } + if (!this->proxy_graphics_methods->draw_text) { + meth->draw_text = NULL; + } + if (!this->proxy_graphics_methods->draw_image) { + meth->draw_image = NULL; + } + if (!this->proxy_graphics_methods->draw_image_warp) { + meth->draw_image_warp = NULL; + } + if (!this->proxy_graphics_methods->draw_drag) { + meth->draw_drag = NULL; + } + if (!this->proxy_graphics_methods->font_new) { + meth->font_new = NULL; + } + if (!this->proxy_graphics_methods->gc_new) { + meth->gc_new = NULL; + } + if (!this->proxy_graphics_methods->background_gc) { + meth->background_gc = NULL; + } + if (!this->proxy_graphics_methods->overlay_new) { + meth->overlay_new = NULL; + } + if (!this->proxy_graphics_methods->image_new) { + meth->image_new = NULL; + } + if (!this->proxy_graphics_methods->image_free) { + meth->image_free = NULL; + } + if (!this->proxy_graphics_methods->get_text_bbox) { + meth->get_text_bbox = NULL; + } + if (!this->proxy_graphics_methods->overlay_disable) { + meth->overlay_disable = NULL; + } + if (!this->proxy_graphics_methods->overlay_resize) { + meth->overlay_resize = NULL; + } + if (!this->proxy_graphics_methods->set_attr) { + meth->set_attr = NULL; + } + if (!this->proxy_graphics_methods->show_native_keyboard) { + meth->show_native_keyboard = NULL; + } + if (!this->proxy_graphics_methods->hide_native_keyboard) { + meth->hide_native_keyboard = NULL; + } + if (!this->proxy_graphics_methods->get_dpi) { + meth->get_dpi = NULL; + } + if (!this->proxy_graphics_methods->draw_polygon_with_holes) { + meth->draw_polygon_with_holes = NULL; + } + + // Add resize callback so we get called when window is resized so we can adjust the svg size + struct callback *callback = callback_new_attr_1(callback_cast(resize_callback_do), attr_resize, this); + callback_list_add(cbl, callback); + return this; +} + +void plugin_init(void) { + dbg(lvl_error, "enter svg_debug plugin_init") + plugin_register_category_graphics("svg_debug", graphics_svg_debug_new); + //plugin_register_category_event("svg_debug", event_svg_debug_new); +} diff --git a/navit/graphics/win32/graphics_win32.c b/navit/graphics/win32/graphics_win32.c index f4eda15f4..3f20daf2b 100644 --- a/navit/graphics/win32/graphics_win32.c +++ b/navit/graphics/win32/graphics_win32.c @@ -1337,7 +1337,7 @@ static int pngdecode(struct graphics_priv *gr, char *name, struct graphics_image /* expand images to bit-depth 8 (only applicable for grayscale images) */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth < 8) - png_set_gray_1_2_4_to_8(png_ptr); + png_set_expand_gray_1_2_4_to_8(png_ptr); /* Expand grayscale to rgb */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) diff --git a/navit/icons/CMakeLists.txt b/navit/icons/CMakeLists.txt index 9817aa25e..ec00ac9a4 100644 --- a/navit/icons/CMakeLists.txt +++ b/navit/icons/CMakeLists.txt @@ -30,7 +30,7 @@ macro(convert_to_png IMAGE_INPUT IMAGE_OUTPUT SCALE) else() set(SCALE_ARGS) endif() - set(COMMAND_ARGS --without-gui --export-background-opacity=0 --export-png ${IMAGE_OUTPUT} ${SCALE_ARGS} ${IMAGE_INPUT}) + set(COMMAND_ARGS --export-type=png --export-background-opacity=0 ${SCALE_ARGS} --export-filename=${IMAGE_OUTPUT} ${IMAGE_INPUT}) else() message(FATAL_ERROR "no svg2png converter defined here.") endif() @@ -127,6 +127,7 @@ foreach (IMAGE_SRC ${FILES_TO_PNG}) endforeach() +if (NOT ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} ) foreach (IMAGE_FILE ${IMAGES_TO_COPY}) add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${IMAGE_FILE}" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${IMAGE_FILE}" @@ -135,6 +136,7 @@ foreach (IMAGE_FILE ${IMAGES_TO_COPY}) ) list(APPEND IMAGE_TARGETS "${CMAKE_CURRENT_BINARY_DIR}/${IMAGE_FILE}") endforeach() +endif() add_custom_target(images ALL DEPENDS ${IMAGE_TARGETS}) add_custom_target(images_resource COMMAND mkdir -p ../resources/share/navit/xpm COMMAND cp ${IMAGE_TARGETS} ../resources/share/navit/xpm) diff --git a/navit/icons/archaeological_site.svg b/navit/icons/archaeological_site.svg index 19fc27283..31cf5c25a 100644 --- a/navit/icons/archaeological_site.svg +++ b/navit/icons/archaeological_site.svg @@ -5,7 +5,18 @@ <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> <dc:title/> + <cc:license + rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" /> </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/publicdomain/zero/1.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> </rdf:RDF> </metadata> <defs id="defs6"/> diff --git a/navit/icons/cave.svg b/navit/icons/cave.svg index c1a900573..575d38a92 100644 --- a/navit/icons/cave.svg +++ b/navit/icons/cave.svg @@ -22,7 +22,18 @@ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> + <cc:license + rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" /> </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/publicdomain/zero/1.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> </rdf:RDF> </metadata> <g diff --git a/navit/icons/ic_launcher_background.svg b/navit/icons/ic_launcher_background.svg new file mode 100644 index 000000000..ab3fe6bd9 --- /dev/null +++ b/navit/icons/ic_launcher_background.svg @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="108" + height="108" + viewBox="0 0 28.574999 28.575001" + version="1.1" + id="svg8" + inkscape:version="0.92.3 (2405546, 2018-03-11)" + sodipodi:docname="ic_launcher_background.svg"> + <defs + id="defs2"> + <linearGradient + id="linearGradient3728"> + <stop + offset="0" + stop-color="#ffda00" + id="stop3730" /> + <stop + offset="1" + stop-color="#f57f0c" + id="stop3732" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3728" + id="linearGradient1447" + x1="2.6458333" + y1="285.35831" + x2="31.220835" + y2="285.35831" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-2.6458333,-2.6458215)" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:zoom="5.6111111" + inkscape:cx="53.904385" + inkscape:cy="55.960396" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + units="px" + showguides="true" + inkscape:guide-bbox="true" + inkscape:snap-page="true" + inkscape:window-width="1600" + inkscape:window-height="816" + inkscape:window-x="0" + inkscape:window-y="28" + inkscape:window-maximized="1" + inkscape:snap-others="true" + inkscape:snap-bbox="true" + inkscape:bbox-nodes="true" + inkscape:bbox-paths="true" + inkscape:object-nodes="true" + inkscape:snap-nodes="true" + inkscape:snap-to-guides="false" + inkscape:snap-object-midpoints="false" + inkscape:snap-center="false" + inkscape:snap-bbox-edge-midpoints="false" + inkscape:snap-bbox-midpoints="false" + inkscape:object-paths="true" + inkscape:snap-grids="true" + inkscape:pagecheckerboard="false"> + <inkscape:grid + type="xygrid" + id="grid815" + empspacing="8" + originx="4.7625" + originy="4.7625" /> + <sodipodi:guide + position="4.7625,0" + orientation="1,0" + id="guide817" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="23.8125,0" + orientation="1,0" + id="guide819" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="0,4.7625" + orientation="0,1" + id="guide821" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="0,23.8125" + orientation="0,1" + id="guide823" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + </sodipodi:namedview> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-268.42498)"> + <rect + style="opacity:1;fill:url(#linearGradient1447);fill-opacity:1;stroke:none;stroke-width:0.79374999;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect1439" + width="28.575001" + height="28.575001" + x="-4.4408921e-16" + y="268.42499" /> + </g> +</svg> diff --git a/navit/icons/ic_launcher_foreground.svg b/navit/icons/ic_launcher_foreground.svg new file mode 100644 index 000000000..ef4b12452 --- /dev/null +++ b/navit/icons/ic_launcher_foreground.svg @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="108" + height="108" + viewBox="0 0 28.574999 28.575001" + version="1.1" + id="svg8" + inkscape:version="0.92.3 (2405546, 2018-03-11)" + sodipodi:docname="ic_launcher_foreground.svg"> + <defs + id="defs2"> + <linearGradient + id="linearGradient3728"> + <stop + offset="0" + stop-color="#ffda00" + id="stop3730" /> + <stop + offset="1" + stop-color="#f57f0c" + id="stop3732" /> + </linearGradient> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#f5820b" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:zoom="5.6111111" + inkscape:cx="53.706082" + inkscape:cy="54" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + units="px" + showguides="true" + inkscape:guide-bbox="true" + inkscape:snap-page="true" + inkscape:window-width="1600" + inkscape:window-height="816" + inkscape:window-x="0" + inkscape:window-y="28" + inkscape:window-maximized="1" + inkscape:snap-others="true" + inkscape:snap-bbox="true" + inkscape:bbox-nodes="true" + inkscape:bbox-paths="true" + inkscape:object-nodes="true" + inkscape:snap-nodes="true" + inkscape:snap-to-guides="false" + inkscape:snap-object-midpoints="false" + inkscape:snap-center="false" + inkscape:snap-bbox-edge-midpoints="false" + inkscape:snap-bbox-midpoints="false" + inkscape:object-paths="true" + inkscape:snap-grids="true" + inkscape:pagecheckerboard="false"> + <inkscape:grid + type="xygrid" + id="grid815" + empspacing="8" + originx="4.7625" + originy="4.7625" /> + <sodipodi:guide + position="4.7625,0" + orientation="1,0" + id="guide817" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="23.8125,0" + orientation="1,0" + id="guide819" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="0,4.7625" + orientation="0,1" + id="guide821" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="0,23.8125" + orientation="0,1" + id="guide823" + inkscape:locked="false" + inkscape:label="" + inkscape:color="rgb(0,0,255)" /> + </sodipodi:namedview> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-268.42498)"> + <g + id="g1398" + transform="matrix(2.8117887,0,0,2.8159822,-37.178409,-521.06388)"> + <path + id="circle1355-6-5-0" + transform="matrix(0.26458333,0,0,0.26458333,0,268.42498)" + d="m 69.146484,59.111328 a 5.14193,5.1423346 0 0 0 -1.498046,0.228516 l 2.550781,4.851562 1,2.251953 h 0.0625 c -0.05216,-0.542362 -0.11448,-1.14695 -0.1875,-1.814453 -0.06274,-0.667464 -0.09375,-1.303289 -0.09375,-1.908203 v -3.263672 a 5.14193,5.1423346 0 0 0 -1.833985,-0.345703 z m -3.978515,1.591797 a 5.3333329,5.3333329 0 0 0 -0.316407,0.394531 5.3333329,5.3333329 0 0 1 0.316407,-0.394531 z m 8.050781,0.113281 a 5.3333329,5.3333329 0 0 1 0.3125,0.408203 5.3333329,5.3333329 0 0 0 -0.3125,-0.408203 z m -8.042969,0.173828 a 5.14193,5.1423346 0 0 0 -1.171875,3.263672 5.14193,5.1423346 0 0 0 1.171875,3.263672 z m 7.994141,0.06445 v 6.392578 a 5.14193,5.1423346 0 0 0 1.117187,-3.19336 5.14193,5.1423346 0 0 0 -1.117187,-3.199218 z m -8.333984,0.06445 a 5.3333329,5.3333329 0 0 0 -0.267579,0.408203 5.3333329,5.3333329 0 0 1 0.267579,-0.408203 z M 73.550781,61.25 a 5.3333329,5.3333329 0 0 1 0.25586,0.417969 A 5.3333329,5.3333329 0 0 0 73.550781,61.25 Z m 0.275391,0.457031 a 5.3333329,5.3333329 0 0 1 0.210937,0.431641 5.3333329,5.3333329 0 0 0 -0.210937,-0.431641 z m -6.742188,0.310547 c 0.05212,0.563225 0.109324,1.167814 0.171875,1.814453 0.07279,0.646602 0.109375,1.27204 0.109375,1.876953 v 3.361328 a 5.14193,5.1423346 0 0 0 1.78125,0.326172 5.14193,5.1423346 0 0 0 1.56836,-0.251953 l -2.566406,-4.904297 -1.001954,-2.222656 z" + style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.94348323;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:connector-curvature="0" /> + <path + inkscape:export-ydpi="960" + inkscape:export-xdpi="960" + sodipodi:nodetypes="cccccccscccccscccccccccccsccccccccccccccsccccccccccccscccccccccccccccccsccccccccscccccccccsccccccccccczccscccz" + inkscape:connector-curvature="0" + id="path1363-0-6-9" + d="m 18.34523,287.68027 -2.57e-4,-0.66573 0.07525,-0.005 c 0.375528,-0.0276 0.726784,-0.18852 0.994434,-0.4554 0.260497,-0.25973 0.417842,-0.58833 0.456602,-0.95356 0.0037,-0.0348 0.0067,-0.0761 0.0067,-0.0918 l 5.1e-5,-0.0287 h 0.65715 c 0.361431,0 0.656288,8.3e-4 0.655236,0.002 -0.0011,10e-4 -0.194008,0.0849 -0.428791,0.18642 -0.234784,0.10144 -0.428648,0.18619 -0.430808,0.1882 -0.0021,0.002 -0.01386,0.0426 -0.02597,0.0901 -0.03745,0.14692 -0.08195,0.26835 -0.14609,0.39869 -0.0474,0.0963 -0.07774,0.1487 -0.140884,0.24321 -0.282438,0.42274 -0.701364,0.71895 -1.204124,0.85141 l -0.02004,0.005 -0.224126,0.45066 -0.224126,0.45067 -2.57e-4,-0.66574 z m -0.250416,0.25886 c -0.09088,-0.20985 -0.166025,-0.38362 -0.16698,-0.38615 -0.0011,-0.003 0.0045,-0.003 0.01521,-10e-4 0.04834,0.009 0.156934,0.0212 0.233246,0.0262 l 0.08607,0.005 v 0.3687 c 0,0.20277 -5.17e-4,0.36867 -0.0012,0.36865 -6.3e-4,0 -0.07551,-0.17173 -0.16639,-0.38159 z m 0.112458,-0.43859 c -0.11655,-0.004 -0.27774,-0.0282 -0.401633,-0.0587 -0.333863,-0.0823 -0.63497,-0.24406 -0.898795,-0.48282 -0.175306,-0.15865 -0.339228,-0.37555 -0.447808,-0.59254 -0.133823,-0.26743 -0.199822,-0.52005 -0.218845,-0.83765 l -0.003,-0.0494 h 0.245304 0.245304 l 0.0029,0.0575 c 0.0034,0.0684 0.01734,0.16786 0.0336,0.24088 0.129105,0.5801 0.570667,1.03662 1.147803,1.18669 0.09279,0.0241 0.254517,0.0481 0.324817,0.0481 h 0.02538 v 0.24557 0.24555 l -0.01035,-9e-4 c -0.0057,-5e-4 -0.02582,-10e-4 -0.04476,-0.002 z m -2.412215,-1.81873 -0.403811,-0.20161 0.383723,-3.5e-4 0.383722,-3.5e-4 0.0031,0.0631 c 0.005,0.10048 0.029,0.28931 0.04233,0.33278 0.0014,0.004 7.2e-4,0.009 -0.0014,0.009 -0.0021,0 -0.185585,-0.0907 -0.407681,-0.20161 z m 0.04685,-0.51192 0.455249,-0.22639 0.0051,-0.0201 c 0.117283,-0.45427 0.388557,-0.85879 0.764306,-1.13967 0.155461,-0.11623 0.337039,-0.21519 0.520976,-0.28396 0.04225,-0.0158 0.160578,-0.0529 0.201337,-0.0632 l 0.02003,-0.005 0.226506,-0.45526 0.226505,-0.45525 1.84e-4,0.67059 1.84e-4,0.67058 -0.06082,0.003 c -0.276758,0.0136 -0.570135,0.11722 -0.806642,0.28493 -0.108357,0.0768 -0.240169,0.20048 -0.318481,0.29874 -0.147166,0.18466 -0.247983,0.38835 -0.303341,0.61287 -0.02413,0.0978 -0.04381,0.23516 -0.04381,0.30564 v 0.0293 l -0.671302,-3e-4 -0.671303,-2.9e-4 z m 4.036163,0.19931 c 0,-0.0152 -0.0032,-0.058 -0.007,-0.095 -0.04715,-0.44897 -0.283842,-0.8539 -0.654554,-1.11979 -0.160125,-0.11485 -0.343297,-0.19907 -0.537117,-0.24692 -0.103467,-0.0256 -0.229085,-0.0437 -0.302703,-0.0437 h -0.03165 v -0.24607 -0.24608 l 0.05622,0.003 c 0.27046,0.0152 0.508594,0.0717 0.745454,0.17701 0.304646,0.13549 0.57804,0.34918 0.78533,0.61381 0.04845,0.0619 0.13372,0.18952 0.170899,0.25588 0.131985,0.23557 0.21819,0.49848 0.249839,0.76196 0.0054,0.0455 0.01634,0.18419 0.01647,0.21 0,0.002 -0.110489,0.003 -0.245554,0.003 h -0.245569 z m 0.565587,-0.0588 c -0.006,-0.0927 -0.01828,-0.19418 -0.03303,-0.27131 -0.005,-0.0263 -0.0086,-0.0482 -0.0081,-0.0486 5.99e-4,-4e-4 0.184922,0.0907 0.409607,0.2025 l 0.408519,0.20323 -0.385749,3e-4 -0.385749,3e-4 -0.0055,-0.0864 z m -1.753592,-1.98152 c -0.08387,-0.017 -0.240907,-0.0342 -0.31181,-0.0343 l -0.03328,-4e-5 v -0.38633 c 0,-0.21249 7.39e-4,-0.38547 0.0016,-0.38443 0.009,0.0107 0.404808,0.81653 0.400792,0.81613 -0.003,-2.9e-4 -0.02877,-0.005 -0.05734,-0.011 z" + style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.0045901;stroke-opacity:1" /> + </g> + </g> +</svg> diff --git a/navit/icons/navit_svg2png b/navit/icons/navit_svg2png index 668613a61..32939c7f6 100755 --- a/navit/icons/navit_svg2png +++ b/navit/icons/navit_svg2png @@ -19,7 +19,7 @@ svgtopng() $svgtopng --width=$1 --height=$2 --output $4 $3 ;; *inkscape) - $svgtopng --without-gui --export-width=$1 --export-height=$2 --export-png=$BUILDDIR/$4 $3 + $svgtopng --export-width=$1 --export-height=$2 --export-type=png --export-filename=$4 $3 ;; *convert) $svgtopng -alpha on -background none $3 -resize $1x$2 $4 diff --git a/navit/item.c b/navit/item.c index ab590cb4e..120675339 100644 --- a/navit/item.c +++ b/navit/item.c @@ -394,6 +394,13 @@ void item_attr_rewind(struct item *it) { * This function returns the next attribute matching `attr_type` from an item and advances the * "attribute pointer" accordingly, so that at the next call the next attribute will be returned. * + * IMPORTANT: Unless you are iterating over attributes, or operating on a “fresh” item (from which no + * other code has had a chance to retrieve an attribute), be sure to call + * {@link item_attr_rewind(struct item *)} before each call to this method. Not doing so may result in + * unpredictable behavior, i.e. attributes not being found if the attribute pointer is already past the + * requested attribute (which depends on the physical ordering of attributes and on the last attribute + * retrieved from the item). + * * This function is not safe to call after destroying the item's map rect, and doing so may cause errors * with some map implementations. * diff --git a/navit/item.h b/navit/item.h index 32ef35dec..d8aefeabe 100644 --- a/navit/item.h +++ b/navit/item.h @@ -111,7 +111,22 @@ struct item_id { #define ITEM_ID_ARGS(x) (x).id_hi,(x).id_lo /** - * Represents an object on a map, such as a POI, a building, a way or a boundary. + * @brief Represents an object on a map. + * + * An item holds the data for an individual item on a map, including its coordinates and various attributes. The item + * type specifies what the map item refers to, such as a POI, a building, a way or a boundary. There are also special + * item types used internally, such as the various kinds of turn instructions. Item types are internally represented as + * numbers. + * + * Outside map implementations, items are generally retrieved from map rectangles, and their methods are implemented by + * the respective map driver. Items retrieved from a map rectangle are generally short-lived: a previously retrieved + * item should be considered invalid when a new item is retrieved from the same map rectangle, or after its map + * rectangle has been destroyed. After that, functions may segfault or return invalid data, and even the item itself + * may have been deallocated. + * + * Actual behavior may differ between map implementations, but do not rely on any behavior not covered by the above + * interface contract. Exceptions apply, of course, for code that is limited to working with items from one particular + * map (typically inside a map implementation). */ struct item { enum item_type type; /**< Type of the item.*/ @@ -126,6 +141,12 @@ extern struct item_range { enum item_type min,max; } item_range_all; +/** + * @brief An item indicating that the map driver is busy fetching more items. + * + * This is a “magic” item which may be returned by one of the query methods of a map driver. Receiving this item means + * that the map driver is currently busy fetching more items, and they can be retrieved at a later point in time. + */ extern struct item busy_item; /* prototypes */ diff --git a/navit/map.c b/navit/map.c index c8cddbcc2..e3034d429 100644 --- a/navit/map.c +++ b/navit/map.c @@ -52,11 +52,6 @@ #include "country.h" #include "xmlconfig.h" -/** - * @brief Holds information about a map - * - * This structure holds information about a map. - */ struct map { NAVIT_OBJECT struct map_methods meth; /**< Structure with pointers to the map plugin's functions */ @@ -64,11 +59,6 @@ struct map { struct callback_list *attr_cbl; /**< List of callbacks that are called when attributes change */ }; -/** - * @brief Describes a rectangular extract of a map - * - * This structure describes a rectangular extract of a map. - */ struct map_rect { struct map *m; /**< The map this extract is from */ struct map_rect_priv *priv; /**< Private data of this map rect, only known to the map plugin */ @@ -375,12 +365,6 @@ void map_rect_destroy(struct map_rect *mr) { } } -/** - * @brief Holds information about a search on a map - * - * This structure holds information about a search performed on a map. This can be - * used as "handle" to retrieve items from a search. - */ struct map_search { struct map *m; struct attr search_attr; diff --git a/navit/map.h b/navit/map.h index 78521bccf..63fa889e3 100644 --- a/navit/map.h +++ b/navit/map.h @@ -47,12 +47,13 @@ struct attr; /** * @brief Used to select data from a map * - * This struct is used to select data from a map. This one the one hand builds a - * rectangle on the map and on the other hand selects an order for items of each - * layer. Note that passing NULL instead of a pointer to such a struct often means - * "get me everything". + * A map selection is a map query, used to select data from a map. It builds a coordinate rectangle on the map and + * selects a range of item types to query the map for. * - * It's possible to link multiple selections in a linked list, see below. + * Multiple rectangular areas and/or non-contiguous ranges of item types can be specified by concatenating multiple map + * selections in a linked list. + * + * Note that passing NULL instead of a pointer to such a struct often means "get me everything". */ struct map_selection { struct map_selection *next; /**< Linked-List pointer */ @@ -236,10 +237,54 @@ struct attr; struct attr_iter; struct callback; struct item; + +/** + * @brief Holds information about a map + * + * A map holds data used for screen display, search and routing. Maps can come in different forms, such as stored in + * files or created on the fly in memory. Flat-file maps typically hold the data commonly found in a road map, such as + * roads, land uses, buildings and POIs. In-memory maps are used internally for data which changes at runtime, such as + * information on the currently active route or traffic reports. + * + * To read data from a map (or add data if the map driver supports it), you need to obtain a map rectangle by calling + * the map’s `map_rect_new` method. By passing a map selection it is possible to restrict the items retrieved from the + * map to a certain region or to certain item types. + */ struct map; + +/** + * @brief Implementation-specific map data. + * + * This struct is defined individually by each map driver and not ment to be accessed outside the map driver. + */ struct map_priv; + +/** + * @brief Describes an extract of a map + * + * A map rectangle is the result of a map query. It can be obtained from the map by calling `map_rect_new` and passing + * a map selection. The resulting map rectangle can be queried for items. Contrary to its name, a map rectangle does + * not necessarily correspond to a rectangle: depending on the map selection it was created from, it can hold data from + * multiple rectangular areas (which may or may not overlap) or from the entire map. + * + * Map rectangles are not guaranteed to be thread-safe, i.e. a map rectangle should never be accessed by more than one + * thread without proper external synchronization. It is recommended that each thread obtain a separate map rectangle. + * + * Map implementations must ensure, however, that accesses to different map rectangles of the same map by different + * threads are properly synchronized. Most importantly, they must ensure that threads reading from one map rectangle + * receive consistent data while another thread is writing to another (which may also happen when reloading data from a + * stored map). + */ struct map_rect; + +/** + * @brief Holds information about a search on a map + * + * This structure holds information about a search performed on a map. This can be + * used as "handle" to retrieve items from a search. + */ struct map_search; + struct map_selection; struct pcoord; struct map *map_new(struct attr *parent, struct attr **attrs); diff --git a/navit/map/binfile/binfile.c b/navit/map/binfile/binfile.c index 6108154b6..ab65dcaf5 100644 --- a/navit/map/binfile/binfile.c +++ b/navit/map/binfile/binfile.c @@ -565,7 +565,7 @@ static int binfile_attr_get(void *priv_data, enum attr_type attr_type, struct at size_rem-=subsize+1; i++; } - mr->attrs[i].type=type_none; + mr->attrs[i].type=attr_none; mr->attrs[i].u.data=NULL; attr->u.attrs=mr->attrs; } else { diff --git a/navit/map/csv/csv.h b/navit/map/csv/csv.h index c32be1eff..c48458c82 100644 --- a/navit/map/csv/csv.h +++ b/navit/map/csv/csv.h @@ -27,19 +27,17 @@ struct map_priv { int id; - struct quadtree_node* tree_root; + struct quadtree_node* tree_root; /**< Root of the quadtree from which items can be retrieved by their coordinates */ int flags; - GHashTable*qitem_hash; - char* filename; - /*need to write map file on exit*/ - int dirty; - int attr_cnt; - enum attr_type *attr_types; - int next_item_idx; - enum item_type item_type; - /*list of quadtree items that have no coord set yet ()*/ - GList* new_items; - char *charset; + GHashTable*qitem_hash; /**< Hash table to retrieve items by their ID */ + char* filename; /**< Name of the file in which the map is stored */ + int dirty; /**< Need to write map file on exit */ + int attr_cnt; /**< Number of elements in `attr_types` */ + enum attr_type *attr_types; /**< Array of attribute types supported by this map */ + int next_item_idx; /**< Zero-based index (`id_lo`) for the next item to be added */ + enum item_type item_type; /**< Item type stored in this map */ + GList* new_items; /**< List of quadtree items that have no coord set yet */ + char *charset; /**< Identifier for the character set of this map */ }; struct map_rect_priv { diff --git a/navit/mapset.c b/navit/mapset.c index 94f1f42be..409437e51 100644 --- a/navit/mapset.c +++ b/navit/mapset.c @@ -36,11 +36,6 @@ #include "map.h" #include "xmlconfig.h" -/** - * @brief A mapset - * - * This structure holds a complete mapset - */ struct mapset { NAVIT_OBJECT GList *maps; /**< Linked list of all the maps in the mapset */ diff --git a/navit/mapset.h b/navit/mapset.h index df6c0d0a7..6aca2afdc 100644 --- a/navit/mapset.h +++ b/navit/mapset.h @@ -30,7 +30,15 @@ struct attr; struct attr_iter; struct item; struct map; + +/** + * @brief A mapset. + * + * A mapset is a collection of (one or more) maps. This allows you to combine data from multiple maps, e.g. one map + * with the road network and another with special POIs. + */ struct mapset; + struct mapset_handle; struct mapset_search; struct mapset *mapset_new(struct attr *parent, struct attr **attrs); diff --git a/navit/maptool/maptool.h b/navit/maptool/maptool.h index 37590e30b..49b13fd92 100644 --- a/navit/maptool/maptool.h +++ b/navit/maptool/maptool.h @@ -406,7 +406,7 @@ int write_aux_tiles(struct zip_info *zip_info); int create_tile_hash(void); void write_tilesdir(struct tile_info *info, struct zip_info *zip_info, FILE *out); void merge_tiles(struct tile_info *info); -struct attr map_information_attrs[32]; +extern struct attr map_information_attrs[32]; void index_init(struct zip_info *info, int version); void index_submap_add(struct tile_info *info, struct tile_head *th); diff --git a/navit/navit.c b/navit/navit.c index 6c22ebadb..671e5d9c0 100644 --- a/navit/navit.c +++ b/navit/navit.c @@ -180,6 +180,9 @@ struct navit { int waypoints_flag; struct coord_geo center; int auto_switch; /*auto switching between day/night layout enabled ?*/ + int tunnel_nightlayout; /* switch to nightlayout if we are in a tunnel? */ + char* layout_before_tunnel; + int sunrise_degrees; }; struct gui *main_loop_gui; @@ -1484,6 +1487,9 @@ navit_new(struct attr *parent, struct attr **attrs) { this_->radius = 30; this_->border = 16; this_->auto_switch = TRUE; + this_->tunnel_nightlayout = FALSE; + this_->layout_before_tunnel = ""; + this_->sunrise_degrees = -5; transform_from_geo(pro, &g, &co); center.x=co.x; @@ -1613,8 +1619,6 @@ void navit_set_destination(struct navit *this_, struct pcoord *c, const char *de } g_free(destination_file); - callback_list_call_attr_0(this_->attr_cbl, attr_destination); - if (this_->route) { struct attr attr; int dstcount; @@ -1637,10 +1641,12 @@ void navit_set_destination(struct navit *this_, struct pcoord *c, const char *de g_free(pc); g_free(destination_file); } - - if (this_->ready == 3 && !(this_->flags & 4)) - navit_draw(this_); } + + callback_list_call_attr_0(this_->attr_cbl, attr_destination); + + if (this_->route && this_->ready == 3 && !(this_->flags & 4)) + navit_draw(this_); } /** @@ -1683,15 +1689,30 @@ void navit_set_destinations(struct navit *this_, struct pcoord *c, int count, co g_free(destination_file); } else this_->destination_valid=0; - callback_list_call_attr_0(this_->attr_cbl, attr_destination); - if (this_->route) { + if (this_->route) route_set_destinations(this_->route, c, count, async); - if (this_->ready == 3) - navit_draw(this_); - } + callback_list_call_attr_0(this_->attr_cbl, attr_destination); + if (this_->route && this_->ready == 3) + navit_draw(this_); } +/** + * @brief Retrieves destinations from the route + * + * Prior to calling this method, you may want to retrieve the number of destinations by calling + * {@link navit_get_destination_count(struct navit *)} and assigning a buffer of sufficient capacity. + * + * If the return value equals `count`, the buffer was either just large enough or too small to hold the + * entire list of destinations; there is no way to tell from the result which is the case. + * + * If the Navit instance does not have a route, the result is 0. + * + * @param this_ The Navit instance + * @param pc Pointer to an array of projected coordinates which will receive the destination coordinates + * @param count Capacity of `pc` + * @return The number of destinations stored in `pc`, never greater than `count` + */ int navit_get_destinations(struct navit *this_, struct pcoord *pc, int count) { if(!this_->route) return 0; @@ -1699,6 +1720,12 @@ int navit_get_destinations(struct navit *this_, struct pcoord *pc, int count) { } +/** + * @brief Get the destinations count for the route + * + * @param this The Navit instance + * @return destination count for the route, or 0 if the Navit instance has no route + */ int navit_get_destination_count(struct navit *this_) { if(!this_->route) return 0; @@ -2733,6 +2760,18 @@ static int navit_set_attr_do(struct navit *this_, struct attr *attr, int init) { attr_updated=(this_->waypoints_flag != !!attr->u.num); this_->waypoints_flag=!!attr->u.num; break; + case attr_tunnel_nightlayout: + attr_updated = (this_->tunnel_nightlayout != !!attr->u.num); + this_->tunnel_nightlayout = !!attr->u.num; + break; + case attr_layout_daynightauto: + attr_updated = (this_->auto_switch != !!attr->u.num); + this_->auto_switch = !!attr->u.num; + break; + case attr_sunrise_degrees: + attr_updated = (this_->sunrise_degrees != attr->u.num); + this_->sunrise_degrees = attr->u.num; + break; default: dbg(lvl_debug, "calling generic setter method for attribute type %s", attr_to_name(attr->type)) return navit_object_set_attr((struct navit_object *) this_, attr); @@ -2948,6 +2987,15 @@ int navit_get_attr(struct navit *this_, enum attr_type type, struct attr *attr, case attr_waypoints_flag: attr->u.num=this_->waypoints_flag; break; + case attr_tunnel_nightlayout: + attr->u.num=this_->tunnel_nightlayout; + break; + case attr_layout_daynightauto: + attr->u.num=this_->auto_switch; + break; + case attr_sunrise_degrees: + attr->u.num=this_->sunrise_degrees; + break; default: dbg(lvl_debug, "calling generic getter method for attribute type %s", attr_to_name(type)) return navit_object_get_attr((struct navit_object *) this_, type, attr, iter); @@ -3464,7 +3512,6 @@ navit_get_displaylist(struct navit *this_) { return this_->displaylist; } -/*todo : make it switch to nightlayout when we are in a tunnel */ void navit_layout_switch(struct navit *n) { int currTs=0; @@ -3474,6 +3521,7 @@ void navit_layout_switch(struct navit *n) { int year, month, day; int after_sunrise = FALSE; int after_sunset = FALSE; + int tunnel = tracking_get_current_tunnel(n->tracking); if (navit_get_attr(n,attr_layout,&layout_attr,NULL)!=1) { return; //No layout - nothing to switch @@ -3495,6 +3543,33 @@ void navit_layout_switch(struct navit *n) { if (n->auto_switch == FALSE) return; + if (n->tunnel_nightlayout) { + if (tunnel) { + // store the current layout name + if(!strcmp(n->layout_before_tunnel, "")) + n->layout_before_tunnel = n->layout_current->name; + + // We are in a tunnel and if we have a nightlayout -> switch to nightlayout + if (l->nightname) { + navit_set_layout_by_name(n, l->nightname); + dbg(lvl_debug, "tunnel -> nightlayout"); + } + return; + + } else { + if (l->dayname) { + if (!strcmp(l->dayname, n->layout_before_tunnel)) { + // restore previous layout + navit_set_layout_by_name(n, l->dayname); + dbg(lvl_debug, "tunnel end -> daylayout"); + } + + // We were in nightlayout before the tunnel, keep it + n->layout_before_tunnel=""; + } + } + } + if (currTs-(n->prevTs)<60) { //We've have to wait a little return; @@ -3506,12 +3581,15 @@ void navit_layout_switch(struct navit *n) { && valid_attr.u.num==attr_position_valid_invalid) { return; //No valid fix yet } + if (vehicle_get_attr(n->vehicle->vehicle, attr_position_coord_geo,&geo_attr,NULL)!=1) { //No position - no sun return; } + //We calculate sunrise anyway, cause it is needed both for day and for night - if (__sunriset__(year,month,day,geo_attr.u.coord_geo->lng,geo_attr.u.coord_geo->lat,-5,1,&trise,&tset)!=0) { + if (__sunriset__(year,month,day,geo_attr.u.coord_geo->lng,geo_attr.u.coord_geo->lat,n->sunrise_degrees,1,&trise, + &tset)!=0) { dbg(lvl_debug,"near the pole sun never rises/sets, so we should never switch profiles"); dbg(lvl_debug,"trise: %u:%u",HOURS(trise),MINUTES(trise)); dbg(lvl_debug,"tset: %u:%u",HOURS(tset),MINUTES(tset)); @@ -3708,7 +3786,36 @@ int navit_get_blocked(struct navit *this_) { void navit_destroy(struct navit *this_) { dbg(lvl_debug,"enter %p",this_); + GList *mapsets; + struct map * map; + struct attr attr; graphics_draw_cancel(this_->gra, this_->displaylist); + + mapsets = this_->mapsets; + while (mapsets) { + GList *maps = NULL; + struct mapset_handle *msh; + msh = mapset_open(mapsets->data); + while (msh && (map = mapset_next(msh, 0))) { + /* Add traffic map (identified by the `attr_traffic` attribute) to list of maps to remove */ + if (map_get_attr(map, attr_traffic, &attr, NULL)) + maps = g_list_append(maps, map); + } + mapset_close(msh); + + /* Remove traffic maps, if any */ + while (maps) { + attr.type = attr_map; + attr.u.map = maps->data; + mapset_remove_attr(mapsets->data, &attr); + attr_free_content(&attr); + maps = g_list_next(maps); + } + if (maps) + g_list_free(maps); + mapsets = g_list_next(mapsets); + } + callback_list_call_attr_1(this_->attr_cbl, attr_destroy, this_); attr_list_free(this_->attrs); diff --git a/navit/navit.dtd b/navit/navit.dtd index 6ab800b96..4d6b4cfe6 100644 --- a/navit/navit.dtd +++ b/navit/navit.dtd @@ -25,6 +25,9 @@ <!ATTLIST navit recent_dest CDATA #IMPLIED> <!ATTLIST navit drag_bitmap CDATA #IMPLIED> <!ATTLIST navit default_layout CDATA #IMPLIED> +<!ATTLIST navit tunnel_nightlayout CDATA #IMPLIED> +<!ATTLIST navit nightlayout_auto CDATA #IMPLIED> +<!ATTLIST navit sunrise_degrees CDATA #IMPLIED> <!ELEMENT gui ANY> <!ATTLIST gui type CDATA #REQUIRED> <!ATTLIST gui menubar CDATA #IMPLIED> diff --git a/navit/navit_shipped.xml b/navit/navit_shipped.xml index 5473349c7..5c2c404dc 100644 --- a/navit/navit_shipped.xml +++ b/navit/navit_shipped.xml @@ -37,6 +37,21 @@ <navit center="11.5666 48.1333" zoom="256" tracking="1" orientation="-1" recent_dest="250" drag_bitmap="0" default_layout="Car"> <!-- Use one of gtk_drawing_area, qt_qpainter or sdl. On windows systems, use win32 --> <graphics type="gtk_drawing_area"/> + + <!-- + To debug the graphics plugin in question it is possible to proxy it with svg_debug + This way every frame will be written as a svg file. In addition to this the real graphics plugin will + be called. To configure this, set type to svg_debug and the name attribute to the proxied plugin. + Parameters are past to the proxied plugin as well. But resize callbacks currently only passed to the proxied + plugin, and not handled by svg_debug, so resizing the window will not update the width and height of the resulting + scg file. But all calls will still be recorded and written to the file, so you will see those drawing when opening + the svg in an editor like inkscape. + Example: + --> + <!-- + <graphics type="svg_debug" name="sdl2" window_title="Alternative attributes as passed to proxied plugin" w="1000" h="1000" /> + --> + <!-- The following line let you select which graphical user interface you'd like to use. Options include internal (optimized for touch screen devices), gtk (useful for desktop computers). diff --git a/navit/osd/core/osd_core.c b/navit/osd/core/osd_core.c index cfbb0655c..40ea4350d 100644 --- a/navit/osd/core/osd_core.c +++ b/navit/osd/core/osd_core.c @@ -8,13 +8,13 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * Boston, MA 02110-1301, USA. */ #include "config.h" @@ -450,7 +450,7 @@ static void osd_route_guard_init(struct osd_priv_common *opc, struct navit *nav) while ((map=mapset_next(msh, 1))) { struct attr attr; if(map_get_attr(map, attr_name, &attr, NULL)) { - if( ! strcmp(this->map_name, attr.u.str) ) { + if(!strcmp(this->map_name, attr.u.str) ) { mr=map_rect_new(map, NULL); if (mr) { while ((item=map_rect_get_item(mr))) { @@ -740,7 +740,7 @@ static void draw_aligned_osd_text(char *buffer, int align, struct osd_item *osd_ } while (*last) { - if (! g_ascii_isspace(*last)) { + if (!g_ascii_isspace(*last)) { lines++; break; } @@ -830,7 +830,7 @@ static void osd_odometer_draw(struct osd_priv_common *opc, struct navit *nav, st int secs; int imperial=0; - char buffer [256+1]=""; + char buffer[256+1]=""; char buffer2[256+1]=""; if(nav) { @@ -903,7 +903,7 @@ static void osd_odometer_draw(struct osd_priv_common *opc, struct navit *nav, st time_buffer = g_strdup_printf("%02d:%02d:%02d",hours,mins,secs); } - buffer [0] = 0; + buffer[0] = 0; buffer2[0] = 0; if(this->text) { str_replace(buffer,this->text,"${avg_spd}",spd_buffer); @@ -2473,11 +2473,11 @@ static void osd_speed_cam_draw(struct osd_priv_common *opc, struct navit *navit, } if(this_->text) { - char buffer [256]=""; + char buffer[256]=""; char buffer2[256]=""; char dir_str[16]; char spd_str[16]; - buffer [0] = 0; + buffer[0] = 0; buffer2[0] = 0; osd_fill_with_bgcolor(&opc->osd_item); @@ -2692,7 +2692,7 @@ static void osd_speed_warner_draw(struct osd_priv_common *opc, struct navit *nav img = this->img_active; } } else { - osd_color = this-> grey; + osd_color = this->grey; img = this->img_off; this->announce_state = eNoWarn; } @@ -2898,6 +2898,19 @@ static char *osd_text_format_attr(struct attr *attr, char *format, int imperial) case attr_position_speed: return format_speed(*attr->u.numd,"",format,imperial); case attr_position_height: + /** + * johnk 8/13/2020 + * if format is "feet" then return feet + * else + * if format is "imperial" + * return meters or feet as controlled by "imperial" + * return meters + */ + if (format && + (!strcmp(format, "feet") || (!strcmp(format, "imperial") && imperial == 1))) { + return (format_float_0(*attr->u.numd * FEET_PER_METER) ); + } + return (format_float_0(*attr->u.numd) ); case attr_position_direction: return format_float_0(*attr->u.numd); case attr_position_magnetic_direction: @@ -2966,7 +2979,7 @@ static char *osd_text_format_attr(struct attr *attr, char *format, int imperial) if (!strcmp(format,"value") || !strcmp(format,"unit")) { char *ret,*tmp=format_distance(attr->u.num," ",imperial); char *pos=strchr(tmp,' '); - if (! pos) + if (!pos) return tmp; *pos++='\0'; if (!strcmp(format,"value")) @@ -2982,7 +2995,7 @@ static char *osd_text_format_attr(struct attr *attr, char *format, int imperial) } else { if (strstr(format, "local;") == format) { textt = iso8601_to_secs(attr->u.str); - memcpy ((void *) &tm, (void *) localtime(&textt), sizeof(tm)); + memcpy((void *) &tm, (void *) localtime(&textt), sizeof(tm)); strftime(buffer, sizeof(buffer), (char *)(format + 6), &tm); } else if ((sscanf(format, "%*c%2d:%2d;", &(text_tm.tm_hour), &(text_tm.tm_min)) == 2) && (strchr("+-", format[0]))) { if (strchr("-", format[0])) { @@ -2990,7 +3003,7 @@ static char *osd_text_format_attr(struct attr *attr, char *format, int imperial) } else { textt = iso8601_to_secs(attr->u.str) + text_tm.tm_hour * 3600 + text_tm.tm_min * 60; } - memcpy ((void *) &tm, (void *) gmtime(&textt), sizeof(tm)); + memcpy((void *) &tm, (void *) gmtime(&textt), sizeof(tm)); strftime(buffer, sizeof(buffer), &format[strcspn(format, ";") + 1], &tm); } else { sscanf(attr->u.str, "%4d-%2d-%2dT%2d:%2d:%2d", &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday), &(tm.tm_hour), &(tm.tm_min), @@ -3214,7 +3227,7 @@ static void osd_text_draw(struct osd_priv_common *opc, struct navit *navit, stru } while (*last) { - if (! g_ascii_isspace(*last)) { + if (!g_ascii_isspace(*last)) { lines++; break; } @@ -3336,7 +3349,7 @@ static void osd_text_prepare(struct osd_priv_common *opc, struct navit *nav) { } end=strstr(start,"}"); - if (! end) + if (!end) break; *end++='\0'; @@ -3525,7 +3538,7 @@ static void osd_gps_status_draw(struct osd_priv_common *opc, struct navit *navit if (gr_image) { p.x = (opc->osd_item.w - gr_image->width) / 2; p.y = (opc->osd_item.h - gr_image->height) / 2; - graphics_draw_image(opc->osd_item.gr, opc->osd_item. graphic_fg, &p, gr_image); + graphics_draw_image(opc->osd_item.gr, opc->osd_item.graphic_fg, &p, gr_image); graphics_image_free(opc->osd_item.gr, gr_image); } g_free(image); @@ -3611,7 +3624,7 @@ static void osd_volume_draw(struct osd_priv_common *opc, struct navit *navit, st if (gr_image) { p.x = (opc->osd_item.w - gr_image->width) / 2; p.y = (opc->osd_item.h - gr_image->height) / 2; - graphics_draw_image(opc->osd_item.gr, opc->osd_item. graphic_fg, &p, gr_image); + graphics_draw_image(opc->osd_item.gr, opc->osd_item.graphic_fg, &p, gr_image); graphics_image_free(opc->osd_item.gr, gr_image); } g_free(image); @@ -3643,7 +3656,7 @@ static void osd_volume_init(struct osd_priv_common *opc, struct navit *nav) { struct volume *this = (struct volume *)opc->data; osd_set_std_graphic(nav, &opc->osd_item, (struct osd_priv *)opc); - navit_add_callback(nav, this->click_cb = callback_new_attr_1(callback_cast (osd_volume_click), attr_button, opc)); + navit_add_callback(nav, this->click_cb = callback_new_attr_1(callback_cast(osd_volume_click), attr_button, opc)); osd_volume_draw(opc, nav, NULL); } @@ -3827,7 +3840,7 @@ static struct osd_priv *osd_scale_new(struct navit *nav, struct osd_methods *met osd_set_std_attr(attrs, &opc->osd_item, TRANSPARENT_BG | ITEM_HAS_TEXT); - navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast (osd_scale_init), attr_graphics_ready, + navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast(osd_scale_init), attr_graphics_ready, opc)); return (struct osd_priv *) opc; @@ -3891,17 +3904,17 @@ static void osd_auxmap_init(struct osd_priv_common *opc, struct navit *nav) { struct color red= {0xffff,0x0,0x0,0xffff}; this->nav=nav; - if (! navit_get_attr(nav, attr_graphics, &attr, NULL)) + if (!navit_get_attr(nav, attr_graphics, &attr, NULL)) return; gra=attr.u.graphics; graphics_add_callback(gra, callback_new_attr_1(callback_cast(osd_auxmap_draw), attr_postdraw, opc)); - if (! navit_get_attr(nav, attr_transformation, &attr, NULL)) + if (!navit_get_attr(nav, attr_transformation, &attr, NULL)) return; this->ntrans=attr.u.transformation; - if (! navit_get_attr(nav, attr_displaylist, &attr, NULL)) + if (!navit_get_attr(nav, attr_displaylist, &attr, NULL) ) return; this->displaylist=attr.u.displaylist; - if (! navit_get_attr(nav, attr_layout, &attr, NULL)) + if (!navit_get_attr(nav, attr_layout, &attr, NULL)) return; this->layout=attr.u.layout; osd_set_std_graphic(nav, &opc->osd_item, NULL); diff --git a/navit/plugin/j1850/j1850.c b/navit/plugin/j1850/j1850.c index 69a9b8fa5..bdef8a4fa 100644 --- a/navit/plugin/j1850/j1850.c +++ b/navit/plugin/j1850/j1850.c @@ -316,7 +316,7 @@ static void osd_j1850_init(struct j1850 *this, struct navit *nav) { graphics_gc_set_linewidth(this->white, this->width); - graphics_gc_set_linewidth(this->osd_item.graphic_fg_white, this->width); + graphics_gc_set_linewidth(this->osd_item.graphic_fg, this->width); event_add_timeout(500, 1, callback_new_1(callback_cast(osd_j1850_draw), this)); diff --git a/navit/route.c b/navit/route.c index 858e51406..9d9ecf23d 100644 --- a/navit/route.c +++ b/navit/route.c @@ -939,6 +939,17 @@ struct map_selection *route_selection; /** * @brief Returns a single map selection + * + * The boundaries of the selection are determined as follows: First a rectangle spanning `c1` and `c2` is + * built (the two coordinates can be any two opposite corners of the rectangle). Then its maximum extension + * (height or width) is determined and multiplied with the percentage specified by `rel`. The resulting + * amount of padding is added to each edge. After that, the amount specified by `abs` is added to each edge. + * + * @param order Map order (deepest tile level) to select + * @param c1 First coordinate + * @param c2 Second coordinate + * @param rel Relative padding to add to the selection rectangle, in percent + * @param abs Absolute padding to add to the selection rectangle */ struct map_selection * route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs) { @@ -1047,7 +1058,8 @@ struct map_selection * route_get_selection(struct route * this_) { int i = 0; GList *tmp; - c[i++] = this_->pos->c; + if (this_->pos) + c[i++] = this_->pos->c; tmp = this_->destinations; while (tmp) { struct route_info *dst = tmp->data; @@ -1062,7 +1074,7 @@ struct map_selection * route_get_selection(struct route * this_) { * * @param sel Start of the list to be destroyed */ -static void route_free_selection(struct map_selection *sel) { +void route_free_selection(struct map_selection *sel) { struct map_selection *next; while (sel) { next=sel->next; @@ -1129,6 +1141,20 @@ void route_set_destinations(struct route *this, struct pcoord *dst, int count, i profile(0,"end"); } +/** + * @brief Retrieves destinations from the route + * + * Prior to calling this method, you may want to retrieve the number of destinations by calling + * {@link route_get_destination_count(struct route *)} and assigning a buffer of sufficient capacity. + * + * If the return value equals `count`, the buffer was either just large enough or too small to hold the + * entire list of destinations; there is no way to tell from the result which is the case. + * + * @param this The route instance + * @param pc Pointer to an array of projected coordinates which will receive the destination coordinates + * @param count Capacity of `pc` + * @return The number of destinations stored in `pc`, never greater than `count` + */ int route_get_destinations(struct route *this, struct pcoord *pc, int count) { int ret=0; GList *l=this->destinations; @@ -1583,11 +1609,7 @@ int route_graph_segment_is_duplicate(struct route_graph_point *start, struct rou * @param this The route graph to insert the segment into * @param start The graph point which should be connected to the start of this segment * @param end The graph point which should be connected to the end of this segment - * @param len The length of this segment - * @param item The item that is represented by this segment - * @param flags Flags for this segment - * @param offset If the item passed in "item" is segmented (i.e. divided into several segments), this indicates the position of this segment within the item - * @param maxspeed The maximum speed allowed on this segment in km/h. -1 if not known. + * @param data The segment data */ void route_graph_add_segment(struct route_graph *this, struct route_graph_point *start, struct route_graph_point *end, struct route_graph_segment_data *data) { @@ -2274,10 +2296,13 @@ static void route_graph_set_traffic_distortion(struct route_graph *this, struct /** * @brief Adds a traffic distortion item to the route graph * + * If `update` is true, the end points of the traffic distortion will have their cost recalculated. Set this to true + * for a partial recalculation of an existing route, false when initially building the route graph. + * * @param this The route graph to add to * @param profile The vehicle profile to use for cost calculations * @param item The item to add, must be of {@code type_traffic_distortion} - * @param update Whether to update the point (true for LPA*, false for Dijkstra) + * @param update Whether to update the end points */ static void route_graph_add_traffic_distortion(struct route_graph *this, struct vehicleprofile *profile, struct item *item, int update) { @@ -2306,10 +2331,12 @@ static void route_graph_add_traffic_distortion(struct route_graph *this, struct e_pnt=route_graph_add_point(this,&l); s_pnt->flags |= RP_TRAFFIC_DISTORTION; e_pnt->flags |= RP_TRAFFIC_DISTORTION; + item_attr_rewind(item); if (item_attr_get(item, attr_maxspeed, &maxspeed_attr)) { data.flags |= AF_SPEED_LIMIT; data.maxspeed=maxspeed_attr.u.num; } + item_attr_rewind(item); if (item_attr_get(item, attr_delay, &delay_attr)) data.len=delay_attr.u.num; route_graph_add_segment(this, s_pnt, e_pnt, &data); @@ -2523,37 +2550,45 @@ static void route_graph_add_street(struct route_graph *this, struct item *item, if (item_coord_get(item, &l, 1)) { if (!(default_flags = item_get_default_flags(item->type))) default_flags = &default_flags_value; + item_attr_rewind(item); if (item_attr_get(item, attr_flags, &attr)) { data.flags = attr.u.num; segmented = (data.flags & AF_SEGMENTED); } else data.flags = *default_flags; + item_attr_rewind(item); if ((data.flags & AF_SPEED_LIMIT) && (item_attr_get(item, attr_maxspeed, &attr))) data.maxspeed = attr.u.num; if (data.flags & AF_DANGEROUS_GOODS) { + item_attr_rewind(item); if (item_attr_get(item, attr_vehicle_dangerous_goods, &attr)) data.dangerous_goods = attr.u.num; else data.flags &= ~AF_DANGEROUS_GOODS; } if (data.flags & AF_SIZE_OR_WEIGHT_LIMIT) { + item_attr_rewind(item); if (item_attr_get(item, attr_vehicle_width, &attr)) data.size_weight.width=attr.u.num; else data.size_weight.width=-1; + item_attr_rewind(item); if (item_attr_get(item, attr_vehicle_height, &attr)) data.size_weight.height=attr.u.num; else data.size_weight.height=-1; + item_attr_rewind(item); if (item_attr_get(item, attr_vehicle_length, &attr)) data.size_weight.length=attr.u.num; else data.size_weight.length=-1; + item_attr_rewind(item); if (item_attr_get(item, attr_vehicle_weight, &attr)) data.size_weight.weight=attr.u.num; else data.size_weight.weight=-1; + item_attr_rewind(item); if (item_attr_get(item, attr_vehicle_axle_weight, &attr)) data.size_weight.axle_weight=attr.u.num; else @@ -2674,10 +2709,8 @@ static int route_graph_is_path_computed(struct route_graph *this_) { * After recalculation, the route path is updated. * * The function uses a modified LPA* algorithm for recalculations. Most modifications were made for compatibility with - * the algorithm used for the initial routing: - * \li The `value` of a node represents the cost to reach the destination and thus decreases along the route - * (eliminating the need for recalculations as the vehicle moves within the route graph) - * \li The heuristic is always assumed to be zero (which would turn A* into Dijkstra, the basis of the main routing + * the old routing algorithm: + * \li The heuristic is always assumed to be zero (which would turn A* into Dijkstra, formerly the basis of the routing * algorithm, and makes our keys one-dimensional) * \li Currently, each pass evaluates all locally inconsistent points, leaving an empty heap at the end (though this * may change in the future). @@ -3157,17 +3190,12 @@ static void route_graph_build_idle(struct route_graph *rg, struct vehicleprofile * add any routing information to the route graph - this has to be done via the route_graph_flood() * function. * - * The function does not create a graph covering the whole map, but only covering the rectangle - * between c1 and c2. - * * @param ms The mapset to build the route graph from - * @param c The coordinates of the destination or next waypoint - * @param c1 Corner 1 of the rectangle to use from the map - * @param c2 Corner 2 of the rectangle to use from the map + * @param c An array of coordinates for the current position, waypoints (if any) and destination + * @param count Number of coordinates in `c` * @param done_cb The callback which will be called when graph is complete * @return The new route graph. */ -// FIXME documentation does not match argument list static struct route_graph *route_graph_build(struct mapset *ms, struct coord *c, int count, struct callback *done_cb, int async, struct vehicleprofile *profile) { diff --git a/navit/route_protected.h b/navit/route_protected.h index 586fde91d..32d61e9bd 100644 --- a/navit/route_protected.h +++ b/navit/route_protected.h @@ -140,7 +140,9 @@ struct route_graph_segment { * each segment. */ struct route_graph { - int busy; /**< The graph is being built */ + int busy; /**< Route calculation is in progress: the graph is being built, + * flooded or the path is being built (a more detailed status can be + * obtained from the route’s status attribute) */ struct map_selection *sel; /**< The rectangle selection for the graph */ struct mapset_handle *h; /**< Handle to the mapset */ struct map *m; /**< Pointer to the currently active map */ @@ -150,7 +152,7 @@ struct route_graph { struct callback *done_cb; /**< Callback when graph is done */ struct event_idle *idle_ev; /**< The pointer to the idle event */ struct route_graph_segment *route_segments; /**< Pointer to the first route_graph_segment in the linked list of all segments */ - struct route_graph_segment *avoid_seg; + struct route_graph_segment *avoid_seg; /**< Segment to which a turnaround penalty (if active) applies */ struct fibheap *heap; /**< Priority queue for points to be expanded */ #define HASH_SIZE 8192 struct route_graph_point *hash[HASH_SIZE]; /**< A hashtable containing all route_graph_points in this graph */ @@ -160,6 +162,7 @@ struct route_graph { /* prototypes */ struct route_graph * route_get_graph(struct route *this_); struct map_selection * route_get_selection(struct route * this_); +void route_free_selection(struct map_selection *sel); void route_add_traffic_distortion(struct route *this_, struct item *item); void route_remove_traffic_distortion(struct route *this_, struct item *item); void route_change_traffic_distortion(struct route *this_, struct item *item); diff --git a/navit/support/espeak/readclause.c b/navit/support/espeak/readclause.c index 172ebad15..eda455901 100644 --- a/navit/support/espeak/readclause.c +++ b/navit/support/espeak/readclause.c @@ -2887,7 +2887,7 @@ if(option_ssml) parag=1; // Unless it's a hyphen or apostrophe (which is used by TranslateClause() ) if(IsBracket(c1)) { - c1 = 0xe000 + '('; // Unicode private useage area. So TranslateRules() knows the bracket name has been spoken + c1 = 0xe000 + '('; // Unicode private usage area. So TranslateRules() knows the bracket name has been spoken } else if(c1 != '-') diff --git a/navit/support/gettext_intl/dcigettext.c b/navit/support/gettext_intl/dcigettext.c index 1b66fba37..72a01a8e9 100644 --- a/navit/support/gettext_intl/dcigettext.c +++ b/navit/support/gettext_intl/dcigettext.c @@ -156,7 +156,7 @@ char *getwd (); # else # if VMS # define getcwd(buf, max) (getcwd) (buf, max, 0) -# else +# elif !(defined(__clang__) && defined(__BIONIC_FORTIFY)) char *getcwd (); # endif # endif diff --git a/navit/textures/CMakeLists.txt b/navit/textures/CMakeLists.txt index 5eb1fcf7e..b59a0a17f 100644 --- a/navit/textures/CMakeLists.txt +++ b/navit/textures/CMakeLists.txt @@ -30,7 +30,7 @@ macro(convert_to_png TEXTURE_INPUT TEXTURE_OUTPUT SCALE) else() set(SCALE_ARGS) endif() - set(COMMAND_ARGS --without-gui --export-background-opacity=0 --export-png ${TEXTURE_OUTPUT} ${SCALE_ARGS} ${TEXTURE_INPUT}) + set(COMMAND_ARGS --export-type=png --export-background-opacity=0 ${SCALE_ARGS} --export-filename=${TEXTURE_OUTPUT} ${TEXTURE_INPUT}) else() message(FATAL_ERROR "no svg2png converter defined here.") endif() @@ -110,6 +110,7 @@ foreach (TEXTURE_SRC ${FILES_TO_PNG}) endforeach() +if (NOT ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} ) foreach (TEXTURE_FILE ${TEXTURES_TO_COPY}) add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${TEXTURE_FILE}" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${TEXTURE_FILE}" @@ -118,6 +119,7 @@ foreach (TEXTURE_FILE ${TEXTURES_TO_COPY}) ) list(APPEND TEXTURE_TARGETS "${CMAKE_CURRENT_BINARY_DIR}/${TEXTURE_FILE}") endforeach() +endif() add_custom_target(textures ALL DEPENDS ${TEXTURE_TARGETS}) add_custom_target(textures_resource COMMAND mkdir -p ../resources/share/navit/textures COMMAND cp ${TEXTURE_TARGETS} ../resources/share/navit/textures) diff --git a/navit/textures/cemetery.svg b/navit/textures/cemetery.svg index f9683d378..a0a34a37a 100644 --- a/navit/textures/cemetery.svg +++ b/navit/textures/cemetery.svg @@ -19,7 +19,18 @@ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> + <cc:license + rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" /> </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/publicdomain/zero/1.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> </rdf:RDF> </metadata> <defs diff --git a/navit/textures/diagonal-stripes-gray.svg b/navit/textures/diagonal-stripes-gray.svg index 7b6858521..6337ced17 100644 --- a/navit/textures/diagonal-stripes-gray.svg +++ b/navit/textures/diagonal-stripes-gray.svg @@ -46,7 +46,18 @@ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> + <cc:license + rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" /> </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/publicdomain/zero/1.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> </rdf:RDF> </metadata> <g diff --git a/navit/textures/diagonal-stripes.svg b/navit/textures/diagonal-stripes.svg index a5ba67996..9bf8e92a4 100644 --- a/navit/textures/diagonal-stripes.svg +++ b/navit/textures/diagonal-stripes.svg @@ -46,7 +46,18 @@ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> + <cc:license + rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" /> </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/publicdomain/zero/1.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> </rdf:RDF> </metadata> <g diff --git a/navit/textures/quarry.svg b/navit/textures/quarry.svg index 1de09a22c..b6ecddd7f 100644 --- a/navit/textures/quarry.svg +++ b/navit/textures/quarry.svg @@ -42,7 +42,18 @@ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> + <cc:license + rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" /> </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/publicdomain/zero/1.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> </rdf:RDF> </metadata> <defs diff --git a/navit/textures/scrub.svg b/navit/textures/scrub.svg index 3e0d18522..7e0143e5b 100644 --- a/navit/textures/scrub.svg +++ b/navit/textures/scrub.svg @@ -46,7 +46,18 @@ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> + <cc:license + rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" /> </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/publicdomain/zero/1.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> </rdf:RDF> </metadata> <g diff --git a/navit/textures/wetland.svg b/navit/textures/wetland.svg index 2c84b04f1..05ea07cb9 100644 --- a/navit/textures/wetland.svg +++ b/navit/textures/wetland.svg @@ -22,7 +22,18 @@ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> + <cc:license + rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" /> </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/publicdomain/zero/1.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> </rdf:RDF> </metadata> <defs diff --git a/navit/textures/wood.svg b/navit/textures/wood.svg index a6f8f7d39..1b5f40d66 100644 --- a/navit/textures/wood.svg +++ b/navit/textures/wood.svg @@ -42,7 +42,18 @@ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title></dc:title> + <cc:license + rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" /> </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/publicdomain/zero/1.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> </rdf:RDF> </metadata> <defs diff --git a/navit/track.c b/navit/track.c index 0bc702b7e..b729c329a 100644 --- a/navit/track.c +++ b/navit/track.c @@ -83,12 +83,12 @@ struct cdf_data { struct tracking { NAVIT_OBJECT - struct callback_list *callback_list; - struct mapset *ms; - struct route *rt; - struct map *map; - struct vehicle *vehicle; - struct vehicleprofile *vehicleprofile; + struct callback_list *callback_list; /**< Callbacks which will be called whenever the position changes */ + struct mapset *ms; /**< The mapset */ + struct route *rt; /**< The route */ + struct map *map; /**< The tracking map which holds our past movements */ + struct vehicle *vehicle; /**< The vehicle from which we are obtaining location data */ + struct vehicleprofile *vehicleprofile; /**< The current vehicle profile */ struct coord last_updated; struct tracking_line *lines; struct tracking_line *curr_line; @@ -98,16 +98,16 @@ struct tracking { struct coord last[2], last_in, last_out; struct cdf_data cdf; struct attr *attr; - int valid; + int valid; /**< Whether we have valid location data */ int time; double direction, direction_matched; - double speed; + double speed; /**< Current speed */ int coord_geo_valid; struct coord_geo coord_geo; enum projection pro; int street_direction; int no_gps; - int tunnel; + int tunnel; /**< Whether we are in a tunnel */ int angle_pref; int connected_pref; int nostop_pref; @@ -119,8 +119,6 @@ struct tracking { }; - - static void tracking_init_cdf(struct cdf_data *cdf, int hist_size) { cdf->extrapolating = 0; cdf->available = 0; @@ -400,6 +398,10 @@ int *tracking_get_current_flags(struct tracking *_this) { return &_this->curr_line->street->flags; } +int tracking_get_current_tunnel(struct tracking *_this) { + return _this->tunnel; +} + static void tracking_get_angles(struct tracking_line *tl) { int i; struct street_data *sd=tl->street; @@ -637,10 +639,11 @@ void tracking_update(struct tracking *tr, struct vehicle *v, struct vehicleprofi !vehicle_get_attr(tr->vehicle, attr_position_direction, &direction_attr, NULL) || !vehicle_get_attr(tr->vehicle, attr_position_coord_geo, &coord_geo, NULL) || !vehicle_get_attr(tr->vehicle, attr_position_time_iso8601, &time_attr, NULL)) { - dbg(lvl_error,"failed to get position data %d %d %d", + dbg(lvl_error,"failed to get position data speed:%d direction:%d coord:%d time:%d", vehicle_get_attr(tr->vehicle, attr_position_speed, &speed_attr, NULL), vehicle_get_attr(tr->vehicle, attr_position_direction, &direction_attr, NULL), - vehicle_get_attr(tr->vehicle, attr_position_coord_geo, &coord_geo, NULL)); + vehicle_get_attr(tr->vehicle, attr_position_coord_geo, &coord_geo, NULL), + vehicle_get_attr(tr->vehicle, attr_position_time_iso8601, &time_attr, NULL)); return; } if (tr->tunnel_extrapolation) { @@ -852,6 +855,7 @@ tracking_new(struct attr *parent, struct attr **attrs) { this->offroad_limit_pref=5000; this->route_pref=300; this->callback_list=callback_list_new(); + this->tunnel=0; if (! attr_generic_get_attr(attrs, NULL, attr_cdf_histsize, &hist_size, NULL)) { diff --git a/navit/track.h b/navit/track.h index 928ef4b00..5713ea4a6 100644 --- a/navit/track.h +++ b/navit/track.h @@ -20,9 +20,12 @@ #ifndef NAVIT_TRACK_H #define NAVIT_TRACK_H #include <time.h> +#include "xmlconfig.h" +#include "coord.h" #ifdef __cplusplus extern "C" { #endif + /* prototypes */ enum attr_type; enum projection; @@ -45,6 +48,7 @@ struct street_data *tracking_get_street_data(struct tracking *tr); int tracking_get_attr(struct tracking *_this, enum attr_type type, struct attr *attr, struct attr_iter *attr_iter); struct item *tracking_get_current_item(struct tracking *_this); int *tracking_get_current_flags(struct tracking *_this); +int tracking_get_current_tunnel(struct tracking *_this); void tracking_flush(struct tracking *tr); void tracking_update(struct tracking *tr, struct vehicle *v, struct vehicleprofile *vehicleprofile, enum projection pro); int tracking_set_attr(struct tracking *tr, struct attr *attr); diff --git a/navit/traffic.c b/navit/traffic.c index f19560829..85bef0baa 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -198,7 +198,7 @@ struct parsed_item { struct attr **attrs; /**< The attributes for the item, `NULL`-terminated */ struct coord *coords; /**< The coordinates for the item */ int coord_count; /**< The number of elements in `coords` */ - int length; /**< The length of the segment in meters */ + int delay; /**< Delay in deciseconds */ int is_matched; /**< Whether any of the maps has a matching item */ }; @@ -731,6 +731,7 @@ static struct item * tm_find_item(struct map_rect *mr, enum item_type type, stru if (attr_generic_get_attr(attrs, NULL, attr_flags, &wanted_flags_attr, NULL)) { if (!item_attr_get(curr, attr_flags, &curr_flags_attr)) continue; + item_attr_rewind(curr); if ((wanted_flags_attr.u.num & AF_ALL) != (curr_flags_attr.u.num & AF_ALL)) continue; continue; @@ -954,10 +955,6 @@ static struct map_rect_priv * tm_rect_new(struct map_priv *priv, struct map_sele int dirty = 0; dbg(lvl_debug,"enter"); - mr=g_new0(struct map_rect_priv, 1); - mr->mpriv = priv; - mr->next_item = priv->items; - /* all other pointers are initially NULL */ /* lazy location matching */ if (sel != NULL) @@ -990,6 +987,12 @@ static struct map_rect_priv * tm_rect_new(struct map_priv *priv, struct map_sele map_selection_destroy(msg_sel); } } + + mr=g_new0(struct map_rect_priv, 1); + mr->mpriv = priv; + mr->next_item = priv->items; + /* all other pointers are initially NULL */ + if (dirty) /* dump message store if new messages have been received */ traffic_dump_messages_to_xml(priv->shared); @@ -1379,6 +1382,7 @@ static int traffic_location_match_attributes(struct traffic_location * this_, st /* road_ref */ if (this_->road_ref) { maxscore += 400; + item_attr_rewind(item); if (item_attr_get(item, attr_street_name_systematic, &attr)) score += (400 * (MAX_MISMATCH - compare_name_systematic(this_->road_ref, attr.u.str))) / MAX_MISMATCH; } @@ -1386,6 +1390,7 @@ static int traffic_location_match_attributes(struct traffic_location * this_, st /* road_name */ if (this_->road_name) { maxscore += 200; + item_attr_rewind(item); if (item_attr_get(item, attr_street_name, &attr)) { // TODO crude comparison in need of refinement if (!strcmp(this_->road_name, attr.u.str)) @@ -1430,12 +1435,14 @@ static int traffic_point_match_attributes(struct traffic_point * this_, struct i /* junction_ref */ if (this_->junction_ref) { maxscore += 400; + item_attr_rewind(item); if (item_attr_get(item, attr_ref, &attr)) score += (400 * (MAX_MISMATCH - compare_name_systematic(this_->junction_ref, attr.u.str))) / MAX_MISMATCH; } /* junction_name */ if (this_->junction_name) { + item_attr_rewind(item); if (item_attr_get(item, attr_label, &attr)) { maxscore += 400; // TODO crude comparison in need of refinement @@ -1560,6 +1567,7 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, if (!strcmp(this_->junction_name, attr.u.str)) has_start_match = 1; } + item_attr_rewind(item); if (item_attr_get(item, attr_street_name_systematic, &attr)) start_ref = g_strdup(attr.u.str); } @@ -1576,6 +1584,7 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, if (!strcmp(this_->junction_name, attr.u.str)) has_end_match = 1; } + item_attr_rewind(item); if (item_attr_get(item, attr_street_name_systematic, &attr)) end_ref = g_strdup(attr.u.str); } @@ -1620,6 +1629,7 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, if (end_name) route_leaves_road |= !strcmp(end_name, attr.u.str); } + item_attr_rewind(item); if (!route_leaves_road && item_attr_get(item, attr_street_name_systematic, &attr)) { if (start_ref) route_leaves_road |= !compare_name_systematic(start_ref, attr.u.str); @@ -1645,6 +1655,7 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, if (end_name) route_leaves_road |= !strcmp(end_name, attr.u.str); } + item_attr_rewind(item); if (!route_leaves_road && item_attr_get(item, attr_street_name_systematic, &attr)) { if (start_ref) route_leaves_road |= !compare_name_systematic(start_ref, attr.u.str); @@ -1981,6 +1992,7 @@ static void traffic_location_populate_route_graph(struct traffic_location * this } else data.flags = *default_flags; + item_attr_rewind(item); if ((data.flags & AF_SPEED_LIMIT) && (item_attr_get(item, attr_maxspeed, &attr))) data.maxspeed = attr.u.num; @@ -3424,9 +3436,6 @@ static int traffic_message_restore_segments(struct traffic_message * this_, stru struct parsed_item * pitem; struct item * item; - /* Location length */ - int loc_len = 0; - /* List of parsed items */ GList * items = NULL, * curr_item; @@ -3529,6 +3538,8 @@ static int traffic_message_restore_segments(struct traffic_message * this_, stru pitem->coord_count = ccnt; pitem->attrs = attr_list_dup(attrs); for (i = 0; attrs[i]; i++) { + if (attrs[i]->type == attr_delay) + pitem->delay = attrs[i]->u.num; g_free(attrs[i]); attrs[i] = NULL; } @@ -3614,6 +3625,7 @@ static int traffic_message_restore_segments(struct traffic_message * this_, stru segmented = 0; } /* Get maxspeed, if any */ + item_attr_rewind(map_item); if ((item_flags & AF_SPEED_LIMIT) && (item_attr_get(map_item, attr_maxspeed, &attr))) maxspeed = attr.u.num; else @@ -3649,12 +3661,8 @@ static int traffic_message_restore_segments(struct traffic_message * this_, stru dbg(lvl_debug, "*****checkpoint RESTORE-6.1, restoring segmented items is not supported yet"); map_item = NULL; } - if (map_item) { + if (map_item) pitem->is_matched = 1; - for (i = 1; i < pitem->coord_count; i++) - pitem->length += transform_distance(map_projection(m), &(ca[i-1]), &(ca[i])); - loc_len += pitem->length; - } } } @@ -3689,11 +3697,10 @@ static int traffic_message_restore_segments(struct traffic_message * this_, stru pitem = (struct parsed_item *) curr_item->data; item = tm_add_item(map, pitem->type, pitem->id_hi, pitem->id_lo, pitem->flags, pitem->attrs, pitem->coords, pitem->coord_count, this_->id); - parsed_item_destroy(pitem); tm_item_add_message_data(item, this_->id, traffic_get_item_speed(item, seg_data, maxspeed), - traffic_get_item_delay(seg_data->delay, pitem->length, loc_len), - NULL, route); + pitem->delay, NULL, route); + parsed_item_destroy(pitem); this_->priv->items[i] = item; i++; } @@ -3842,31 +3849,33 @@ static int traffic_message_is_valid(struct traffic_message * this_) { return 0; } if (!this_->receive_time || !this_->update_time) { - dbg(lvl_debug, "receive_time or update_time not supplied"); + dbg(lvl_debug, "%s: receive_time or update_time not supplied", this_->id); return 0; } if (!this_->is_cancellation) { if (!this_->expiration_time && !this_->end_time) { - dbg(lvl_debug, "not a cancellation, but neither expiration_time nor end_time supplied"); + dbg(lvl_debug, "%s: not a cancellation, but neither expiration_time nor end_time supplied", + this_->id); return 0; } if (!this_->location) { - dbg(lvl_debug, "not a cancellation, but no location supplied"); + dbg(lvl_debug, "%s: not a cancellation, but no location supplied", this_->id); return 0; } if (!traffic_location_is_valid(this_->location)) { - dbg(lvl_debug, "not a cancellation, but location is invalid"); + dbg(lvl_debug, "%s: not a cancellation, but location is invalid", this_->id); return 0; } if (!this_->event_count || !this_->events) { - dbg(lvl_debug, "not a cancellation, but no events supplied"); + dbg(lvl_debug, "%s: not a cancellation, but no events supplied", this_->id); return 0; } for (i = 0; i < this_->event_count; i++) if (this_->events[i]) has_valid_events |= traffic_event_is_valid(this_->events[i]); if (!has_valid_events) { - dbg(lvl_debug, "not a cancellation, but all events (%d in total) are invalid", this_->event_count); + dbg(lvl_debug, "%s: not a cancellation, but all events (%d in total) are invalid", + this_->id, this_->event_count); return 0; } } @@ -4626,7 +4635,6 @@ static struct traffic * traffic_new(struct attr *parent, struct attr **attrs) { navit_object_destroy((struct navit_object *) this_); return NULL; } - navit_object_ref((struct navit_object *) this_); dbg(lvl_debug,"return %p", this_); // TODO do this once and cycle through all plugins @@ -4888,7 +4896,7 @@ static void traffic_xml_end(xml_context *dummy, const char *tag_name, void *data count, (struct traffic_event **) children); if (!traffic_message_is_valid(message)) { - dbg(lvl_error, "malformed message detected, skipping"); + dbg(lvl_error, "%s: malformed message detected, skipping", message->id); traffic_message_destroy(message); } else state->messages = g_list_append(state->messages, message); @@ -4945,7 +4953,9 @@ static void traffic_xml_end(xml_context *dummy, const char *tag_name, void *data state->si = NULL; /* TODO preserve unknown (and thus invalid) events if they have maxspeed set */ if (!traffic_event_is_valid(event)) { - dbg(lvl_debug, "invalid or unknown event detected, skipping"); + dbg(lvl_debug, "invalid or unknown event %s/%s detected, skipping", + traffic_xml_get_attr("class", el->names, el->values), + traffic_xml_get_attr("type", el->names, el->values)); traffic_event_destroy(event); } else state->events = g_list_append(state->events, event); @@ -5800,7 +5810,6 @@ struct map * traffic_get_map(struct traffic *this_) { attrs[4] = NULL; this_->shared->map = map_new(NULL, attrs); - navit_object_ref((struct navit_object *) this_->shared->map); /* populate map with previously stored messages */ filename = g_strjoin(NULL, navit_get_user_data_directory(TRUE), "/traffic.xml", NULL); @@ -5938,6 +5947,13 @@ void traffic_set_route(struct traffic *this_, struct route *rt) { this_->shared->rt = rt; } +void traffic_destroy(struct traffic *this_) { + if (this_->meth.destroy) + this_->meth.destroy(this_->priv); + attr_list_free(this_->attrs); + g_free(this_); +} + struct object_func traffic_func = { attr_traffic, (object_func_new)traffic_new, @@ -5948,7 +5964,7 @@ struct object_func traffic_func = { (object_func_add_attr)navit_object_add_attr, (object_func_remove_attr)navit_object_remove_attr, (object_func_init)NULL, - (object_func_destroy)navit_object_destroy, + (object_func_destroy)traffic_destroy, (object_func_dup)NULL, (object_func_ref)navit_object_ref, (object_func_unref)navit_object_unref, diff --git a/navit/traffic.h b/navit/traffic.h index bf0ca907e..f695ad156 100644 --- a/navit/traffic.h +++ b/navit/traffic.h @@ -58,6 +58,24 @@ extern "C" { #endif /** + * @brief Translates a Navit tile order to a minimum road class as used in TraFF. + * + * This can be used to translate a map selection into a TraFF filter. + * + * The tile order is the lowest tile level in which an object of a certain type can be placed (higher numbers + * correspond to lower levels). Currently, 8 is the maximum order for `highway_city`, `highway_land` and + * `street_n_lanes`, equivalent to `MOTORWAY` and `TRUNK`. 10 is the maximum order for `street_4_city` and + * `street_4_land` (`SECONDARY`), 12 for `street_3_city` and `street_3_land` (`TERTIARY`). All others can + * be placed in any tile level. + * + * This macro returns `PRIMARY`, `SECONDARY` and `TERTIARY` for the three bins above these cut-off orders, + * corresponding to one level below the lowest road class we expect to find there. (Not considering that + * low-level roads can be placed into higher-level tiles if they cross a tile boundary of the next lower + * level.) Below the lowest cut-off order, the macro returns NULL. + */ +#define order_to_min_road_class(x) (x <= 8 ? "PRIMARY" : x <= 10 ? "SECONDARY" : x <= 12 ? "TERTIARY" : NULL) + +/** * @brief Classes for events. */ /* If additional event classes are introduced, traffic_event_is_valid() must be adapted to recognize them. */ @@ -239,6 +257,7 @@ struct traffic_message_priv; */ struct traffic_methods { struct traffic_message **(* get_messages)(struct traffic_priv * this_); /**< Retrieves new messages from the traffic plugin */ + void (*destroy)(struct traffic_priv * this_); /**< Destructor for the traffic plugin */ }; /** @@ -989,6 +1008,11 @@ void traffic_set_mapset(struct traffic *this_, struct mapset *ms); */ void traffic_set_route(struct traffic *this_, struct route *rt); +/** + * @brief Destructor. + */ +void traffic_destroy(struct traffic *this_); + /* end of prototypes */ #ifdef __cplusplus } diff --git a/navit/traffic/dummy/traffic_dummy.c b/navit/traffic/dummy/traffic_dummy.c index b838752dc..2ab4073d4 100644 --- a/navit/traffic/dummy/traffic_dummy.c +++ b/navit/traffic/dummy/traffic_dummy.c @@ -154,6 +154,7 @@ struct traffic_message ** traffic_dummy_get_messages(struct traffic_priv * this_ */ static struct traffic_methods traffic_dummy_meth = { traffic_dummy_get_messages, + NULL, }; /** diff --git a/navit/traffic/null/traffic_null.c b/navit/traffic/null/traffic_null.c index 94546a666..02fc461c6 100644 --- a/navit/traffic/null/traffic_null.c +++ b/navit/traffic/null/traffic_null.c @@ -65,6 +65,7 @@ struct traffic_message ** traffic_null_get_messages(struct traffic_priv * this_) */ static struct traffic_methods traffic_null_meth = { traffic_null_get_messages, + NULL, }; /** diff --git a/navit/traffic/traff_android/traffic_traff_android.c b/navit/traffic/traff_android/traffic_traff_android.c index 266f51a0c..e0862ec5c 100644 --- a/navit/traffic/traff_android/traffic_traff_android.c +++ b/navit/traffic/traff_android/traffic_traff_android.c @@ -22,7 +22,7 @@ * * @brief The TraFF plugin for Android * - * This plugin receives TraFF feeds via Android broadcasts. + * This plugin receives TraFF feeds via Android broadcasts and content providers. */ #include <string.h> @@ -36,13 +36,31 @@ #include "item.h" #include "attr.h" #include "coord.h" +#include "map.h" +#include "route_protected.h" +#include "route.h" +#include "transform.h" #include "xmlconfig.h" #include "android.h" #include "traffic.h" #include "plugin.h" #include "callback.h" +#include "vehicle.h" #include "debug.h" #include "navit.h" +#include "util.h" + +/** + * @brief Minimum area around the current position for which to retrieve traffic updates. + * + * 100000 is equivalent to around 50 km on each side of the current position. The actual subscription area + * can be larger, allowing for a subscription area to be kept over multiple position updates. + * + * The actual subscription area around the current location is stored in + * {@link struct traffic_priv::position_rect} and updated in + * {@link traffic_traff_android_position_callback(struct traffic_priv *, struct navit *, struct vehicle *)}. + */ +#define POSITION_RECT_SIZE 100000 /** * @brief Stores information about the plugin instance. @@ -50,13 +68,38 @@ struct traffic_priv { struct navit * nav; /**< The navit instance */ struct callback * cbid; /**< The callback function for TraFF feeds **/ + int position_valid; /**< Whether Navit currently has a valid position */ + struct coord_rect * position_rect; /**< Rectangle around last known vehicle position (in `projection_mg`) */ + struct map_selection * route_map_sel; /**< Map selection for the current route */ jclass NavitTraffClass; /**< The `NavitTraff` class */ jobject NavitTraff; /**< An instance of `NavitTraff` */ }; +void traffic_traff_android_destroy(struct traffic_priv * this_); struct traffic_message ** traffic_traff_android_get_messages(struct traffic_priv * this_); /** + * @brief Destructor. + */ +void traffic_traff_android_destroy(struct traffic_priv * this_) { + jmethodID cid; + + cid = (*jnienv)->GetMethodID(jnienv, this_->NavitTraffClass, "close", "()V"); + if (cid == NULL) { + dbg(lvl_error,"no method found"); + return; /* exception thrown */ + } + (*jnienv)->CallVoidMethod(jnienv, this_->NavitTraff, cid); + + if (this_->position_rect) + g_free(this_->position_rect); + this_->position_rect = NULL; + if (this_->route_map_sel) + route_free_selection(this_->route_map_sel); + this_->route_map_sel = NULL; +} + +/** * @brief Returns an empty traffic report. * * @return Always `NULL` @@ -70,6 +113,7 @@ struct traffic_message ** traffic_traff_android_get_messages(struct traffic_priv */ static struct traffic_methods traffic_traff_android_meth = { traffic_traff_android_get_messages, + traffic_traff_android_destroy, }; @@ -109,12 +153,133 @@ static void traffic_traff_android_on_feed_received(struct traffic_priv * this_, /** + * @brief Sets the route map selection + * + * @param this_ The instance which will handle the selection update + */ +static void traffic_traff_android_set_selection(struct traffic_priv * this_) { + struct route * route; + struct coord_geo lu, rl; + gchar *filter_list; + jstring j_filter_list; + gchar *min_road_class; + jmethodID cid; + + if (this_->route_map_sel) + route_free_selection(this_->route_map_sel); + this_->route_map_sel = NULL; + if (navit_get_destination_count(this_->nav) && (route = (navit_get_route(this_->nav)))) + this_->route_map_sel = route_get_selection(route); + + /* start building the filter list */ + filter_list = g_strconcat_printf(NULL, "<filter_list>\n"); + if (this_->position_rect) { + transform_to_geo(projection_mg, &this_->position_rect->lu, &lu); + transform_to_geo(projection_mg, &this_->position_rect->rl, &rl); + filter_list = g_strconcat_printf(filter_list, " <filter bbox=\"%.5f %.5f %.5f %.5f\"/>\n", + rl.lat, lu.lng, lu.lat, rl.lng); + } + for (struct map_selection * sel = this_->route_map_sel; sel; sel = sel->next) { + transform_to_geo(projection_mg, &sel->u.c_rect.lu, &lu); + transform_to_geo(projection_mg, &sel->u.c_rect.rl, &rl); + min_road_class = order_to_min_road_class(sel->order); + if (!min_road_class) + filter_list = g_strconcat_printf(filter_list, " <filter bbox=\"%.5f %.5f %.5f %.5f\"/>\n", + rl.lat, lu.lng, lu.lat, rl.lng); + else + filter_list = g_strconcat_printf(filter_list, " <filter min_road_class=\"%s\" bbox=\"%.5f %.5f %.5f %.5f\"/>\n", + min_road_class, rl.lat, lu.lng, lu.lat, rl.lng); + } + /* the trailing \0 is required for NewStringUTF */ + filter_list = g_strconcat_printf(filter_list, "</filter_list>\0"); + j_filter_list = (*jnienv)->NewStringUTF(jnienv, filter_list); + cid = (*jnienv)->GetMethodID(jnienv, this_->NavitTraffClass, "onFilterUpdate", "(Ljava/lang/String;)V"); + if (cid) + (*jnienv)->CallVoidMethod(jnienv, this_->NavitTraff, cid, j_filter_list); + g_free(filter_list); +} + + +/** + * @brief Callback for destination changes + * + * @param this_ The instance which will handle the destination update + */ +static void traffic_traff_android_destination_callback(struct traffic_priv * this_) { + traffic_traff_android_set_selection(this_); +} + + +/** + * @brief Callback for navigation status changes + * + * This callback is necessary to force an update of existing subscriptions when Navit acquires a new + * position (after not having had valid position information), as the map selection will change when + * the current position becomes known for the first time. + * + * @param this_ The instance which will handle the navigation status update + * @param status The status of the navigation engine (the value of the {@code nav_status} attribute) + */ +static void traffic_traff_android_status_callback(struct traffic_priv * this_, int status) { + int new_position_valid = (status != 1); + if (new_position_valid && !this_->position_valid) { + this_->position_valid = new_position_valid; + traffic_traff_android_set_selection(this_); + } else if (new_position_valid != this_->position_valid) + this_->position_valid = new_position_valid; +} + + +/** + * @brief Callback for position changes + * + * This updates {@link struct traffic_priv::position_rect} if the vehicle has moved far enough from its + * center to be within {@link POSITION_RECT_SIZE} of one of its boundaries. The new rectangle is created + * with twice that amount of padding, allowing the vehicle to move for at least that distance before the + * subscription needs to be updated again. + * + * @param this_ The instance which will handle the position update + * @param navit The Navit instance + * @param vehicle The vehicle which delivered the position update and from which the position can be queried + */ +static void traffic_traff_android_position_callback(struct traffic_priv * this_, struct navit *navit, + struct vehicle *vehicle) { + struct attr attr; + struct coord c; + struct coord_rect cr; + jmethodID cid; + if (!vehicle_get_attr(vehicle, attr_position_coord_geo, &attr, NULL)) + return; + transform_from_geo(projection_mg, attr.u.coord_geo, &c); + cr.lu = c; + cr.rl = c; + cr.lu.x -= POSITION_RECT_SIZE; + cr.rl.x += POSITION_RECT_SIZE; + cr.lu.y += POSITION_RECT_SIZE; + cr.rl.y -= POSITION_RECT_SIZE; + if (!this_->position_rect) + this_->position_rect = g_new0(struct coord_rect, 1); + if (!coord_rect_contains(this_->position_rect, &cr.lu) || !coord_rect_contains(this_->position_rect, &cr.rl)) { + cr.lu.x -= POSITION_RECT_SIZE; + cr.rl.x += POSITION_RECT_SIZE; + cr.lu.y += POSITION_RECT_SIZE; + cr.rl.y -= POSITION_RECT_SIZE; + *(this_->position_rect) = cr; + traffic_traff_android_set_selection(this_); + } +} + + +/** * @brief Initializes a traff_android plugin * * @return True on success, false on failure */ static int traffic_traff_android_init(struct traffic_priv * this_) { jmethodID cid; + struct route * route; + struct attr attr; + struct navigation * navigation; if (!android_find_class_global("org/navitproject/navit/NavitTraff", &this_->NavitTraffClass)) return 0; @@ -131,6 +296,15 @@ static int traffic_traff_android_init(struct traffic_priv * this_) { if (this_->NavitTraff) this_->NavitTraff = (*jnienv)->NewGlobalRef(jnienv, this_->NavitTraff); + /* register callbacks for position and destination changes */ + navit_add_callback(this_->nav, callback_new_attr_1(callback_cast(traffic_traff_android_position_callback), + attr_position_coord_geo, this_)); + navit_add_callback(this_->nav, callback_new_attr_1(callback_cast(traffic_traff_android_destination_callback), + attr_destination, this_)); + if ((navigation = navit_get_navigation(this_->nav))) + navigation_register_callback(navigation, attr_nav_status, + callback_new_attr_1(callback_cast(traffic_traff_android_status_callback), attr_nav_status, this_)); + return 1; } @@ -154,6 +328,9 @@ static struct traffic_priv * traffic_traff_android_new(struct navit *nav, struct ret = g_new0(struct traffic_priv, 1); ret->nav = nav; ret->cbid = callback_new_1(callback_cast(traffic_traff_android_on_feed_received), ret); + ret->position_valid = 0; + ret->position_rect = NULL; + ret->route_map_sel = NULL; /* TODO populate members, if any */ *meth = traffic_traff_android_meth; diff --git a/navit/util.c b/navit/util.c index cf4412938..0dfdab20e 100644 --- a/navit/util.c +++ b/navit/util.c @@ -479,6 +479,19 @@ GList *g_hash_to_list_keys(GHashTable *h) { return ret; } +/** + * @brief Appends a formatted string and appends it to an existing one. + * + * Usage is similar to the familiar C functions that take a format string and a variable argument list. + * + * Return value is a concatenation of `buffer` (unless it is NULL) and `fmt`, with the remaining arguments + * inserted into `fmt`. + * + * @param buffer An existing string, can be null and will be freed by this function + * @param fmt A format string (will not be altered) + * + * @return A newly allocated string, see description. The caller is responsible for freeing the returned string. + */ gchar *g_strconcat_printf(gchar *buffer, gchar *fmt, ...) { gchar *str,*ret; va_list ap; diff --git a/navit/vehicle/geoclue/CMakeLists.txt b/navit/vehicle/geoclue/CMakeLists.txt new file mode 100644 index 000000000..2a447ab02 --- /dev/null +++ b/navit/vehicle/geoclue/CMakeLists.txt @@ -0,0 +1,2 @@ +module_add_library(vehicle_geoclue vehicle_geoclue.c) +target_link_libraries(vehicle_geoclue ${GeoClue_LIBRARIES}) diff --git a/navit/vehicle/geoclue/vehicle_geoclue.c b/navit/vehicle/geoclue/vehicle_geoclue.c new file mode 100644 index 000000000..6384a1cc3 --- /dev/null +++ b/navit/vehicle/geoclue/vehicle_geoclue.c @@ -0,0 +1,236 @@ +/* + * Navit, a modular navigation system. + * Copyright 2020 Navit Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include <stdlib.h> +#include <locale.h> +#include <glib/gi18n.h> +#include <geoclue.h> +#include "debug.h" +#include "callback.h" +#include "coord.h" +#include "item.h" +#include "vehicle.h" +#include "plugin.h" + +/** + * @defgroup vehicle-gypsy Vehicle GeoClue + * @ingroup vehicle-plugins + * @brief The Vehicle to gain position data from GeoClue. + * @Author jkoan + * @date 2020 + * + * @{ + */ + + +struct vehicle_priv { + GClueLocation *location; + char *bla; + struct callback_list *cbl; + double speed; + double direction; + double height; + struct coord_geo geo; + int accuracy; + char* time_str; + GClueSimple *simple; +}; +GClueClient *client = NULL; + +/** + * @brief Free the geoclue_vehicle + * + * @param priv + * @returns nothing + */ +static void vehicle_geoclue_destroy(struct vehicle_priv *priv) { + g_clear_object(&client); + g_clear_object(&priv->simple); +} + +static void print_location(GClueSimple *simple, + GParamSpec *pspec, + gpointer user_data) { + GClueLocation *location; + gdouble altitude; + gdouble speed; + gdouble direction; + GVariant *timestamp; + struct vehicle_priv *priv = user_data; + + location = gclue_simple_get_location(simple); + + priv->geo.lat = gclue_location_get_latitude(location); + priv->geo.lng = gclue_location_get_longitude(location); + priv->accuracy = gclue_location_get_accuracy(location); + altitude = gclue_location_get_altitude(location); + if(altitude != -G_MAXDOUBLE) { + priv->height=altitude; + } + speed = gclue_location_get_speed(location); + if(speed != -G_MAXDOUBLE) { + priv->speed=speed; + } + direction = gclue_location_get_heading(location); + if(direction != -G_MAXDOUBLE) { + priv->direction=direction; + } + + timestamp= gclue_location_get_timestamp(location); + if(timestamp) { + GDateTime *date_time; + glong second_since_epoch; + + + g_variant_get (timestamp, "(tt)", &second_since_epoch, NULL); + + date_time = g_date_time_new_from_unix_local (second_since_epoch); + + priv->time_str = g_date_time_format_iso8601(g_date_time_to_utc(date_time)); + + } + callback_list_call_attr_0(priv->cbl, attr_position_coord_geo); +} + +static void on_client_active_notify(GClueClient *client, + GParamSpec *pspec, + gpointer user_data) { + if(gclue_client_get_active(client)) + return; + + g_print("Geolocation disabled. Quitting..\n"); + //vehicle_geoclue_destroy(&user_data); +} + +static void on_simple_ready(GObject *source_object, + GAsyncResult *res, + gpointer user_data) { + GError *error = NULL; + + struct vehicle_priv* priv = user_data; + + priv->simple = gclue_simple_new_finish(res, &error); + if(error != NULL) { + dbg(lvl_error,"Failed to connect to GeoClue2 service: %s", error->message); + + exit(-1); + } + client = gclue_simple_get_client(priv->simple); + if(client) { + g_object_ref(client); + dbg(lvl_debug,"Client object: %s\n", + g_dbus_proxy_get_object_path(G_DBUS_PROXY(client))); + + g_signal_connect(client, + "notify::active", + G_CALLBACK(on_client_active_notify), + NULL); + } + print_location(priv->simple,NULL,priv); + + g_signal_connect(priv->simple, + "notify::location", + G_CALLBACK(print_location), + priv); +} + +/** + * @brief Provide the outside with information + * + * @param priv + * @param type TODO: What can this be? + * @param attr + * @returns true/false + */ +static int vehicle_geoclue_position_attr_get(struct vehicle_priv *priv, + enum attr_type type, struct attr *attr) { + switch(type) { + case attr_position_height: + attr->u.numd = &priv->height; + break; + case attr_position_speed: + attr->u.numd = &priv->speed; + break; + case attr_position_direction: + attr->u.numd = &priv->direction; + break; + case attr_position_qual: + attr->u.num = priv->accuracy; + break; + case attr_position_coord_geo: + attr->u.coord_geo = &priv->geo; + break; + case attr_position_time_iso8601: + if(!priv->time_str) { + return 0; + } + attr->u.str=priv->time_str; + break; + case attr_active: + return 1; + default: + return 0; + } + attr->type = type; + return 1; +} + +struct vehicle_methods vehicle_geoclue_methods = { + .destroy = vehicle_geoclue_destroy, + .position_attr_get = vehicle_geoclue_position_attr_get, +}; + +/** + * @brief Create geoclue_vehicle + * + * @param meth[out] Methodes supported by geoclue Plugin + * @param cbl[in] Callback List reference + * @param attrs Configuration attributes + * @returns vehicle_priv The newly created Vehicle priv + */ +static struct vehicle_priv *vehicle_geoclue_new(struct vehicle_methods *meth, + struct callback_list *cbl, + struct attr **attrs) { + struct vehicle_priv *ret; + dbg(lvl_debug, "enter"); + + *meth = vehicle_geoclue_methods; + + ret = (struct vehicle_priv*)g_new0(struct vehicle_priv, 1); + ret->cbl = cbl; + gclue_simple_new("navit", + GCLUE_ACCURACY_LEVEL_EXACT, + NULL, + on_simple_ready, + ret + ); + return ret; +}; + +/** + * @brief register vehicle_geoclue + * + * @returns nothing + */ +void plugin_init(void) { + dbg(lvl_error, "enter"); + plugin_register_category_vehicle("geoclue", vehicle_geoclue_new); +}; + diff --git a/navit/vehicle/gpsd/vehicle_gpsd.c b/navit/vehicle/gpsd/vehicle_gpsd.c index ea3aaf1f8..9dbc18aa4 100644 --- a/navit/vehicle/gpsd/vehicle_gpsd.c +++ b/navit/vehicle/gpsd/vehicle_gpsd.c @@ -26,6 +26,7 @@ #include <gpsbt.h> #include <errno.h> #endif +#include "config.h" #include "debug.h" #include "callback.h" #include "plugin.h" @@ -166,7 +167,12 @@ vehicle_gpsd_callback(struct gps_data_t *data, const char *buf, size_t len, data->set &= ~SATELLITE_SET; } if (data->set & STATUS_SET) { +#if GPSD_API_MAJOR_VERSION >= 10 + priv->status = data->fix.status; +#else priv->status = data->status; +#endif // GPSD_API_MAJOR_VERSION >= 10 + data->set &= ~STATUS_SET; } if (data->set & MODE_SET) { @@ -203,9 +209,10 @@ vehicle_gpsd_callback(struct gps_data_t *data, const char *buf, size_t len, data->set &= ~LATLON_SET; } // If data->fix.speed is NAN, then the drawing gets jumpy. - if (! isnan(data->fix.speed) && priv->fix_type > 0) { - callback_list_call_attr_0(priv->cbl, attr_position_coord_geo); - } + //if (! isnan(data->fix.speed) && priv->fix_type > 0) { + + callback_list_call_attr_0(priv->cbl, attr_position_coord_geo); + dbg(lvl_info,"speed ok"); } @@ -231,6 +238,7 @@ static int vehicle_gpsd_try_open(struct vehicle_priv *priv) { priv->gps = gps_open(source + 7, port); if(!priv->gps) { #endif + priv->cbt = callback_new_1(callback_cast(vehicle_gpsd_try_open), priv); dbg(lvl_error,"gps_open failed for '%s'. Retrying in %d seconds. Have you started gpsd?", priv->source, priv->retry_interval); g_free(source); @@ -307,10 +315,11 @@ static void vehicle_gpsd_close(struct vehicle_priv *priv) { } if (priv->gps) { gps_close(priv->gps); -#if GPSD_API_MAJOR_VERSION >= 5 - g_free(priv->gps); -#endif - priv->gps = NULL; +//if we release the gps object a reconnect is no longer working. +//#if GPSD_API_MAJOR_VERSION >= 5 +// g_free(priv->gps); +//#endif +// priv->gps = NULL; } #ifdef HAVE_GPSBT err = gpsbt_stop(&priv->context); diff --git a/navit/xmlconfig.h b/navit/xmlconfig.h index d5697d53c..bcd0ceec9 100644 --- a/navit/xmlconfig.h +++ b/navit/xmlconfig.h @@ -116,7 +116,7 @@ extern struct object_func map_func, mapset_func, navit_func, osd_func, tracking_ layout_func, roadprofile_func, vehicleprofile_func, layer_func, config_func, profile_option_func, script_func, log_func, speech_func, navigation_func, route_func, traffic_func; -#define HAS_OBJECT_FUNC(x) ((x) == attr_map || (x) == attr_mapset || (x) == attr_navit || (x) == attr_osd || (x) == attr_trackingo || (x) == attr_vehicle || (x) == attr_maps || (x) == attr_layout || (x) == attr_roadprofile || (x) == attr_vehicleprofile || (x) == attr_layer || (x) == attr_config || (x) == attr_profile_option || (x) == attr_script || (x) == attr_log || (x) == attr_speech || (x) == attr_navigation || (x) == attr_route) +#define HAS_OBJECT_FUNC(x) ((x) == attr_map || (x) == attr_mapset || (x) == attr_navit || (x) == attr_osd || (x) == attr_trackingo || (x) == attr_vehicle || (x) == attr_maps || (x) == attr_layout || (x) == attr_roadprofile || (x) == attr_vehicleprofile || (x) == attr_layer || (x) == attr_config || (x) == attr_profile_option || (x) == attr_script || (x) == attr_log || (x) == attr_speech || (x) == attr_navigation || (x) == attr_route || (x) == attr_traffic) #define NAVIT_OBJECT struct object_func *func; int refcount; struct attr **attrs; struct navit_object { diff --git a/scripts/build_android.sh b/scripts/build_android.sh index 836ead59b..4c2ba02bd 100755 --- a/scripts/build_android.sh +++ b/scripts/build_android.sh @@ -22,21 +22,26 @@ export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin export JVM_OPTS="-Xmx3200m" export GRADLE_OPTS='-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' +BUILD_PATH="android-builddir" + +[ -d $BUILD_PATH ] || mkdir -p $BUILD_PATH +pushd $BUILD_PATH + # processing xml is messed up a bit after the original introduction of gradle # so require a useless install of ant here even if using gradle/ninja echo Run CMake test -z "$PKG_CONFIG_LIBDIR" && export PKG_CONFIG_LIBDIR="" # Force cmake below to run ignore build host libraries when using pkgconfig. # Note: If you want to compile against specific target libraries that are searched using pkgconfig, please run this script with variable PKG_CONFIG_LIBDIR set to the appropriate path -cmake ./ -Dvehicle/gpsd_dbus:BOOL=FALSE -Dsvg2png_scaling:STRING=-1,24,32,48,64,96,128,192,256 -Dsvg2png_scaling_nav:STRING=-1,24,32,48,64,96,128,192,256 -Dsvg2png_scaling_flag:STRING=-1,24,32,64,96 -DXSL_PROCESSING=y -DXSLTS=android -DANDROID=y -DDISABLE_CXX=y || exit 1 +cmake ../ -Dvehicle/gpsd_dbus:BOOL=FALSE -Dsvg2png_scaling:STRING=-1,24,32,48,64,96,128,192,256 -Dsvg2png_scaling_nav:STRING=-1,24,32,48,64,96,128,192,256 -Dsvg2png_scaling_flag:STRING=-1,24,32,64,96 -DXSL_PROCESSING=y -DXSLTS=android -DANDROID=y -DDISABLE_CXX=y || exit 1 echo Process icons pushd navit/icons make || exit 32 -rm -rf ../android/res/drawable-nodpi -mkdir ../android/res/drawable-nodpi -cp ./*.png ../android/res/drawable-nodpi -pushd ../android/res/drawable-nodpi +rm -rf ../../android/res/drawable-nodpi +mkdir -p ../../android/res/drawable-nodpi +cp ./*.png ../../android/res/drawable-nodpi +pushd ../../android/res/drawable-nodpi rename -f 'y/A-Z/a-z/' ./*.png popd popd @@ -44,10 +49,10 @@ popd echo Process translations pushd po make || exit 64 -rm -rf ../navit/android/res/raw -mkdir ../navit/android/res/raw -cp ./*.mo ../navit/android/res/raw -pushd ../navit/android/res/raw +rm -rf ../android/res/raw +mkdir -p ../android/res/raw +cp ./*.mo ../android/res/raw +pushd ../android/res/raw rename -f 'y/A-Z/a-z/' ./*.mo popd popd @@ -56,10 +61,11 @@ popd echo Process xml config files make navit_config_xml || exit 96 -pushd navit rm -rf ./android/assets mkdir -p ./android/assets -cp -R config ./android/assets/ +cp -R ./navit/config ./android/assets/ + +#run gradle from root dir, not $BUILD_PATH popd echo Chmod permissions @@ -72,6 +78,6 @@ echo Build ./gradlew assembleDebug || exit 128 echo Build finished. -echo APK should be in "navit/android/build/outputs/apk" and can be installed with +echo APK should be in "build/outputs/apk" and can be installed with echo ./gradlew installDebug diff --git a/scripts/setup_publish_keys.sh b/scripts/setup_publish_keys.sh index 2b1331d8e..b363d9d32 100755 --- a/scripts/setup_publish_keys.sh +++ b/scripts/setup_publish_keys.sh @@ -7,8 +7,7 @@ if [[ -n $GOOGLE_KEY ]]; then fi if [[ -n $KEY ]]; then wget "https://github.com/navit-gps/infrastructure-blackbox/raw/master/keyrings/keystore.gpg" - openssl aes-256-cbc -d -in keystore.gpg -md md5 -k $KEY > ~/.keystore - keytool -importkeystore -srcstorepass "$STORE_PASS" -deststorepass "$STORE_PASS" -srckeystore ~/.keystore -destkeystore ~/.keystore -deststoretype pkcs12 - keytool -keypasswd -alias $KEY_ALIAS -storepass $STORE_PASS -new $KEY_PASS -keystore ~/.keystore - rm keystore.gpg + openssl aes-256-cbc -d -in keystore.gpg -md md5 -k $KEY > keystore + keytool -importkeystore -srcstorepass "$STORE_PASS" -deststorepass "$STORE_PASS" -srckeystore keystore -destkeystore ~/.keystore -deststoretype pkcs12 + rm keystore.gpg keystore fi diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 5cac9edd2..000000000 --- a/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include 'navit:android' |