68 Commits

Author SHA1 Message Date
Emux
e62e27cf22 0.16.0 2021-05-27 18:47:05 +03:00
Emux
76bf76a090 Update Applications.md 2021-05-27 15:46:06 +03:00
Emux
e906305910 Update changelog 2021-05-17 16:49:50 +03:00
Александр
08b94a0c42 Distant labels rendering (#844) 2021-05-17 16:46:36 +03:00
Emux
c508bde844 TileSource.OpenResult: allow null error messages (#837) 2021-05-12 14:45:20 +03:00
Emux
d4b7e34d17 Update Gradle (#835) 2021-05-05 14:28:17 +03:00
Emux
d5543bd7ef Map scale bar improvements (#828) 2021-04-13 13:52:28 +03:00
Emux
354bc16ead InputHandler: keyboard improvements (#827) 2021-04-13 12:36:54 +03:00
Emux
8889235690 Update Android Gradle plugin (#826) 2021-04-07 14:48:04 +03:00
Emux
9b43d7f498 JCenter deprecation (#825) 2021-04-07 14:02:12 +03:00
Emux
ef2d2dd197 ContentResolverResourceProvider: honor also absolute file references in theme resources (#823) 2021-03-31 15:04:26 +03:00
Emux
1245158ba3 SVG Salamander (#819) 2021-03-27 19:47:24 +02:00
Emux
ef5f7acbdf JCenter (#818) 2021-03-27 19:37:53 +02:00
Emux
e1c24ee8cf InputHandler: keyboard improvements (#817) 2021-03-24 18:10:28 +02:00
Emux
9f5ddd2381 Update docs 2021-03-17 13:09:01 +02:00
Emux
1fbc501bef Update docs 2021-03-16 19:41:43 +02:00
Emux
d7c69e12d6 Maven central (#813) 2021-03-16 18:34:31 +02:00
Emux
1fa86b5e07 GitHub Discussions 2021-03-16 17:26:09 +02:00
Emux
efed81bdeb Update ISSUE_TEMPLATE.md 2021-03-15 10:29:21 +02:00
Emux
a308eb48ac Update OkHttp (#811) 2021-03-14 15:58:53 +02:00
Emux
5926dd3e65 Render themes: add river labels (#810) 2021-03-04 15:37:39 +02:00
Emux
a11e620792 Render themes: improve lake labels (#809) 2021-03-04 14:41:33 +02:00
Emux
6850eff26c ContentResolverResourceProvider should handle document Uris correctly (#808) 2021-03-01 11:09:43 +02:00
Emux
ddf94ae2ca ZipXmlThemeResourceProvider: add method to just scan zip for xml themes (#807) 2021-02-22 14:06:03 +02:00
Emux
22ed9653ec AndroidBitmap: convert unsupported bitmap formats (#805) 2021-01-29 16:51:31 +02:00
Emux
3bb8ce00c5 Render themes: Android scoped storage, zip render theme, custom resource providers (#804) 2021-01-21 15:01:19 +02:00
Emux
b9cbd97c40 Nautical unit adapter with feet (#803) 2021-01-12 18:12:16 +02:00
Emux
6801b895e4 Mapsforge themes compatibility improvements #100 (#802) 2021-01-11 17:30:44 +02:00
Emux
c0d5f4a0ca 0.15.0 2021-01-01 18:59:48 +02:00
Emux
2859a18d72 Deploy improvements 2021-01-01 18:44:53 +02:00
Emux
869446ad13 JobQueue.clear: change log level 2020-12-31 14:06:54 +02:00
Emux
b2fd22885e Samples: reorder theme dispose 2020-12-28 14:12:01 +02:00
Meibes
7d6c623a80 Samples MapFragment: use theme dispose function (#800) 2020-12-28 13:43:56 +02:00
Emux
6bea801bf6 Samples: use theme dispose function 2020-12-28 12:12:14 +02:00
Emux
d446a3448b Samples: add theme.dispose 2020-12-28 11:56:32 +02:00
Emux
d006ba5361 VectorTileLayer: code improvements 2020-12-25 14:53:19 +02:00
Meibes
0eb4f3752f OSMUtils.isArea: reorder 'if' based on OSM stats (#799) 2020-12-24 10:33:12 +02:00
Emux
789c280fc2 OSMUtils.isArea improvements #798 2020-12-23 17:16:08 +02:00
Meibes
a881eec9b1 OSMUtils.isArea improvements (#798) 2020-12-23 13:31:41 +02:00
Meibes
1bc1d88464 Android Samples: add Fragment example (#796) 2020-12-22 11:40:34 +02:00
Emux
1c18221f05 ReadBuffer: fix docs 2020-12-13 13:26:21 +02:00
Emux
f4162acf04 Update Android build tools 2020-12-10 12:06:10 +02:00
Emux
1138978c22 Use --release=7 for compiling the non-android libraries on Java >= 9 (#795) 2020-12-03 13:30:31 +02:00
Emux
bd43baba20 TileLayer: move tileSource in parent class (#794) 2020-11-30 17:47:14 +02:00
Meibes
2e6da74af8 Color: fix parseColor javadoc (#793) 2020-11-28 12:20:09 +02:00
Meibes
f6561d2a2e OsmTileLayer: add constructor (#792) 2020-11-28 12:18:16 +02:00
Emux
45a42bb242 Samples improvements #785 2020-11-24 14:13:56 +02:00
Emux
3043173814 Symbol scale option (#790) 2020-11-15 17:20:52 +02:00
Emux
cde5d898c7 Update Integration.md 2020-11-11 10:57:48 +02:00
Emux
58f6215c0f Samples improvements #785 2020-10-21 17:57:49 +03:00
Emux
d7d6fa57ac Parameters: increase maximum buffer size for map files (Japan) (#789) 2020-10-19 13:39:22 +03:00
Emux
57bf615ab7 Update Gradle (#788) 2020-10-13 14:11:45 +03:00
Emux
9bf3161010 Update Android Gradle plugin 2020-10-08 15:18:35 +03:00
Emux
98a977ea72 Merge pull request #786 from mapsforge/xml
Render theme xml pull parser
2020-09-25 16:58:44 +03:00
Emux
661bc08bbf Render theme xml pull parser, fix #431 2020-09-25 16:57:52 +03:00
Emux
804c8c4603 Merge pull request #785 from mapsforge/storage
Android: scoped storage example
2020-09-24 14:18:41 +03:00
Emux
e103c38e3e Android: scoped storage example 2020-09-24 14:18:20 +03:00
Emux
e3b4ff502e Merge pull request #784 from mapsforge/mapsforge
Mapsforge: map stream support
2020-09-24 14:02:48 +03:00
Emux
6116ebb348 Mapsforge: map stream support 2020-09-24 14:00:49 +03:00
Emux
5c3a728d05 Merge pull request #783 from mapsforge/content
Render theme from Android content providers
2020-09-24 13:54:14 +03:00
Emux
2070145880 Render theme from Android content providers 2020-09-24 13:52:13 +03:00
Emux
e9a670f274 Update Android samples 2020-09-17 10:46:17 +03:00
Emux
e5c87ba06e Merge pull request #782 from mapsforge/android
Update Android
2020-09-09 17:57:22 +03:00
Emux
fa992b93f5 Update Android 2020-09-09 17:47:42 +03:00
Emux
bf67074cf3 Merge pull request #781 from mapsforge/cache
Android samples: use OkHttp cache
2020-09-02 17:09:48 +03:00
Emux
074320d6d2 Android samples: use OkHttp cache 2020-09-02 17:08:39 +03:00
Emux
6616c22a32 Update changelog 2020-08-30 20:24:41 +03:00
Izumi Kawashima
1ddba0fe8f Use org.gretty instead of org.akhikhl.gretty maven repository (#780) 2020-08-30 18:09:28 +03:00
103 changed files with 3973 additions and 880 deletions

View File

@@ -4,8 +4,8 @@ jdk:
- openjdk8
env:
global:
- ANDROID=29
- ANDROID_BUILD_TOOLS=29.0.3
- ANDROID=30
- ANDROID_BUILD_TOOLS=30.0.3
- GRADLE_OPTS="-Xmx2048m"
- secure: sW674wuFZOuoX7jHQHDbX3j8NxL8JxR07cyq+CrrqJ537dU9lxWQmMBRUpOb+p/q7sQ74PUtiKJkmFgKCSJSAKY+nr6GJ8P/q6u5TUKbmUWODSn8znehX2zualfvFwpF4PILok/wUzXBQE62jn4lUua7cMdsHRMNHbLmKqBoVL0meObDDjsaJ/RCbOPuruy3FmgvXPp0+Y4zl1GsklDSyjFzg4LBzjAk9Ryvh1O4zvJBkkyfCgurLKCnOKIPy3v5fPMS9oDfO1aarAVGoZZe416pvTW4hb8cdB6kn9XWYDob4NDFX/sP5k7XIhd/NAIn9LrKFg0sLtATaKLX+BcasF1CgDR/u6+SEeQd5QaRF7Go2Nq5Ltuu4OIFONI2qhEeVDDK6Otf2WSWj9KPno2GHuumBfbg4ypWoJgmZrMXk8JeVV/OP/0jIQz3p/7yfF21X1XBEqYaVHPAMKdEYYkCSa46KfACyOt6LfnkuCHtoTOpFo7sq0omIA2HOtpIx1u3vMBUyAbQqT6cokkKB1b6gNTFwhHc+8ybfLFPljJB8cWshI+V/b06S6fekRmvTNxvDykWNsdlkENBYqc9hMfjcT4hO4K+76SWN62mimQYODvFyfTVMC7WkQ3k/XEnmqUPV5XkbaILbS1d/tA57N148FiJ5/QXtI6Y94imubYyVqU=
- secure: AdKSZKA4gMuKXI4X4dQNJqcMv5OmPIHdN8fpy55Y9yoOQPQHZE3Zwc4QDWBh20q298jyEC854tVTPTysdZ7h+2s2FhsprYv1Bt/QNzKIrLpeIMj2quuVGMbdPuk08y55gost94KwVLJv0sIDpRlB/PEQkA7Mg/UDsT9zR8E1Ms5x+ul2C8e1ag0zzNl1wVnT5jY8WCp74uA/XXCcJl/80qT1stUERazCKwbKNo007hi7rdm4HA7YGevORq8e2r67je+WIBZUAwrHT0Zjuo4ibwUii4LdwvjuN3w0Z6e9Wf4x5bBqGgnih0T31uom2yPjNx+U/c2AWI+Nxfy/SEF2U+9bjBEZ3ZhI7F1B9ofXo2mhvvsVDiUrymMBbG2V64C9kAzeUh7xIBTqIrbdtpAEBV9FlLAtF2swVTwtCgZgcVTOt3RKXCi3X3nk3cuH7PAorFa/QGfT4xxVu2011FVAt2Rm7SD0ZWztZTSTz/4Nt/egtGBOJfrCc7oLEygLzDmLqsqCwCROITVQjWLjrtqDyLteaNiSXeNIQMKun3izApbXnHmXB+FV3R3EZocboqk3v5bmPTahnG6Ghc2zknWyyxSx+O9qIfOpHUL8JMJiT82lUQUeibtCn7DCE8wVQ/gYC5i+a+KO/d3NemSzIFlZ8aoUiEPYq18dYlsDXeLXwF0=

View File

@@ -12,7 +12,7 @@ VTM (Vector Tile Map) was developed within the [OpenScienceMap](https://github.c
See the **[integration guide](docs/Integration.md)** and [changelog](docs/Changelog.md). And read through [how to contribute](docs/CONTRIBUTING.md) guidelines.
If you have any questions or problems, don't hesitate to ask our public [forum](https://groups.google.com/group/mapsforge-dev) for help.
If you have any questions or problems, don't hesitate to ask the Discussions for help.
## Features
- Java map library

View File

@@ -1,10 +1,10 @@
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
classpath 'com.android.tools.build:gradle:4.1.3'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
}
}
@@ -14,7 +14,7 @@ allprojects {
version = 'master-SNAPSHOT'
ext.isReleaseVersion = !version.endsWith("SNAPSHOT")
ext.androidBuildVersionTools = "29.0.3"
ext.androidBuildVersionTools = "30.0.3"
ext.gdxVersion = "1.9.10"
ext.gwtVersion = "2.8.2"
ext.slf4jVersion = "1.7.28"
@@ -28,12 +28,12 @@ allprojects {
}
}
static def androidCompileSdk() { return 29 }
static def androidCompileSdk() { return 30 }
// 14 for Support Library, 16 for sqlite-android
static def androidMinSdk() { return 16 }
static def androidTargetSdk() { return 29 }
static def androidTargetSdk() { return 30 }
static def versionCode() { return 1 }
@@ -42,13 +42,19 @@ def versionName() { return version }
subprojects {
repositories {
google()
jcenter()
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url "https://plugins.gradle.org/m2/" }
}
tasks.withType(JavaCompile) {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
options.encoding = 'UTF-8'
if (JavaVersion.current().isJava9Compatible()) {
if (!project.properties.containsKey('android')) {
options.compilerArgs.addAll(['--release', '7'])
}
}
}
}

View File

@@ -9,6 +9,7 @@ if (project.hasProperty("android")) {
task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += project.android.libraryVariants.toList().first().javaCompileProvider.get().classpath
}
} else {
task sourcesJar(type: Jar) {

View File

@@ -9,7 +9,7 @@
| [GPSLogger II](https://play.google.com/store/apps/details?id=com.emacberry.gpslogger) | Map and navigation, Fitness & Cycling application | Proprietary/Free | Android | Closed |
| [HabanaTrans](https://play.google.com/store/apps/details?id=cu.pabloapk.habanatrans&hl=es_419) | Public transport, map offline, gps, routing | Proprietary/Free | Android | Closed |
| [Hunt Cyprus](https://play.google.com/store/apps/developer?id=Talent+S.A.) | Map and navigation application for hunters | Proprietary/Free and Commercial | Android | Closed |
| [Kurviger](https://kurviger.de/en) | Route planner specialized on motorcyclists | Proprietary/Free and Commercial | Android | Closed |
| [Kurviger](https://kurviger.de/en) | Route planner specialized on motorcyclists | Proprietary/Free (in-app purchases) | Android | Closed |
| [MapTrek](http://maptrek.mobi) | Application for outdoor activities | GPL3/Free and Commercial | Android | Open |
| [MyRunningApp](https://play.google.com/store/apps/details?id=it.nimarsolutions.rungpstracker) | Fitness app | Proprietary/Free | Android | Closed |
| [MyTourbook](http://mytourbook.sourceforge.net/mytourbook/) | Visualize and analyze tours | GPL2/Free | Desktop | Open |
@@ -21,5 +21,3 @@
| [VTM with Eclipse RCP](https://github.com/wolfgang-ch/vtm-with-rcp) | VTM with an Eclipse RCP application | GPL3/Free | Desktop | Open |
| [Walkaholic](https://play.google.com/store/apps/details?id=com.walkaholic.hikeapp) | Hiking app with official routes and online/offline maps | Proprietary/Free (in-app purchases) | Android | Closed |
| [XCTrack](http://xctrack.org/) | Flight computer for paraglider pilots | Proprietary/Free | Android | Closed |
You know an application that is missing here? Please inform us by sending a message via our public [forum](https://groups.google.com/group/mapsforge-dev).

View File

@@ -2,7 +2,7 @@
As an open source project, we welcome new contributors and appreciate your help.
Before you start working on an unresolved issue or try to implement a new feature, please contact us via our public [forum](https://groups.google.com/group/mapsforge-dev). We will then discuss the best way to realize your proposal and figure out how we can help you to get started quickly.
Before you start working on an unresolved issue or try to implement a new feature, please contact us via the Discussions. We will then discuss the best way to realize your proposal and figure out how we can help you to get started quickly.
If you are only requesting a small change in the code, you may attach a patch file to the corresponding issue, but it is best to create a pull request on Github. Make sure that your patch is derived from the latest version in our **master** repository, otherwise we might be unable to apply it. Important is to keep pull requests simple with one feature in each. Please follow our code and style conventions.

View File

@@ -1,5 +1,32 @@
# Changelog
## New since 0.16.0
- Many other minor improvements and bug fixes
- [Solved issues](https://github.com/mapsforge/vtm/issues?q=is%3Aclosed+milestone%3A0.17.0)
## Version 0.16.0 (2021-05-27)
- Android: scoped storage map / theme example [#804](https://github.com/mapsforge/vtm/pull/804)
- Render theme from zip archive [#804](https://github.com/mapsforge/vtm/pull/804)
- Render themes: custom resource providers [#804](https://github.com/mapsforge/vtm/pull/804)
- Nautical unit adapter with feet [#803](https://github.com/mapsforge/vtm/pull/803)
- Distant labels rendering option [#844](https://github.com/mapsforge/vtm/pull/844)
- `Parameters.DISTANT_LABELS`
- Many other minor improvements and bug fixes
- [Solved issues](https://github.com/mapsforge/vtm/issues?q=is%3Aclosed+milestone%3A0.16.0)
## Version 0.15.0 (2021-01-01)
- Android: scoped storage map example [#785](https://github.com/mapsforge/vtm/pull/785)
- Mapsforge: map stream support [#784](https://github.com/mapsforge/vtm/pull/784)
- Render theme from Android content providers [#783](https://github.com/mapsforge/vtm/pull/783)
- Render theme xml pull parser [#786](https://github.com/mapsforge/vtm/pull/786)
- Symbol scale option [#790](https://github.com/mapsforge/vtm/pull/790)
- `Parameters.SYMBOL_SCALING`
- Many other minor improvements and bug fixes
- [Solved issues](https://github.com/mapsforge/vtm/issues?q=is%3Aclosed+milestone%3A0.15.0)
## Version 0.14.0 (2020-08-25)
- Render themes: symbol styles [#769](https://github.com/mapsforge/vtm/pull/769)
@@ -207,7 +234,7 @@
- Many other minor improvements and bug fixes
- [Solved issues](https://github.com/mapsforge/vtm/issues?q=is%3Aclosed+milestone%3A0.7.0)
## Version 0.6.0 (2016-10-28) - VTM revive
## Version 0.6.0 (2016-10-28) - VTM revival
- Mapsforge maps **v4** support [#34](https://github.com/mapsforge/vtm/issues/34)
- Render theme SVG resources [#60](https://github.com/mapsforge/vtm/issues/60)
@@ -224,6 +251,8 @@
- libGDX layer gestures [#151](https://github.com/mapsforge/vtm/issues/151)
- Render theme area tessellation option [#37](https://github.com/mapsforge/vtm/issues/37)
- Render theme resources optional location prefixes [#66](https://github.com/mapsforge/vtm/issues/66)
- Render theme from input stream [#161](https://github.com/mapsforge/vtm/issues/161)
- Render theme from Android assets [#162](https://github.com/mapsforge/vtm/issues/162)
- Graphics API platform enhancements [#92](https://github.com/mapsforge/vtm/issues/92)
- GeoPoint & BoundingBox improvements [#201](https://github.com/mapsforge/vtm/issues/201) [#200](https://github.com/mapsforge/vtm/issues/200)
- vtm-jts module [#53](https://github.com/mapsforge/vtm/issues/53)

View File

@@ -1 +1 @@
For questions or discussion please use the [forum](https://groups.google.com/group/mapsforge-dev).
For questions, reports and feature requests please use the Discussions.

View File

@@ -10,6 +10,7 @@ Current version is [![Maven Central](https://img.shields.io/maven-central/v/org.
```groovy
implementation 'org.mapsforge:vtm:[CURRENT-VERSION]'
implementation 'org.mapsforge:vtm-themes:[CURRENT-VERSION]'
implementation 'net.sf.kxml:kxml2:2.3.0'
implementation 'org.slf4j:slf4j-api:1.7.28'
```
@@ -47,23 +48,19 @@ Detailed iOS instructions can be found [here](ios.md).
### Desktop
```groovy
repositories {
maven { url 'https://jitpack.io' }
}
implementation 'org.mapsforge:vtm-gdx:[CURRENT-VERSION]'
implementation 'org.mapsforge:vtm-desktop:[CURRENT-VERSION]'
implementation 'org.mapsforge:vtm-desktop:[CURRENT-VERSION]:natives-linux'
implementation 'org.mapsforge:vtm-desktop:[CURRENT-VERSION]:natives-osx'
implementation 'org.mapsforge:vtm-desktop:[CURRENT-VERSION]:natives-windows'
implementation 'org.mapsforge:vtm-desktop-lwjgl:[CURRENT-VERSION]'
implementation 'com.badlogicgames.gdx:gdx:1.9.10'
implementation 'com.badlogicgames.gdx:gdx-platform:1.9.10:natives-desktop'
implementation 'com.github.blackears:svgSalamander:v1.1.1'
implementation 'com.formdev:svgSalamander:1.1.2.4'
```
### Desktop (LWJGL)
```groovy
implementation 'org.mapsforge:vtm-desktop-lwjgl:[CURRENT-VERSION]'
implementation 'com.badlogicgames.gdx:gdx-backend-lwjgl:1.9.10'
implementation 'org.lwjgl.lwjgl:lwjgl:2.9.3'
implementation 'org.lwjgl.lwjgl:lwjgl-platform:2.9.3:natives-linux'
@@ -73,6 +70,7 @@ implementation 'org.lwjgl.lwjgl:lwjgl-platform:2.9.3:natives-windows'
### Desktop (LWJGL 3)
```groovy
implementation 'org.mapsforge:vtm-desktop-lwjgl3:[CURRENT-VERSION]'
implementation 'com.badlogicgames.gdx:gdx-backend-lwjgl3:1.9.10'
implementation 'org.lwjgl:lwjgl:3.2.3'
implementation 'org.lwjgl:lwjgl:3.2.3:natives-linux'
@@ -93,7 +91,7 @@ implementation 'org.locationtech.jts:jts-core:1.15.1'
```groovy
implementation 'org.mapsforge:vtm-http:[CURRENT-VERSION]'
// https://github.com/square/okhttp/issues/4481
implementation 'com.squareup.okhttp3:okhttp:3.12.5'
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
implementation 'com.squareup.okio:okio:1.15.0'
```

View File

@@ -8,5 +8,3 @@
- [OpenAndroMaps](https://www.openandromaps.org/en/)
- [OpenMaps](https://openmaps.eu/)
- [vector.city](https://vector.city/)
You know a Mapsforge map provider that is missing here? Please inform us by sending a message via our public [forum](https://groups.google.com/group/mapsforge-dev).

View File

@@ -1,8 +1,6 @@
# RenderTheme
**This article describes how to use XML-based render-themes to style maps.**
If you have any questions or problems, don't hesitate to ask our public [forum](https://groups.google.com/group/mapsforge-dev) for help.
This article describes how to use XML-based render-themes to style maps.
## Introduction

View File

@@ -6,14 +6,12 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
android.useAndroidX=true

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -15,6 +15,7 @@
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true">
<activity
android:name=".Samples"
@@ -33,6 +34,9 @@
<activity
android:name=".ClusterMarkerOverlayActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".FragmentActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".GettingStarted"
android:configChanges="keyboardHidden|orientation|screenSize" />
@@ -60,12 +64,6 @@
<activity
android:name=".MapsforgeActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".MapsforgeActivity$MapFilePicker"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".MapsforgeActivity$ThemeFilePicker"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name=".MapsforgeS3DBActivity"
android:configChanges="keyboardHidden|orientation|screenSize" />

View File

@@ -16,11 +16,11 @@ dependencies {
implementation project(':vtm-gdx')
implementation project(':vtm-gdx-poi3d')
implementation 'org.mapsforge:mapsforge-poi-android:0.14.0'
implementation 'org.mapsforge:sqlite-android:0.14.0:natives-armeabi-v7a'
implementation 'org.mapsforge:sqlite-android:0.14.0:natives-arm64-v8a'
implementation 'org.mapsforge:sqlite-android:0.14.0:natives-x86'
implementation 'org.mapsforge:sqlite-android:0.14.0:natives-x86_64'
implementation 'org.mapsforge:mapsforge-poi-android:0.16.0'
implementation 'org.mapsforge:sqlite-android:0.16.0:natives-armeabi-v7a'
implementation 'org.mapsforge:sqlite-android:0.16.0:natives-arm64-v8a'
implementation 'org.mapsforge:sqlite-android:0.16.0:natives-x86'
implementation 'org.mapsforge:sqlite-android:0.16.0:natives-x86_64'
}
android {

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/empty_fragment_text" />
</RelativeLayout>

View File

@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<org.oscim.android.MapView
<RelativeLayout
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/replace_fragment"
android:showAsAction="never"
android:title="@string/replace_fragment" />
</menu>

View File

@@ -20,6 +20,9 @@
<item
android:id="@+id/theme_newtron"
android:title="@string/theme_newtron" />
<item
android:id="@+id/theme_external_archive"
android:title="@string/theme_external_archive" />
<item
android:id="@+id/theme_external"
android:title="@string/theme_external" />

View File

@@ -6,7 +6,8 @@
<string name="theme_osmagray">Osmagray</string>
<string name="theme_tubes">Tubes</string>
<string name="theme_newtron">NewTron</string>
<string name="theme_external">External theme</string>
<string name="theme_external">External theme (Android 5)</string>
<string name="theme_external_archive">External theme archive</string>
<string name="styler_mode_line">Line</string>
<string name="styler_mode_area">Area</string>
<string name="styler_mode_outline">Outline</string>
@@ -15,6 +16,7 @@
<string name="style_2">Hide nature</string>
<string name="menu_gridlayer">Grid</string>
<string name="dialog_reverse_geocoding_title">Reverse Geocoding</string>
<string name="dialog_theme_title">Select a theme</string>
<string name="add">Add</string>
<string name="cancel">Cancel</string>
<string name="error">Error</string>
@@ -28,5 +30,7 @@
<string name="warning">Warning</string>
<string name="startup_message_mbtiles">To run this sample activity, you need an MBTiles database installed on storage.\n\nadb push %s %s</string>
<string name="exit">Exit</string>
<string name="replace_fragment">Replace fragment</string>
<string name="empty_fragment_text">This is a fragment to test the back stack behaviour of the map fragment.</string>
</resources>

View File

@@ -1,6 +1,6 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2016-2018 devemux86
* Copyright 2016-2020 devemux86
* Copyright 2017 Longri
*
* This program is free software: you can redistribute it and/or modify it under the
@@ -16,18 +16,11 @@
*/
package org.oscim.android.filepicker;
import org.oscim.theme.ExternalRenderTheme;
import org.oscim.theme.ThemeFile;
import org.oscim.theme.XmlThemeBuilder;
import org.oscim.theme.ThemeLoader;
import org.oscim.tiling.TileSource.OpenResult;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import java.io.File;
import javax.xml.parsers.SAXParserFactory;
/**
* Accepts all valid render theme XML files.
*/
@@ -36,13 +29,8 @@ public final class ValidRenderTheme implements ValidFileFilter {
@Override
public boolean accept(File file) {
try {
ThemeFile theme = new ExternalRenderTheme(file.getAbsolutePath());
DefaultHandler renderThemeHandler = new XmlThemeBuilder(theme);
XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
xmlReader.setContentHandler(renderThemeHandler);
xmlReader.parse(new InputSource(theme.getRenderThemeAsStream()));
ThemeLoader.load(file.getAbsolutePath());
mOpenResult = OpenResult.SUCCESS;
} catch (Exception e) {
mOpenResult = new OpenResult(e.getMessage());

View File

@@ -1,6 +1,6 @@
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2018 devemux86
* Copyright 2016-2020 devemux86
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -20,8 +20,8 @@ package org.oscim.android.test;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import org.oscim.android.cache.TileCache;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import org.oscim.core.MapPosition;
import org.oscim.layers.TileGridLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
@@ -29,11 +29,10 @@ import org.oscim.theme.VtmThemes;
import org.oscim.tiling.TileSource;
import org.oscim.tiling.source.OkHttpEngine;
import org.oscim.tiling.source.oscimap4.OSciMap4TileSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
public class BaseMapActivity extends MapActivity {
static final Logger log = LoggerFactory.getLogger(BaseMapActivity.class);
static final boolean USE_CACHE = false;
@@ -41,8 +40,6 @@ public class BaseMapActivity extends MapActivity {
TileSource mTileSource;
TileGridLayer mGridLayer;
private TileCache mCache;
public BaseMapActivity(int contentView) {
super(contentView);
}
@@ -54,15 +51,19 @@ public class BaseMapActivity extends MapActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (USE_CACHE) {
// Cache the tiles into file system
File cacheDirectory = new File(getExternalCacheDir(), "tiles");
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(cacheDirectory, cacheSize);
builder.cache(cache);
}
mTileSource = OSciMap4TileSource.builder()
.httpFactory(new OkHttpEngine.OkHttpFactory())
.httpFactory(new OkHttpEngine.OkHttpFactory(builder))
.build();
if (USE_CACHE) {
mCache = new TileCache(this, null, "tile.db");
mCache.setCacheSize(512 * (1 << 10));
mTileSource.setCache(mCache);
}
mBaseLayer = mMap.setBaseMap(mTileSource);
/* set initial position on first run */
@@ -72,14 +73,6 @@ public class BaseMapActivity extends MapActivity {
mMap.setMapPosition(53.08, 8.83, Math.pow(2, 16));
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mCache != null)
mCache.dispose();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {

View File

@@ -16,22 +16,21 @@
package org.oscim.android.test;
import android.os.Bundle;
import org.oscim.android.cache.TileCache;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import org.oscim.core.MapPosition;
import org.oscim.core.MercatorProjection;
import org.oscim.layers.tile.bitmap.BitmapTileLayer;
import org.oscim.renderer.MapRenderer;
import org.oscim.tiling.source.OkHttpEngine;
import org.oscim.tiling.source.bitmap.BitmapTileSource;
import org.oscim.tiling.source.bitmap.DefaultSources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.Collections;
public class BitmapTileActivity extends MapActivity {
static final Logger log = LoggerFactory.getLogger(BitmapTileActivity.class);
private static final boolean USE_CACHE = false;
private final BitmapTileSource mTileSource;
@@ -43,12 +42,9 @@ public class BitmapTileActivity extends MapActivity {
public BitmapTileActivity(BitmapTileSource tileSource) {
super(R.layout.activity_map);
tileSource.setHttpRequestHeaders(Collections.singletonMap("User-Agent", "vtm-android-example"));
mTileSource = tileSource;
}
private TileCache mCache;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -58,31 +54,24 @@ public class BitmapTileActivity extends MapActivity {
if (mTileSource == null)
return;
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (USE_CACHE) {
String cacheFile = mTileSource.getUrl()
.toString()
.replaceFirst("https?://", "")
.replaceAll("/", "-");
log.debug("use bitmap cache {}", cacheFile);
mCache = new TileCache(this, null, cacheFile);
mCache.setCacheSize(512 * (1 << 10));
mTileSource.setCache(mCache);
// Cache the tiles into file system
File cacheDirectory = new File(getExternalCacheDir(), "tiles");
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(cacheDirectory, cacheSize);
builder.cache(cache);
}
mTileSource.setHttpEngine(new OkHttpEngine.OkHttpFactory(builder));
mTileSource.setHttpRequestHeaders(Collections.singletonMap("User-Agent", "vtm-android-example"));
mBitmapLayer = new BitmapTileLayer(mMap, mTileSource);
mMap.layers().add(mBitmapLayer);
//loooop(1);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mCache != null)
mCache.dispose();
}
// Stress testing
void loooop(final int i) {
final long time = (long) (500 + Math.random() * 1000);

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2020 Meibes
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.android.test;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@SuppressWarnings("deprecation")
public class BlankFragment extends Fragment {
static BlankFragment newInstance() {
BlankFragment instance = new BlankFragment();
Bundle args = new Bundle();
instance.setArguments(args);
return instance;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_blank, container, false);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2020 Meibes
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.android.test;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class FragmentActivity extends Activity {
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_fragment);
setTitle(getClass().getSimpleName());
if (savedInstanceState == null) {
Fragment mapFragment = MapFragment.newInstance();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, mapFragment).commit();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.fragment_menu, menu);
return true;
}
@SuppressWarnings("deprecation")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.replace_fragment) {
Fragment blankFragment = BlankFragment.newInstance();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, blankFragment);
ft.addToBackStack(null);
ft.commit();
return true;
}
return super.onOptionsItemSelected(item);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2018-2019 devemux86
* Copyright 2018-2020 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -15,6 +15,9 @@
package org.oscim.android.test;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import org.oscim.android.MapView;
import org.oscim.backend.CanvasAdapter;
@@ -25,23 +28,24 @@ import org.oscim.renderer.GLViewport;
import org.oscim.scalebar.DefaultMapScaleBar;
import org.oscim.scalebar.MapScaleBar;
import org.oscim.scalebar.MapScaleBarLayer;
import org.oscim.theme.IRenderTheme;
import org.oscim.theme.VtmThemes;
import org.oscim.tiling.source.mapfile.MapFileTileSource;
import java.io.File;
import java.io.FileInputStream;
/**
* A very basic Android app example.
* <p>
* You'll need a map with filename berlin.map from download.mapsforge.org in device storage:
* /sdcard/Android/data/org.oscim.android.test/files/
* You'll need a map with filename berlin.map from download.mapsforge.org in device storage.
*/
public class GettingStarted extends Activity {
// Name of the map file in device storage
private static final String MAP_FILE = "berlin.map";
// Request code for selecting a map file
private static final int SELECT_MAP_FILE = 0;
private MapView mapView;
private IRenderTheme theme;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -51,10 +55,30 @@ public class GettingStarted extends Activity {
mapView = new MapView(this);
setContentView(mapView);
// Tile source
MapFileTileSource tileSource = new MapFileTileSource();
String mapPath = new File(getExternalFilesDir(null), MAP_FILE).getAbsolutePath();
if (tileSource.setMapFile(mapPath)) {
// Open map
Intent intent = new Intent(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, SELECT_MAP_FILE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SELECT_MAP_FILE && resultCode == Activity.RESULT_OK) {
if (data != null) {
Uri uri = data.getData();
openMap(uri);
}
}
}
private void openMap(Uri uri) {
try {
// Tile source
MapFileTileSource tileSource = new MapFileTileSource();
FileInputStream fis = (FileInputStream) getContentResolver().openInputStream(uri);
tileSource.setMapFileInputStream(fis);
// Vector layer
VectorTileLayer tileLayer = mapView.map().setBaseMap(tileSource);
@@ -65,7 +89,7 @@ public class GettingStarted extends Activity {
mapView.map().layers().add(new LabelLayer(mapView.map(), tileLayer));
// Render theme
mapView.map().setTheme(VtmThemes.DEFAULT);
theme = mapView.map().setTheme(VtmThemes.DEFAULT);
// Scale bar
MapScaleBar mapScaleBar = new DefaultMapScaleBar(mapView.map());
@@ -76,6 +100,11 @@ public class GettingStarted extends Activity {
// Note: this map position is specific to Berlin area
mapView.map().setMapPosition(52.517037, 13.38886, 1 << 12);
} catch (Exception e) {
/*
* In case of map file errors avoid crash, but developers should handle these cases!
*/
e.printStackTrace();
}
}
@@ -94,6 +123,7 @@ public class GettingStarted extends Activity {
@Override
protected void onDestroy() {
mapView.onDestroy();
theme.dispose();
super.onDestroy();
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright 2018-2020 devemux86
* Copyright 2020 Meibes
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.android.test;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import org.oscim.android.MapView;
import org.oscim.backend.CanvasAdapter;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
import org.oscim.renderer.GLViewport;
import org.oscim.scalebar.DefaultMapScaleBar;
import org.oscim.scalebar.MapScaleBar;
import org.oscim.scalebar.MapScaleBarLayer;
import org.oscim.theme.IRenderTheme;
import org.oscim.theme.VtmThemes;
import org.oscim.tiling.source.mapfile.MapFileTileSource;
import java.io.File;
/**
* You'll need a map with filename berlin.map from download.mapsforge.org in device storage.
*/
@SuppressWarnings("deprecation")
public class MapFragment extends Fragment {
private MapView mapView;
private IRenderTheme theme;
public static MapFragment newInstance() {
MapFragment instance = new MapFragment();
Bundle args = new Bundle();
instance.setArguments(args);
return instance;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_map, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mapView = new MapView(getActivity());
RelativeLayout relativeLayout = view.findViewById(R.id.mapView);
relativeLayout.addView(mapView);
// Tile source
MapFileTileSource tileSource = new MapFileTileSource();
File file = new File(getActivity().getExternalFilesDir(null), "berlin.map");
tileSource.setMapFile(file.getAbsolutePath());
// Vector layer
VectorTileLayer tileLayer = mapView.map().setBaseMap(tileSource);
// Building layer
mapView.map().layers().add(new BuildingLayer(mapView.map(), tileLayer));
// Label layer
mapView.map().layers().add(new LabelLayer(mapView.map(), tileLayer));
// Render theme
theme = mapView.map().setTheme(VtmThemes.DEFAULT);
// Scale bar
MapScaleBar mapScaleBar = new DefaultMapScaleBar(mapView.map());
MapScaleBarLayer mapScaleBarLayer = new MapScaleBarLayer(mapView.map(), mapScaleBar);
mapScaleBarLayer.getRenderer().setPosition(GLViewport.Position.BOTTOM_LEFT);
mapScaleBarLayer.getRenderer().setOffset(5 * CanvasAdapter.getScale(), 0);
mapView.map().layers().add(mapScaleBarLayer);
// Note: this map position is specific to Berlin area
mapView.map().setMapPosition(52.517037, 13.38886, 1 << 12);
}
@Override
public void onResume() {
super.onResume();
if (mapView != null) {
mapView.onResume();
}
}
@Override
public void onPause() {
if (mapView != null) {
mapView.onPause();
}
super.onPause();
}
@Override
public void onDestroyView() {
if (mapView != null) {
mapView.onDestroy();
mapView = null;
}
if (theme != null) {
theme.dispose();
theme = null;
}
super.onDestroyView();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2018-2019 devemux86
* Copyright 2018-2020 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -16,10 +16,10 @@ package org.oscim.android.test;
import android.os.Build;
import android.os.Bundle;
import okhttp3.Cache;
import okhttp3.CipherSuite;
import okhttp3.ConnectionSpec;
import okhttp3.OkHttpClient;
import org.oscim.android.cache.TileCache;
import org.oscim.layers.tile.bitmap.BitmapTileLayer;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
@@ -30,6 +30,7 @@ import org.oscim.tiling.source.UrlTileSource;
import org.oscim.tiling.source.bitmap.DefaultSources;
import org.oscim.tiling.source.mvt.MapilionMvtTileSource;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -41,13 +42,18 @@ public class MapilionMvtActivity extends MapActivity {
private static final boolean USE_CACHE = false;
private TileCache mCache;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (USE_CACHE) {
// Cache the tiles into file system
File cacheDirectory = new File(getExternalCacheDir(), "tiles");
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(cacheDirectory, cacheSize);
builder.cache(cache);
}
// https://github.com/square/okhttp/issues/4053
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
@@ -71,13 +77,6 @@ public class MapilionMvtActivity extends MapActivity {
//.locale("en")
.build();
if (USE_CACHE) {
// Cache the tiles into a local SQLite database
mCache = new TileCache(this, null, "tile.db");
mCache.setCacheSize(512 * (1 << 10));
tileSource.setCache(mCache);
}
VectorTileLayer l = mMap.setBaseMap(tileSource);
mMap.setTheme(VtmThemes.OPENMAPTILES);
@@ -91,12 +90,4 @@ public class MapilionMvtActivity extends MapActivity {
mMap.layers().add(new BuildingLayer(mMap, l));
mMap.layers().add(new LabelLayer(mMap, l));
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mCache != null)
mCache.dispose();
}
}

View File

@@ -1,8 +1,9 @@
/*
* Copyright 2014 Hannes Janetzek
* Copyright 2016-2018 devemux86
* Copyright 2016-2021 devemux86
* Copyright 2017 Longri
* Copyright 2018 Gustl22
* Copyright 2021 eddiemuc
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -19,15 +20,18 @@
*/
package org.oscim.android.test;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.view.Menu;
import android.view.MenuItem;
import org.oscim.android.filepicker.FilePicker;
import org.oscim.android.filepicker.FilterByFileExtension;
import org.oscim.android.filepicker.ValidMapFile;
import org.oscim.android.filepicker.ValidRenderTheme;
import org.oscim.android.theme.ContentRenderTheme;
import org.oscim.android.theme.ContentResolverResourceProvider;
import org.oscim.backend.CanvasAdapter;
import org.oscim.core.MapElement;
import org.oscim.core.MapPosition;
@@ -42,23 +46,29 @@ import org.oscim.layers.tile.vector.labeling.LabelLayer;
import org.oscim.renderer.BitmapRenderer;
import org.oscim.renderer.GLViewport;
import org.oscim.renderer.bucket.RenderBuckets;
import org.oscim.scalebar.DefaultMapScaleBar;
import org.oscim.scalebar.ImperialUnitAdapter;
import org.oscim.scalebar.MapScaleBar;
import org.oscim.scalebar.MapScaleBarLayer;
import org.oscim.scalebar.MetricUnitAdapter;
import org.oscim.theme.ExternalRenderTheme;
import org.oscim.theme.ThemeUtils;
import org.oscim.theme.VtmThemes;
import org.oscim.scalebar.*;
import org.oscim.theme.*;
import org.oscim.theme.styles.AreaStyle;
import org.oscim.theme.styles.RenderStyle;
import org.oscim.tiling.source.mapfile.MapFileTileSource;
import org.oscim.tiling.source.mapfile.MapInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.zip.ZipInputStream;
public class MapsforgeActivity extends MapActivity {
private static final Logger log = LoggerFactory.getLogger(MapsforgeActivity.class);
static final int SELECT_MAP_FILE = 0;
static final int SELECT_THEME_FILE = SELECT_MAP_FILE + 1;
private static final int SELECT_THEME_ARCHIVE = 1;
private static final int SELECT_THEME_DIR = 2;
static final int SELECT_THEME_FILE = 3;
private static final Tag ISSEA_TAG = new Tag("natural", "issea");
private static final Tag NOSEA_TAG = new Tag("natural", "nosea");
@@ -66,8 +76,10 @@ public class MapsforgeActivity extends MapActivity {
private TileGridLayer mGridLayer;
private Menu mMenu;
private boolean mS3db;
private final boolean mS3db;
IRenderTheme mTheme;
VectorTileLayer mTileLayer;
private Uri mThemeDirUri;
public MapsforgeActivity() {
this(false);
@@ -87,22 +99,10 @@ public class MapsforgeActivity extends MapActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startActivityForResult(new Intent(this, MapFilePicker.class),
SELECT_MAP_FILE);
}
public static class MapFilePicker extends FilePicker {
public MapFilePicker() {
setFileDisplayFilter(new FilterByFileExtension(".map"));
setFileSelectFilter(new ValidMapFile());
}
}
public static class ThemeFilePicker extends FilePicker {
public ThemeFilePicker() {
setFileDisplayFilter(new FilterByFileExtension(".xml"));
setFileSelectFilter(new ValidRenderTheme());
}
Intent intent = new Intent(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, SELECT_MAP_FILE);
}
@Override
@@ -117,33 +117,53 @@ public class MapsforgeActivity extends MapActivity {
switch (item.getItemId()) {
case R.id.theme_default:
mMap.setTheme(VtmThemes.DEFAULT);
if (mTheme != null)
mTheme.dispose();
mTheme = mMap.setTheme(VtmThemes.DEFAULT);
item.setChecked(true);
return true;
case R.id.theme_osmarender:
mMap.setTheme(VtmThemes.OSMARENDER);
if (mTheme != null)
mTheme.dispose();
mTheme = mMap.setTheme(VtmThemes.OSMARENDER);
item.setChecked(true);
return true;
case R.id.theme_osmagray:
mMap.setTheme(VtmThemes.OSMAGRAY);
if (mTheme != null)
mTheme.dispose();
mTheme = mMap.setTheme(VtmThemes.OSMAGRAY);
item.setChecked(true);
return true;
case R.id.theme_tubes:
mMap.setTheme(VtmThemes.TRONRENDER);
if (mTheme != null)
mTheme.dispose();
mTheme = mMap.setTheme(VtmThemes.TRONRENDER);
item.setChecked(true);
return true;
case R.id.theme_newtron:
mMap.setTheme(VtmThemes.NEWTRON);
if (mTheme != null)
mTheme.dispose();
mTheme = mMap.setTheme(VtmThemes.NEWTRON);
item.setChecked(true);
return true;
case R.id.theme_external_archive:
Intent intent = new Intent(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, SELECT_THEME_ARCHIVE);
return true;
case R.id.theme_external:
startActivityForResult(new Intent(this, ThemeFilePicker.class),
SELECT_THEME_FILE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
return false;
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(intent, SELECT_THEME_DIR);
return true;
case R.id.gridlayer:
@@ -165,20 +185,23 @@ public class MapsforgeActivity extends MapActivity {
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SELECT_MAP_FILE) {
if (resultCode != RESULT_OK || intent == null || intent.getStringExtra(FilePicker.SELECTED_FILE) == null) {
if (resultCode != Activity.RESULT_OK || data == null) {
finish();
return;
}
MapFileTileSource mTileSource = new MapFileTileSource();
//mTileSource.setPreferredLanguage("en");
String file = intent.getStringExtra(FilePicker.SELECTED_FILE);
if (mTileSource.setMapFile(file)) {
try {
Uri uri = data.getData();
mTileLayer = mMap.setBaseMap(mTileSource);
MapFileTileSource tileSource = new MapFileTileSource();
//tileSource.setPreferredLanguage("en");
FileInputStream fis = (FileInputStream) getContentResolver().openInputStream(uri);
tileSource.setMapFileInputStream(fis);
mTileLayer = mMap.setBaseMap(tileSource);
loadTheme(null);
if (mS3db)
@@ -187,58 +210,114 @@ public class MapsforgeActivity extends MapActivity {
mMap.layers().add(new BuildingLayer(mMap, mTileLayer));
mMap.layers().add(new LabelLayer(mMap, mTileLayer));
DefaultMapScaleBar mMapScaleBar = new DefaultMapScaleBar(mMap);
mMapScaleBar.setScaleBarMode(DefaultMapScaleBar.ScaleBarMode.BOTH);
mMapScaleBar.setDistanceUnitAdapter(MetricUnitAdapter.INSTANCE);
mMapScaleBar.setSecondaryDistanceUnitAdapter(ImperialUnitAdapter.INSTANCE);
mMapScaleBar.setScaleBarPosition(MapScaleBar.ScaleBarPosition.BOTTOM_LEFT);
DefaultMapScaleBar mapScaleBar = new DefaultMapScaleBar(mMap);
mapScaleBar.setScaleBarMode(DefaultMapScaleBar.ScaleBarMode.BOTH);
mapScaleBar.setDistanceUnitAdapter(MetricUnitAdapter.INSTANCE);
mapScaleBar.setSecondaryDistanceUnitAdapter(ImperialUnitAdapter.INSTANCE);
mapScaleBar.setScaleBarPosition(MapScaleBar.ScaleBarPosition.BOTTOM_LEFT);
MapScaleBarLayer mapScaleBarLayer = new MapScaleBarLayer(mMap, mMapScaleBar);
MapScaleBarLayer mapScaleBarLayer = new MapScaleBarLayer(mMap, mapScaleBar);
BitmapRenderer renderer = mapScaleBarLayer.getRenderer();
renderer.setPosition(GLViewport.Position.BOTTOM_LEFT);
renderer.setOffset(5 * CanvasAdapter.getScale(), 0);
mMap.layers().add(mapScaleBarLayer);
MapInfo info = mTileSource.getMapInfo();
MapInfo info = tileSource.getMapInfo();
if (!info.boundingBox.contains(mMap.getMapPosition().getGeoPoint())) {
MapPosition pos = new MapPosition();
pos.setByBoundingBox(info.boundingBox, Tile.SIZE * 4, Tile.SIZE * 4);
mMap.setMapPosition(pos);
mPrefs.clear();
}
} catch (Exception e) {
log.error(e.getMessage());
finish();
}
} else if (requestCode == SELECT_THEME_FILE) {
if (resultCode != RESULT_OK || intent == null || intent.getStringExtra(FilePicker.SELECTED_FILE) == null) {
} else if (requestCode == SELECT_THEME_ARCHIVE) {
if (resultCode != Activity.RESULT_OK || data == null)
return;
}
String file = intent.getStringExtra(FilePicker.SELECTED_FILE);
ExternalRenderTheme externalRenderTheme = new ExternalRenderTheme(file);
try {
final Uri uri = data.getData();
// Use tessellation with sea and land for Mapsforge themes
if (ThemeUtils.isMapsforgeTheme(externalRenderTheme)) {
mTileLayer.addHook(new VectorTileLayer.TileLoaderThemeHook() {
final List<String> xmlThemes = ZipXmlThemeResourceProvider.scanXmlThemes(new ZipInputStream(new BufferedInputStream(getContentResolver().openInputStream(uri))));
if (xmlThemes.isEmpty())
return;
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.dialog_theme_title);
builder.setSingleChoiceItems(xmlThemes.toArray(new String[0]), -1, new DialogInterface.OnClickListener() {
@Override
public boolean process(MapTile tile, RenderBuckets buckets, MapElement element, RenderStyle style, int level) {
if (element.tags.contains(ISSEA_TAG) || element.tags.contains(SEA_TAG) || element.tags.contains(NOSEA_TAG)) {
if (style instanceof AreaStyle)
((AreaStyle) style).mesh = true;
public void onClick(DialogInterface dialog, int which) {
try {
dialog.dismiss();
ThemeFile theme = new ZipRenderTheme(xmlThemes.get(which), new ZipXmlThemeResourceProvider(new ZipInputStream(new BufferedInputStream(getContentResolver().openInputStream(uri)))));
if (mTheme != null)
mTheme.dispose();
mTheme = mMap.setTheme(theme);
mapsforgeTheme(mTheme);
mMenu.findItem(R.id.theme_external_archive).setChecked(true);
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
@Override
public void complete(MapTile tile, boolean success) {
}
});
builder.show();
} catch (IOException e) {
e.printStackTrace();
}
} else if (requestCode == SELECT_THEME_DIR) {
if (resultCode != Activity.RESULT_OK || data == null)
return;
mMap.setTheme(externalRenderTheme);
mThemeDirUri = data.getData();
// Now we have the directory for resources, but we need to let the user also select a theme file
Intent intent = new Intent(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, mThemeDirUri);
startActivityForResult(intent, SELECT_THEME_FILE);
} else if (requestCode == SELECT_THEME_FILE) {
if (resultCode != Activity.RESULT_OK || data == null)
return;
Uri uri = data.getData();
ThemeFile theme = new ContentRenderTheme(getContentResolver(), uri);
theme.setResourceProvider(new ContentResolverResourceProvider(getContentResolver(), mThemeDirUri));
if (mTheme != null)
mTheme.dispose();
mTheme = mMap.setTheme(theme);
mapsforgeTheme(mTheme);
mMenu.findItem(R.id.theme_external).setChecked(true);
}
}
protected void loadTheme(final String styleId) {
mMap.setTheme(VtmThemes.DEFAULT);
if (mTheme != null)
mTheme.dispose();
mTheme = mMap.setTheme(VtmThemes.DEFAULT);
}
private void mapsforgeTheme(IRenderTheme theme) {
if (!theme.isMapsforgeTheme())
return;
// Use tessellation with sea and land for Mapsforge themes
mTileLayer.addHook(new VectorTileLayer.TileLoaderThemeHook() {
@Override
public boolean process(MapTile tile, RenderBuckets buckets, MapElement element, RenderStyle style, int level) {
if (element.tags.contains(ISSEA_TAG) || element.tags.contains(SEA_TAG) || element.tags.contains(NOSEA_TAG)) {
if (style instanceof AreaStyle)
((AreaStyle) style).mesh = true;
}
return false;
}
@Override
public void complete(MapTile tile, boolean success) {
}
});
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2017 devemux86
* Copyright 2016-2020 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -17,7 +17,6 @@ package org.oscim.android.test;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import org.oscim.android.theme.AssetsRenderTheme;
import org.oscim.theme.XmlRenderThemeMenuCallback;
import org.oscim.theme.XmlRenderThemeStyleLayer;
@@ -58,7 +57,9 @@ public class MapsforgeStyleActivity extends MapsforgeActivity {
@Override
protected void loadTheme(final String styleId) {
mMap.setTheme(new AssetsRenderTheme(getAssets(), "", "vtm/stylemenu.xml", new XmlRenderThemeMenuCallback() {
if (mTheme != null)
mTheme.dispose();
mTheme = mMap.setTheme(new AssetsRenderTheme(getAssets(), "", "vtm/stylemenu.xml", new XmlRenderThemeMenuCallback() {
@Override
public Set<String> getCategories(XmlRenderThemeStyleMenu renderThemeStyleMenu) {
// Use the selected style or the default

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2018 devemux86
* Copyright 2017-2020 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -15,8 +15,8 @@
package org.oscim.android.test;
import android.os.Bundle;
import org.oscim.android.cache.TileCache;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
@@ -25,41 +25,35 @@ import org.oscim.tiling.source.OkHttpEngine;
import org.oscim.tiling.source.UrlTileSource;
import org.oscim.tiling.source.geojson.MapzenGeojsonTileSource;
import java.io.File;
public class MapzenGeojsonActivity extends MapActivity {
private static final boolean USE_CACHE = false;
private TileCache mCache;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (USE_CACHE) {
// Cache the tiles into file system
File cacheDirectory = new File(getExternalCacheDir(), "tiles");
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(cacheDirectory, cacheSize);
builder.cache(cache);
}
UrlTileSource tileSource = MapzenGeojsonTileSource.builder()
.apiKey("xxxxxxx") // Put a proper API key
.httpFactory(new OkHttpEngine.OkHttpFactory())
.httpFactory(new OkHttpEngine.OkHttpFactory(builder))
//.locale("en")
.build();
if (USE_CACHE) {
// Cache the tiles into a local SQLite database
mCache = new TileCache(this, null, "tile.db");
mCache.setCacheSize(512 * (1 << 10));
tileSource.setCache(mCache);
}
VectorTileLayer l = mMap.setBaseMap(tileSource);
mMap.setTheme(VtmThemes.MAPZEN);
mMap.layers().add(new BuildingLayer(mMap, l));
mMap.layers().add(new LabelLayer(mMap, l));
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mCache != null)
mCache.dispose();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2018 devemux86
* Copyright 2016-2020 devemux86
* Copyright 2017 Mathieu De Brito
*
* This program is free software: you can redistribute it and/or modify it under the
@@ -16,8 +16,8 @@
package org.oscim.android.test;
import android.os.Bundle;
import org.oscim.android.cache.TileCache;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
@@ -26,41 +26,35 @@ import org.oscim.tiling.source.OkHttpEngine;
import org.oscim.tiling.source.UrlTileSource;
import org.oscim.tiling.source.mvt.MapzenMvtTileSource;
import java.io.File;
public class MapzenMvtActivity extends MapActivity {
private static final boolean USE_CACHE = false;
private TileCache mCache;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (USE_CACHE) {
// Cache the tiles into file system
File cacheDirectory = new File(getExternalCacheDir(), "tiles");
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(cacheDirectory, cacheSize);
builder.cache(cache);
}
UrlTileSource tileSource = MapzenMvtTileSource.builder()
.apiKey("xxxxxxx") // Put a proper API key
.httpFactory(new OkHttpEngine.OkHttpFactory())
.httpFactory(new OkHttpEngine.OkHttpFactory(builder))
//.locale("en")
.build();
if (USE_CACHE) {
// Cache the tiles into a local SQLite database
mCache = new TileCache(this, null, "tile.db");
mCache.setCacheSize(512 * (1 << 10));
tileSource.setCache(mCache);
}
VectorTileLayer l = mMap.setBaseMap(tileSource);
mMap.setTheme(VtmThemes.MAPZEN);
mMap.layers().add(new BuildingLayer(mMap, l));
mMap.layers().add(new LabelLayer(mMap, l));
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mCache != null)
mCache.dispose();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2018 devemux86
* Copyright 2018-2020 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -15,8 +15,8 @@
package org.oscim.android.test;
import android.os.Bundle;
import org.oscim.android.cache.TileCache;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
@@ -25,41 +25,35 @@ import org.oscim.tiling.source.OkHttpEngine;
import org.oscim.tiling.source.UrlTileSource;
import org.oscim.tiling.source.geojson.NextzenGeojsonTileSource;
import java.io.File;
public class NextzenGeojsonActivity extends MapActivity {
private static final boolean USE_CACHE = false;
private TileCache mCache;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (USE_CACHE) {
// Cache the tiles into file system
File cacheDirectory = new File(getExternalCacheDir(), "tiles");
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(cacheDirectory, cacheSize);
builder.cache(cache);
}
UrlTileSource tileSource = NextzenGeojsonTileSource.builder()
.apiKey("xxxxxxx") // Put a proper API key
.httpFactory(new OkHttpEngine.OkHttpFactory())
.httpFactory(new OkHttpEngine.OkHttpFactory(builder))
//.locale("en")
.build();
if (USE_CACHE) {
// Cache the tiles into a local SQLite database
mCache = new TileCache(this, null, "tile.db");
mCache.setCacheSize(512 * (1 << 10));
tileSource.setCache(mCache);
}
VectorTileLayer l = mMap.setBaseMap(tileSource);
mMap.setTheme(VtmThemes.MAPZEN);
mMap.layers().add(new BuildingLayer(mMap, l));
mMap.layers().add(new LabelLayer(mMap, l));
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mCache != null)
mCache.dispose();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2018 devemux86
* Copyright 2018-2020 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -15,8 +15,8 @@
package org.oscim.android.test;
import android.os.Bundle;
import org.oscim.android.cache.TileCache;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
@@ -25,41 +25,35 @@ import org.oscim.tiling.source.OkHttpEngine;
import org.oscim.tiling.source.UrlTileSource;
import org.oscim.tiling.source.mvt.NextzenMvtTileSource;
import java.io.File;
public class NextzenMvtActivity extends MapActivity {
private static final boolean USE_CACHE = false;
private TileCache mCache;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (USE_CACHE) {
// Cache the tiles into file system
File cacheDirectory = new File(getExternalCacheDir(), "tiles");
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(cacheDirectory, cacheSize);
builder.cache(cache);
}
UrlTileSource tileSource = NextzenMvtTileSource.builder()
.apiKey("xxxxxxx") // Put a proper API key
.httpFactory(new OkHttpEngine.OkHttpFactory())
.httpFactory(new OkHttpEngine.OkHttpFactory(builder))
//.locale("en")
.build();
if (USE_CACHE) {
// Cache the tiles into a local SQLite database
mCache = new TileCache(this, null, "tile.db");
mCache.setCacheSize(512 * (1 << 10));
tileSource.setCache(mCache);
}
VectorTileLayer l = mMap.setBaseMap(tileSource);
mMap.setTheme(VtmThemes.MAPZEN);
mMap.layers().add(new BuildingLayer(mMap, l));
mMap.layers().add(new LabelLayer(mMap, l));
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mCache != null)
mCache.dispose();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2018 devemux86
* Copyright 2016-2020 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -15,8 +15,8 @@
package org.oscim.android.test;
import android.os.Bundle;
import org.oscim.android.cache.TileCache;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
@@ -25,41 +25,35 @@ import org.oscim.tiling.source.OkHttpEngine;
import org.oscim.tiling.source.UrlTileSource;
import org.oscim.tiling.source.mvt.OpenMapTilesMvtTileSource;
import java.io.File;
public class OpenMapTilesMvtActivity extends MapActivity {
private static final boolean USE_CACHE = false;
private TileCache mCache;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (USE_CACHE) {
// Cache the tiles into file system
File cacheDirectory = new File(getExternalCacheDir(), "tiles");
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(cacheDirectory, cacheSize);
builder.cache(cache);
}
UrlTileSource tileSource = OpenMapTilesMvtTileSource.builder()
.apiKey("xxxxxxx") // Put a proper API key
.httpFactory(new OkHttpEngine.OkHttpFactory())
.httpFactory(new OkHttpEngine.OkHttpFactory(builder))
//.locale("en")
.build();
if (USE_CACHE) {
// Cache the tiles into a local SQLite database
mCache = new TileCache(this, null, "tile.db");
mCache.setCacheSize(512 * (1 << 10));
tileSource.setCache(mCache);
}
VectorTileLayer l = mMap.setBaseMap(tileSource);
mMap.setTheme(VtmThemes.OPENMAPTILES);
mMap.layers().add(new BuildingLayer(mMap, l));
mMap.layers().add(new LabelLayer(mMap, l));
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mCache != null)
mCache.dispose();
}
}

View File

@@ -28,7 +28,6 @@ package org.oscim.android.test;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
@@ -87,8 +86,8 @@ public class Samples extends Activity {
LinearLayout linearLayout = findViewById(R.id.samples);
linearLayout.addView(createButton(GettingStarted.class));
linearLayout.addView(createLabel(null));
linearLayout.addView(createButton(SimpleMapActivity.class));
linearLayout.addView(createButton(MapsforgeActivity.class));
linearLayout.addView(createButton(SimpleMapActivity.class));
linearLayout.addView(createButton(MBTilesMvtActivity.class));
linearLayout.addView(createButton(MapilionMvtActivity.class));
/*linearLayout.addView(createButton(MapzenMvtActivity.class));
@@ -126,5 +125,6 @@ public class Samples extends Activity {
linearLayout.addView(createButton(GdxPoi3DActivity.class));
linearLayout.addView(createButton(OverpassActivity.class));
linearLayout.addView(createButton(ClusterMarkerOverlayActivity.class));
linearLayout.addView(createButton(FragmentActivity.class));
}
}

View File

@@ -1,7 +1,7 @@
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2016 Longri
* Copyright 2016-2018 devemux86
* Copyright 2016-2021 devemux86
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -22,7 +22,6 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import org.oscim.backend.CanvasAdapter;
import org.oscim.utils.GraphicUtils;
import org.oscim.utils.IOUtils;
@@ -39,6 +38,7 @@ public class AndroidBitmap implements org.oscim.backend.canvas.Bitmap {
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
try {
GLUtils.getType(bitmap);
GLUtils.getInternalFormat(bitmap);
} catch (IllegalArgumentException e) {
bitmap = bitmap.copy(ARGB_8888, false);
}
@@ -95,6 +95,9 @@ public class AndroidBitmap implements org.oscim.backend.canvas.Bitmap {
@Override
public void uploadToTexture(boolean replace) {
if (mBitmap.isRecycled())
return;
int format = GLUtils.getInternalFormat(mBitmap);
int type = GLUtils.getType(mBitmap);

View File

@@ -30,6 +30,7 @@ import org.oscim.backend.canvas.Canvas;
import org.oscim.backend.canvas.Paint;
import org.oscim.layers.marker.MarkerSymbol;
import org.oscim.layers.marker.MarkerSymbol.HotspotPlace;
import org.oscim.theme.XmlThemeResourceProvider;
import java.io.IOException;
import java.io.InputStream;
@@ -69,8 +70,8 @@ public final class AndroidGraphics extends CanvasAdapter {
}
@Override
public Bitmap loadBitmapAssetImpl(String relativePathPrefix, String src, int width, int height, int percent) throws IOException {
return createBitmap(relativePathPrefix, src, width, height, percent);
public Bitmap loadBitmapAssetImpl(String relativePathPrefix, String src, XmlThemeResourceProvider resourceProvider, int width, int height, int percent) throws IOException {
return createBitmap(relativePathPrefix, src, resourceProvider, width, height, percent);
}
@Override

View File

@@ -1,7 +1,8 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2016-2017 devemux86
* Copyright 2016-2021 devemux86
* Copyright 2017 Andrey Novikov
* Copyright 2021 eddiemuc
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -18,11 +19,10 @@ package org.oscim.android.theme;
import android.content.res.AssetManager;
import android.text.TextUtils;
import org.oscim.theme.IRenderTheme.ThemeException;
import org.oscim.theme.ThemeFile;
import org.oscim.theme.ThemeUtils;
import org.oscim.theme.XmlRenderThemeMenuCallback;
import org.oscim.theme.XmlThemeResourceProvider;
import org.oscim.utils.Utils;
import java.io.IOException;
@@ -37,8 +37,10 @@ public class AssetsRenderTheme implements ThemeFile {
private final AssetManager mAssetManager;
private final String mFileName;
private boolean mMapsforgeTheme;
private XmlRenderThemeMenuCallback mMenuCallback;
private final String mRelativePathPrefix;
private XmlThemeResourceProvider mResourceProvider;
/**
* @param assetManager the Android asset manager.
@@ -100,13 +102,28 @@ public class AssetsRenderTheme implements ThemeFile {
}
}
@Override
public XmlThemeResourceProvider getResourceProvider() {
return mResourceProvider;
}
@Override
public boolean isMapsforgeTheme() {
return ThemeUtils.isMapsforgeTheme(this);
return mMapsforgeTheme;
}
@Override
public void setMapsforgeTheme(boolean mapsforgeTheme) {
mMapsforgeTheme = mapsforgeTheme;
}
@Override
public void setMenuCallback(XmlRenderThemeMenuCallback menuCallback) {
mMenuCallback = menuCallback;
}
@Override
public void setResourceProvider(XmlThemeResourceProvider resourceProvider) {
mResourceProvider = resourceProvider;
}
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright 2020-2021 devemux86
* Copyright 2021 eddiemuc
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.android.theme;
import android.content.ContentResolver;
import android.net.Uri;
import org.oscim.theme.IRenderTheme.ThemeException;
import org.oscim.theme.ThemeFile;
import org.oscim.theme.XmlRenderThemeMenuCallback;
import org.oscim.theme.XmlThemeResourceProvider;
import java.io.IOException;
import java.io.InputStream;
/**
* An ContentRenderTheme allows for customizing the rendering style of the map
* via an XML from the Android content providers.
*/
public class ContentRenderTheme implements ThemeFile {
private static final long serialVersionUID = 1L;
private final ContentResolver mContentResolver;
private boolean mMapsforgeTheme;
private XmlRenderThemeMenuCallback mMenuCallback;
private XmlThemeResourceProvider mResourceProvider;
private final Uri mUri;
/**
* @param contentResolver the Android content resolver.
* @param uri the XML render theme URI.
* @throws ThemeException if an error occurs while reading the render theme XML.
*/
public ContentRenderTheme(ContentResolver contentResolver, Uri uri) throws ThemeException {
this(contentResolver, uri, null);
}
/**
* @param contentResolver the Android content resolver.
* @param uri the XML render theme URI.
* @param menuCallback the interface callback to create a settings menu on the fly.
* @throws ThemeException if an error occurs while reading the render theme XML.
*/
public ContentRenderTheme(ContentResolver contentResolver, Uri uri, XmlRenderThemeMenuCallback menuCallback) throws ThemeException {
mContentResolver = contentResolver;
mUri = uri;
mMenuCallback = menuCallback;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (!(obj instanceof ContentRenderTheme)) {
return false;
}
ContentRenderTheme other = (ContentRenderTheme) obj;
if (getRenderThemeAsStream() != other.getRenderThemeAsStream()) {
return false;
}
return true;
}
@Override
public XmlRenderThemeMenuCallback getMenuCallback() {
return mMenuCallback;
}
@Override
public String getRelativePathPrefix() {
return "";
}
@Override
public InputStream getRenderThemeAsStream() throws ThemeException {
try {
return mContentResolver.openInputStream(mUri);
} catch (IOException e) {
throw new ThemeException(e.getMessage());
}
}
@Override
public XmlThemeResourceProvider getResourceProvider() {
return mResourceProvider;
}
@Override
public boolean isMapsforgeTheme() {
return mMapsforgeTheme;
}
@Override
public void setMapsforgeTheme(boolean mapsforgeTheme) {
mMapsforgeTheme = mapsforgeTheme;
}
@Override
public void setMenuCallback(XmlRenderThemeMenuCallback menuCallback) {
mMenuCallback = menuCallback;
}
@Override
public void setResourceProvider(XmlThemeResourceProvider resourceProvider) {
mResourceProvider = resourceProvider;
}
}

View File

@@ -0,0 +1,179 @@
/*
* Copyright 2021 eddiemuc
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.android.theme;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.DocumentsContract;
import org.oscim.backend.CanvasAdapter;
import org.oscim.theme.XmlThemeResourceProvider;
import org.oscim.utils.IOUtils;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.*;
/**
* An xml theme resource provider resolving resources using Android scoped storage (document framework).
* <p>
* Implementation note: these methods do not use DocumentFile internally,
* but query directly for document info due to vastly better performance.
* Also for better performance, this implementation caches resource uris.
* <p>
* Note: this implementation requires minimum Android 5.0 (API 21)
*/
public class ContentResolverResourceProvider implements XmlThemeResourceProvider {
private final ContentResolver contentResolver;
private final Uri relativeRootUri;
private final boolean isDocumentUri;
private final Map<String, Uri> resourceUriCache = new HashMap<>();
private static class DocumentInfo {
private final String name;
private final Uri uri;
private final boolean isDirectory;
private DocumentInfo(String name, Uri uri, boolean isDirectory) {
this.name = name;
this.uri = uri;
this.isDirectory = isDirectory;
}
}
/**
* Creates a new content resolver resource provider.
*
* @param contentResolver content resolver used to read content.
* @param relativeRootUri uri pointing to a directory.
* Uri is assumed to be a pure tree Uri (as e.g. returned by {@link Intent#ACTION_OPEN_DOCUMENT_TREE}).
*/
public ContentResolverResourceProvider(ContentResolver contentResolver, Uri relativeRootUri) {
this(contentResolver, relativeRootUri, false);
}
/**
* Creates a new content resolver resource provider.
*
* @param contentResolver content resolver used to read content.
* @param relativeRootUri uri pointing to a directory.
* @param isDocumentUri Uris as returned e.g. by {@link Intent#ACTION_OPEN_DOCUMENT_TREE}) cannot directly be used to scan directories and read content.
* They must be converted to document uris first using {@link DocumentsContract#buildChildDocumentsUriUsingTree(Uri, String)}.
* However, in some situations this conversion was done previously by caller (e.g. if root dir should be subdirectory of a directory returned by {@link Intent#ACTION_OPEN_DOCUMENT_TREE}).
* In these cases, converted Uri will point to original root directory which is not always the wanted behaviour.
* Thus, this parameter allows caller to control whether conversion should be done or not.
* If set to true, then given Uri is considered to be a document uri already and no conversion is done.
* If set to false, uri is considered to be a pure tree uri as returned e.g. by {@link Intent#ACTION_OPEN_DOCUMENT_TREE}) and it is converted.
*/
public ContentResolverResourceProvider(ContentResolver contentResolver, Uri relativeRootUri, boolean isDocumentUri) {
this.contentResolver = contentResolver;
this.relativeRootUri = relativeRootUri;
this.isDocumentUri = isDocumentUri;
refreshCache();
}
/**
* Build uri cache for one dir level (recursive function).
*/
private void buildCacheLevel(String prefix, Uri dirUri) {
List<DocumentInfo> docs = queryDir(dirUri);
for (DocumentInfo doc : docs) {
if (doc.isDirectory) {
buildCacheLevel(prefix + doc.name + "/", doc.uri);
} else {
// Store both relative urls and absolute urls
resourceUriCache.put(CanvasAdapter.PREFIX_FILE + prefix + doc.name, doc.uri);
resourceUriCache.put(CanvasAdapter.PREFIX_FILE + "/" + prefix + doc.name, doc.uri);
}
}
}
@Override
public InputStream createInputStream(String relativePath, String source) throws FileNotFoundException {
Uri docUri = resourceUriCache.get(source);
if (docUri != null) {
return contentResolver.openInputStream(docUri);
}
return null;
}
/**
* Query the content of a directory using scoped storage.
*
* @return a list of arrays with info [0: name (String), 1: uri (Uri), 2: isDir (boolean)]
*/
private List<DocumentInfo> queryDir(Uri dirUri) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return Collections.emptyList();
}
if (dirUri == null) {
return Collections.emptyList();
}
List<DocumentInfo> result = new ArrayList<>();
Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(dirUri, DocumentsContract.getDocumentId(dirUri));
String[] columns = new String[]{
DocumentsContract.Document.COLUMN_DOCUMENT_ID,
DocumentsContract.Document.COLUMN_DISPLAY_NAME,
DocumentsContract.Document.COLUMN_MIME_TYPE
};
Cursor c = null;
try {
c = contentResolver.query(childrenUri, columns, null, null, null);
while (c.moveToNext()) {
String documentId = c.getString(0);
String name = c.getString(1);
String mimeType = c.getString(2);
Uri uri = DocumentsContract.buildDocumentUriUsingTree(dirUri, documentId);
boolean isDir = DocumentsContract.Document.MIME_TYPE_DIR.equals(mimeType);
result.add(new DocumentInfo(name, uri, isDir));
}
return result;
} finally {
IOUtils.closeQuietly(c);
}
}
/**
* Refresh the uri cache by recreating it.
*/
private void refreshCache() {
resourceUriCache.clear();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
if (relativeRootUri == null) {
return;
}
Uri dirUri = relativeRootUri;
if (!isDocumentUri) {
// Convert "tree uri" to a "document uri"
dirUri = DocumentsContract.buildDocumentUriUsingTree(dirUri, DocumentsContract.getTreeDocumentId(dirUri));
}
buildCacheLevel("", dirUri);
}
}

View File

@@ -15,6 +15,7 @@
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/application_name"
android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true">
<!-- android:theme="@style/Theme.TileMap" -->

View File

@@ -5,7 +5,7 @@ dependencies {
implementation project(':vtm-extras')
implementation project(':vtm-themes')
// https://github.com/square/okhttp/issues/4481
implementation 'com.squareup.okhttp3:okhttp:3.12.5'
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
implementation "org.slf4j:slf4j-android:$slf4jVersion"
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2016 devemux86
* Copyright 2016-2020 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -15,40 +15,30 @@
*/
package org.oscim.app.filefilter;
import org.oscim.theme.ExternalRenderTheme;
import org.oscim.theme.ThemeFile;
import org.oscim.theme.XmlThemeBuilder;
import org.oscim.theme.ThemeLoader;
import org.oscim.tiling.TileSource.OpenResult;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import java.io.File;
import javax.xml.parsers.SAXParserFactory;
/**
* Accepts all valid render theme XML files.
*/
public final class ValidRenderTheme implements ValidFileFilter {
private OpenResult openResult;
private OpenResult mOpenResult;
@Override
public boolean accept(File file) {
try {
ThemeFile theme = new ExternalRenderTheme(file.getAbsolutePath());
XmlThemeBuilder renderThemeHandler = new XmlThemeBuilder(theme);
XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
xmlReader.setContentHandler(renderThemeHandler);
xmlReader.parse(new InputSource(theme.getRenderThemeAsStream()));
this.openResult = OpenResult.SUCCESS;
ThemeLoader.load(file.getAbsolutePath());
mOpenResult = OpenResult.SUCCESS;
} catch (Exception e) {
this.openResult = new OpenResult(e.getMessage());
mOpenResult = new OpenResult(e.getMessage());
}
return this.openResult.isSuccess();
return mOpenResult.isSuccess();
}
@Override
public OpenResult getFileOpenResult() {
return this.openResult;
return mOpenResult;
}
}

View File

@@ -3,7 +3,7 @@ apply plugin: 'maven'
dependencies {
api project(':vtm-gdx')
api 'com.github.blackears:svgSalamander:v1.1.1'
api 'com.formdev:svgSalamander:1.1.2.4'
}
sourceSets {

View File

@@ -23,11 +23,9 @@ import org.oscim.backend.Platform;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.backend.canvas.Canvas;
import org.oscim.backend.canvas.Paint;
import org.oscim.theme.XmlThemeResourceProvider;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
@@ -119,7 +117,7 @@ public class AwtGraphics extends CanvasAdapter {
}
@Override
public Bitmap loadBitmapAssetImpl(String relativePathPrefix, String src, int width, int height, int percent) throws IOException {
return createBitmap(relativePathPrefix, src, width, height, percent);
public Bitmap loadBitmapAssetImpl(String relativePathPrefix, String src, XmlThemeResourceProvider resourceProvider, int width, int height, int percent) throws IOException {
return createBitmap(relativePathPrefix, src, resourceProvider, width, height, percent);
}
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2017 devemux86
* Copyright 2016-2021 devemux86
* Copyright 2017 Longri
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
@@ -22,7 +22,6 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Input.Buttons;
import com.badlogic.gdx.InputProcessor;
import org.oscim.layers.GenericLayer;
import org.oscim.layers.GroupLayer;
import org.oscim.layers.Layer;
@@ -79,19 +78,19 @@ public class InputHandler implements InputProcessor {
break;
case Input.Keys.UP:
mViewport.moveMap(0, -50);
mMap.updateMap(true);
break;
case Input.Keys.DOWN:
mViewport.moveMap(0, 50);
mMap.updateMap(true);
break;
case Input.Keys.DOWN:
mViewport.moveMap(0, -50);
mMap.updateMap(true);
break;
case Input.Keys.LEFT:
mViewport.moveMap(-50, 0);
mViewport.moveMap(50, 0);
mMap.updateMap(true);
break;
case Input.Keys.RIGHT:
mViewport.moveMap(50, 0);
mViewport.moveMap(-50, 0);
mMap.updateMap(true);
break;
case Input.Keys.D:
@@ -110,6 +109,15 @@ public class InputHandler implements InputProcessor {
mMap.animator().animateZoom(500, 2, 0, 0);
mMap.updateMap(false);
break;
case Input.Keys.MINUS:
mMap.animator().animateZoom(500, 0.5, 0, 0);
mMap.updateMap(true);
break;
case Input.Keys.PLUS:
case Input.Keys.EQUALS:
mMap.animator().animateZoom(500, 2, 0, 0);
mMap.updateMap(true);
break;
case Input.Keys.NUM_1:
mMap.setTheme(VtmThemes.DEFAULT);

View File

@@ -4,7 +4,7 @@ apply plugin: 'maven'
dependencies {
api project(':vtm')
// https://github.com/square/okhttp/issues/4481
api 'com.squareup.okhttp3:okhttp:3.12.5'
api 'com.squareup.okhttp3:okhttp:3.12.13'
}
sourceSets {

View File

@@ -1,6 +1,6 @@
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.7'

View File

@@ -19,7 +19,6 @@
package org.oscim.ios.test;
import com.badlogic.gdx.graphics.glutils.GLVersion;
import org.oscim.backend.GLAdapter;
import org.oscim.backend.canvas.Color;
import org.oscim.core.GeoPoint;
@@ -74,7 +73,7 @@ public class IOSPathLayerTest extends GdxMap {
mMap.setMapPosition(0, 0, 1 << 2);
tex = Utils.loadTexture("", "patterns/pike.png", 0, 0, 100);
tex = Utils.loadTexture("", "patterns/pike.png", null, 0, 0, 100);
// tex = new TextureItem(CanvasAdapter.getBitmapAsset("", "patterns/pike.png"));
tex.mipmap = true;

View File

@@ -1,6 +1,6 @@
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.7'

View File

@@ -21,6 +21,7 @@ import org.oscim.backend.Platform;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.backend.canvas.Canvas;
import org.oscim.backend.canvas.Paint;
import org.oscim.theme.XmlThemeResourceProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -70,7 +71,7 @@ public class IosGraphics extends CanvasAdapter {
}
@Override
protected Bitmap loadBitmapAssetImpl(String relativePathPrefix, String src, int width, int height, int percent) throws IOException {
return createBitmap(relativePathPrefix, src, width, height, percent);
protected Bitmap loadBitmapAssetImpl(String relativePathPrefix, String src, XmlThemeResourceProvider resourceProvider, int width, int height, int percent) throws IOException {
return createBitmap(relativePathPrefix, src, resourceProvider, width, height, percent);
}
}

View File

@@ -45,7 +45,7 @@ public class ExternalRenderThemeTest extends GdxMapApp {
try {
IRenderTheme theme = ThemeLoader.load(name);
mapLayer.setRenderTheme(theme);
mapLayer.setTheme(theme);
MapRenderer.setBackgroundColor(theme.getMapBackground());
} catch (ThemeException e) {
e.printStackTrace();
@@ -80,7 +80,7 @@ public class ExternalRenderThemeTest extends GdxMapApp {
// IRenderTheme theme =
// ThemeLoader.load("themes/elevate/theme.xml");
// IRenderTheme theme = ThemeLoader.load("themes/vmap/theme.xml");
l.setRenderTheme(theme);
l.setTheme(theme);
MapRenderer.setBackgroundColor(theme.getMapBackground());
} catch (ThemeException e) {
e.printStackTrace();

View File

@@ -39,7 +39,7 @@ public class ThemeTest extends GdxMapApp {
VectorTileLayer l = mMap.setBaseMap(ts);
l.setRenderTheme(new RenderTheme());
l.setTheme(new RenderTheme());
MapRenderer.setBackgroundColor(0xffcccccc);

View File

@@ -13,4 +13,5 @@ dependencies {
sourceSets {
main.java.srcDirs = ['src']
test.java.srcDirs = ['test']
test.resources.srcDirs = ['resources']
}

Binary file not shown.

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2021 eddiemuc
* Copyright 2021 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.theme;
import org.junit.Assert;
import org.junit.Test;
import org.oscim.utils.IOUtils;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.zip.ZipInputStream;
public class ZipXmlThemeResourceProviderTest {
@Test
public void openZip() throws IOException {
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(ZipXmlThemeResourceProviderTest.class.getResourceAsStream("/xmlthemetest.zip")));
Assert.assertNotNull(zis);
ZipXmlThemeResourceProvider zts = new ZipXmlThemeResourceProvider(zis);
// All files contained
Assert.assertNotNull(zts.createInputStream(null, "file:one.xml"));
Assert.assertNotNull(zts.createInputStream(null, "file:two.xml"));
Assert.assertNotNull(zts.createInputStream(null, "file:res/three.xml"));
Assert.assertNotNull(zts.createInputStream(null, "file:res/blue_star_1.svg"));
Assert.assertNotNull(zts.createInputStream(null, "file:res/test.txt"));
Assert.assertNotNull(zts.createInputStream(null, "file:res/sub/four.xml"));
Assert.assertNotNull(zts.createInputStream(null, "file:res/sub/blue_star_sub_1.svg"));
Assert.assertNotNull(zts.createInputStream(null, "file:res/sub/blue_star_sub_2.svg"));
//Relative Reference ok
Assert.assertNotNull(zts.createInputStream("", "file:res/sub/blue_star_sub_2.svg"));
Assert.assertNotNull(zts.createInputStream("res", "file:sub/blue_star_sub_2.svg"));
Assert.assertNotNull(zts.createInputStream("/", "file:res/sub/blue_star_sub_2.svg"));
Assert.assertNotNull(zts.createInputStream("/res", "file:sub/blue_star_sub_2.svg"));
Assert.assertNotNull(zts.createInputStream("res/", "file:/sub/blue_star_sub_2.svg"));
// Can get same files using various other formats
Assert.assertNotNull(zts.createInputStream(null, "res/sub/blue_star_sub_2.svg"));
Assert.assertNotNull(zts.createInputStream(null, "/res/sub/blue_star_sub_2.svg"));
Assert.assertNotNull(zts.createInputStream(null, "file:/res/sub/blue_star_sub_2.svg"));
// Dirs NOT contained!
Assert.assertNull(zts.createInputStream(null, "file:res/"));
Assert.assertEquals(8, zts.getCount());
List<String> xmlThemes = zts.getXmlThemes();
Assert.assertEquals(4, xmlThemes.size());
Assert.assertTrue(xmlThemes.contains("one.xml"));
Assert.assertTrue(xmlThemes.contains("two.xml"));
Assert.assertTrue(xmlThemes.contains("res/three.xml"));
Assert.assertTrue(xmlThemes.contains("res/sub/four.xml"));
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(zts.createInputStream(null, "file:res/test.txt")));
String line = reader.readLine();
Assert.assertEquals(line, "This is a test");
} finally {
IOUtils.closeQuietly(reader);
}
}
@Test
public void openEmpty() throws IOException {
Assert.assertTrue(new ZipXmlThemeResourceProvider(null).getXmlThemes().isEmpty());
}
@Test
public void scanZipForXmlThemes() throws IOException {
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(ZipXmlThemeResourceProviderTest.class.getResourceAsStream("/xmlthemetest.zip")));
Assert.assertNotNull(zis);
List<String> xmlThemes = ZipXmlThemeResourceProvider.scanXmlThemes(zis);
Assert.assertEquals(4, xmlThemes.size());
Assert.assertTrue(xmlThemes.contains("one.xml"));
Assert.assertTrue(xmlThemes.contains("two.xml"));
Assert.assertTrue(xmlThemes.contains("res/three.xml"));
Assert.assertTrue(xmlThemes.contains("res/sub/four.xml"));
}
}

View File

@@ -10,11 +10,11 @@ dependencies {
implementation 'com.fifesoft:rsyntaxtextarea:2.6.1'
implementation 'com.jtattoo:JTattoo:1.6.11'
implementation 'org.mapsforge:mapsforge-core:0.14.0'
implementation 'org.mapsforge:mapsforge-map:0.14.0'
implementation 'org.mapsforge:mapsforge-map-awt:0.14.0'
implementation 'org.mapsforge:mapsforge-map-reader:0.14.0'
implementation 'org.mapsforge:mapsforge-themes:0.14.0'
implementation 'org.mapsforge:mapsforge-core:0.16.0'
implementation 'org.mapsforge:mapsforge-map:0.16.0'
implementation 'org.mapsforge:mapsforge-map-awt:0.16.0'
implementation 'org.mapsforge:mapsforge-map-reader:0.16.0'
implementation 'org.mapsforge:mapsforge-themes:0.16.0'
implementation 'net.sf.kxml:kxml2:2.3.0'
}

View File

@@ -456,12 +456,14 @@
<m k="lock" v="yes|true">
<line stroke="#f8f8f8" use="fix" width="0.5" />
</m>
<text fill="#404000" k="name" size="14" stroke="#aaffffff" stroke-width="2.0" />
</m>
<m e="way">
<m closed="yes" k="natural" v="water">
<area use="water" />
<caption area-size="0.4" fill="#404000" k="name" size="16" stroke="#aaffffff"
<caption area-size="0.2" fill="#404000" k="name" size="16" stroke="#aaffffff"
stroke-width="2.0" />
<!--<line use="water:outline" />-->
</m>

View File

@@ -400,6 +400,8 @@
<m k="rank" v="9" zoom-min="9">
<line fade="9" use="water" width="0.1" />
</m>
<text fill="#404000" k="name" size="14" stroke="#aaffffff" stroke-width="2.0" />
</m>
<!-- TODO this breaks the rendering -->
<!--<m v="riverbank|dock">
@@ -420,7 +422,7 @@
<m e="way">
<m closed="yes" k="kind" v="water">
<area use="water" />
<caption area-size="0.4" fill="#404000" k="name" size="16" stroke="#aaffffff"
<caption area-size="0.2" fill="#404000" k="name" size="16" stroke="#aaffffff"
stroke-width="2.0" />
<!--<line use="water:outline" />-->
</m>

View File

@@ -374,11 +374,13 @@
<m k="lock" v="yes|true">
<line cap="butt" stroke="#f8f8f8" width="1.5" />
</m>
<text fill="#404000" k="name" size="14" stroke="#aaffffff" stroke-width="2.0" />
</m>
<m k="natural" v="water">
<area use="water" />
<caption area-size="0.4" fill="#404000" k="name" size="16" stroke="#aaffffff"
<caption area-size="0.2" fill="#404000" k="name" size="16" stroke="#aaffffff"
stroke-width="2.0" />
<!--<line use="water:outline" width="0.5" fix="true" />-->
</m>

View File

@@ -368,7 +368,7 @@
</m>
<m k="layer" v="water_name">
<caption area-size="0.4" fill="#404000" k="name" size="16" stroke="#aaffffff"
<caption area-size="0.2" fill="#404000" k="name" size="16" stroke="#aaffffff"
stroke-width="2.0" />
</m>
@@ -387,6 +387,8 @@
<line use="river" width="0.3" />
</m>
</m>
<text fill="#404000" k="name" size="14" stroke="#aaffffff" stroke-width="2.0" />
</m>
<!-- building -->

View File

@@ -267,6 +267,8 @@
<line cap="butt" stroke="#000000" width="2.0" />
<line cap="butt" stroke="#f8f8f8" width="1.5" />
</m>
<text fill="#3b3b3b" k="name" size="14" stroke="#aaffffff" stroke-width="2.0" />
</m>
@@ -306,7 +308,7 @@
<m k="natural" v="water">
<area use="water" />
<caption area-size="0.4" fill="#3b3b3b" k="name" size="16" stroke="#aaffffff"
<caption area-size="0.2" fill="#3b3b3b" k="name" size="16" stroke="#aaffffff"
stroke-width="2.0" />
</m>

View File

@@ -267,6 +267,8 @@
<line cap="butt" stroke="#000000" width="2.0" />
<line cap="butt" stroke="#f8f8f8" width="1.5" />
</m>
<text fill="#404000" k="name" size="14" stroke="#aaffffff" stroke-width="2.0" />
</m>
@@ -306,7 +308,7 @@
<m k="natural" v="water">
<area use="water" />
<caption area-size="0.4" fill="#404000" k="name" size="16" stroke="#aaffffff"
<caption area-size="0.2" fill="#404000" k="name" size="16" stroke="#aaffffff"
stroke-width="2.0" />
</m>

View File

@@ -374,11 +374,13 @@
<m k="lock" v="yes|true">
<line cap="butt" stroke="#f8f8f8" width="1.5" />
</m>
<text fill="#404000" k="name" size="14" stroke="#aaffffff" stroke-width="2.0" />
</m>
<m k="natural" v="water">
<area use="water" />
<caption area-size="0.4" fill="#404000" k="name" size="16" stroke="#aaffffff"
<caption area-size="0.2" fill="#404000" k="name" size="16" stroke="#aaffffff"
stroke-width="2.0" />
<!--<line use="water:outline" width="0.5" fix="true" />-->
</m>

View File

@@ -1,9 +1,10 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2017 devemux86
* Copyright 2016-2021 devemux86
* Copyright 2017 nebular
* Copyright 2017 Andrey Novikov
* Copyright 2021 eddiemuc
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -59,12 +60,25 @@ public enum VtmThemes implements ThemeFile {
return AssetAdapter.readFileAsStream(mPath);
}
@Override
public XmlThemeResourceProvider getResourceProvider() {
return null;
}
@Override
public boolean isMapsforgeTheme() {
return false;
}
@Override
public void setMapsforgeTheme(boolean mapsforgeTheme) {
}
@Override
public void setMenuCallback(XmlRenderThemeMenuCallback menuCallback) {
}
@Override
public void setResourceProvider(XmlThemeResourceProvider resourceProvider) {
}
}

View File

@@ -1,16 +1,17 @@
buildscript {
repositories {
jcenter()
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath 'org.wisepersist:gwt-gradle-plugin:1.0.13'
classpath 'org.akhikhl.gretty:gretty:2.0.0'
classpath 'gradle.plugin.org.gretty:gretty:3.0.3'
}
}
apply plugin: 'gwt'
apply plugin: 'war'
apply plugin: 'org.akhikhl.gretty'
apply plugin: 'org.gretty'
sourceSets {
main.java.srcDirs = ['src']

View File

@@ -1,16 +1,17 @@
buildscript {
repositories {
jcenter()
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath 'org.wisepersist:gwt-gradle-plugin:1.0.13'
classpath 'org.akhikhl.gretty:gretty:2.0.0'
classpath 'gradle.plugin.org.gretty:gretty:3.0.3'
}
}
apply plugin: 'gwt'
apply plugin: 'war'
apply plugin: 'org.akhikhl.gretty'
apply plugin: 'org.gretty'
sourceSets {
main.java.srcDirs = ['src']

View File

@@ -1,6 +1,6 @@
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'org.wisepersist:gwt-gradle-plugin:1.0.13'
@@ -75,6 +75,9 @@ gwt {
//}
javadoc {
if (JavaVersion.current().isJava9Compatible()) {
options.addStringOption("-release", "8")
}
options.addStringOption("sourcepath", "")
}

View File

@@ -21,11 +21,11 @@ package org.oscim.gdx.client;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.TextMetrics;
import org.oscim.backend.CanvasAdapter;
import org.oscim.backend.Platform;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.backend.canvas.Paint;
import org.oscim.theme.XmlThemeResourceProvider;
import java.io.File;
import java.io.InputStream;
@@ -68,7 +68,7 @@ public class GwtGdxGraphics extends CanvasAdapter {
}
@Override
public Bitmap loadBitmapAssetImpl(String relativePathPrefix, String src, int width, int height, int percent) {
public Bitmap loadBitmapAssetImpl(String relativePathPrefix, String src, XmlThemeResourceProvider resourceProvider, int width, int height, int percent) {
String pathName = (relativePathPrefix == null || relativePathPrefix.length() == 0 ? "" : relativePathPrefix + File.separatorChar) + src;
return new GwtBitmap(pathName);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,76 @@
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
package org.xmlpull.v1;
/**
* This exception is thrown to signal XML Pull Parser related faults.
*
* @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
*/
public class XmlPullParserException extends Exception {
protected Throwable detail;
protected int row = -1;
protected int column = -1;
/* public XmlPullParserException() {
}*/
public XmlPullParserException(String s) {
super(s);
}
/*
public XmlPullParserException(String s, Throwable thrwble) {
super(s);
this.detail = thrwble;
}
public XmlPullParserException(String s, int row, int column) {
super(s);
this.row = row;
this.column = column;
}
*/
public XmlPullParserException(String msg, XmlPullParser parser, Throwable chain) {
super ((msg == null ? "" : msg+" ")
+ (parser == null ? "" : "(position:"+parser.getPositionDescription()+") ")
+ (chain == null ? "" : "caused by: "+chain));
if (parser != null) {
this.row = parser.getLineNumber();
this.column = parser.getColumnNumber();
}
this.detail = chain;
}
public Throwable getDetail() { return detail; }
// public void setDetail(Throwable cause) { this.detail = cause; }
public int getLineNumber() { return row; }
public int getColumnNumber() { return column; }
/*
public String getMessage() {
if(detail == null)
return super.getMessage();
else
return super.getMessage() + "; nested exception is: \n\t"
+ detail.getMessage();
}
*/
//NOTE: code that prints this and detail is difficult in J2ME
public void printStackTrace() {
if (detail == null) {
super.printStackTrace();
} else {
synchronized(System.err) {
System.err.println(super.getMessage() + "; nested exception is:");
detail.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,237 @@
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
package org.xmlpull.v1;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* This class is used to create implementations of XML Pull Parser defined in XMPULL V1 API.
*
* @see XmlPullParser
*
* @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
* @author Stefan Haustein
*/
public class XmlPullParserFactory {
public static final String PROPERTY_NAME = "org.xmlpull.v1.XmlPullParserFactory";
protected ArrayList parserClasses;
protected ArrayList serializerClasses;
/** Unused, but we have to keep it because it's public API. */
protected String classNamesLocation = null;
// features are kept there
// TODO: This can't be made final because it's a public API.
protected HashMap<String, Boolean> features = new HashMap<String, Boolean>();
/**
* Protected constructor to be called by factory implementations.
*/
protected XmlPullParserFactory() {
parserClasses = new ArrayList<String>();
serializerClasses = new ArrayList<String>();
// GWT
/*try {
parserClasses.add(Class.forName("com.android.org.kxml2.io.KXmlParser"));
serializerClasses.add(Class.forName("com.android.org.kxml2.io.KXmlSerializer"));
} catch (ClassNotFoundException e) {
throw new AssertionError();
}*/
}
/**
* Set the features to be set when XML Pull Parser is created by this factory.
* <p><b>NOTE:</b> factory features are not used for XML Serializer.
*
* @param name string with URI identifying feature
* @param state if true feature will be set; if false will be ignored
*/
public void setFeature(String name, boolean state) throws XmlPullParserException {
features.put(name, state);
}
/**
* Return the current value of the feature with given name.
* <p><b>NOTE:</b> factory features are not used for XML Serializer.
*
* @param name The name of feature to be retrieved.
* @return The value of named feature.
* Unknown features are <string>always</strong> returned as false
*/
public boolean getFeature(String name) {
Boolean value = features.get(name);
return value != null ? value.booleanValue() : false;
}
/**
* Specifies that the parser produced by this factory will provide
* support for XML namespaces.
* By default the value of this is set to false.
*
* @param awareness true if the parser produced by this code
* will provide support for XML namespaces; false otherwise.
*/
public void setNamespaceAware(boolean awareness) {
features.put (XmlPullParser.FEATURE_PROCESS_NAMESPACES, awareness);
}
/**
* Indicates whether or not the factory is configured to produce
* parsers which are namespace aware
* (it simply set feature XmlPullParser.FEATURE_PROCESS_NAMESPACES to true or false).
*
* @return true if the factory is configured to produce parsers
* which are namespace aware; false otherwise.
*/
public boolean isNamespaceAware() {
return getFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES);
}
/**
* Specifies that the parser produced by this factory will be validating
* (it simply set feature XmlPullParser.FEATURE_VALIDATION to true or false).
*
* By default the value of this is set to false.
*
* @param validating - if true the parsers created by this factory must be validating.
*/
public void setValidating(boolean validating) {
features.put(XmlPullParser.FEATURE_VALIDATION, validating);
}
/**
* Indicates whether or not the factory is configured to produce parsers
* which validate the XML content during parse.
*
* @return true if the factory is configured to produce parsers
* which validate the XML content during parse; false otherwise.
*/
public boolean isValidating() {
return getFeature(XmlPullParser.FEATURE_VALIDATION);
}
/**
* Creates a new instance of a XML Pull Parser
* using the currently configured factory features.
*
* @return A new instance of a XML Pull Parser.
*/
public XmlPullParser newPullParser() throws XmlPullParserException {
final XmlPullParser pp = getParserInstance();
for (Map.Entry<String, Boolean> entry : features.entrySet()) {
// NOTE: This test is needed for compatibility reasons. We guarantee
// that we only set a feature on a parser if its value is true.
if (entry.getValue()) {
pp.setFeature(entry.getKey(), entry.getValue());
}
}
return pp;
}
private XmlPullParser getParserInstance() throws XmlPullParserException {
ArrayList<Exception> exceptions = null;
if (parserClasses != null && !parserClasses.isEmpty()) {
exceptions = new ArrayList<Exception>();
for (Object o : parserClasses) {
// GWT
/*try {
if (o != null) {
Class<?> parserClass = (Class<?>) o;
return (XmlPullParser) parserClass.newInstance();
}
} catch (InstantiationException e) {
exceptions.add(e);
} catch (IllegalAccessException e) {
exceptions.add(e);
} catch (ClassCastException e) {
exceptions.add(e);
}*/
}
}
throw newInstantiationException("Invalid parser class list", exceptions);
}
private XmlSerializer getSerializerInstance() throws XmlPullParserException {
ArrayList<Exception> exceptions = null;
if (serializerClasses != null && !serializerClasses.isEmpty()) {
exceptions = new ArrayList<Exception>();
for (Object o : serializerClasses) {
// GWT
/*try {
if (o != null) {
Class<?> serializerClass = (Class<?>) o;
return (XmlSerializer) serializerClass.newInstance();
}
} catch (InstantiationException e) {
exceptions.add(e);
} catch (IllegalAccessException e) {
exceptions.add(e);
} catch (ClassCastException e) {
exceptions.add(e);
}*/
}
}
throw newInstantiationException("Invalid serializer class list", exceptions);
}
private static XmlPullParserException newInstantiationException(String message,
ArrayList<Exception> exceptions) {
if (exceptions == null || exceptions.isEmpty()) {
return new XmlPullParserException(message);
} else {
XmlPullParserException exception = new XmlPullParserException(message);
for (Exception ex : exceptions) {
exception.addSuppressed(ex);
}
return exception;
}
}
/**
* Creates a new instance of a XML Serializer.
*
* <p><b>NOTE:</b> factory features are not used for XML Serializer.
*
* @return A new instance of a XML Serializer.
* @throws XmlPullParserException if a parser cannot be created which satisfies the
* requested configuration.
*/
public XmlSerializer newSerializer() throws XmlPullParserException {
return getSerializerInstance();
}
/**
* Creates a new instance of a PullParserFactory that can be used
* to create XML pull parsers. The factory will always return instances
* of Android's built-in {@link XmlPullParser} and {@link XmlSerializer}.
*/
public static XmlPullParserFactory newInstance () throws XmlPullParserException {
return new XmlPullParserFactory();
}
/**
* Creates a factory that always returns instances of Android's built-in
* {@link XmlPullParser} and {@link XmlSerializer} implementation. This
* <b>does not</b> support factories capable of creating arbitrary parser
* and serializer implementations. Both arguments to this method are unused.
*/
public static XmlPullParserFactory newInstance (String unused, Class unused2)
throws XmlPullParserException {
return newInstance();
}
}

View File

@@ -0,0 +1,325 @@
package org.xmlpull.v1;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
/**
* Define an interface to serialization of XML Infoset.
* This interface abstracts away if serialized XML is XML 1.0 compatible text or
* other formats of XML 1.0 serializations (such as binary XML for example with WBXML).
*
* <p><b>PLEASE NOTE:</b> This interface will be part of XmlPull 1.2 API.
* It is included as basis for discussion. It may change in any way.
*
* <p>Exceptions that may be thrown are: IOException or runtime exception
* (more runtime exceptions can be thrown but are not declared and as such
* have no semantics defined for this interface):
* <ul>
* <li><em>IllegalArgumentException</em> - for almost all methods to signal that
* argument is illegal
* <li><em>IllegalStateException</em> - to signal that call has good arguments but
* is not expected here (violation of contract) and for features/properties
* when requesting setting unimplemented feature/property
* (UnsupportedOperationException would be better but it is not in MIDP)
* </ul>
*
* <p><b>NOTE:</b> writing CDSECT, ENTITY_REF, IGNORABLE_WHITESPACE,
* PROCESSING_INSTRUCTION, COMMENT, and DOCDECL in some implementations
* may not be supported (for example when serializing to WBXML).
* In such case IllegalStateException will be thrown and it is recommended
* to use an optional feature to signal that implementation is not
* supporting this kind of output.
*/
public interface XmlSerializer {
/**
* Set feature identified by name (recommended to be URI for uniqueness).
* Some well known optional features are defined in
* <a href="http://www.xmlpull.org/v1/doc/features.html">
* http://www.xmlpull.org/v1/doc/features.html</a>.
*
* If feature is not recognized or can not be set
* then IllegalStateException MUST be thrown.
*
* @exception IllegalStateException If the feature is not supported or can not be set
*/
void setFeature(String name,
boolean state)
throws IllegalArgumentException, IllegalStateException;
/**
* Return the current value of the feature with given name.
* <p><strong>NOTE:</strong> unknown properties are <strong>always</strong> returned as null
*
* @param name The name of feature to be retrieved.
* @return The value of named feature.
* @exception IllegalArgumentException if feature string is null
*/
boolean getFeature(String name);
/**
* Set the value of a property.
* (the property name is recommended to be URI for uniqueness).
* Some well known optional properties are defined in
* <a href="http://www.xmlpull.org/v1/doc/properties.html">
* http://www.xmlpull.org/v1/doc/properties.html</a>.
*
* If property is not recognized or can not be set
* then IllegalStateException MUST be thrown.
*
* @exception IllegalStateException if the property is not supported or can not be set
*/
void setProperty(String name,
Object value)
throws IllegalArgumentException, IllegalStateException;
/**
* Look up the value of a property.
*
* The property name is any fully-qualified URI. I
* <p><strong>NOTE:</strong> unknown properties are <string>always</strong> returned as null
*
* @param name The name of property to be retrieved.
* @return The value of named property.
*/
Object getProperty(String name);
/**
* Set to use binary output stream with given encoding.
*/
void setOutput (OutputStream os, String encoding)
throws IOException, IllegalArgumentException, IllegalStateException;
/**
* Set the output to the given writer.
* <p><b>WARNING</b> no information about encoding is available!
*/
void setOutput (Writer writer)
throws IOException, IllegalArgumentException, IllegalStateException;
/**
* Write &lt;&#63;xml declaration with encoding (if encoding not null)
* and standalone flag (if standalone not null)
* This method can only be called just after setOutput.
*/
void startDocument (String encoding, Boolean standalone)
throws IOException, IllegalArgumentException, IllegalStateException;
/**
* Finish writing. All unclosed start tags will be closed and output
* will be flushed. After calling this method no more output can be
* serialized until next call to setOutput()
*/
void endDocument ()
throws IOException, IllegalArgumentException, IllegalStateException;
/**
* Binds the given prefix to the given namespace.
* This call is valid for the next element including child elements.
* The prefix and namespace MUST be always declared even if prefix
* is not used in element (startTag() or attribute()) - for XML 1.0
* it must result in declaring <code>xmlns:prefix='namespace'</code>
* (or <code>xmlns:prefix="namespace"</code> depending what character is used
* to quote attribute value).
*
* <p><b>NOTE:</b> this method MUST be called directly before startTag()
* and if anything but startTag() or setPrefix() is called next there will be exception.
* <p><b>NOTE:</b> prefixes "xml" and "xmlns" are already bound
* and can not be redefined see:
* <a href="http://www.w3.org/XML/xml-names-19990114-errata#NE05">Namespaces in XML Errata</a>.
* <p><b>NOTE:</b> to set default namespace use as prefix empty string.
*
* @param prefix must be not null (or IllegalArgumentException is thrown)
* @param namespace must be not null
*/
void setPrefix (String prefix, String namespace)
throws IOException, IllegalArgumentException, IllegalStateException;
/**
* Return namespace that corresponds to given prefix
* If there is no prefix bound to this namespace return null
* but if generatePrefix is false then return generated prefix.
*
* <p><b>NOTE:</b> if the prefix is empty string "" and default namespace is bound
* to this prefix then empty string ("") is returned.
*
* <p><b>NOTE:</b> prefixes "xml" and "xmlns" are already bound
* will have values as defined
* <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML specification</a>
*/
String getPrefix (String namespace, boolean generatePrefix)
throws IllegalArgumentException;
/**
* Returns the current depth of the element.
* Outside the root element, the depth is 0. The
* depth is incremented by 1 when startTag() is called.
* The depth is decremented after the call to endTag()
* event was observed.
*
* <pre>
* &lt;!-- outside --&gt; 0
* &lt;root&gt; 1
* sometext 1
* &lt;foobar&gt; 2
* &lt;/foobar&gt; 2
* &lt;/root&gt; 1
* &lt;!-- outside --&gt; 0
* </pre>
*/
int getDepth();
/**
* Returns the namespace URI of the current element as set by startTag().
*
* <p><b>NOTE:</b> that means in particular that: <ul>
* <li>if there was startTag("", ...) then getNamespace() returns ""
* <li>if there was startTag(null, ...) then getNamespace() returns null
* </ul>
*
* @return namespace set by startTag() that is currently in scope
*/
String getNamespace ();
/**
* Returns the name of the current element as set by startTag().
* It can only be null before first call to startTag()
* or when last endTag() is called to close first startTag().
*
* @return namespace set by startTag() that is currently in scope
*/
String getName();
/**
* Writes a start tag with the given namespace and name.
* If there is no prefix defined for the given namespace,
* a prefix will be defined automatically.
* The explicit prefixes for namespaces can be established by calling setPrefix()
* immediately before this method.
* If namespace is null no namespace prefix is printed but just name.
* If namespace is empty string then serializer will make sure that
* default empty namespace is declared (in XML 1.0 xmlns='')
* or throw IllegalStateException if default namespace is already bound
* to non-empty string.
*/
XmlSerializer startTag (String namespace, String name)
throws IOException, IllegalArgumentException, IllegalStateException;
/**
* Write an attribute. Calls to attribute() MUST follow a call to
* startTag() immediately. If there is no prefix defined for the
* given namespace, a prefix will be defined automatically.
* If namespace is null or empty string
* no namespace prefix is printed but just name.
*/
XmlSerializer attribute (String namespace, String name, String value)
throws IOException, IllegalArgumentException, IllegalStateException;
/**
* Write end tag. Repetition of namespace and name is just for avoiding errors.
* <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were
* very difficult to find...
* If namespace is null no namespace prefix is printed but just name.
* If namespace is empty string then serializer will make sure that
* default empty namespace is declared (in XML 1.0 xmlns='').
*/
XmlSerializer endTag (String namespace, String name)
throws IOException, IllegalArgumentException, IllegalStateException;
// /**
// * Writes a start tag with the given namespace and name.
// * <br />If there is no prefix defined (prefix == null) for the given namespace,
// * a prefix will be defined automatically.
// * <br />If explicit prefixes is passed (prefix != null) then it will be used
// *and namespace declared if not already declared or
// * throw IllegalStateException the same prefix was already set on this
// * element (setPrefix()) and was bound to different namespace.
// * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
// * <br />If namespace is null then no namespace prefix is printed but just name.
// * <br />If namespace is empty string then serializer will make sure that
// * default empty namespace is declared (in XML 1.0 xmlns='')
// * or throw IllegalStateException if default namespace is already bound
// * to non-empty string.
// */
// XmlSerializer startTag (String prefix, String namespace, String name)
// throws IOException, IllegalArgumentException, IllegalStateException;
//
// /**
// * Write an attribute. Calls to attribute() MUST follow a call to
// * startTag() immediately.
// * <br />If there is no prefix defined (prefix == null) for the given namespace,
// * a prefix will be defined automatically.
// * <br />If explicit prefixes is passed (prefix != null) then it will be used
// * and namespace declared if not already declared or
// * throw IllegalStateException the same prefix was already set on this
// * element (setPrefix()) and was bound to different namespace.
// * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
// * <br />If namespace is null then no namespace prefix is printed but just name.
// * <br />If namespace is empty string then serializer will make sure that
// * default empty namespace is declared (in XML 1.0 xmlns='')
// * or throw IllegalStateException if default namespace is already bound
// * to non-empty string.
// */
// XmlSerializer attribute (String prefix, String namespace, String name, String value)
// throws IOException, IllegalArgumentException, IllegalStateException;
//
// /**
// * Write end tag. Repetition of namespace, prefix, and name is just for avoiding errors.
// * <br />If namespace or name arguments are different from corresponding startTag call
// * then IllegalArgumentException is thrown, if prefix argument is not null and is different
// * from corresponding starTag then IllegalArgumentException is thrown.
// * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
// * <br />If namespace is null then no namespace prefix is printed but just name.
// * <br />If namespace is empty string then serializer will make sure that
// * default empty namespace is declared (in XML 1.0 xmlns='').
// * <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were
// * very difficult to find...</p>
// */
// ALEK: This is really optional as prefix in end tag MUST correspond to start tag but good for error checking
// XmlSerializer endTag (String prefix, String namespace, String name)
// throws IOException, IllegalArgumentException, IllegalStateException;
/**
* Writes text, where special XML chars are escaped automatically
*/
XmlSerializer text (String text)
throws IOException, IllegalArgumentException, IllegalStateException;
/**
* Writes text, where special XML chars are escaped automatically
*/
XmlSerializer text (char [] buf, int start, int len)
throws IOException, IllegalArgumentException, IllegalStateException;
void cdsect (String text)
throws IOException, IllegalArgumentException, IllegalStateException;
void entityRef (String text) throws IOException,
IllegalArgumentException, IllegalStateException;
void processingInstruction (String text)
throws IOException, IllegalArgumentException, IllegalStateException;
void comment (String text)
throws IOException, IllegalArgumentException, IllegalStateException;
void docdecl (String text)
throws IOException, IllegalArgumentException, IllegalStateException;
void ignorableWhitespace (String text)
throws IOException, IllegalArgumentException, IllegalStateException;
/**
* Write all pending output to the stream.
* If method startTag() or attribute() was called then start tag is closed (final &gt;)
* before flush() is called on underlying output stream.
*
* <p><b>NOTE:</b> if there is need to close start tag
* (so no more attribute() calls are allowed) but without flushing output
* call method text() with empty string (text("")).
*
*/
void flush ()
throws IOException;
}

View File

@@ -2,6 +2,7 @@ apply plugin: 'java-library'
apply plugin: 'maven'
dependencies {
api 'net.sf.kxml:kxml2:2.3.0'
api "org.slf4j:slf4j-api:$slf4jVersion"
compileOnly 'com.google.code.findbugs:jsr305:3.0.2'
}

View File

@@ -1,7 +1,8 @@
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2018 devemux86
* Copyright 2016-2021 devemux86
* Copyright 2017 Longri
* Copyright 2021 eddiemuc
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -21,6 +22,7 @@ package org.oscim.backend;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.backend.canvas.Canvas;
import org.oscim.backend.canvas.Paint;
import org.oscim.theme.XmlThemeResourceProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +39,7 @@ public abstract class CanvasAdapter {
private static final Logger log = LoggerFactory.getLogger(CanvasAdapter.class);
private static final String PREFIX_ASSETS = "assets:";
private static final String PREFIX_FILE = "file:";
public static final String PREFIX_FILE = "file:";
/**
* The instance provided by backend
@@ -59,6 +61,11 @@ public abstract class CanvasAdapter {
*/
public static Platform platform = Platform.UNKNOWN;
/**
* The symbol scale.
*/
public static float symbolScale = 1;
/**
* The text scale.
*/
@@ -151,34 +158,45 @@ public abstract class CanvasAdapter {
* @param src the resource
* @return the bitmap
*/
protected abstract Bitmap loadBitmapAssetImpl(String relativePathPrefix, String src, int width, int height, int percent) throws IOException;
protected abstract Bitmap loadBitmapAssetImpl(String relativePathPrefix, String src, XmlThemeResourceProvider resourceProvider, int width, int height, int percent) throws IOException;
public static Bitmap getBitmapAsset(String relativePathPrefix, String src) throws IOException {
return getBitmapAsset(relativePathPrefix, src, 0, 0, 100);
return getBitmapAsset(relativePathPrefix, src, null, 0, 0, 100);
}
public static Bitmap getBitmapAsset(String relativePathPrefix, String src, int width, int height, int percent) throws IOException {
return g.loadBitmapAssetImpl(relativePathPrefix, src, width, height, percent);
public static Bitmap getBitmapAsset(String relativePathPrefix, String src, XmlThemeResourceProvider resourceProvider, int width, int height, int percent) throws IOException {
return g.loadBitmapAssetImpl(relativePathPrefix, src, resourceProvider, width, height, percent);
}
protected static Bitmap createBitmap(String relativePathPrefix, String src, int width, int height, int percent) throws IOException {
protected static Bitmap createBitmap(String relativePathPrefix, String src, XmlThemeResourceProvider resourceProvider, int width, int height, int percent) throws IOException {
if (src == null || src.length() == 0) {
// no image source defined
return null;
}
InputStream inputStream;
if (src.startsWith(PREFIX_ASSETS)) {
src = src.substring(PREFIX_ASSETS.length());
inputStream = inputStreamFromAssets(relativePathPrefix, src);
} else if (src.startsWith(PREFIX_FILE)) {
src = src.substring(PREFIX_FILE.length());
inputStream = inputStreamFromFile(relativePathPrefix, src);
} else {
inputStream = inputStreamFromFile(relativePathPrefix, src);
InputStream inputStream = null;
if (resourceProvider != null) {
try {
inputStream = resourceProvider.createInputStream(relativePathPrefix, src);
} catch (IOException ioe) {
log.debug("Exception trying to access resource: " + src + " using custom provider: " + ioe);
// Ignore and try to resolve input stream using the standard process
}
}
if (inputStream == null)
if (inputStream == null) {
if (src.startsWith(PREFIX_ASSETS)) {
src = src.substring(PREFIX_ASSETS.length());
inputStream = inputStreamFromAssets(relativePathPrefix, src);
} else if (src.startsWith(PREFIX_FILE)) {
src = src.substring(PREFIX_FILE.length());
inputStream = inputStreamFromFile(relativePathPrefix, src);
} else {
inputStream = inputStreamFromFile(relativePathPrefix, src);
if (inputStream == null)
inputStream = inputStreamFromAssets(relativePathPrefix, src);
}
}
// Fallback to internal resources

View File

@@ -254,8 +254,8 @@ public final class Color {
* exception. Supported formats are:
* #RRGGBB
* #AARRGGBB
* 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta',
* 'yellow', 'lightgray', 'darkgray'
* rgb(r, g, b)
* rgba(r, g, b, a)
*
* @param colorString the color string
* @return the int

View File

@@ -56,7 +56,7 @@ public class JobQueue {
if (t.state(LOADING | CANCEL)) {
t.setState(NONE);
} else {
log.error("Wrong tile in queue {} {}", t, t.state());
log.debug("Wrong tile in queue {} {}", t, t.state());
}
tiles[i] = null;
}

View File

@@ -1,6 +1,7 @@
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2016 Andrey Novikov
* Copyright 2020 devemux86
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -22,16 +23,10 @@ import org.oscim.event.Event;
import org.oscim.layers.Layer;
import org.oscim.map.Map;
import org.oscim.map.Map.UpdateListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.oscim.tiling.TileSource;
/**
* TODO - add a TileLayer.Builder
*/
public abstract class TileLayer extends Layer implements UpdateListener {
static final Logger log = LoggerFactory.getLogger(TileLayer.class);
private int mNumLoaders = 4;
/**
@@ -42,6 +37,8 @@ public abstract class TileLayer extends Layer implements UpdateListener {
protected TileLoader[] mTileLoader;
protected TileSource mTileSource;
public TileLayer(Map map, TileManager tileManager, TileRenderer renderer) {
super(map);
renderer.setTileManager(tileManager);
@@ -116,6 +113,8 @@ public abstract class TileLayer extends Layer implements UpdateListener {
loader.finish();
loader.dispose();
}
if (mTileSource != null)
mTileSource.close();
}
void notifyLoaders() {
@@ -148,4 +147,8 @@ public abstract class TileLayer extends Layer implements UpdateListener {
public TileManager getManager() {
return mTileManager;
}
public TileSource getTileSource() {
return mTileSource;
}
}

View File

@@ -1,7 +1,7 @@
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2017 Andrey Novikov
* Copyright 2017-2018 devemux86
* Copyright 2017-2020 devemux86
* Copyright 2019 Gustl22
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
@@ -38,8 +38,6 @@ public class BitmapTileLayer extends TileLayer {
private static final int CACHE_LIMIT = 40;
protected final TileSource mTileSource;
/**
* Bitmap alpha in range 0 to 1.
*/

View File

@@ -1,5 +1,6 @@
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2020 devemux86
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -34,8 +35,6 @@ public class S3DBTileLayer extends TileLayer {
private static final int MIN_ZOOM = 16;
private static final int MAX_ZOOM = 16;
private final TileSource mTileSource;
public S3DBTileLayer(Map map, TileSource tileSource) {
this(map, tileSource, true, false);
}

View File

@@ -21,6 +21,7 @@ import org.oscim.core.Tag;
import org.oscim.core.TagSet;
import org.oscim.layers.tile.TileLoader;
import org.oscim.map.Map;
import org.oscim.tiling.TileSource;
import org.oscim.utils.Utils;
public class OsmTileLayer extends VectorTileLayer {
@@ -36,6 +37,12 @@ public class OsmTileLayer extends VectorTileLayer {
mTileManager.setZoomLevel(zoomMin, zoomMax);
}
public OsmTileLayer(Map map, TileSource tileSource) {
this(map);
setTileSource(tileSource);
}
@Override
protected TileLoader createLoader() {
return new OsmTileLoader(this);

View File

@@ -1,6 +1,7 @@
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2016 Longri
* Copyright 2020 devemux86
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -18,11 +19,7 @@
package org.oscim.layers.tile.vector;
import org.oscim.core.MapElement;
import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileLayer;
import org.oscim.layers.tile.TileLoader;
import org.oscim.layers.tile.TileManager;
import org.oscim.layers.tile.VectorTileRenderer;
import org.oscim.layers.tile.*;
import org.oscim.map.Map;
import org.oscim.renderer.bucket.RenderBuckets;
import org.oscim.theme.IRenderTheme;
@@ -42,7 +39,11 @@ import org.slf4j.LoggerFactory;
public class VectorTileLayer extends TileLayer {
static final Logger log = LoggerFactory.getLogger(VectorTileLayer.class);
protected TileSource mTileSource;
private final List<LList<TileLoaderProcessHook>> mLoaderProcessHooks = new List<>();
private final List<LList<TileLoaderThemeHook>> mLoaderThemeHooks = new List<>();
private IRenderTheme mTheme;
public VectorTileLayer(Map map, TileSource tileSource) {
this(map, new TileManager(map,
@@ -104,14 +105,18 @@ public class VectorTileLayer extends TileLayer {
return true;
}
public TileSource getTileSource() {
return mTileSource;
/**
* Set {@link IRenderTheme} used by {@link TileLoader}
*/
@Deprecated
public void setRenderTheme(IRenderTheme theme) {
setTheme(theme);
}
/**
* Set {@link IRenderTheme} used by {@link TileLoader}
*/
public void setRenderTheme(IRenderTheme theme) {
public void setTheme(IRenderTheme theme) {
/* wait for loaders to finish all current jobs to
* not change theme instance hold by loader instance
* while running */
@@ -127,8 +132,6 @@ public class VectorTileLayer extends TileLayer {
resumeLoaders();
}
private IRenderTheme mTheme;
public IRenderTheme getTheme() {
return mTheme;
}
@@ -164,12 +167,6 @@ public class VectorTileLayer extends TileLayer {
public void complete(MapTile tile, boolean success);
}
private List<LList<TileLoaderProcessHook>> mLoaderProcessHooks =
new List<LList<TileLoaderProcessHook>>();
private List<LList<TileLoaderThemeHook>> mLoaderThemeHooks =
new List<LList<TileLoaderThemeHook>>();
public void addHook(TileLoaderProcessHook h) {
mLoaderProcessHooks.append(new LList<TileLoaderProcessHook>(h));
}
@@ -178,13 +175,6 @@ public class VectorTileLayer extends TileLayer {
mLoaderThemeHooks.append(new LList<TileLoaderThemeHook>(h));
}
@Override
public void onDetach() {
super.onDetach();
if (mTileSource != null)
mTileSource.close();
}
public void callThemeHooks(MapTile tile, RenderBuckets layers, MapElement element,
RenderStyle style, int level) {

View File

@@ -2,6 +2,7 @@
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2019 devemux86
* Copyright 2018 Gustl22
* Copyright 2021 blakfast
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -31,6 +32,7 @@ import org.oscim.renderer.bucket.SymbolItem;
import org.oscim.renderer.bucket.TextItem;
import org.oscim.theme.styles.TextStyle;
import org.oscim.utils.FastMath;
import org.oscim.utils.Parameters;
import org.oscim.utils.geom.OBB2D;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -49,6 +51,7 @@ public class LabelPlacement {
return (LabelTileData) tile.getData(LabelLayer.LABEL_DATA);
}
private static final float DISTANCE_COEFFICIENT = 3;
private static final float MIN_CAPTION_DIST = 5;
private static final float MIN_WAY_DIST = 3;
@@ -352,9 +355,18 @@ public class LabelPlacement {
}
/* estimation for visible area to be labeled */
int mw = (mMap.getWidth() + Tile.SIZE) / 2;
int mh = (mMap.getHeight() + Tile.SIZE) / 2;
mSquareRadius = mw * mw + mh * mh;
if (Parameters.DISTANT_LABELS) {
int mw = mMap.getWidth();
int mh = mMap.getHeight();
float k = pos.tilt / mMap.viewport().getMaxTilt() * DISTANCE_COEFFICIENT;
if (k < 0.5)
k = 0.5f;
mSquareRadius = (mw * mw + mh * mh) * k;
} else {
int mw = (mMap.getWidth() + Tile.SIZE) / 2;
int mh = (mMap.getHeight() + Tile.SIZE) / 2;
mSquareRadius = mw * mw + mh * mh;
}
/* scale of tiles zoom-level relative to current position */
double scale = pos.scale / (1 << zoom);

View File

@@ -2,7 +2,7 @@
* Copyright 2013 Hannes Janetzek
* Copyright 2016 Andrey Novikov
* Copyright 2016 Stephan Leuschner
* Copyright 2016-2019 devemux86
* Copyright 2016-2020 devemux86
* Copyright 2016 Longri
* Copyright 2018 Gustl22
*
@@ -24,11 +24,7 @@ package org.oscim.map;
import org.oscim.core.BoundingBox;
import org.oscim.core.Box;
import org.oscim.core.MapPosition;
import org.oscim.event.Event;
import org.oscim.event.EventDispatcher;
import org.oscim.event.EventListener;
import org.oscim.event.Gesture;
import org.oscim.event.MotionEvent;
import org.oscim.event.*;
import org.oscim.layers.AbstractMapEventLayer;
import org.oscim.layers.Layer;
import org.oscim.layers.MapEventLayer;
@@ -189,16 +185,18 @@ public abstract class Map implements TaskQueue {
* Utility function to set theme of base vector-layer and
* use map background color from theme.
*/
public void setTheme(ThemeFile theme) {
setTheme(theme, false);
public IRenderTheme setTheme(ThemeFile theme) {
return setTheme(theme, false);
}
/**
* Utility function to set theme of base vector-layer, optionally
* to all vector layers and use map background color from theme.
*/
public void setTheme(ThemeFile theme, boolean allLayers) {
setTheme(ThemeLoader.load(theme), allLayers);
public IRenderTheme setTheme(ThemeFile theme, boolean allLayers) {
IRenderTheme renderTheme = ThemeLoader.load(theme);
setTheme(renderTheme, allLayers);
return renderTheme;
}
public void setTheme(IRenderTheme theme) {
@@ -213,7 +211,7 @@ public abstract class Map implements TaskQueue {
boolean themeSet = false;
for (Layer layer : mLayers) {
if (layer instanceof VectorTileLayer) {
((VectorTileLayer) layer).setRenderTheme(theme);
((VectorTileLayer) layer).setTheme(theme);
themeSet = true;
if (!allLayers)
break;

View File

@@ -1,7 +1,7 @@
/*
* Copyright 2010, 2011, 2012, 2013 mapsforge.org
* Copyright 2014 Ludwig M Brinckmann
* Copyright 2014-2019 devemux86
* Copyright 2014-2021 devemux86
* Copyright 2014 Erik Duisters
* Copyright 2014 Christian Pesch
*
@@ -66,6 +66,11 @@ public class DefaultMapScaleBar extends MapScaleBar {
this.paintScaleTextStroke = createTextPaint(Color.WHITE, 2, Paint.Style.STROKE);
}
public void setColor(int color) {
this.paintScaleBar.setColor(color);
this.paintScaleText.setColor(color);
}
/**
* @return the secondary {@link DistanceUnitAdapter} in use by this MapScaleBar
*/
@@ -100,7 +105,7 @@ public class DefaultMapScaleBar extends MapScaleBar {
paint.setColor(color);
paint.setStrokeWidth(strokeWidth * this.scale);
paint.setStyle(style);
paint.setStrokeCap(Paint.Cap.SQUARE);
paint.setStrokeCap(Paint.Cap.ROUND);
return paint;
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2014 Christian Pesch
* Copyright 2014-2021 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.scalebar;
public class NauticalImperialUnitAdapter implements DistanceUnitAdapter {
public static final NauticalImperialUnitAdapter INSTANCE = new NauticalImperialUnitAdapter();
public static final double METER_FOOT_RATIO = 0.3048;
public static final int ONE_MILE = 6076;
public static final int[] SCALE_BAR_VALUES = {30380000, 12152000, 6076000, 3038000, 1215200, 607600, 303800,
121520, 60760, 30380, 12152, 6076, 3038, 1000, 500, 200, 100, 50, 20, 10, 5, 2, 1};
@Override
public double getMeterRatio() {
return METER_FOOT_RATIO;
}
@Override
public int[] getScaleBarValues() {
return SCALE_BAR_VALUES;
}
@Override
public String getScaleText(int mapScaleValue) {
if (mapScaleValue < ONE_MILE / 2) {
return mapScaleValue + " ft";
}
if (mapScaleValue == ONE_MILE / 2) {
return "0.5 nmi";
}
return (mapScaleValue / ONE_MILE) + " nmi";
}
}

View File

@@ -1,8 +1,9 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2017 devemux86
* Copyright 2016-2021 devemux86
* Copyright 2017 Andrey Novikov
* Copyright 2021 eddiemuc
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -34,8 +35,10 @@ public class ExternalRenderTheme implements ThemeFile {
private static final long serialVersionUID = 1L;
private final long mFileModificationDate;
private boolean mMapsforgeTheme;
private XmlRenderThemeMenuCallback mMenuCallback;
private final String mPath;
private XmlThemeResourceProvider mResourceProvider;
/**
* @param fileName the path to the XML render theme file.
@@ -108,13 +111,28 @@ public class ExternalRenderTheme implements ThemeFile {
return is;
}
@Override
public XmlThemeResourceProvider getResourceProvider() {
return mResourceProvider;
}
@Override
public boolean isMapsforgeTheme() {
return ThemeUtils.isMapsforgeTheme(this);
return mMapsforgeTheme;
}
@Override
public void setMapsforgeTheme(boolean mapsforgeTheme) {
mMapsforgeTheme = mapsforgeTheme;
}
@Override
public void setMenuCallback(XmlRenderThemeMenuCallback menuCallback) {
mMenuCallback = menuCallback;
}
@Override
public void setResourceProvider(XmlThemeResourceProvider resourceProvider) {
mResourceProvider = resourceProvider;
}
}

View File

@@ -1,6 +1,7 @@
/*
* Copyright 2016-2017 devemux86
* Copyright 2016-2021 devemux86
* Copyright 2017 Andrey Novikov
* Copyright 2021 eddiemuc
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -18,8 +19,6 @@ package org.oscim.theme;
import org.oscim.theme.IRenderTheme.ThemeException;
import org.oscim.utils.Utils;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
@@ -30,14 +29,17 @@ public class StreamRenderTheme implements ThemeFile {
private static final long serialVersionUID = 1L;
private final InputStream mInputStream;
private boolean mMapsforgeTheme;
private XmlRenderThemeMenuCallback mMenuCallback;
private final String mRelativePathPrefix;
private XmlThemeResourceProvider mResourceProvider;
/**
* @param relativePathPrefix the prefix for all relative resource paths.
* @param inputStream an input stream containing valid render theme XML data.
* @throws ThemeException if an error occurs while reading the render theme XML.
*/
public StreamRenderTheme(String relativePathPrefix, InputStream inputStream) {
public StreamRenderTheme(String relativePathPrefix, InputStream inputStream) throws ThemeException {
this(relativePathPrefix, inputStream, null);
}
@@ -45,11 +47,11 @@ public class StreamRenderTheme implements ThemeFile {
* @param relativePathPrefix the prefix for all relative resource paths.
* @param inputStream an input stream containing valid render theme XML data.
* @param menuCallback the interface callback to create a settings menu on the fly.
* @throws ThemeException if an error occurs while reading the render theme XML.
*/
public StreamRenderTheme(String relativePathPrefix, InputStream inputStream, XmlRenderThemeMenuCallback menuCallback) {
public StreamRenderTheme(String relativePathPrefix, InputStream inputStream, XmlRenderThemeMenuCallback menuCallback) throws ThemeException {
mRelativePathPrefix = relativePathPrefix;
mInputStream = new BufferedInputStream(inputStream);
mInputStream.mark(0);
mInputStream = inputStream;
mMenuCallback = menuCallback;
}
@@ -82,21 +84,31 @@ public class StreamRenderTheme implements ThemeFile {
@Override
public InputStream getRenderThemeAsStream() throws ThemeException {
try {
mInputStream.reset();
} catch (IOException e) {
throw new ThemeException(e.getMessage());
}
return mInputStream;
}
@Override
public XmlThemeResourceProvider getResourceProvider() {
return mResourceProvider;
}
@Override
public boolean isMapsforgeTheme() {
return ThemeUtils.isMapsforgeTheme(this);
return mMapsforgeTheme;
}
@Override
public void setMapsforgeTheme(boolean mapsforgeTheme) {
mMapsforgeTheme = mapsforgeTheme;
}
@Override
public void setMenuCallback(XmlRenderThemeMenuCallback menuCallback) {
mMenuCallback = menuCallback;
}
@Override
public void setResourceProvider(XmlThemeResourceProvider resourceProvider) {
mResourceProvider = resourceProvider;
}
}

View File

@@ -1,8 +1,9 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2017 devemux86
* Copyright 2016-2021 devemux86
* Copyright 2017 Andrey Novikov
* Copyright 2021 eddiemuc
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -44,6 +45,11 @@ public interface ThemeFile extends Serializable {
*/
InputStream getRenderThemeAsStream() throws ThemeException;
/**
* @return a custom provider to retrieve resources internally referenced by "src" attribute (e.g. images, icons).
*/
XmlThemeResourceProvider getResourceProvider();
/**
* Tells ThemeLoader if theme file is in Mapsforge format
*
@@ -51,8 +57,18 @@ public interface ThemeFile extends Serializable {
*/
boolean isMapsforgeTheme();
/**
* @param mapsforgeTheme true if theme file is in Mapsforge format
*/
void setMapsforgeTheme(boolean mapsforgeTheme);
/**
* @param menuCallback the interface callback to create a settings menu on the fly.
*/
void setMenuCallback(XmlRenderThemeMenuCallback menuCallback);
/**
* @param resourceProvider a custom provider to retrieve resources internally referenced by "src" attribute (e.g. images, icons).
*/
void setResourceProvider(XmlThemeResourceProvider resourceProvider);
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright 2017 Longri
* Copyright 2017-2018 devemux86
* Copyright 2017-2021 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -17,7 +17,6 @@ package org.oscim.theme;
import org.oscim.backend.CanvasAdapter;
import org.oscim.backend.Platform;
import org.oscim.backend.XMLReaderAdapter;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.renderer.atlas.TextureAtlas;
import org.oscim.renderer.atlas.TextureRegion;
@@ -26,8 +25,11 @@ import org.oscim.theme.rule.Rule;
import org.oscim.theme.styles.RenderStyle;
import org.oscim.theme.styles.SymbolStyle;
import org.oscim.theme.styles.SymbolStyle.SymbolBuilder;
import org.oscim.utils.IOUtils;
import org.oscim.utils.TextureAtlasUtils;
import org.xmlpull.v1.XmlPullParser;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -51,20 +53,23 @@ public class XmlAtlasThemeBuilder extends XmlThemeBuilder {
* @throws ThemeException if an error occurs while parsing the render theme XML.
*/
public static IRenderTheme read(ThemeFile theme, ThemeCallback themeCallback) throws ThemeException {
Map<Object, TextureRegion> outputMap = new HashMap<>();
List<TextureAtlas> atlasList = new ArrayList<>();
XmlAtlasThemeBuilder renderThemeHandler = new XmlAtlasThemeBuilder(theme, themeCallback, outputMap, atlasList);
InputStream inputStream = null;
try {
new XMLReaderAdapter().parse(renderThemeHandler, theme.getRenderThemeAsStream());
XmlPullParser pullParser = getXmlPullParserFactory().newPullParser();
Map<Object, TextureRegion> outputMap = new HashMap<>();
List<TextureAtlas> atlasList = new ArrayList<>();
XmlAtlasThemeBuilder renderThemeHandler = new XmlAtlasThemeBuilder(theme, pullParser, themeCallback, outputMap, atlasList);
inputStream = theme.getRenderThemeAsStream();
pullParser.setInput(inputStream, null);
renderThemeHandler.processRenderTheme();
TextureAtlasUtils.createTextureRegions(renderThemeHandler.bitmapMap, outputMap, atlasList,
true, CanvasAdapter.platform == Platform.IOS);
return replaceThemeSymbols(renderThemeHandler.mRenderTheme, outputMap);
} catch (Exception e) {
throw new ThemeException(e.getMessage());
} finally {
IOUtils.closeQuietly(inputStream);
}
TextureAtlasUtils.createTextureRegions(renderThemeHandler.bitmapMap, outputMap, atlasList,
true, CanvasAdapter.platform == Platform.IOS);
return replaceThemeSymbols(renderThemeHandler.mRenderTheme, outputMap);
}
private static IRenderTheme replaceThemeSymbols(RenderTheme renderTheme, Map<Object, TextureRegion> regionMap) {
@@ -98,21 +103,21 @@ public class XmlAtlasThemeBuilder extends XmlThemeBuilder {
private final Map<Object, Bitmap> bitmapMap = new HashMap<>();
public XmlAtlasThemeBuilder(ThemeFile theme,
public XmlAtlasThemeBuilder(ThemeFile theme, XmlPullParser pullParser,
Map<Object, TextureRegion> regionMap, List<TextureAtlas> atlasList) {
this(theme, null, regionMap, atlasList);
this(theme, pullParser, null, regionMap, atlasList);
}
public XmlAtlasThemeBuilder(ThemeFile theme, ThemeCallback themeCallback,
public XmlAtlasThemeBuilder(ThemeFile theme, XmlPullParser pullParser, ThemeCallback themeCallback,
Map<Object, TextureRegion> regionMap, List<TextureAtlas> atlasList) {
super(theme, themeCallback);
super(theme, pullParser, themeCallback);
this.regionMap = regionMap;
this.atlasList = atlasList;
}
@Override
RenderTheme createTheme(Rule[] rules) {
return new AtlasRenderTheme(mMapBackground, mTextScale, rules, mLevels, mMapsforgeTheme, regionMap, atlasList);
return new AtlasRenderTheme(mMapBackground, mTextScale, rules, mLevels, mTheme.isMapsforgeTheme(), regionMap, atlasList);
}
@Override

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2021 eddiemuc
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.theme;
import java.io.IOException;
import java.io.InputStream;
/**
* Interface for a provider of resources referenced inside XML themes.
*/
public interface XmlThemeResourceProvider {
/**
* @param relativePath a relative path to use as a base for search in the resource provuider
* @param source a source string parsed out of an XML render theme "src" attribute.
* @return an InputStream to read the resource data from.
* @throws IOException if the resource cannot be found or an access error occurred.
*/
InputStream createInputStream(String relativePath, String source) throws IOException;
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright 2021 devemux86
* Copyright 2021 eddiemuc
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.theme;
import org.oscim.theme.IRenderTheme.ThemeException;
import org.oscim.utils.Utils;
import java.io.IOException;
import java.io.InputStream;
/**
* A ZipRenderTheme allows for customizing the rendering style of the map
* via an XML from an archive.
*/
public class ZipRenderTheme implements ThemeFile {
private static final long serialVersionUID = 1L;
private boolean mMapsforgeTheme;
private XmlRenderThemeMenuCallback mMenuCallback;
private final String mRelativePathPrefix;
private XmlThemeResourceProvider mResourceProvider;
protected final String mXmlTheme;
/**
* @param xmlTheme the XML theme path in the archive.
* @param resourceProvider the custom provider to retrieve resources internally referenced by "src" attribute (e.g. images, icons).
* @throws ThemeException if an error occurs while reading the render theme XML.
*/
public ZipRenderTheme(String xmlTheme, XmlThemeResourceProvider resourceProvider) throws ThemeException {
this(xmlTheme, resourceProvider, null);
}
/**
* @param xmlTheme the XML theme path in the archive.
* @param resourceProvider the custom provider to retrieve resources internally referenced by "src" attribute (e.g. images, icons).
* @param menuCallback the interface callback to create a settings menu on the fly.
* @throws ThemeException if an error occurs while reading the render theme XML.
*/
public ZipRenderTheme(String xmlTheme, XmlThemeResourceProvider resourceProvider, XmlRenderThemeMenuCallback menuCallback) throws ThemeException {
mXmlTheme = xmlTheme;
mResourceProvider = resourceProvider;
mMenuCallback = menuCallback;
mRelativePathPrefix = xmlTheme.substring(0, xmlTheme.lastIndexOf("/") + 1);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (!(obj instanceof ZipRenderTheme)) {
return false;
}
ZipRenderTheme other = (ZipRenderTheme) obj;
if (getRenderThemeAsStream() != other.getRenderThemeAsStream()) {
return false;
}
if (!Utils.equals(mRelativePathPrefix, other.mRelativePathPrefix)) {
return false;
}
return true;
}
@Override
public XmlRenderThemeMenuCallback getMenuCallback() {
return mMenuCallback;
}
@Override
public String getRelativePathPrefix() {
return mRelativePathPrefix;
}
@Override
public InputStream getRenderThemeAsStream() throws ThemeException {
try {
return mResourceProvider.createInputStream(mRelativePathPrefix, mXmlTheme.substring(mXmlTheme.lastIndexOf("/") + 1));
} catch (IOException e) {
throw new ThemeException(e.getMessage());
}
}
@Override
public XmlThemeResourceProvider getResourceProvider() {
return mResourceProvider;
}
@Override
public boolean isMapsforgeTheme() {
return mMapsforgeTheme;
}
@Override
public void setMapsforgeTheme(boolean mapsforgeTheme) {
mMapsforgeTheme = mapsforgeTheme;
}
@Override
public void setMenuCallback(XmlRenderThemeMenuCallback menuCallback) {
mMenuCallback = menuCallback;
}
@Override
public void setResourceProvider(XmlThemeResourceProvider resourceProvider) {
mResourceProvider = resourceProvider;
}
}

View File

@@ -0,0 +1,167 @@
/*
* Copyright 2021 eddiemuc
* Copyright 2021 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.theme;
import org.oscim.backend.CanvasAdapter;
import org.oscim.utils.IOUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* Resource provider reading resource files out of a zip input stream.
* <p>
* Resources are cached.
*/
public class ZipXmlThemeResourceProvider implements XmlThemeResourceProvider {
private final Map<String, byte[]> files = new HashMap<>();
private final List<String> xmlThemes = new ArrayList<>();
/**
* @param zipInputStream zip stream to read resources from
* @throws IOException if a problem occurs reading the stream
*/
public ZipXmlThemeResourceProvider(ZipInputStream zipInputStream) throws IOException {
this(zipInputStream, Integer.MAX_VALUE);
}
/**
* @param zipInputStream zip stream to read resources from
* @param maxResourceSizeToCache only resources in the zip stream with a maximum size of this parameter (in bytes) are cached and provided
* @throws IOException if a problem occurs reading the stream
*/
public ZipXmlThemeResourceProvider(ZipInputStream zipInputStream, int maxResourceSizeToCache) throws IOException {
if (zipInputStream == null) {
return;
}
try {
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
if (zipEntry.isDirectory() || zipEntry.getSize() > maxResourceSizeToCache) {
continue;
}
byte[] entry = streamToBytes(zipInputStream, (int) zipEntry.getSize());
String fileName = zipEntryName(zipEntry.getName());
files.put(fileName, entry);
if (isXmlTheme(fileName)) {
xmlThemes.add(fileName);
}
}
} finally {
IOUtils.closeQuietly(zipInputStream);
}
}
@Override
public InputStream createInputStream(String relativePath, String source) {
String sourceKey = source;
if (sourceKey.startsWith(CanvasAdapter.PREFIX_FILE)) {
sourceKey = sourceKey.substring(CanvasAdapter.PREFIX_FILE.length());
}
if (sourceKey.startsWith("/")) {
sourceKey = sourceKey.substring(1);
}
if (relativePath != null) {
if (relativePath.startsWith("/")) {
relativePath = relativePath.substring(1);
}
if (relativePath.endsWith("/")) {
relativePath = relativePath.substring(0, relativePath.length() - 1);
}
sourceKey = relativePath.isEmpty() ? sourceKey : relativePath + "/" + sourceKey;
}
if (files.containsKey(sourceKey)) {
return new ByteArrayInputStream(files.get(sourceKey));
}
return null;
}
/**
* @return the number of files in the archive.
*/
public int getCount() {
return files.size();
}
/**
* @return the XML theme paths in the archive.
*/
public List<String> getXmlThemes() {
return xmlThemes;
}
private static boolean isXmlTheme(String fileName) {
return fileName.toLowerCase(Locale.ROOT).endsWith(".xml");
}
/**
* Scans a given zip stream for contained xml themes without actually reading and storing its content in memory.
* <p>
* This method is useful to find out which xml themes are available across multiple zip files
* without actually have to read them all into memory.
*
* @param zipInputStream zip stream to read resources from
* @return the XML theme paths in the archive
* @throws IOException if a problem occurs reading the stream
*/
public static List<String> scanXmlThemes(ZipInputStream zipInputStream) throws IOException {
if (zipInputStream == null) {
return Collections.emptyList();
}
List<String> xmlThemes = new ArrayList<>();
try {
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
if (zipEntry.isDirectory()) {
continue;
}
String fileName = zipEntryName(zipEntry.getName());
if (isXmlTheme(fileName)) {
xmlThemes.add(fileName);
}
}
} finally {
IOUtils.closeQuietly(zipInputStream);
}
return xmlThemes;
}
private static byte[] streamToBytes(InputStream in, int size) throws IOException {
byte[] bytes = new byte[size];
int count, offset = 0;
while ((count = in.read(bytes, offset, size)) > 0) {
size -= count;
offset += count;
}
return bytes;
}
private static String zipEntryName(String name) {
if (name.startsWith("/")) {
return name.substring(1);
}
return name;
}
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2018 devemux86
* Copyright 2016-2021 devemux86
* Copyright 2017 Andrey Novikov
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
@@ -204,11 +204,11 @@ public abstract class TileSource {
private final boolean success;
/**
* @param errorMessage a textual message describing the error, must not be null.
* @param errorMessage a textual message describing the error.
*/
public OpenResult(String errorMessage) {
if (errorMessage == null) {
throw new IllegalArgumentException("error message must not be null");
errorMessage = "error";
}
this.success = false;

View File

@@ -1,5 +1,6 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2017-2020 devemux86
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -20,7 +21,8 @@ import org.oscim.tiling.source.mapfile.header.SubFileParameter;
import org.oscim.utils.LRUCache;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Collections;
import java.util.Map;
import java.util.logging.Level;
@@ -44,15 +46,15 @@ class IndexCache {
* SubFileParameter.BYTES_PER_INDEX_ENTRY;
private final Map<IndexCacheEntryKey, byte[]> map;
private final RandomAccessFile randomAccessFile;
private final FileChannel fileChannel;
/**
* @param randomAccessFile the map file from which the index should be read and cached.
* @param capacity the maximum number of entries in the cache.
* @param inputChannel the map file from which the index should be read and cached.
* @param capacity the maximum number of entries in the cache.
* @throws IllegalArgumentException if the capacity is negative.
*/
IndexCache(RandomAccessFile randomAccessFile, int capacity) {
this.randomAccessFile = randomAccessFile;
IndexCache(FileChannel inputChannel, int capacity) {
this.fileChannel = inputChannel;
this.map = Collections.synchronizedMap(new LRUCache<IndexCacheEntryKey, byte[]>(capacity));
}
@@ -97,11 +99,14 @@ class IndexCache {
int remainingIndexSize = (int) (subFileParameter.indexEndAddress - indexBlockPosition);
int indexBlockSize = Math.min(SIZE_OF_INDEX_BLOCK, remainingIndexSize);
indexBlock = new byte[indexBlockSize];
ByteBuffer indexBlockWrapper = ByteBuffer.wrap(indexBlock, 0, indexBlockSize);
this.randomAccessFile.seek(indexBlockPosition);
if (this.randomAccessFile.read(indexBlock, 0, indexBlockSize) != indexBlockSize) {
LOG.warning("reading the current index block has failed");
return -1;
synchronized (this.fileChannel) {
this.fileChannel.position(indexBlockPosition);
if (this.fileChannel.read(indexBlockWrapper) != indexBlockSize) {
LOG.warning("reading the current index block has failed");
return -1;
}
}
// put the index block in the map

View File

@@ -2,7 +2,7 @@
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2013, 2014 Hannes Janetzek
* Copyright 2014-2015 Ludwig M Brinckmann
* Copyright 2016-2019 devemux86
* Copyright 2016-2020 devemux86
* Copyright 2016 Andrey Novikov
* Copyright 2017-2018 Gustl22
* Copyright 2018 Bezzu
@@ -38,8 +38,9 @@ import org.oscim.utils.geom.TileSeparator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -202,8 +203,7 @@ public class MapDatabase implements ITileDataSource {
private long mFileSize;
private boolean mDebugFile;
private RandomAccessFile mInputFile;
private ReadBuffer mReadBuffer;
private FileChannel mInputChannel;
private String mSignatureBlock;
private String mSignaturePoi;
private String mSignatureWay;
@@ -227,11 +227,15 @@ public class MapDatabase implements ITileDataSource {
public MapDatabase(MapFileTileSource tileSource) throws IOException {
mTileSource = tileSource;
try {
/* open the file in read only mode */
mInputFile = new RandomAccessFile(tileSource.mapFile, "r");
mFileSize = mInputFile.length();
mReadBuffer = new ReadBuffer(mInputFile);
// false positive: stream gets closed when the channel is closed
// see e.g. http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4796385
if (tileSource.mapFileInputStream != null)
mInputChannel = tileSource.mapFileInputStream.getChannel();
else {
FileInputStream fis = new FileInputStream(tileSource.mapFile);
mInputChannel = fis.getChannel();
}
mFileSize = mInputChannel.size();
} catch (IOException e) {
log.error(e.getMessage());
/* make sure that the file is closed */
@@ -314,12 +318,10 @@ public class MapDatabase implements ITileDataSource {
@Override
public void dispose() {
mReadBuffer = null;
if (mInputFile != null) {
if (mInputChannel != null) {
try {
mInputFile.close();
mInputFile = null;
mInputChannel.close();
mInputChannel = null;
} catch (IOException e) {
log.error(e.getMessage());
}
@@ -351,13 +353,13 @@ public class MapDatabase implements ITileDataSource {
private void processBlock(QueryParameters queryParameters,
SubFileParameter subFileParameter, ITileDataSink mapDataSink,
BoundingBox boundingBox, Selector selector,
MapReadResult mapReadResult) {
MapReadResult mapReadResult, ReadBuffer readBuffer) {
if (!processBlockSignature()) {
if (!processBlockSignature(readBuffer)) {
return;
}
int[][] zoomTable = readZoomTable(subFileParameter);
int[][] zoomTable = readZoomTable(subFileParameter, readBuffer);
if (zoomTable == null) {
return;
}
@@ -366,7 +368,7 @@ public class MapDatabase implements ITileDataSource {
int waysOnQueryZoomLevel = zoomTable[zoomTableRow][1];
/* get the relative offset to the first stored way in the block */
int firstWayOffset = mReadBuffer.readUnsignedInt();
int firstWayOffset = readBuffer.readUnsignedInt();
if (firstWayOffset < 0) {
log.warn(INVALID_FIRST_WAY_OFFSET + firstWayOffset);
if (mDebugFile) {
@@ -376,8 +378,8 @@ public class MapDatabase implements ITileDataSource {
}
/* add the current buffer position to the relative first way offset */
firstWayOffset += mReadBuffer.getBufferPosition();
if (firstWayOffset > mReadBuffer.getBufferSize()) {
firstWayOffset += readBuffer.getBufferPosition();
if (firstWayOffset > readBuffer.getBufferSize()) {
log.warn(INVALID_FIRST_WAY_OFFSET + firstWayOffset);
if (mDebugFile) {
log.warn(DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
@@ -391,13 +393,13 @@ public class MapDatabase implements ITileDataSource {
if (mapReadResult != null)
pois = new ArrayList<>();
if (!processPOIs(mapDataSink, poisOnQueryZoomLevel, boundingBox, filterRequired, pois)) {
if (!processPOIs(mapDataSink, poisOnQueryZoomLevel, boundingBox, filterRequired, pois, readBuffer)) {
return;
}
/* finished reading POIs, check if the current buffer position is valid */
if (mReadBuffer.getBufferPosition() > firstWayOffset) {
log.warn("invalid buffer position: " + mReadBuffer.getBufferPosition());
if (readBuffer.getBufferPosition() > firstWayOffset) {
log.warn("invalid buffer position: " + readBuffer.getBufferPosition());
if (mDebugFile) {
log.warn(DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
}
@@ -405,13 +407,13 @@ public class MapDatabase implements ITileDataSource {
}
/* move the pointer to the first way */
mReadBuffer.setBufferPosition(firstWayOffset);
readBuffer.setBufferPosition(firstWayOffset);
List<Way> ways = null;
if (mapReadResult != null && Selector.POIS != selector)
ways = new ArrayList<>();
if (!processWays(queryParameters, mapDataSink, waysOnQueryZoomLevel, boundingBox, filterRequired, selector, ways)) {
if (!processWays(queryParameters, mapDataSink, waysOnQueryZoomLevel, boundingBox, filterRequired, selector, ways, readBuffer)) {
return;
}
@@ -576,10 +578,9 @@ public class MapDatabase implements ITileDataSource {
}
/* seek to the current block in the map file */
mInputFile.seek(subFileParameter.startAddress + blockPointer);
/* read the current block into the buffer */
if (!mReadBuffer.readFromFile(blockSize)) {
ReadBuffer readBuffer = new ReadBuffer(mInputChannel);
if (!readBuffer.readFromFile(subFileParameter.startAddress + blockPointer, blockSize)) {
/* skip the current block */
log.warn("reading current block has failed: " + blockSize);
return;
@@ -596,7 +597,7 @@ public class MapDatabase implements ITileDataSource {
mTileLatitude = (int) (tileLatitudeDeg * 1E6);
mTileLongitude = (int) (tileLongitudeDeg * 1E6);
processBlock(queryParams, subFileParameter, mapDataSink, boundingBox, selector, mapReadResult);
processBlock(queryParams, subFileParameter, mapDataSink, boundingBox, selector, mapReadResult, readBuffer);
}
}
}
@@ -607,10 +608,10 @@ public class MapDatabase implements ITileDataSource {
* @return true if the block signature could be processed successfully,
* false otherwise.
*/
private boolean processBlockSignature() {
private boolean processBlockSignature(ReadBuffer readBuffer) {
if (mDebugFile) {
/* get and check the block signature */
mSignatureBlock = mReadBuffer.readUTF8EncodedString(SIGNATURE_LENGTH_BLOCK);
mSignatureBlock = readBuffer.readUTF8EncodedString(SIGNATURE_LENGTH_BLOCK);
if (!mSignatureBlock.startsWith("###TileStart")) {
log.warn("invalid block signature: " + mSignatureBlock);
return false;
@@ -628,7 +629,7 @@ public class MapDatabase implements ITileDataSource {
* otherwise.
*/
private boolean processPOIs(ITileDataSink mapDataSink, int numberOfPois, BoundingBox boundingBox,
boolean filterRequired, List<PointOfInterest> pois) {
boolean filterRequired, List<PointOfInterest> pois, ReadBuffer readBuffer) {
Tag[] poiTags = mTileSource.fileInfo.poiTags;
MapElement e = mElem;
@@ -638,7 +639,7 @@ public class MapDatabase implements ITileDataSource {
if (mDebugFile) {
/* get and check the POI signature */
mSignaturePoi = mReadBuffer.readUTF8EncodedString(SIGNATURE_LENGTH_POI);
mSignaturePoi = readBuffer.readUTF8EncodedString(SIGNATURE_LENGTH_POI);
if (!mSignaturePoi.startsWith("***POIStart")) {
log.warn("invalid POI signature: " + mSignaturePoi);
log.warn(DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
@@ -647,12 +648,12 @@ public class MapDatabase implements ITileDataSource {
}
/* get the POI latitude offset (VBE-S) */
int latitude = mTileLatitude + mReadBuffer.readSignedInt();
int latitude = mTileLatitude + readBuffer.readSignedInt();
/* get the POI longitude offset (VBE-S) */
int longitude = mTileLongitude + mReadBuffer.readSignedInt();
int longitude = mTileLongitude + readBuffer.readSignedInt();
/* get the special byte which encodes multiple flags */
byte specialByte = mReadBuffer.readByte();
byte specialByte = readBuffer.readByte();
/* bit 1-4 represent the layer */
byte layer = (byte) ((specialByte & POI_LAYER_BITMASK) >>> POI_LAYER_SHIFT);
@@ -661,29 +662,29 @@ public class MapDatabase implements ITileDataSource {
byte numberOfTags = (byte) (specialByte & POI_NUMBER_OF_TAGS_BITMASK);
if (numberOfTags != 0) {
if (!mReadBuffer.readTags(e.tags, poiTags, numberOfTags))
if (!readBuffer.readTags(e.tags, poiTags, numberOfTags))
return false;
}
/* get the feature bitmask (1 byte) */
byte featureByte = mReadBuffer.readByte();
byte featureByte = readBuffer.readByte();
/* bit 1-3 enable optional features
* check if the POI has a name */
if ((featureByte & POI_FEATURE_NAME) != 0) {
String str = mTileSource.extractLocalized(mReadBuffer.readUTF8EncodedString());
String str = mTileSource.extractLocalized(readBuffer.readUTF8EncodedString());
e.tags.add(new Tag(Tag.KEY_NAME, str, false));
}
/* check if the POI has a house number */
if ((featureByte & POI_FEATURE_HOUSE_NUMBER) != 0) {
String str = mReadBuffer.readUTF8EncodedString();
String str = readBuffer.readUTF8EncodedString();
e.tags.add(new Tag(Tag.KEY_HOUSE_NUMBER, str, false));
}
/* check if the POI has an elevation */
if ((featureByte & POI_FEATURE_ELEVATION) != 0) {
String str = Integer.toString(mReadBuffer.readSignedInt());
String str = Integer.toString(readBuffer.readSignedInt());
e.tags.add(new Tag(Tag.KEY_ELE, str, false));
}
mTileProjection.projectPoint(latitude, longitude, e);
@@ -712,9 +713,9 @@ public class MapDatabase implements ITileDataSource {
return true;
}
private boolean processWayDataBlock(MapElement e, boolean doubleDeltaEncoding, boolean isLine, List<GeoPoint[]> wayCoordinates, int[] labelPosition) {
private boolean processWayDataBlock(MapElement e, boolean doubleDeltaEncoding, boolean isLine, List<GeoPoint[]> wayCoordinates, int[] labelPosition, ReadBuffer readBuffer) {
/* get and check the number of way coordinate blocks (VBE-U) */
int numBlocks = mReadBuffer.readUnsignedInt();
int numBlocks = readBuffer.readUnsignedInt();
if (numBlocks < 1 || numBlocks > Short.MAX_VALUE) {
log.warn("invalid number of way coordinate blocks: " + numBlocks);
return false;
@@ -726,7 +727,7 @@ public class MapDatabase implements ITileDataSource {
/* read the way coordinate blocks */
for (int coordinateBlock = 0; coordinateBlock < numBlocks; ++coordinateBlock) {
int numWayNodes = mReadBuffer.readUnsignedInt();
int numWayNodes = readBuffer.readUnsignedInt();
if (numWayNodes < 2 || numWayNodes > Short.MAX_VALUE) {
log.warn("invalid number of way nodes: " + numWayNodes);
@@ -744,7 +745,7 @@ public class MapDatabase implements ITileDataSource {
// label position must be set on first coordinate block
wayLengths[coordinateBlock] = decodeWayNodes(doubleDeltaEncoding, e, len, isLine,
coordinateBlock == 0 ? labelPosition : null, waySegment);
coordinateBlock == 0 ? labelPosition : null, waySegment, readBuffer);
if (wayCoordinates != null)
wayCoordinates.add(waySegment);
@@ -753,9 +754,9 @@ public class MapDatabase implements ITileDataSource {
return true;
}
private int decodeWayNodes(boolean doubleDelta, MapElement e, int length, boolean isLine, int[] labelPosition, GeoPoint[] waySegment) {
private int decodeWayNodes(boolean doubleDelta, MapElement e, int length, boolean isLine, int[] labelPosition, GeoPoint[] waySegment, ReadBuffer readBuffer) {
int[] buffer = mIntBuffer;
mReadBuffer.readSignedInt(buffer, length);
readBuffer.readSignedInt(buffer, length);
float[] outBuffer = e.ensurePointSize(e.pointNextPos + length, true);
int outPos = e.pointNextPos;
@@ -848,7 +849,7 @@ public class MapDatabase implements ITileDataSource {
*/
private boolean processWays(QueryParameters queryParameters, ITileDataSink mapDataSink,
int numberOfWays, BoundingBox boundingBox, boolean filterRequired,
Selector selector, List<Way> ways) {
Selector selector, List<Way> ways, ReadBuffer readBuffer) {
Tag[] wayTags = mTileSource.fileInfo.wayTags;
MapElement e = mElem;
@@ -860,9 +861,9 @@ public class MapDatabase implements ITileDataSource {
stringOffset = 0;
if (mTileSource.experimental) {
stringsSize = mReadBuffer.readUnsignedInt();
stringOffset = mReadBuffer.getBufferPosition();
mReadBuffer.skipBytes(stringsSize);
stringsSize = readBuffer.readUnsignedInt();
stringOffset = readBuffer.getBufferPosition();
readBuffer.skipBytes(stringsSize);
}
//setTileClipping(queryParameters);
@@ -873,7 +874,7 @@ public class MapDatabase implements ITileDataSource {
if (mDebugFile) {
// get and check the way signature
mSignatureWay = mReadBuffer.readUTF8EncodedString(SIGNATURE_LENGTH_WAY);
mSignatureWay = readBuffer.readUTF8EncodedString(SIGNATURE_LENGTH_WAY);
if (!mSignatureWay.startsWith("---WayStart")) {
log.warn("invalid way signature: " + mSignatureWay);
log.warn(DEBUG_SIGNATURE_BLOCK + mSignatureBlock);
@@ -882,7 +883,7 @@ public class MapDatabase implements ITileDataSource {
}
if (queryParameters.useTileBitmask) {
elementCounter = mReadBuffer.skipWays(queryParameters.queryTileBitmask,
elementCounter = readBuffer.skipWays(queryParameters.queryTileBitmask,
elementCounter);
if (elementCounter == 0)
@@ -891,19 +892,19 @@ public class MapDatabase implements ITileDataSource {
if (elementCounter < 0)
return false;
if (mTileSource.experimental && mReadBuffer.lastTagPosition > 0) {
int pos = mReadBuffer.getBufferPosition();
mReadBuffer.setBufferPosition(mReadBuffer.lastTagPosition);
if (mTileSource.experimental && readBuffer.lastTagPosition > 0) {
int pos = readBuffer.getBufferPosition();
readBuffer.setBufferPosition(readBuffer.lastTagPosition);
byte numberOfTags =
(byte) (mReadBuffer.readByte() & WAY_NUMBER_OF_TAGS_BITMASK);
if (!mReadBuffer.readTags(e.tags, wayTags, numberOfTags))
(byte) (readBuffer.readByte() & WAY_NUMBER_OF_TAGS_BITMASK);
if (!readBuffer.readTags(e.tags, wayTags, numberOfTags))
return false;
mReadBuffer.setBufferPosition(pos);
readBuffer.setBufferPosition(pos);
}
} else {
int wayDataSize = mReadBuffer.readUnsignedInt();
int wayDataSize = readBuffer.readUnsignedInt();
if (wayDataSize < 0) {
log.warn("invalid way data size: " + wayDataSize);
if (mDebugFile) {
@@ -914,11 +915,11 @@ public class MapDatabase implements ITileDataSource {
}
/* ignore the way tile bitmask (2 bytes) */
mReadBuffer.skipBytes(2);
readBuffer.skipBytes(2);
}
/* get the special byte which encodes multiple flags */
byte specialByte = mReadBuffer.readByte();
byte specialByte = readBuffer.readByte();
/* bit 1-4 represent the layer */
byte layer = (byte) ((specialByte & WAY_LAYER_BITMASK) >>> WAY_LAYER_SHIFT);
@@ -926,12 +927,12 @@ public class MapDatabase implements ITileDataSource {
byte numberOfTags = (byte) (specialByte & WAY_NUMBER_OF_TAGS_BITMASK);
if (numberOfTags != 0) {
if (!mReadBuffer.readTags(e.tags, wayTags, numberOfTags))
if (!readBuffer.readTags(e.tags, wayTags, numberOfTags))
return false;
}
/* get the feature bitmask (1 byte) */
byte featureByte = mReadBuffer.readByte();
byte featureByte = readBuffer.readByte();
/* bit 1-6 enable optional features */
boolean featureWayDoubleDeltaEncoding =
@@ -943,42 +944,42 @@ public class MapDatabase implements ITileDataSource {
if (mTileSource.experimental) {
if (hasName) {
int textPos = mReadBuffer.readUnsignedInt();
String str = mTileSource.extractLocalized(mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos));
int textPos = readBuffer.readUnsignedInt();
String str = mTileSource.extractLocalized(readBuffer.readUTF8EncodedStringAt(stringOffset + textPos));
e.tags.add(new Tag(Tag.KEY_NAME, str, false));
}
if (hasHouseNr) {
int textPos = mReadBuffer.readUnsignedInt();
String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos);
int textPos = readBuffer.readUnsignedInt();
String str = readBuffer.readUTF8EncodedStringAt(stringOffset + textPos);
e.tags.add(new Tag(Tag.KEY_HOUSE_NUMBER, str, false));
}
if (hasRef) {
int textPos = mReadBuffer.readUnsignedInt();
String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos);
int textPos = readBuffer.readUnsignedInt();
String str = readBuffer.readUTF8EncodedStringAt(stringOffset + textPos);
e.tags.add(new Tag(Tag.KEY_REF, str, false));
}
} else {
if (hasName) {
String str = mTileSource.extractLocalized(mReadBuffer.readUTF8EncodedString());
String str = mTileSource.extractLocalized(readBuffer.readUTF8EncodedString());
e.tags.add(new Tag(Tag.KEY_NAME, str, false));
}
if (hasHouseNr) {
String str = mReadBuffer.readUTF8EncodedString();
String str = readBuffer.readUTF8EncodedString();
e.tags.add(new Tag(Tag.KEY_HOUSE_NUMBER, str, false));
}
if (hasRef) {
String str = mReadBuffer.readUTF8EncodedString();
String str = readBuffer.readUTF8EncodedString();
e.tags.add(new Tag(Tag.KEY_REF, str, false));
}
}
int[] labelPosition = null;
if ((featureByte & WAY_FEATURE_LABEL_POSITION) != 0) {
labelPosition = readOptionalLabelPosition();
labelPosition = readOptionalLabelPosition(readBuffer);
}
if ((featureByte & WAY_FEATURE_DATA_BLOCKS_BYTE) != 0) {
wayDataBlocks = mReadBuffer.readUnsignedInt();
wayDataBlocks = readBuffer.readUnsignedInt();
if (wayDataBlocks < 1) {
log.warn("invalid number of way data blocks: " + wayDataBlocks);
@@ -999,7 +1000,7 @@ public class MapDatabase implements ITileDataSource {
if (ways != null)
wayNodes = new ArrayList<>();
if (!processWayDataBlock(e, featureWayDoubleDeltaEncoding, linearFeature, wayNodes, labelPosition))
if (!processWayDataBlock(e, featureWayDoubleDeltaEncoding, linearFeature, wayNodes, labelPosition, readBuffer))
return false;
/* drop invalid outer ring */
@@ -1152,14 +1153,14 @@ public class MapDatabase implements ITileDataSource {
return mapReadResult;
}
private int[] readOptionalLabelPosition() {
private int[] readOptionalLabelPosition(ReadBuffer readBuffer) {
int[] labelPosition = new int[2];
/* get the label position latitude offset (VBE-S) */
labelPosition[1] = mReadBuffer.readSignedInt();
labelPosition[1] = readBuffer.readSignedInt();
/* get the label position longitude offset (VBE-S) */
labelPosition[0] = mReadBuffer.readSignedInt();
labelPosition[0] = readBuffer.readSignedInt();
return labelPosition;
}
@@ -1187,7 +1188,7 @@ public class MapDatabase implements ITileDataSource {
return readMapData(upperLeft, lowerRight, Selector.POIS);
}
private int[][] readZoomTable(SubFileParameter subFileParameter) {
private int[][] readZoomTable(SubFileParameter subFileParameter, ReadBuffer readBuffer) {
int rows = subFileParameter.zoomLevelMax - subFileParameter.zoomLevelMin + 1;
int[][] zoomTable = new int[rows][2];
@@ -1195,8 +1196,8 @@ public class MapDatabase implements ITileDataSource {
int cumulatedNumberOfWays = 0;
for (int row = 0; row < rows; row++) {
cumulatedNumberOfPois += mReadBuffer.readUnsignedInt();
cumulatedNumberOfWays += mReadBuffer.readUnsignedInt();
cumulatedNumberOfPois += readBuffer.readUnsignedInt();
cumulatedNumberOfWays += readBuffer.readUnsignedInt();
zoomTable[row][0] = cumulatedNumberOfPois;
zoomTable[row][1] = cumulatedNumberOfWays;

View File

@@ -1,7 +1,7 @@
/*
* Copyright 2013 mapsforge.org
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2018 devemux86
* Copyright 2016-2020 devemux86
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@@ -25,13 +25,13 @@ import org.oscim.tiling.OverzoomTileDataSource;
import org.oscim.tiling.TileSource;
import org.oscim.tiling.source.mapfile.header.MapFileHeader;
import org.oscim.tiling.source.mapfile.header.MapFileInfo;
import org.oscim.utils.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
public class MapFileTileSource extends TileSource implements IMapFileTileSource {
private static final Logger log = LoggerFactory.getLogger(MapFileTileSource.class);
@@ -40,14 +40,14 @@ public class MapFileTileSource extends TileSource implements IMapFileTileSource
* Amount of cache blocks that the index cache should store.
*/
private static final int INDEX_CACHE_SIZE = 64;
private static final String READ_ONLY_MODE = "r";
MapFileHeader fileHeader;
MapFileInfo fileInfo;
IndexCache databaseIndexCache;
boolean experimental;
File mapFile;
private RandomAccessFile mInputFile;
FileInputStream mapFileInputStream;
private FileChannel inputChannel;
/**
* The preferred language when extracting labels from this tile source.
@@ -98,6 +98,10 @@ public class MapFileTileSource extends TileSource implements IMapFileTileSource
return true;
}
public void setMapFileInputStream(FileInputStream fileInputStream) {
this.mapFileInputStream = fileInputStream;
}
@Override
public void setPreferredLanguage(String preferredLanguage) {
this.preferredLanguage = preferredLanguage;
@@ -105,31 +109,38 @@ public class MapFileTileSource extends TileSource implements IMapFileTileSource
@Override
public OpenResult open() {
if (!options.containsKey("file"))
if (mapFileInputStream == null && !options.containsKey("file"))
return new OpenResult("no map file set");
try {
// make sure to close any previously opened file first
//close();
// false positive: stream gets closed when the channel is closed
// see e.g. http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4796385
File file = null;
if (mapFileInputStream != null)
inputChannel = mapFileInputStream.getChannel();
else {
// make sure to close any previously opened file first
//close();
File file = new File(options.get("file"));
file = new File(options.get("file"));
// check if the file exists and is readable
if (!file.exists()) {
return new OpenResult("file does not exist: " + file);
} else if (!file.isFile()) {
return new OpenResult("not a file: " + file);
} else if (!file.canRead()) {
return new OpenResult("cannot read file: " + file);
// check if the file exists and is readable
if (!file.exists()) {
return new OpenResult("file does not exist: " + file);
} else if (!file.isFile()) {
return new OpenResult("not a file: " + file);
} else if (!file.canRead()) {
return new OpenResult("cannot read file: " + file);
}
FileInputStream fis = new FileInputStream(file);
inputChannel = fis.getChannel();
}
// open the file in read only mode
mInputFile = new RandomAccessFile(file, READ_ONLY_MODE);
long mFileSize = mInputFile.length();
ReadBuffer mReadBuffer = new ReadBuffer(mInputFile);
long fileSize = inputChannel.size();
ReadBuffer readBuffer = new ReadBuffer(inputChannel);
fileHeader = new MapFileHeader();
OpenResult openResult = fileHeader.readHeader(mReadBuffer, mFileSize);
OpenResult openResult = fileHeader.readHeader(readBuffer, fileSize);
if (!openResult.isSuccess()) {
close();
@@ -137,10 +148,7 @@ public class MapFileTileSource extends TileSource implements IMapFileTileSource
}
fileInfo = fileHeader.getMapFileInfo();
mapFile = file;
databaseIndexCache = new IndexCache(mInputFile, INDEX_CACHE_SIZE);
// Experimental?
//experimental = fileInfo.fileVersion == 4;
databaseIndexCache = new IndexCache(inputChannel, INDEX_CACHE_SIZE);
log.debug("File version: " + fileInfo.fileVersion);
return OpenResult.SUCCESS;
@@ -164,8 +172,14 @@ public class MapFileTileSource extends TileSource implements IMapFileTileSource
@Override
public void close() {
IOUtils.closeQuietly(mInputFile);
mInputFile = null;
if (inputChannel != null) {
try {
inputChannel.close();
inputChannel = null;
} catch (IOException e) {
log.error(e.getMessage());
}
}
fileHeader = null;
fileInfo = null;
mapFile = null;

View File

@@ -1,7 +1,8 @@
/*
* Copyright 2010, 2011, 2012, 2013 mapsforge.org
* Copyright 2015-2016 devemux86
* Copyright 2015-2020 devemux86
* Copyright 2015-2016 lincomatic
* Copyright 2020 Meibes
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -19,19 +20,31 @@ package org.oscim.tiling.source.mapfile;
import org.oscim.core.MapElement;
import org.oscim.core.Tag;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
public final class OSMUtils {
private static final Set<String> areaKeys = new HashSet<>(Arrays.asList(
"building", "natural", "landuse", "amenity", "leisure", "aeroway",
"highway", "barrier",
"railway",
"area"
));
/**
* Heuristic to determine from attributes if a map element is likely to be an area.
* Precondition for this call is that the first and last node of a map element are the
* same, so that this method should only return false if it is known that the
* feature should not be an area even if the geometry is a polygon.
* <p/>
* <p>
* Determining what is an area is neigh impossible in OSM, this method inspects tag elements
* to give a likely answer. See http://wiki.openstreetmap.org/wiki/The_Future_of_Areas and
* http://wiki.openstreetmap.org/wiki/Way
* <p>
* The order in which the if-clauses are checked is determined with the help from https://taginfo.openstreetmap.org
*
* @param mapElement the map element (which is assumed to be closed and have enough nodes to be an area)
* @return true if tags indicate this is an area, otherwise false.
@@ -41,34 +54,35 @@ public final class OSMUtils {
for (int i = 0; i < mapElement.tags.size(); i++) {
Tag tag = mapElement.tags.get(i);
String key = tag.key.toLowerCase(Locale.ENGLISH);
String value = tag.value.toLowerCase(Locale.ENGLISH);
if ("area".equals(key)) {
// obvious result
if (("yes").equals(value) || ("y").equals(value) || ("true").equals(value)) {
return true;
}
if (("no").equals(value) || ("n").equals(value) || ("false").equals(value)) {
return false;
}
if (!areaKeys.contains(key)) {
continue;
}
// as specified by http://wiki.openstreetmap.org/wiki/Key:area
if ("aeroway".equals(key) || "building".equals(key) || "landuse".equals(key) || "leisure".equals(key) || "natural".equals(key) || "amenity".equals(key)) {
if ("building".equals(key) || "natural".equals(key) || "landuse".equals(key) || "amenity".equals(key) || "leisure".equals(key) || "aeroway".equals(key)) {
// as specified by http://wiki.openstreetmap.org/wiki/Key:area
return true;
}
if ("highway".equals(key) || "barrier".equals(key)) {
} else if ("highway".equals(key) || "barrier".equals(key)) {
// false unless something else overrides this.
result = false;
}
if ("railway".equals(key)) {
} else if ("railway".equals(key)) {
String value = tag.value.toLowerCase(Locale.ENGLISH);
// there is more to the railway tag then just rails, this excludes the
// most common railway lines from being detected as areas if they are closed.
// Since this method is only called if the first and last node are the same
// this should be safe
if ("rail".equals(value) || "tram".equals(value) || "subway".equals(value)
|| "monorail".equals(value) || "narrow_gauge".equals(value) || "preserved".equals(value)
|| "light_rail".equals(value) || "construction".equals(value)) {
|| "narrow_gauge".equals(value) || "light_rail".equals(value)
|| "construction".equals(value) || "preserved".equals(value)
|| "monorail".equals(value)) {
result = false;
}
} else if ("area".equals(key)) {
String value = tag.value.toLowerCase(Locale.ENGLISH);
if (("yes").equals(value) || ("y").equals(value) || ("true").equals(value)) {
return true;
}
if (("no").equals(value) || ("n").equals(value) || ("false").equals(value)) {
return false;
}
}
}
return result;

Some files were not shown because too many files have changed in this diff Show More