Rename Gradle targets Android (#2226)
This commit is contained in:
4
platform/android/MapLibreAndroid/.gitignore
vendored
Normal file
4
platform/android/MapLibreAndroid/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
dependency-graph-mapbox-libraries.png
|
||||
src/test/resources/mobile-event*
|
||||
local.properties
|
||||
|
||||
8
platform/android/MapLibreAndroid/README.md
Normal file
8
platform/android/MapLibreAndroid/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# MapLibre Native for Android
|
||||
|
||||
This is the API documentation for the Android API of [MapLibre Native](https://github.com/maplibre/maplibre-native).
|
||||
|
||||
## See Also
|
||||
|
||||
- [Getting Started Guide](https://maplibre.org/maplibre-native/docs/book/android/getting-started-guide.html)
|
||||
- [Source code Android API](https://github.com/maplibre/maplibre-native/tree/main/platform/android)
|
||||
168
platform/android/MapLibreAndroid/build.gradle
Normal file
168
platform/android/MapLibreAndroid/build.gradle
Normal file
@@ -0,0 +1,168 @@
|
||||
import org.jetbrains.dokka.gradle.DokkaTask
|
||||
|
||||
plugins {
|
||||
id 'org.jmailen.kotlinter'
|
||||
id 'org.jetbrains.dokka' version '1.7.20'
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: "com.jaredsburrows.license"
|
||||
apply plugin: 'kotlin-android'
|
||||
apply from: "${rootDir}/gradle/native-build.gradle"
|
||||
|
||||
dependencies {
|
||||
lintChecks project(":MapLibreAndroidLint")
|
||||
api dependenciesList.mapboxJavaGeoJSON
|
||||
api dependenciesList.mapboxAndroidGestures
|
||||
|
||||
implementation dependenciesList.mapboxJavaTurf
|
||||
implementation dependenciesList.supportAnnotations
|
||||
implementation dependenciesList.supportFragmentV4
|
||||
implementation dependenciesList.okhttp3
|
||||
implementation dependenciesList.timber
|
||||
implementation dependenciesList.interpolator
|
||||
|
||||
testImplementation dependenciesList.junit
|
||||
testImplementation dependenciesList.mockito
|
||||
testImplementation dependenciesList.mockk
|
||||
testImplementation dependenciesList.robolectric
|
||||
testImplementation dependenciesList.commonsIO
|
||||
testImplementation dependenciesList.assertjcore
|
||||
|
||||
androidTestImplementation dependenciesList.testRunner
|
||||
androidTestImplementation dependenciesList.testRules
|
||||
}
|
||||
|
||||
tasks.withType(DokkaTask.class) {
|
||||
moduleName.set("MapLibre Native for Android")
|
||||
|
||||
dokkaSourceSets {
|
||||
|
||||
configureEach {
|
||||
includes.from("README.md")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion androidVersions.compileSdkVersion
|
||||
buildToolsVersion androidSdkVersions.buildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion androidVersions.minSdkVersion
|
||||
targetSdkVersion androidVersions.targetSdkVersion
|
||||
buildConfigField "String", "GIT_REVISION_SHORT", String.format("\"%s\"", getGitRevision())
|
||||
buildConfigField "String", "GIT_REVISION", String.format("\"%s\"", getGitRevision(false))
|
||||
buildConfigField "String", "MAPBOX_SDK_IDENTIFIER", String.format("\"%s\"", "mapbox-maps-android")
|
||||
buildConfigField "String", "MAPBOX_SDK_VERSION", String.format("\"%s\"", project.VERSION_NAME)
|
||||
buildConfigField "String", "MAPBOX_VERSION_STRING", String.format("\"Mapbox/%s\"", project.VERSION_NAME)
|
||||
buildConfigField "String", "MAPBOX_EVENTS_USER_AGENT", String.format("\"mapbox-maps-android/%s\"", project.VERSION_NAME)
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DMLN_LEGACY_RENDERER=ON", "-DMLN_DRAWABLE_RENDERER=OFF"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions += "renderer"
|
||||
productFlavors {
|
||||
create("legacy") {
|
||||
dimension = "renderer"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DMLN_LEGACY_RENDERER=ON", "-DMLN_DRAWABLE_RENDERER=OFF"
|
||||
}
|
||||
}
|
||||
}
|
||||
create("drawable") {
|
||||
dimension = "renderer"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DMLN_LEGACY_RENDERER=OFF", "-DMLN_DRAWABLE_RENDERER=ON"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build native libraries
|
||||
List nativeTargets = ["maplibre"]
|
||||
if (project.hasProperty("mapbox.with_test")) {
|
||||
nativeTargets.add("mbgl-test")
|
||||
}
|
||||
if (project.hasProperty("mapbox.with_benchmark")) {
|
||||
nativeTargets.add("mbgl-benchmark")
|
||||
}
|
||||
nativeBuild(nativeTargets)
|
||||
|
||||
// avoid naming conflicts, force usage of prefix
|
||||
resourcePrefix 'maplibre_'
|
||||
|
||||
sourceSets {
|
||||
// limit amount of exposed library resources
|
||||
main.res.srcDirs += 'src/main/res-public'
|
||||
}
|
||||
|
||||
|
||||
testOptions {
|
||||
unitTests {
|
||||
returnDefaultValues true
|
||||
|
||||
// Roboelectric 4.0 required config
|
||||
// http://robolectric.org/migrating/#migrating-to-40
|
||||
includeAndroidResources = true
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
testCoverageEnabled false
|
||||
jniDebuggable true
|
||||
debuggable true
|
||||
}
|
||||
}
|
||||
namespace 'org.maplibre.android'
|
||||
lint {
|
||||
checkAllWarnings true
|
||||
disable 'MissingTranslation', 'TypographyQuotes', 'ObsoleteLintCustomCheck', 'MissingPermission', 'WrongThreadInterprocedural'
|
||||
warningsAsErrors false
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
licenseReport {
|
||||
generateHtmlReport = false
|
||||
generateJsonReport = true
|
||||
copyHtmlReportToAssets = false
|
||||
copyJsonReportToAssets = false
|
||||
}
|
||||
|
||||
def static getGitRevision(shortRev = true) {
|
||||
def cmd = shortRev ? "git rev-parse --short HEAD" : "git rev-parse HEAD"
|
||||
def proc = cmd.execute()
|
||||
def ref = proc.text.trim()
|
||||
return ref
|
||||
}
|
||||
|
||||
configurations {
|
||||
all*.exclude group: 'commons-logging', module: 'commons-logging'
|
||||
all*.exclude group: 'commons-collections', module: 'commons-collections'
|
||||
}
|
||||
|
||||
apply from: "${rootDir}/gradle/gradle-javadoc.gradle"
|
||||
apply from: "${rootDir}/gradle/gradle-checkstyle.gradle"
|
||||
apply from: "${rootDir}/gradle/gradle-dependencies-graph.gradle"
|
||||
apply from: "${rootDir}/gradle/gradle-update-vendor-modules.gradle"
|
||||
apply from: "${rootDir}/gradle/android-nitpick.gradle"
|
||||
apply from: "${rootDir}/gradle/gradle-publish.gradle"
|
||||
// intentionally disabled
|
||||
// apply from: "${rootDir}/gradle/jacoco-report.gradle"
|
||||
9
platform/android/MapLibreAndroid/gradle.properties
Normal file
9
platform/android/MapLibreAndroid/gradle.properties
Normal file
@@ -0,0 +1,9 @@
|
||||
VERSION_NAME=11.0.0-pre4
|
||||
|
||||
# Only build native dependencies for the current ABI
|
||||
# See https://code.google.com/p/android/issues/detail?id=221098#c20
|
||||
android.buildOnlyTargetAbi=true
|
||||
|
||||
# Roboelectric 4.0 required config for < Android Studio v3.3.0
|
||||
# http://robolectric.org/migrating/#migrating-to-40
|
||||
android.enableUnitTestBinaryResources=true
|
||||
7
platform/android/MapLibreAndroid/lint.xml
Normal file
7
platform/android/MapLibreAndroid/lint.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<lint>
|
||||
<!-- Ignore errors caused by OkHTTP -->
|
||||
<issue id="InvalidPackage" severity="ignore">
|
||||
<ignore path="*/okio-1.2.0.jar" />
|
||||
</issue>
|
||||
</lint>
|
||||
49
platform/android/MapLibreAndroid/proguard-rules.pro
vendored
Normal file
49
platform/android/MapLibreAndroid/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ../sdk/tools/proguard/proguard-android.txt,
|
||||
# contents of this file will be appended into proguard-android.txt
|
||||
-keepattributes Signature, *Annotation*, EnclosingMethod
|
||||
|
||||
# Reflection on classes from native code
|
||||
-keep class com.google.gson.JsonArray { *; }
|
||||
-keep class com.google.gson.JsonElement { *; }
|
||||
-keep class com.google.gson.JsonObject { *; }
|
||||
-keep class com.google.gson.JsonPrimitive { *; }
|
||||
-dontnote com.google.gson.**
|
||||
|
||||
# dontnote for keeps the entry point x but not the descriptor class y
|
||||
-dontnote org.maplibre.android.maps.MapLibreMap$OnFpsChangedListener
|
||||
-dontnote org.maplibre.android.style.layers.PropertyValue
|
||||
-dontnote org.maplibre.android.maps.MapLibreMap
|
||||
-dontnote org.maplibre.android.maps.MapLibreMapOptions
|
||||
-dontnote org.maplibre.android.log.LoggerDefinition
|
||||
|
||||
# config for okhttp 3.11.0, https://github.com/square/okhttp/pull/3354
|
||||
-dontwarn javax.annotation.**
|
||||
-dontnote okhttp3.internal.**
|
||||
-dontwarn org.codehaus.**
|
||||
|
||||
# config for mapbox-sdk-geojson:3.0.1
|
||||
-keep class com.mapbox.geojson.** { *; }
|
||||
-dontwarn com.google.auto.value.**
|
||||
|
||||
# config for additional notes
|
||||
-dontnote org.robolectric.Robolectric
|
||||
-dontnote libcore.io.Memory
|
||||
-dontnote com.google.protobuf.**
|
||||
-dontnote android.net.**
|
||||
-dontnote org.apache.http.**
|
||||
|
||||
# config for mapbox-sdk-services
|
||||
# while we don't include this dependency directly
|
||||
# a large amount of users combine it with our SDK
|
||||
# we aren't able to provide a proguard config in that project (jar vs aar)
|
||||
-dontwarn com.sun.xml.internal.ws.spi.db.*
|
||||
|
||||
# okhttp
|
||||
-dontwarn org.bouncycastle.jsse.BCSSLSocket
|
||||
-dontwarn org.bouncycastle.jsse.BCSSLParameters
|
||||
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
|
||||
-dontwarn org.conscrypt.*
|
||||
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
|
||||
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
|
||||
-dontwarn org.openjsse.net.ssl.OpenJSSE
|
||||
219
platform/android/MapLibreAndroid/src/cpp/CMakeLists.txt
Normal file
219
platform/android/MapLibreAndroid/src/cpp/CMakeLists.txt
Normal file
@@ -0,0 +1,219 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
add_subdirectory(../../../../../
|
||||
../../../../../${ANDROID_ABI})
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
target_compile_options(mbgl-compiler-options INTERFACE -frtti)
|
||||
|
||||
add_library(maplibre SHARED
|
||||
${PROJECT_SOURCE_DIR}/main.cpp
|
||||
${PROJECT_SOURCE_DIR}/jni_native.cpp
|
||||
${PROJECT_SOURCE_DIR}/jni_native.hpp
|
||||
${PROJECT_SOURCE_DIR}/file_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/file_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/http_file_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/collator.cpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/collator_jni.hpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/number_format.cpp
|
||||
${PROJECT_SOURCE_DIR}/i18n/number_format_jni.hpp
|
||||
${PROJECT_SOURCE_DIR}/logger.cpp
|
||||
${PROJECT_SOURCE_DIR}/logger.hpp
|
||||
${PROJECT_SOURCE_DIR}/logging_android.cpp
|
||||
${PROJECT_SOURCE_DIR}/text/local_glyph_rasterizer.cpp
|
||||
${PROJECT_SOURCE_DIR}/text/local_glyph_rasterizer_jni.hpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_backend.cpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_backend.hpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_frontend.cpp
|
||||
${PROJECT_SOURCE_DIR}/android_renderer_frontend.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/marker.cpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/marker.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/multi_point.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polygon.cpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polygon.hpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polyline.cpp
|
||||
${PROJECT_SOURCE_DIR}/annotation/polyline.hpp
|
||||
${PROJECT_SOURCE_DIR}/asset_manager.hpp
|
||||
${PROJECT_SOURCE_DIR}/asset_manager_file_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/asset_manager_file_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/connectivity_listener.cpp
|
||||
${PROJECT_SOURCE_DIR}/connectivity_listener.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/collection.cpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/collection.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/color.cpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/color.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/constant.cpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/constant.hpp
|
||||
${PROJECT_SOURCE_DIR}/conversion/conversion.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature_collection.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/feature_collection.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry_collection.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/geometry_collection.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/line_string.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/line_string.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_line_string.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_line_string.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_point.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_point.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_polygon.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/multi_polygon.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/point.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/point.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/polygon.cpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/polygon.hpp
|
||||
${PROJECT_SOURCE_DIR}/geojson/util.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_bounds.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_bounds.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_quad.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/lat_lng_quad.hpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/projected_meters.cpp
|
||||
${PROJECT_SOURCE_DIR}/geometry/projected_meters.hpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/pointf.cpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/pointf.hpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/rectf.cpp
|
||||
${PROJECT_SOURCE_DIR}/graphics/rectf.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_array.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_array.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_element.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_element.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_object.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_object.hpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_primitive.cpp
|
||||
${PROJECT_SOURCE_DIR}/gson/json_primitive.hpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.cpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.hpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.cpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.hpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.cpp
|
||||
${PROJECT_SOURCE_DIR}/java/util.hpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.cpp
|
||||
${PROJECT_SOURCE_DIR}/java_types.hpp
|
||||
${PROJECT_SOURCE_DIR}/maplibre.cpp
|
||||
${PROJECT_SOURCE_DIR}/maplibre.hpp
|
||||
${PROJECT_SOURCE_DIR}/map/camera_position.cpp
|
||||
${PROJECT_SOURCE_DIR}/map/camera_position.hpp
|
||||
${PROJECT_SOURCE_DIR}/map/image.cpp
|
||||
${PROJECT_SOURCE_DIR}/map/image.hpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer.cpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer.hpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer_runnable.cpp
|
||||
${PROJECT_SOURCE_DIR}/map_renderer_runnable.hpp
|
||||
${PROJECT_SOURCE_DIR}/native_map_view.cpp
|
||||
${PROJECT_SOURCE_DIR}/native_map_view.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_manager.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_manager.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_definition.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_definition.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_error.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_error.hpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_status.cpp
|
||||
${PROJECT_SOURCE_DIR}/offline/offline_region_status.hpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshot.cpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshot.hpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshotter.cpp
|
||||
${PROJECT_SOURCE_DIR}/snapshotter/map_snapshotter.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/android_conversion.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/filter.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/filter.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/position.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/position.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/property_expression.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/property_value.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/transition_options.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/transition_options.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/url_or_tileset.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/conversion/url_or_tileset.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted_section.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/formatted_section.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/background_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/background_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/circle_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/circle_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/custom_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/custom_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_extrusion_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_extrusion_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/fill_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/heatmap_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/heatmap_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/hillshade_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/hillshade_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer_manager.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/layer_manager.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/line_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/line_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/raster_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/raster_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/symbol_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/symbol_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/location_indicator_layer.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/layers/location_indicator_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/light.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/light.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/position.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/position.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/custom_geometry_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/custom_geometry_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/geojson_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/geojson_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/image_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/image_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_dem_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_dem_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/raster_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/unknown_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/unknown_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/vector_source.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/sources/vector_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/transition_options.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/transition_options.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/value.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/value.hpp
|
||||
${PROJECT_SOURCE_DIR}/util/default_style.cpp
|
||||
${PROJECT_SOURCE_DIR}/util/tile_server_options.cpp
|
||||
${PROJECT_SOURCE_DIR}/util/default_style.hpp
|
||||
${PROJECT_SOURCE_DIR}/util/tile_server_options.hpp)
|
||||
|
||||
target_include_directories(
|
||||
maplibre
|
||||
PRIVATE ${PROJECT_SOURCE_DIR}
|
||||
../../../../../src
|
||||
../../../src
|
||||
../../../../default/include)
|
||||
|
||||
target_compile_options(maplibre
|
||||
PRIVATE $<$<CONFIG:Release>:-Oz>
|
||||
$<$<CONFIG:Release>:-Qunused-arguments>
|
||||
$<$<CONFIG:Release>:-flto>
|
||||
$<$<CONFIG:Release>:-fvisibility=hidden>
|
||||
$<$<CONFIG:Release>:-fvisibility-inlines-hidden>)
|
||||
|
||||
target_link_libraries(maplibre
|
||||
PRIVATE $<$<CONFIG:Release>:-Oz>
|
||||
$<$<CONFIG:Release>:-Wl,--icf=all>
|
||||
$<$<CONFIG:Release>:-Wl,--gc-sections>
|
||||
$<$<CONFIG:Release>:-flto>
|
||||
$<$<CONFIG:Release>:-fuse-ld=gold>
|
||||
Mapbox::Base::jni.hpp
|
||||
mbgl-core
|
||||
mbgl-vendor-unique_resource)
|
||||
|
||||
install(TARGETS maplibre LIBRARY DESTINATION lib)
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "android_renderer_backend.hpp"
|
||||
|
||||
#include <mbgl/gfx/backend_scope.hpp>
|
||||
#include <mbgl/gl/context.hpp>
|
||||
#include <mbgl/gl/renderable_resource.hpp>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class AndroidGLRenderableResource final : public mbgl::gl::RenderableResource {
|
||||
public:
|
||||
AndroidGLRenderableResource(AndroidRendererBackend& backend_)
|
||||
: backend(backend_) {}
|
||||
|
||||
void bind() override {
|
||||
assert(gfx::BackendScope::exists());
|
||||
backend.setFramebufferBinding(0);
|
||||
backend.setViewport(0, 0, backend.getSize());
|
||||
}
|
||||
|
||||
void swap() override { backend.swap(); }
|
||||
|
||||
private:
|
||||
AndroidRendererBackend& backend;
|
||||
};
|
||||
|
||||
AndroidRendererBackend::AndroidRendererBackend()
|
||||
: gl::RendererBackend(gfx::ContextMode::Unique),
|
||||
mbgl::gfx::Renderable({64, 64}, std::make_unique<AndroidGLRenderableResource>(*this)) {}
|
||||
|
||||
AndroidRendererBackend::~AndroidRendererBackend() = default;
|
||||
|
||||
gl::ProcAddress AndroidRendererBackend::getExtensionFunctionPointer(const char* name) {
|
||||
assert(gfx::BackendScope::exists());
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::updateViewPort() {
|
||||
assert(gfx::BackendScope::exists());
|
||||
setViewport(0, 0, size);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::resizeFramebuffer(int width, int height) {
|
||||
size = {static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
|
||||
}
|
||||
|
||||
PremultipliedImage AndroidRendererBackend::readFramebuffer() {
|
||||
assert(gfx::BackendScope::exists());
|
||||
return gl::RendererBackend::readFramebuffer(size);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::updateAssumedState() {
|
||||
assumeFramebufferBinding(0);
|
||||
assumeViewport(0, 0, size);
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::markContextLost() {
|
||||
if (context) {
|
||||
getContext<gl::Context>().setCleanupOnDestruction(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::setSwapBehavior(SwapBehaviour swapBehaviour_) {
|
||||
swapBehaviour = swapBehaviour_;
|
||||
}
|
||||
|
||||
void AndroidRendererBackend::swap() {
|
||||
if (swapBehaviour == SwapBehaviour::Flush) {
|
||||
static_cast<gl::Context&>(getContext()).finish();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/renderable.hpp>
|
||||
#include <mbgl/gl/renderer_backend.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class AndroidRendererBackend : public gl::RendererBackend, public mbgl::gfx::Renderable {
|
||||
public:
|
||||
AndroidRendererBackend();
|
||||
~AndroidRendererBackend() override;
|
||||
|
||||
void updateViewPort();
|
||||
|
||||
// Ensures the current context is not cleaned up when destroyed
|
||||
void markContextLost();
|
||||
|
||||
void resizeFramebuffer(int width, int height);
|
||||
PremultipliedImage readFramebuffer();
|
||||
|
||||
void setSwapBehavior(SwapBehaviour swapBehaviour);
|
||||
void swap();
|
||||
|
||||
private:
|
||||
SwapBehaviour swapBehaviour = SwapBehaviour::NoFlush;
|
||||
|
||||
// mbgl::gfx::RendererBackend implementation
|
||||
public:
|
||||
mbgl::gfx::Renderable& getDefaultRenderable() override { return *this; }
|
||||
|
||||
protected:
|
||||
void activate() override {
|
||||
// no-op
|
||||
}
|
||||
void deactivate() override {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// mbgl::gl::RendererBackend implementation
|
||||
protected:
|
||||
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
|
||||
void updateAssumedState() override;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,137 @@
|
||||
#include "android_renderer_frontend.hpp"
|
||||
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/renderer/renderer.hpp>
|
||||
#include <mbgl/renderer/renderer_observer.hpp>
|
||||
#include <mbgl/util/async_task.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
|
||||
#include "android_renderer_backend.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
// Forwards RendererObserver signals to the given
|
||||
// Delegate RendererObserver on the given RunLoop
|
||||
class ForwardingRendererObserver : public RendererObserver {
|
||||
public:
|
||||
ForwardingRendererObserver(util::RunLoop& mapRunLoop, RendererObserver& delegate_)
|
||||
: mailbox(std::make_shared<Mailbox>(mapRunLoop)),
|
||||
delegate(delegate_, mailbox) {}
|
||||
|
||||
~ForwardingRendererObserver() { mailbox->close(); }
|
||||
|
||||
void onInvalidate() override { delegate.invoke(&RendererObserver::onInvalidate); }
|
||||
|
||||
void onResourceError(std::exception_ptr err) override { delegate.invoke(&RendererObserver::onResourceError, err); }
|
||||
|
||||
void onWillStartRenderingMap() override { delegate.invoke(&RendererObserver::onWillStartRenderingMap); }
|
||||
|
||||
void onWillStartRenderingFrame() override { delegate.invoke(&RendererObserver::onWillStartRenderingFrame); }
|
||||
|
||||
void onDidFinishRenderingFrame(RenderMode mode,
|
||||
bool repaintNeeded,
|
||||
bool placementChanged,
|
||||
double frameEncodingTime,
|
||||
double frameRenderingTime) override {
|
||||
void (RendererObserver::*f)(
|
||||
RenderMode, bool, bool, double, double) = &RendererObserver::onDidFinishRenderingFrame;
|
||||
delegate.invoke(f, mode, repaintNeeded, placementChanged, frameEncodingTime, frameRenderingTime);
|
||||
}
|
||||
|
||||
void onDidFinishRenderingMap() override { delegate.invoke(&RendererObserver::onDidFinishRenderingMap); }
|
||||
|
||||
void onStyleImageMissing(const std::string& id, const StyleImageMissingCallback& done) override {
|
||||
delegate.invoke(&RendererObserver::onStyleImageMissing, id, done);
|
||||
}
|
||||
|
||||
void onRemoveUnusedStyleImages(const std::vector<std::string>& ids) override {
|
||||
delegate.invoke(&RendererObserver::onRemoveUnusedStyleImages, ids);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Mailbox> mailbox;
|
||||
ActorRef<RendererObserver> delegate;
|
||||
};
|
||||
|
||||
AndroidRendererFrontend::AndroidRendererFrontend(MapRenderer& mapRenderer_)
|
||||
: mapRenderer(mapRenderer_),
|
||||
mapRunLoop(util::RunLoop::Get()),
|
||||
updateAsyncTask(std::make_unique<util::AsyncTask>([this]() {
|
||||
mapRenderer.update(std::move(updateParams));
|
||||
mapRenderer.requestRender();
|
||||
})) {}
|
||||
|
||||
AndroidRendererFrontend::~AndroidRendererFrontend() = default;
|
||||
|
||||
void AndroidRendererFrontend::reset() {
|
||||
mapRenderer.reset();
|
||||
}
|
||||
|
||||
void AndroidRendererFrontend::setObserver(RendererObserver& observer) {
|
||||
assert(util::RunLoop::Get());
|
||||
// Don't call the Renderer directly, but use MapRenderer#setObserver to make sure
|
||||
// the Renderer may be re-initialised without losing the RendererObserver reference.
|
||||
mapRenderer.setObserver(std::make_unique<ForwardingRendererObserver>(*mapRunLoop, observer));
|
||||
}
|
||||
|
||||
void AndroidRendererFrontend::update(std::shared_ptr<UpdateParameters> params) {
|
||||
updateParams = std::move(params);
|
||||
updateAsyncTask->send();
|
||||
}
|
||||
|
||||
void AndroidRendererFrontend::reduceMemoryUse() {
|
||||
mapRenderer.actor().invoke(&Renderer::reduceMemoryUse);
|
||||
}
|
||||
|
||||
std::vector<Feature> AndroidRendererFrontend::querySourceFeatures(const std::string& sourceID,
|
||||
const SourceQueryOptions& options) const {
|
||||
// Waits for the result from the orchestration thread and returns
|
||||
return mapRenderer.actor().ask(&Renderer::querySourceFeatures, sourceID, options).get();
|
||||
}
|
||||
|
||||
std::vector<Feature> AndroidRendererFrontend::queryRenderedFeatures(const ScreenBox& box,
|
||||
const RenderedQueryOptions& options) const {
|
||||
// Select the right overloaded method
|
||||
std::vector<Feature> (Renderer::*fn)(const ScreenBox&, const RenderedQueryOptions&)
|
||||
const = &Renderer::queryRenderedFeatures;
|
||||
|
||||
// Waits for the result from the orchestration thread and returns
|
||||
return mapRenderer.actor().ask(fn, box, options).get();
|
||||
}
|
||||
|
||||
std::vector<Feature> AndroidRendererFrontend::queryRenderedFeatures(const ScreenCoordinate& point,
|
||||
const RenderedQueryOptions& options) const {
|
||||
// Select the right overloaded method
|
||||
std::vector<Feature> (Renderer::*fn)(const ScreenCoordinate&, const RenderedQueryOptions&)
|
||||
const = &Renderer::queryRenderedFeatures;
|
||||
|
||||
// Waits for the result from the orchestration thread and returns
|
||||
return mapRenderer.actor().ask(fn, point, options).get();
|
||||
}
|
||||
|
||||
AnnotationIDs AndroidRendererFrontend::queryPointAnnotations(const ScreenBox& box) const {
|
||||
// Waits for the result from the orchestration thread and returns
|
||||
return mapRenderer.actor().ask(&Renderer::queryPointAnnotations, box).get();
|
||||
}
|
||||
|
||||
AnnotationIDs AndroidRendererFrontend::queryShapeAnnotations(const ScreenBox& box) const {
|
||||
// Waits for the result from the orchestration thread and returns
|
||||
return mapRenderer.actor().ask(&Renderer::queryShapeAnnotations, box).get();
|
||||
}
|
||||
|
||||
FeatureExtensionValue AndroidRendererFrontend::queryFeatureExtensions(
|
||||
const std::string& sourceID,
|
||||
const Feature& feature,
|
||||
const std::string& extension,
|
||||
const std::string& extensionField,
|
||||
const std::optional<std::map<std::string, mbgl::Value>>& args) const {
|
||||
return mapRenderer.actor()
|
||||
.ask(&Renderer::queryFeatureExtensions, sourceID, feature, extension, extensionField, args)
|
||||
.get();
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/actor/actor.hpp>
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
#include <mbgl/renderer/renderer_frontend.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
|
||||
#include "map_renderer.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class RenderedQueryOptions;
|
||||
class SourceQueryOptions;
|
||||
|
||||
namespace util {
|
||||
|
||||
class AsyncTask;
|
||||
|
||||
} // namespace util
|
||||
|
||||
namespace android {
|
||||
|
||||
class AndroidRendererFrontend : public RendererFrontend {
|
||||
public:
|
||||
AndroidRendererFrontend(MapRenderer&);
|
||||
~AndroidRendererFrontend() override;
|
||||
|
||||
void reset() override;
|
||||
void setObserver(RendererObserver&) override;
|
||||
|
||||
void update(std::shared_ptr<UpdateParameters>) override;
|
||||
|
||||
// Feature querying
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const RenderedQueryOptions&) const;
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const RenderedQueryOptions&) const;
|
||||
std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions&) const;
|
||||
AnnotationIDs queryPointAnnotations(const ScreenBox& box) const;
|
||||
AnnotationIDs queryShapeAnnotations(const ScreenBox& box) const;
|
||||
|
||||
// Feature extension query
|
||||
FeatureExtensionValue queryFeatureExtensions(const std::string& sourceID,
|
||||
const Feature& feature,
|
||||
const std::string& extension,
|
||||
const std::string& extensionField,
|
||||
const std::optional<std::map<std::string, mbgl::Value>>& args) const;
|
||||
|
||||
// Memory
|
||||
void reduceMemoryUse();
|
||||
|
||||
private:
|
||||
MapRenderer& mapRenderer;
|
||||
util::RunLoop* mapRunLoop;
|
||||
std::unique_ptr<util::AsyncTask> updateAsyncTask;
|
||||
std::shared_ptr<UpdateParameters> updateParams;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "marker.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
mbgl::Point<double> Marker::getPosition(jni::JNIEnv& env, const jni::Object<Marker>& marker) {
|
||||
static auto& javaClass = jni::Class<Marker>::Singleton(env);
|
||||
static auto positionField = javaClass.GetField<jni::Object<LatLng>>(env, "position");
|
||||
return LatLng::getGeometry(env, marker.Get(env, positionField));
|
||||
}
|
||||
|
||||
std::string Marker::getIconId(jni::JNIEnv& env, const jni::Object<Marker>& marker) {
|
||||
static auto& javaClass = jni::Class<Marker>::Singleton(env);
|
||||
static auto iconIdField = javaClass.GetField<jni::String>(env, "iconId");
|
||||
return jni::Make<std::string>(env, marker.Get(env, iconIdField));
|
||||
}
|
||||
|
||||
void Marker::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Marker>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../geometry/lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Marker : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/annotations/Marker"; };
|
||||
|
||||
static mbgl::Point<double> getPosition(jni::JNIEnv&, const jni::Object<Marker>&);
|
||||
|
||||
static std::string getIconId(jni::JNIEnv&, const jni::Object<Marker>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "../geometry/lat_lng.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class MultiPoint : protected mbgl::util::noncopyable {
|
||||
protected:
|
||||
template <class Geometry>
|
||||
static Geometry toGeometry(JNIEnv& env, const jni::Object<java::util::List>& pointsList) {
|
||||
auto jarray = java::util::List::toArray<LatLng>(env, pointsList);
|
||||
|
||||
std::size_t size = jarray.Length(env);
|
||||
|
||||
Geometry geometry;
|
||||
geometry.reserve(size);
|
||||
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
geometry.push_back(LatLng::getGeometry(env, jarray.Get(env, i)));
|
||||
}
|
||||
|
||||
return geometry;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "polygon.hpp"
|
||||
|
||||
#include "../conversion/color.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, const jni::Object<Polygon>& polygon) {
|
||||
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
|
||||
static auto points = javaClass.GetField<jni::Object<java::util::List>>(env, "points");
|
||||
static auto holes = javaClass.GetField<jni::Object<java::util::List>>(env, "holes");
|
||||
static auto alpha = javaClass.GetField<float>(env, "alpha");
|
||||
static auto fillColor = javaClass.GetField<int>(env, "fillColor");
|
||||
static auto strokeColor = javaClass.GetField<int>(env, "strokeColor");
|
||||
|
||||
mbgl::Polygon<double> geometry{MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, polygon.Get(env, points))};
|
||||
|
||||
auto jHoleListsArray = java::util::List::toArray<java::util::List>(env, polygon.Get(env, holes));
|
||||
|
||||
std::size_t jHoleListsSize = jHoleListsArray.Length(env);
|
||||
for (std::size_t i = 0; i < jHoleListsSize; i++) {
|
||||
geometry.push_back(MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, jHoleListsArray.Get(env, i)));
|
||||
}
|
||||
|
||||
mbgl::FillAnnotation annotation{geometry};
|
||||
annotation.opacity = polygon.Get(env, alpha);
|
||||
annotation.color = *conversion::convert<mbgl::Color>(env, polygon.Get(env, fillColor));
|
||||
annotation.outlineColor = *conversion::convert<mbgl::Color>(env, polygon.Get(env, strokeColor));
|
||||
|
||||
return annotation;
|
||||
}
|
||||
|
||||
void Polygon::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Polygon>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
|
||||
#include "multi_point.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Polygon : private MultiPoint {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/annotations/Polygon"; };
|
||||
|
||||
static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, const jni::Object<Polygon>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "polyline.hpp"
|
||||
|
||||
#include "../conversion/color.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, const jni::Object<Polyline>& polyline) {
|
||||
static auto& javaClass = jni::Class<Polyline>::Singleton(env);
|
||||
static auto points = javaClass.GetField<jni::Object<java::util::List>>(env, "points");
|
||||
static auto alpha = javaClass.GetField<float>(env, "alpha");
|
||||
static auto color = javaClass.GetField<int>(env, "color");
|
||||
static auto width = javaClass.GetField<float>(env, "width");
|
||||
|
||||
mbgl::LineAnnotation annotation{MultiPoint::toGeometry<mbgl::LineString<double>>(env, polyline.Get(env, points))};
|
||||
|
||||
annotation.opacity = polyline.Get(env, alpha);
|
||||
annotation.color = *conversion::convert<mbgl::Color>(env, polyline.Get(env, color));
|
||||
annotation.width = polyline.Get(env, width);
|
||||
|
||||
return annotation;
|
||||
}
|
||||
|
||||
void Polyline::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Polyline>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
|
||||
#include "multi_point.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Polyline : private MultiPoint {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/annotations/Polyline"; };
|
||||
|
||||
static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, const jni::Object<Polyline>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
12
platform/android/MapLibreAndroid/src/cpp/asset_manager.hpp
Normal file
12
platform/android/MapLibreAndroid/src/cpp/asset_manager.hpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class AssetManager {
|
||||
public:
|
||||
static constexpr auto Name() { return "android/content/res/AssetManager"; };
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,101 @@
|
||||
#include "asset_manager_file_source.hpp"
|
||||
|
||||
#include <mbgl/platform/settings.hpp>
|
||||
#include <mbgl/storage/file_source_request.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/resource_options.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
#include <mbgl/util/url.hpp>
|
||||
#include <mbgl/util/util.hpp>
|
||||
|
||||
#include <android/asset_manager.h>
|
||||
#include <android/asset_manager_jni.h>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class AssetManagerFileSource::Impl {
|
||||
public:
|
||||
Impl(ActorRef<Impl>,
|
||||
AAssetManager* assetManager_,
|
||||
const ResourceOptions resourceOptions_,
|
||||
const ClientOptions clientOptions_)
|
||||
: resourceOptions(resourceOptions_.clone()),
|
||||
clientOptions(clientOptions_.clone()),
|
||||
assetManager(assetManager_) {}
|
||||
|
||||
void request(const std::string& url, ActorRef<FileSourceRequest> req) {
|
||||
// Note: AssetManager already prepends "assets" to the filename.
|
||||
const std::string path = mbgl::util::percentDecode(url.substr(8));
|
||||
|
||||
Response response;
|
||||
|
||||
if (AAsset* asset = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_BUFFER)) {
|
||||
response.data = std::make_shared<std::string>(reinterpret_cast<const char*>(AAsset_getBuffer(asset)),
|
||||
AAsset_getLength64(asset));
|
||||
AAsset_close(asset);
|
||||
} else {
|
||||
response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound,
|
||||
"Could not read asset");
|
||||
}
|
||||
|
||||
req.invoke(&FileSourceRequest::setResponse, response);
|
||||
}
|
||||
|
||||
void setResourceOptions(ResourceOptions options) { resourceOptions = options; }
|
||||
|
||||
ResourceOptions getResourceOptions() { return resourceOptions.clone(); }
|
||||
|
||||
void setClientOptions(ClientOptions options) { clientOptions = options; }
|
||||
|
||||
ClientOptions getClientOptions() { return clientOptions.clone(); }
|
||||
|
||||
private:
|
||||
AAssetManager* assetManager;
|
||||
ResourceOptions resourceOptions;
|
||||
ClientOptions clientOptions;
|
||||
};
|
||||
|
||||
AssetManagerFileSource::AssetManagerFileSource(jni::JNIEnv& env,
|
||||
const jni::Object<android::AssetManager>& assetManager_,
|
||||
const ResourceOptions resourceOptions,
|
||||
const ClientOptions clientOptions)
|
||||
: assetManager(jni::NewGlobal(env, assetManager_)),
|
||||
impl(std::make_unique<util::Thread<Impl>>(
|
||||
util::makeThreadPrioritySetter(platform::EXPERIMENTAL_THREAD_PRIORITY_FILE),
|
||||
"AssetManagerFileSource",
|
||||
AAssetManager_fromJava(&env, jni::Unwrap(assetManager.get())),
|
||||
resourceOptions.clone(),
|
||||
clientOptions.clone())) {}
|
||||
|
||||
AssetManagerFileSource::~AssetManagerFileSource() = default;
|
||||
|
||||
std::unique_ptr<AsyncRequest> AssetManagerFileSource::request(const Resource& resource, Callback callback) {
|
||||
auto req = std::make_unique<FileSourceRequest>(std::move(callback));
|
||||
|
||||
impl->actor().invoke(&Impl::request, resource.url, req->actor());
|
||||
|
||||
return std::move(req);
|
||||
}
|
||||
|
||||
bool AssetManagerFileSource::canRequest(const Resource& resource) const {
|
||||
return 0 == resource.url.rfind(mbgl::util::ASSET_PROTOCOL, 0);
|
||||
}
|
||||
|
||||
void AssetManagerFileSource::setResourceOptions(ResourceOptions options) {
|
||||
impl->actor().invoke(&Impl::setResourceOptions, options.clone());
|
||||
}
|
||||
|
||||
ResourceOptions AssetManagerFileSource::getResourceOptions() {
|
||||
return impl->actor().ask(&Impl::getResourceOptions).get();
|
||||
}
|
||||
|
||||
void AssetManagerFileSource::setClientOptions(ClientOptions options) {
|
||||
impl->actor().invoke(&Impl::setClientOptions, options.clone());
|
||||
}
|
||||
|
||||
ClientOptions AssetManagerFileSource::getClientOptions() {
|
||||
return impl->actor().ask(&Impl::getClientOptions).get();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
#include <mbgl/storage/resource_options.hpp>
|
||||
#include <mbgl/util/client_options.hpp>
|
||||
|
||||
#include "asset_manager.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace util {
|
||||
template <typename T>
|
||||
class Thread;
|
||||
} // namespace util
|
||||
|
||||
class AssetManagerFileSource : public FileSource {
|
||||
public:
|
||||
AssetManagerFileSource(jni::JNIEnv&,
|
||||
const jni::Object<android::AssetManager>&,
|
||||
const ResourceOptions,
|
||||
const ClientOptions);
|
||||
~AssetManagerFileSource() override;
|
||||
|
||||
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
|
||||
bool canRequest(const Resource&) const override;
|
||||
|
||||
void setResourceOptions(ResourceOptions options) override;
|
||||
ResourceOptions getResourceOptions() override;
|
||||
|
||||
void setClientOptions(ClientOptions options) override;
|
||||
ClientOptions getClientOptions() override;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
jni::Global<jni::Object<android::AssetManager>> assetManager;
|
||||
std::unique_ptr<util::Thread<Impl>> impl;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "connectivity_listener.hpp"
|
||||
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* Invoked when the construction is initiated from the jvm
|
||||
*/
|
||||
ConnectivityListener::ConnectivityListener(jni::JNIEnv&) {}
|
||||
|
||||
ConnectivityListener::~ConnectivityListener() {}
|
||||
|
||||
void ConnectivityListener::onConnectivityStateChanged(jni::JNIEnv&, jni::jboolean connected) {
|
||||
NetworkStatus::Set(connected ? NetworkStatus::Status::Online : NetworkStatus::Status::Offline);
|
||||
}
|
||||
|
||||
void ConnectivityListener::registerNative(jni::JNIEnv& env) {
|
||||
// Lookup the class
|
||||
static auto& javaClass = jni::Class<ConnectivityListener>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
// Register the peer
|
||||
jni::RegisterNativePeer<ConnectivityListener>(
|
||||
env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
std::make_unique<ConnectivityListener, JNIEnv&>,
|
||||
"initialize",
|
||||
"finalize",
|
||||
METHOD(&ConnectivityListener::onConnectivityStateChanged, "nativeOnConnectivityStateChanged"));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class ConnectivityListener : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/net/NativeConnectivityListener"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
/*
|
||||
* Called when a Java object was created from the jvm side
|
||||
*/
|
||||
ConnectivityListener(jni::JNIEnv&);
|
||||
|
||||
~ConnectivityListener();
|
||||
|
||||
void onConnectivityStateChanged(jni::JNIEnv&, jni::jboolean);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "collection.hpp"
|
||||
#include "constant.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
std::vector<std::string> toVector(JNIEnv& env, const jni::Array<jni::String>& array) {
|
||||
std::size_t len = array.Length(env);
|
||||
std::vector<std::string> vector;
|
||||
vector.reserve(len);
|
||||
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
vector.push_back(jni::Make<std::string>(env, array.Get(env, i)));
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
jni::Local<jni::Array<jni::String>> toArray(JNIEnv& env, const std::vector<std::string>& vector) {
|
||||
auto result = jni::Array<jni::String>::New(env, vector.size());
|
||||
|
||||
for (std::size_t i = 0; i < vector.size(); i++) {
|
||||
result.Set(env, i, jni::Make<jni::String>(env, vector.at(i)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "conversion.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
std::vector<std::string> toVector(JNIEnv& env, const jni::Array<jni::String>& array);
|
||||
jni::Local<jni::Array<jni::String>> toArray(JNIEnv& env, const std::vector<std::string>&);
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "color.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
Result<mbgl::Color> Converter<mbgl::Color, int>::operator()(jni::JNIEnv&, const int& color) const {
|
||||
float r = (color >> 16) & 0xFF;
|
||||
float g = (color >> 8) & 0xFF;
|
||||
float b = (color) & 0xFF;
|
||||
float a = (color >> 24) & 0xFF;
|
||||
return {mbgl::Color(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f)};
|
||||
}
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "conversion.hpp"
|
||||
|
||||
#include <mbgl/util/color.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
template <>
|
||||
struct Converter<mbgl::Color, int> {
|
||||
Result<mbgl::Color> operator()(jni::JNIEnv&, const int& color) const;
|
||||
};
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,86 @@
|
||||
#include "constant.hpp"
|
||||
#include "collection.hpp"
|
||||
#include "../style/formatted.hpp"
|
||||
|
||||
#include <mbgl/util/string.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, bool>::operator()(jni::JNIEnv& env,
|
||||
const bool& value) const {
|
||||
return jni::Box(env, value ? jni::jni_true : jni::jni_false);
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, float>::operator()(jni::JNIEnv& env,
|
||||
const float& value) const {
|
||||
return jni::Box(env, value);
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, double>::operator()(jni::JNIEnv& env,
|
||||
const double& value) const {
|
||||
return jni::Box(env, value);
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::string>::operator()(
|
||||
jni::JNIEnv& env, const std::string& value) const {
|
||||
return jni::Make<jni::String>(env, value);
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, Color>::operator()(jni::JNIEnv& env,
|
||||
const Color& value) const {
|
||||
return jni::Make<jni::String>(env, value.stringify());
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, style::expression::Formatted>::operator()(
|
||||
jni::JNIEnv& env, const style::expression::Formatted& value) const {
|
||||
return Formatted::New(env, value);
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::vector<std::string>>::operator()(
|
||||
jni::JNIEnv& env, const std::vector<std::string>& value) const {
|
||||
auto result = jni::Array<jni::String>::New(env, value.size());
|
||||
|
||||
for (std::size_t i = 0; i < value.size(); i++) {
|
||||
result.Set(env, i, jni::Make<jni::String>(env, value.at(i)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::vector<float>>::operator()(
|
||||
jni::JNIEnv& env, const std::vector<float>& value) const {
|
||||
auto result = jni::Array<jni::Float>::New(env, value.size());
|
||||
|
||||
for (std::size_t i = 0; i < value.size(); i++) {
|
||||
result.Set(env, i, jni::Box(env, value.at(i)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::vector<double>>::operator()(
|
||||
jni::JNIEnv& env, const std::vector<double>& value) const {
|
||||
auto result = jni::Array<jni::Double>::New(env, value.size());
|
||||
|
||||
for (std::size_t i = 0; i < value.size(); i++) {
|
||||
result.Set(env, i, jni::Box(env, value.at(i)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, style::expression::Image>::operator()(
|
||||
jni::JNIEnv& env, const style::expression::Image& value) const {
|
||||
return jni::Make<jni::String>(env, value.id());
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, mbgl::style::Rotation>::operator()(
|
||||
jni::JNIEnv& env, const mbgl::style::Rotation& value) const {
|
||||
return jni::Box(env, value.getAngle());
|
||||
}
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
132
platform/android/MapLibreAndroid/src/cpp/conversion/constant.hpp
Normal file
132
platform/android/MapLibreAndroid/src/cpp/conversion/constant.hpp
Normal file
@@ -0,0 +1,132 @@
|
||||
#pragma once
|
||||
|
||||
#include "conversion.hpp"
|
||||
|
||||
#include <mbgl/util/color.hpp>
|
||||
#include <mbgl/util/enum.hpp>
|
||||
|
||||
#include <mbgl/style/expression/formatted.hpp>
|
||||
#include <mbgl/style/expression/image.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <mbgl/style/rotation.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, bool> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const bool& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, float> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const float& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, double> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const double& value) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* All integrals. java is limited to 64 bit signed, so...
|
||||
* TODO: use BigDecimal for > 64 / unsigned?
|
||||
*/
|
||||
template <typename T>
|
||||
struct Converter<jni::Local<jni::Object<>>, T, typename std::enable_if<std::is_integral<T>::value>::type> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const T& value) const {
|
||||
return jni::Box(env, jni::jlong(value));
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: convert integral types to primitive jni types
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::string> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::string& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, Color> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const Color& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, style::expression::Formatted> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const style::expression::Formatted& value) const;
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::array<float, N>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::array<float, N>& value) const {
|
||||
std::vector<float> v;
|
||||
for (const float& id : value) {
|
||||
v.push_back(id);
|
||||
}
|
||||
return convert<jni::Local<jni::Object<>>, std::vector<float>>(env, v);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::array<double, N>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::array<double, N>& value) const {
|
||||
std::vector<double> v;
|
||||
for (const double& id : value) {
|
||||
v.push_back(id);
|
||||
}
|
||||
return convert<jni::Local<jni::Object<>>, std::vector<double>>(env, v);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::vector<std::string>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::vector<float>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<float>& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::vector<double>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<double>& value) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Converter<jni::Local<jni::Object<>>, T, typename std::enable_if_t<std::is_enum<T>::value>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const T& value) const {
|
||||
return convert<jni::Local<jni::Object<>>, std::string>(env, Enum<T>::toString(value));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Converter<jni::Local<jni::Object<>>, std::vector<T>, typename std::enable_if_t<std::is_enum<T>::value>> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<T>& value) const {
|
||||
auto result = jni::Array<jni::String>::New(env, value.size());
|
||||
for (std::size_t i = 0; i < value.size(); ++i) {
|
||||
result.Set(env, i, jni::Make<jni::String>(env, Enum<T>::toString(value.at(i))));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, style::expression::Image> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const style::expression::Image& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, mbgl::style::Rotation> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const mbgl::style::Rotation& value) const;
|
||||
};
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/variant.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
struct Error {
|
||||
std::string message;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Result : private variant<T, Error> {
|
||||
public:
|
||||
using variant<T, Error>::variant;
|
||||
|
||||
explicit operator bool() const { return this->template is<T>(); }
|
||||
|
||||
T& operator*() {
|
||||
assert(this->template is<T>());
|
||||
return this->template get<T>();
|
||||
}
|
||||
|
||||
const T& operator*() const {
|
||||
assert(this->template is<T>());
|
||||
return this->template get<T>();
|
||||
}
|
||||
|
||||
const Error& error() const {
|
||||
assert(this->template is<Error>());
|
||||
return this->template get<Error>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class V, class Enable = void>
|
||||
struct Converter;
|
||||
|
||||
template <class T, typename V, class... Args>
|
||||
Result<T> convert(jni::JNIEnv& env, const V& value, Args&&... args) {
|
||||
return Converter<T, V>()(env, value, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
284
platform/android/MapLibreAndroid/src/cpp/file_source.cpp
Normal file
284
platform/android/MapLibreAndroid/src/cpp/file_source.cpp
Normal file
@@ -0,0 +1,284 @@
|
||||
#include "file_source.hpp"
|
||||
|
||||
#include "attach_env.hpp"
|
||||
#include "maplibre.hpp"
|
||||
|
||||
#include <mbgl/actor/actor.hpp>
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/storage/file_source_manager.hpp>
|
||||
#include <mbgl/storage/resource_options.hpp>
|
||||
#include <mbgl/storage/resource_transform.hpp>
|
||||
#include <mbgl/util/client_options.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <mbgl/storage/sqlite3.hpp>
|
||||
|
||||
#include "asset_manager_file_source.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
// FileSource //
|
||||
|
||||
FileSource::FileSource(jni::JNIEnv& _env,
|
||||
const jni::String& apiKey,
|
||||
const jni::String& _cachePath,
|
||||
const jni::Object<TileServerOptions>& _options)
|
||||
: activationCounter(std::optional<int>(1)) {
|
||||
std::string path = jni::Make<std::string>(_env, _cachePath);
|
||||
mapbox::sqlite::setTempPath(path);
|
||||
|
||||
mbgl::FileSourceManager::get()->registerFileSourceFactory(
|
||||
mbgl::FileSourceType::Asset,
|
||||
[](const mbgl::ResourceOptions& resourceOptions, const mbgl::ClientOptions& clientOptions) {
|
||||
auto env{android::AttachEnv()};
|
||||
std::unique_ptr<mbgl::FileSource> assetFileSource;
|
||||
if (android::MapLibre::hasInstance(*env)) {
|
||||
auto assetManager = android::MapLibre::getAssetManager(*env);
|
||||
assetFileSource = std::make_unique<AssetManagerFileSource>(
|
||||
*env, assetManager, resourceOptions.clone(), clientOptions.clone());
|
||||
}
|
||||
return assetFileSource;
|
||||
});
|
||||
|
||||
auto tileServerOptions = TileServerOptions::getTileServerOptions(_env, _options);
|
||||
resourceOptions.withTileServerOptions(tileServerOptions)
|
||||
.withApiKey(apiKey ? jni::Make<std::string>(_env, apiKey) : "")
|
||||
.withCachePath(path + DATABASE_FILE);
|
||||
|
||||
// Create a core file sources
|
||||
// TODO: Split Android FileSource API to smaller interfaces
|
||||
resourceLoader = mbgl::FileSourceManager::get()->getFileSource(
|
||||
mbgl::FileSourceType::ResourceLoader, resourceOptions, clientOptions);
|
||||
databaseSource = std::static_pointer_cast<mbgl::DatabaseFileSource>(std::shared_ptr<mbgl::FileSource>(
|
||||
mbgl::FileSourceManager::get()->getFileSource(mbgl::FileSourceType::Database, resourceOptions, clientOptions)));
|
||||
onlineSource = mbgl::FileSourceManager::get()->getFileSource(
|
||||
mbgl::FileSourceType::Network, resourceOptions, clientOptions);
|
||||
}
|
||||
|
||||
FileSource::~FileSource() {}
|
||||
|
||||
void FileSource::setTileServerOptions(jni::JNIEnv& _env, const jni::Object<TileServerOptions>& _options) {
|
||||
auto tileServerOptions = TileServerOptions::getTileServerOptions(_env, _options);
|
||||
resourceOptions.withTileServerOptions(tileServerOptions);
|
||||
resourceLoader->setResourceOptions(resourceOptions.clone());
|
||||
databaseSource->setResourceOptions(resourceOptions.clone());
|
||||
onlineSource->setResourceOptions(resourceOptions.clone());
|
||||
}
|
||||
|
||||
jni::Local<jni::String> FileSource::getApiKey(jni::JNIEnv& env) {
|
||||
if (auto* token = onlineSource->getProperty(mbgl::API_KEY_KEY).getString()) {
|
||||
return jni::Make<jni::String>(env, *token);
|
||||
}
|
||||
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
|
||||
return jni::Make<jni::String>(env, "");
|
||||
}
|
||||
|
||||
void FileSource::setApiKey(jni::JNIEnv& env, const jni::String& token) {
|
||||
if (onlineSource) {
|
||||
onlineSource->setProperty(mbgl::API_KEY_KEY, token ? jni::Make<std::string>(env, token) : "");
|
||||
} else {
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
void FileSource::setAPIBaseUrl(jni::JNIEnv& env, const jni::String& url) {
|
||||
if (onlineSource) {
|
||||
onlineSource->setProperty(mbgl::API_BASE_URL_KEY, jni::Make<std::string>(env, url));
|
||||
} else {
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
jni::Local<jni::String> FileSource::getAPIBaseUrl(jni::JNIEnv& env) {
|
||||
if (auto* url = onlineSource->getProperty(mbgl::API_BASE_URL_KEY).getString()) {
|
||||
return jni::Make<jni::String>(env, std::string(*url));
|
||||
}
|
||||
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
|
||||
return jni::Make<jni::String>(env, "");
|
||||
}
|
||||
|
||||
void FileSource::setResourceTransform(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource::ResourceTransformCallback>& transformCallback) {
|
||||
// Core could be built without support for network resource provider.
|
||||
if (!onlineSource) {
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Online functionality is disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (transformCallback) {
|
||||
auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, transformCallback);
|
||||
resourceTransform = std::make_unique<Actor<ResourceTransform::TransformCallback>>(
|
||||
*Scheduler::GetCurrent(),
|
||||
// Capture the ResourceTransformCallback object as a managed
|
||||
// global into the lambda. It is released automatically when
|
||||
// we're setting a new ResourceTransform in a subsequent call.
|
||||
// Note: we're converting it to shared_ptr because this lambda
|
||||
// is converted to a std::function, which requires copyability
|
||||
// of its captured variables.
|
||||
[callback = std::make_shared<decltype(global)>(std::move(global))](
|
||||
mbgl::Resource::Kind kind, const std::string& url_, ResourceTransform::FinishedCallback cb) {
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
cb(FileSource::ResourceTransformCallback::onURL(*_env, *callback, int(kind), url_));
|
||||
});
|
||||
onlineSource->setResourceTransform(
|
||||
{[actorRef = resourceTransform->self()](
|
||||
Resource::Kind kind, const std::string& url, ResourceTransform::FinishedCallback cb) {
|
||||
actorRef.invoke(&ResourceTransform::TransformCallback::operator(), kind, url, std::move(cb));
|
||||
}});
|
||||
} else {
|
||||
// Reset the callback
|
||||
resourceTransform.reset();
|
||||
onlineSource->setResourceTransform({});
|
||||
}
|
||||
}
|
||||
|
||||
void FileSource::setResourceCachePath(jni::JNIEnv& env,
|
||||
const jni::String& path,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>& _callback) {
|
||||
if (!databaseSource) {
|
||||
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Offline functionality is disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pathChangeCallback) {
|
||||
FileSource::ResourcesCachePathChangeCallback::onError(
|
||||
env, _callback, jni::Make<jni::String>(env, "Another resources cache path change is in progress"));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string newPath = jni::Make<std::string>(env, path);
|
||||
mapbox::sqlite::setTempPath(newPath);
|
||||
|
||||
auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, _callback);
|
||||
pathChangeCallback = Scheduler::GetCurrent()->bindOnce(
|
||||
[this, callback = std::make_shared<decltype(global)>(std::move(global)), newPath] {
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
FileSource::ResourcesCachePathChangeCallback::onSuccess(
|
||||
*_env, *callback, jni::Make<jni::String>(*_env, newPath));
|
||||
pathChangeCallback = {};
|
||||
});
|
||||
|
||||
databaseSource->setDatabasePath(newPath + DATABASE_FILE, pathChangeCallback);
|
||||
}
|
||||
|
||||
void FileSource::resume(jni::JNIEnv&) {
|
||||
if (!resourceLoader) {
|
||||
return;
|
||||
}
|
||||
|
||||
activationCounter.value()++;
|
||||
if (activationCounter == 1) {
|
||||
resourceLoader->resume();
|
||||
}
|
||||
}
|
||||
|
||||
void FileSource::pause(jni::JNIEnv&) {
|
||||
if (!resourceLoader) {
|
||||
return;
|
||||
}
|
||||
|
||||
activationCounter.value()--;
|
||||
if (activationCounter == 0) {
|
||||
resourceLoader->pause();
|
||||
}
|
||||
}
|
||||
|
||||
jni::jboolean FileSource::isResumed(jni::JNIEnv&) {
|
||||
return (jboolean)(activationCounter > 0);
|
||||
}
|
||||
|
||||
FileSource* FileSource::getNativePeer(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) {
|
||||
static auto& javaClass = jni::Class<FileSource>::Singleton(env);
|
||||
static auto field = javaClass.GetField<jlong>(env, "nativePtr");
|
||||
return reinterpret_cast<FileSource*>(jFileSource.Get(env, field));
|
||||
}
|
||||
|
||||
mbgl::ResourceOptions FileSource::getSharedResourceOptions(jni::JNIEnv& env,
|
||||
const jni::Object<FileSource>& jFileSource) {
|
||||
FileSource* fileSource = FileSource::getNativePeer(env, jFileSource);
|
||||
// Core could be compiled without support for any sources.
|
||||
if (fileSource) {
|
||||
return fileSource->resourceOptions.clone();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
mbgl::ClientOptions FileSource::getSharedClientOptions(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) {
|
||||
FileSource* fileSource = FileSource::getNativePeer(env, jFileSource);
|
||||
// Core could be compiled without support for any sources.
|
||||
if (fileSource) {
|
||||
return fileSource->clientOptions.clone();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// FileSource::ResourcesCachePathChangeCallback //
|
||||
|
||||
void FileSource::ResourcesCachePathChangeCallback::onSuccess(
|
||||
jni::JNIEnv& env,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>& callback,
|
||||
const jni::String& path) {
|
||||
static auto& javaClass = jni::Class<FileSource::ResourcesCachePathChangeCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void(jni::String)>(env, "onSuccess");
|
||||
|
||||
callback.Call(env, method, path);
|
||||
}
|
||||
|
||||
void FileSource::ResourcesCachePathChangeCallback::onError(
|
||||
jni::JNIEnv& env,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>& callback,
|
||||
const jni::String& message) {
|
||||
static auto& javaClass = jni::Class<FileSource::ResourcesCachePathChangeCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void(jni::String)>(env, "onError");
|
||||
|
||||
callback.Call(env, method, message);
|
||||
}
|
||||
|
||||
void FileSource::registerNative(jni::JNIEnv& env) {
|
||||
// Ensure the classes are cached. If they're requested for the
|
||||
// first time on a background thread, Android's class loader heuristics will fail.
|
||||
// https://developer.android.com/training/articles/perf-jni#faq_FindClass
|
||||
jni::Class<ResourceTransformCallback>::Singleton(env);
|
||||
jni::Class<ResourcesCachePathChangeCallback>::Singleton(env);
|
||||
|
||||
static auto& javaClass = jni::Class<FileSource>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
// Register the peer
|
||||
jni::RegisterNativePeer<FileSource>(
|
||||
env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
jni::MakePeer<FileSource, const jni::String&, const jni::String&, const jni::Object<TileServerOptions>&>,
|
||||
"initialize",
|
||||
"finalize",
|
||||
METHOD(&FileSource::setTileServerOptions, "setTileServerOptions"),
|
||||
METHOD(&FileSource::getApiKey, "getApiKey"),
|
||||
METHOD(&FileSource::setApiKey, "setApiKey"),
|
||||
METHOD(&FileSource::setAPIBaseUrl, "setApiBaseUrl"),
|
||||
METHOD(&FileSource::getAPIBaseUrl, "getApiBaseUrl"),
|
||||
METHOD(&FileSource::setResourceTransform, "setResourceTransform"),
|
||||
METHOD(&FileSource::setResourceCachePath, "setResourceCachePath"),
|
||||
METHOD(&FileSource::resume, "activate"),
|
||||
METHOD(&FileSource::pause, "deactivate"),
|
||||
METHOD(&FileSource::isResumed, "isActivated"));
|
||||
}
|
||||
|
||||
// FileSource::ResourceTransformCallback //
|
||||
|
||||
std::string FileSource::ResourceTransformCallback::onURL(
|
||||
jni::JNIEnv& env, const jni::Object<FileSource::ResourceTransformCallback>& callback, int kind, std::string url_) {
|
||||
static auto& javaClass = jni::Class<FileSource::ResourceTransformCallback>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String(jni::jint, jni::String)>(env, "onURL");
|
||||
|
||||
return jni::Make<std::string>(env, callback.Call(env, method, kind, jni::Make<jni::String>(env, url_)));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
103
platform/android/MapLibreAndroid/src/cpp/file_source.hpp
Normal file
103
platform/android/MapLibreAndroid/src/cpp/file_source.hpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/storage/database_file_source.hpp>
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/storage/resource_options.hpp>
|
||||
#include <mbgl/storage/resource_transform.hpp>
|
||||
|
||||
#include "asset_manager.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "util/tile_server_options.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template <typename T>
|
||||
class Actor;
|
||||
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* Peer class for the Android FileSource holder. Ensures that a single core
|
||||
* FileSource of a ResourceLoader type is used.
|
||||
*/
|
||||
class FileSource {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/storage/FileSource"; };
|
||||
|
||||
struct ResourceTransformCallback {
|
||||
static constexpr auto Name() {
|
||||
return "org/maplibre/android/storage/"
|
||||
"FileSource$ResourceTransformCallback";
|
||||
}
|
||||
|
||||
static std::string onURL(jni::JNIEnv&,
|
||||
const jni::Object<FileSource::ResourceTransformCallback>&,
|
||||
int,
|
||||
std::string);
|
||||
};
|
||||
|
||||
struct ResourcesCachePathChangeCallback {
|
||||
static constexpr auto Name() {
|
||||
return "org/maplibre/android/storage/"
|
||||
"FileSource$ResourcesCachePathChangeCallback";
|
||||
}
|
||||
|
||||
static void onSuccess(jni::JNIEnv&,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>&,
|
||||
const jni::String&);
|
||||
|
||||
static void onError(jni::JNIEnv&,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>&,
|
||||
const jni::String&);
|
||||
};
|
||||
|
||||
FileSource(jni::JNIEnv&, const jni::String&, const jni::String&, const jni::Object<TileServerOptions>&);
|
||||
|
||||
~FileSource();
|
||||
|
||||
void setTileServerOptions(jni::JNIEnv& _env, const jni::Object<TileServerOptions>& _options);
|
||||
|
||||
jni::Local<jni::String> getApiKey(jni::JNIEnv&);
|
||||
|
||||
void setApiKey(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
jni::Local<jni::String> getAPIBaseUrl(jni::JNIEnv&);
|
||||
|
||||
void setAPIBaseUrl(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
void setResourceTransform(jni::JNIEnv&, const jni::Object<FileSource::ResourceTransformCallback>&);
|
||||
|
||||
void setResourceCachePath(jni::JNIEnv&,
|
||||
const jni::String&,
|
||||
const jni::Object<FileSource::ResourcesCachePathChangeCallback>&);
|
||||
|
||||
void resume(jni::JNIEnv&);
|
||||
|
||||
void pause(jni::JNIEnv&);
|
||||
|
||||
jni::jboolean isResumed(jni::JNIEnv&);
|
||||
|
||||
static FileSource* getNativePeer(jni::JNIEnv&, const jni::Object<FileSource>&);
|
||||
|
||||
static mbgl::ResourceOptions getSharedResourceOptions(jni::JNIEnv&, const jni::Object<FileSource>&);
|
||||
|
||||
static mbgl::ClientOptions getSharedClientOptions(jni::JNIEnv&, const jni::Object<FileSource>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
private:
|
||||
const std::string DATABASE_FILE = "/mbgl-offline.db";
|
||||
std::optional<int> activationCounter;
|
||||
mbgl::ResourceOptions resourceOptions;
|
||||
mbgl::ClientOptions clientOptions;
|
||||
std::unique_ptr<Actor<ResourceTransform::TransformCallback>> resourceTransform;
|
||||
std::function<void()> pathChangeCallback;
|
||||
std::shared_ptr<mbgl::DatabaseFileSource> databaseSource;
|
||||
std::shared_ptr<mbgl::FileSource> onlineSource;
|
||||
std::shared_ptr<mbgl::FileSource> resourceLoader;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
88
platform/android/MapLibreAndroid/src/cpp/geojson/feature.cpp
Normal file
88
platform/android/MapLibreAndroid/src/cpp/geojson/feature.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "feature.hpp"
|
||||
#include "geometry.hpp"
|
||||
#include "../gson/json_object.hpp"
|
||||
|
||||
#include <mbgl/util/string.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
using namespace gson;
|
||||
|
||||
mbgl::GeoJSONFeature Feature::convert(jni::JNIEnv& env, const jni::Object<Feature>& jFeature) {
|
||||
static auto& javaClass = jni::Class<Feature>::Singleton(env);
|
||||
static auto id = javaClass.GetMethod<jni::String()>(env, "id");
|
||||
static auto geometry = javaClass.GetMethod<jni::Object<Geometry>()>(env, "geometry");
|
||||
static auto properties = javaClass.GetMethod<jni::Object<gson::JsonObject>()>(env, "properties");
|
||||
|
||||
auto jId = jFeature.Call(env, id);
|
||||
|
||||
using mbid = mapbox::feature::identifier;
|
||||
|
||||
return mbgl::GeoJSONFeature{Geometry::convert(env, jFeature.Call(env, geometry)),
|
||||
JsonObject::convert(env, jFeature.Call(env, properties)),
|
||||
jId ? mbid{jni::Make<std::string>(env, jId)} : mbid{mapbox::feature::null_value}};
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn feature identifier into std::string
|
||||
*/
|
||||
class FeatureIdVisitor {
|
||||
public:
|
||||
template <class T>
|
||||
std::string operator()(const T& i) const {
|
||||
return util::toString(i);
|
||||
}
|
||||
|
||||
std::string operator()(const std::string& i) const { return i; }
|
||||
|
||||
std::string operator()(const std::nullptr_t&) const { return {}; }
|
||||
|
||||
std::string operator()(const mapbox::feature::null_value_t&) const { return {}; }
|
||||
};
|
||||
|
||||
jni::Local<jni::Object<Feature>> convertFeature(jni::JNIEnv& env, const mbgl::GeoJSONFeature& value) {
|
||||
static auto& javaClass = jni::Class<Feature>::Singleton(env);
|
||||
static auto method =
|
||||
javaClass.GetStaticMethod<jni::Object<Feature>(jni::Object<Geometry>, jni::Object<JsonObject>, jni::String)>(
|
||||
env, "fromGeometry");
|
||||
|
||||
return javaClass.Call(
|
||||
env,
|
||||
method,
|
||||
Geometry::New(env, value.geometry),
|
||||
JsonObject::New(env, value.properties),
|
||||
jni::Make<jni::String>(env,
|
||||
value.id.is<mbgl::NullValue>() ? std::string{} : value.id.match(FeatureIdVisitor())));
|
||||
}
|
||||
|
||||
jni::Local<jni::Array<jni::Object<Feature>>> Feature::convert(jni::JNIEnv& env,
|
||||
const std::vector<mbgl::Feature>& value) {
|
||||
auto features = jni::Array<jni::Object<Feature>>::New(env, value.size());
|
||||
|
||||
for (size_t i = 0; i < value.size(); ++i) {
|
||||
features.Set(env, i, convertFeature(env, static_cast<mbgl::GeoJSONFeature>(value.at(i))));
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
jni::Local<jni::Array<jni::Object<Feature>>> Feature::convert(jni::JNIEnv& env,
|
||||
const std::vector<mbgl::GeoJSONFeature>& value) {
|
||||
auto features = jni::Array<jni::Object<Feature>>::New(env, value.size());
|
||||
|
||||
for (size_t i = 0; i < value.size(); ++i) {
|
||||
features.Set(env, i, convertFeature(env, value.at(i)));
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
void Feature::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Feature>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
24
platform/android/MapLibreAndroid/src/cpp/geojson/feature.hpp
Normal file
24
platform/android/MapLibreAndroid/src/cpp/geojson/feature.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/feature.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Feature {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Feature"; };
|
||||
|
||||
static mbgl::GeoJSONFeature convert(jni::JNIEnv&, const jni::Object<Feature>&);
|
||||
static jni::Local<jni::Array<jni::Object<Feature>>> convert(jni::JNIEnv&, const std::vector<mbgl::Feature>&);
|
||||
static jni::Local<jni::Array<jni::Object<Feature>>> convert(jni::JNIEnv&, const std::vector<mbgl::GeoJSONFeature>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "feature_collection.hpp"
|
||||
|
||||
#include "feature.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env,
|
||||
const jni::Object<FeatureCollection>& jCollection) {
|
||||
auto collection = mbgl::FeatureCollection();
|
||||
|
||||
if (jCollection) {
|
||||
auto jFeatureList = FeatureCollection::features(env, jCollection);
|
||||
auto jFeatures = java::util::List::toArray<Feature>(env, jFeatureList);
|
||||
auto size = size_t(jFeatures.Length(env));
|
||||
collection.reserve(size);
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
collection.push_back(Feature::convert(env, jFeatures.Get(env, i)));
|
||||
}
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> FeatureCollection::features(
|
||||
jni::JNIEnv& env, const jni::Object<FeatureCollection>& jCollection) {
|
||||
static auto& javaClass = jni::Class<FeatureCollection>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List>()>(env, "features");
|
||||
return jCollection.Call(env, method);
|
||||
}
|
||||
|
||||
void FeatureCollection::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<FeatureCollection>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class FeatureCollection {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/FeatureCollection"; };
|
||||
|
||||
static mbgl::FeatureCollection convert(jni::JNIEnv&, const jni::Object<FeatureCollection>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> features(jni::JNIEnv&, const jni::Object<FeatureCollection>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include "point.hpp"
|
||||
#include "multi_point.hpp"
|
||||
#include "line_string.hpp"
|
||||
#include "multi_line_string.hpp"
|
||||
#include "polygon.hpp"
|
||||
#include "multi_polygon.hpp"
|
||||
#include "geometry_collection.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
/**
|
||||
* Turn mapbox::geometry type into Java GeoJson Geometries
|
||||
*/
|
||||
class GeometryEvaluator {
|
||||
public:
|
||||
jni::JNIEnv &env;
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::EmptyGeometry &) const {
|
||||
// FIXME: mapbox-java needs to have its own Empty type.
|
||||
return GeometryCollection::New(env, {});
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::Point<double> &geometry) const {
|
||||
return Point::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::LineString<double> &geometry) const {
|
||||
return LineString::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiLineString<double> &geometry) const {
|
||||
return MultiLineString::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiPoint<double> &geometry) const {
|
||||
return MultiPoint::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::Polygon<double> &geometry) const {
|
||||
return Polygon::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiPolygon<double> &geometry) const {
|
||||
return MultiPolygon::New(env, geometry);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Geometry>> operator()(const mapbox::geometry::geometry_collection<double> &geometry) const {
|
||||
return GeometryCollection::New(env, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
jni::Local<jni::Object<Geometry>> Geometry::New(jni::JNIEnv &env, mbgl::Geometry<double> geometry) {
|
||||
GeometryEvaluator evaluator{env};
|
||||
return mbgl::Geometry<double>::visit(geometry, evaluator);
|
||||
}
|
||||
|
||||
mbgl::Geometry<double> Geometry::convert(jni::JNIEnv &env, const jni::Object<Geometry> &jGeometry) {
|
||||
auto type = Geometry::getType(env, jGeometry);
|
||||
if (type == Point::Type()) {
|
||||
return {Point::convert(env, jni::Cast(env, jni::Class<Point>::Singleton(env), jGeometry))};
|
||||
} else if (type == MultiPoint::Type()) {
|
||||
return {MultiPoint::convert(env, jni::Cast(env, jni::Class<MultiPoint>::Singleton(env), jGeometry))};
|
||||
} else if (type == LineString::Type()) {
|
||||
return {LineString::convert(env, jni::Cast(env, jni::Class<LineString>::Singleton(env), jGeometry))};
|
||||
} else if (type == MultiLineString::Type()) {
|
||||
return {MultiLineString::convert(env, jni::Cast(env, jni::Class<MultiLineString>::Singleton(env), jGeometry))};
|
||||
} else if (type == Polygon::Type()) {
|
||||
return {Polygon::convert(env, jni::Cast(env, jni::Class<Polygon>::Singleton(env), jGeometry))};
|
||||
} else if (type == MultiPolygon::Type()) {
|
||||
return {MultiPolygon::convert(env, jni::Cast(env, jni::Class<MultiPolygon>::Singleton(env), jGeometry))};
|
||||
} else if (type == GeometryCollection::Type()) {
|
||||
return {GeometryCollection::convert(env,
|
||||
jni::Cast(env, jni::Class<GeometryCollection>::Singleton(env), jGeometry))};
|
||||
}
|
||||
|
||||
throw std::runtime_error(std::string{"Unsupported GeoJSON type: "} + type);
|
||||
}
|
||||
|
||||
std::string Geometry::getType(jni::JNIEnv &env, const jni::Object<Geometry> &jGeometry) {
|
||||
static auto &javaClass = jni::Class<Geometry>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String()>(env, "type");
|
||||
return jni::Make<std::string>(env, jGeometry.Call(env, method));
|
||||
}
|
||||
|
||||
void Geometry::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<Geometry>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Geometry {
|
||||
public:
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Geometry"; };
|
||||
|
||||
static jni::Local<jni::Object<Geometry>> New(jni::JNIEnv&, mbgl::Geometry<double>);
|
||||
|
||||
static mbgl::Geometry<double> convert(jni::JNIEnv&, const jni::Object<Geometry>&);
|
||||
|
||||
static std::string getType(jni::JNIEnv&, const jni::Object<Geometry>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "geometry_collection.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<GeometryCollection>> GeometryCollection::New(
|
||||
jni::JNIEnv& env, const mapbox::geometry::geometry_collection<double>& collection) {
|
||||
// Create an array of geometries
|
||||
auto jarray = jni::Array<jni::Object<Geometry>>::New(env, collection.size());
|
||||
|
||||
for (size_t i = 0; i < collection.size(); i++) {
|
||||
jarray.Set(env, i, Geometry::New(env, collection.at(i)));
|
||||
}
|
||||
|
||||
// create the GeometryCollection
|
||||
static auto& javaClass = jni::Class<GeometryCollection>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<GeometryCollection>(jni::Object<java::util::List>)>(
|
||||
env, "fromGeometries");
|
||||
return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray));
|
||||
}
|
||||
|
||||
mapbox::geometry::geometry_collection<double> GeometryCollection::convert(
|
||||
jni::JNIEnv& env, const jni::Object<GeometryCollection>& jCollection) {
|
||||
// Get geometries
|
||||
static auto& javaClass = jni::Class<GeometryCollection>::Singleton(env);
|
||||
static auto getGeometries = javaClass.GetMethod<jni::Object<java::util::List>()>(env, "geometries");
|
||||
|
||||
// Turn into array
|
||||
auto jarray = java::util::List::toArray<Geometry>(env, jCollection.Call(env, getGeometries));
|
||||
|
||||
// Convert each geometry
|
||||
mapbox::geometry::geometry_collection<double> collection{};
|
||||
|
||||
auto size = jarray.Length(env);
|
||||
for (jni::jsize i = 0; i < size; i++) {
|
||||
collection.push_back(Geometry::convert(env, jarray.Get(env, i)));
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
void GeometryCollection::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<GeometryCollection>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class GeometryCollection {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/GeometryCollection"; };
|
||||
static constexpr auto Type() { return "GeometryCollection"; };
|
||||
|
||||
static jni::Local<jni::Object<GeometryCollection>> New(jni::JNIEnv&,
|
||||
const mapbox::geometry::geometry_collection<double>&);
|
||||
|
||||
static mapbox::geometry::geometry_collection<double> convert(jni::JNIEnv&, const jni::Object<GeometryCollection>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "line_string.hpp"
|
||||
#include "point.hpp"
|
||||
#include "util.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<LineString>> LineString::New(jni::JNIEnv& env, const mbgl::LineString<double>& lineString) {
|
||||
static auto& javaClass = jni::Class<LineString>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<LineString>(jni::Object<java::util::List>)>(
|
||||
env, "fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsList(env, lineString));
|
||||
}
|
||||
|
||||
mapbox::geojson::line_string LineString::convert(jni::JNIEnv& env, const jni::Object<LineString>& jLineString) {
|
||||
mapbox::geojson::line_string lineString;
|
||||
|
||||
if (jLineString) {
|
||||
lineString = LineString::convert(env, LineString::coordinates(env, jLineString));
|
||||
}
|
||||
|
||||
return lineString;
|
||||
}
|
||||
|
||||
mapbox::geojson::line_string LineString::convert(jni::JNIEnv& env,
|
||||
const jni::Object<java::util::List /*<Point>*/>& jPointList) {
|
||||
mapbox::geojson::line_string lineString;
|
||||
|
||||
if (jPointList) {
|
||||
auto jPointArray = java::util::List::toArray<Point>(env, jPointList);
|
||||
auto size = jPointArray.Length(env);
|
||||
lineString.reserve(size);
|
||||
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
lineString.push_back(Point::convert(env, jPointArray.Get(env, i)));
|
||||
}
|
||||
}
|
||||
|
||||
return lineString;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> LineString::coordinates(jni::JNIEnv& env,
|
||||
const jni::Object<LineString>& jLineString) {
|
||||
static auto& javaClass = jni::Class<LineString>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List>()>(env, "coordinates");
|
||||
return jLineString.Call(env, method);
|
||||
}
|
||||
|
||||
void LineString::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<LineString>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class LineString {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/LineString"; };
|
||||
static constexpr auto Type() { return "LineString"; };
|
||||
|
||||
static jni::Local<jni::Object<LineString>> New(jni::JNIEnv&, const mbgl::LineString<double>&);
|
||||
|
||||
static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object<LineString>&);
|
||||
|
||||
static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object<java::util::List /*<Point>*/>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<LineString>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "multi_line_string.hpp"
|
||||
|
||||
#include "line_string.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<MultiLineString>> MultiLineString::New(jni::JNIEnv& env,
|
||||
const mbgl::MultiLineString<double>& multiLineString) {
|
||||
static auto& javaClass = jni::Class<MultiLineString>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<MultiLineString>(jni::Object<java::util::List>)>(
|
||||
env, "fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsListsList(env, multiLineString));
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv& env,
|
||||
const jni::Object<MultiLineString>& jMultiLineString) {
|
||||
mapbox::geojson::multi_line_string multiLineString;
|
||||
|
||||
if (jMultiLineString) {
|
||||
multiLineString = MultiLineString::convert(env, MultiLineString::coordinates(env, jMultiLineString));
|
||||
}
|
||||
|
||||
return multiLineString;
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_line_string MultiLineString::convert(
|
||||
jni::JNIEnv& env, const jni::Object<java::util::List /*<java::util::List<Point>>*/>& jPointListsList) {
|
||||
mapbox::geojson::multi_line_string multiLineString;
|
||||
|
||||
if (jPointListsList) {
|
||||
auto jPositionListsArray = java::util::List::toArray<java::util::List>(env, jPointListsList);
|
||||
|
||||
auto size = jPositionListsArray.Length(env);
|
||||
multiLineString.reserve(size);
|
||||
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
multiLineString.push_back(LineString::convert(env, jPositionListsArray.Get(env, i)));
|
||||
}
|
||||
}
|
||||
|
||||
return multiLineString;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> MultiLineString::coordinates(
|
||||
jni::JNIEnv& env, const jni::Object<MultiLineString>& jLineString) {
|
||||
static auto& javaClass = jni::Class<MultiLineString>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List>()>(env, "coordinates");
|
||||
return jLineString.Call(env, method);
|
||||
}
|
||||
|
||||
void MultiLineString::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<MultiLineString>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "../java/util.hpp"
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class MultiLineString {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/MultiLineString"; };
|
||||
static constexpr auto Type() { return "MultiLineString"; };
|
||||
|
||||
static jni::Local<jni::Object<MultiLineString>> New(jni::JNIEnv&, const mbgl::MultiLineString<double>&);
|
||||
|
||||
static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, const jni::Object<MultiLineString>&);
|
||||
|
||||
static mapbox::geojson::multi_line_string convert(
|
||||
jni::JNIEnv&, const jni::Object<java::util::List /*<java::util::List<Point>>*/>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiLineString>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "multi_point.hpp"
|
||||
|
||||
#include "line_string.hpp"
|
||||
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<MultiPoint>> MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint<double>& multiPoint) {
|
||||
static auto& javaClass = jni::Class<MultiPoint>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<MultiPoint>(jni::Object<java::util::List>)>(
|
||||
env, "fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsList(env, multiPoint));
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv& env, const jni::Object<MultiPoint>& jMultiPoint) {
|
||||
mapbox::geojson::multi_point multiPoint;
|
||||
|
||||
if (jMultiPoint) {
|
||||
multiPoint = convertExplicit<mapbox::geojson::multi_point>(
|
||||
LineString::convert(env, MultiPoint::coordinates(env, jMultiPoint)));
|
||||
}
|
||||
|
||||
return multiPoint;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> MultiPoint::coordinates(jni::JNIEnv& env,
|
||||
const jni::Object<MultiPoint>& jMultiPoint) {
|
||||
static auto& javaClass = jni::Class<MultiPoint>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List>()>(env, "coordinates");
|
||||
return jMultiPoint.Call(env, method);
|
||||
}
|
||||
|
||||
void MultiPoint::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<MultiPoint>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class MultiPoint {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/MultiPoint"; };
|
||||
static constexpr auto Type() { return "MultiPoint"; };
|
||||
|
||||
static jni::Local<jni::Object<MultiPoint>> New(jni::JNIEnv&, const mbgl::MultiPoint<double>&);
|
||||
|
||||
static mapbox::geojson::multi_point convert(jni::JNIEnv&, const jni::Object<MultiPoint>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiPoint>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "multi_polygon.hpp"
|
||||
|
||||
#include "polygon.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<MultiPolygon>> MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon<double>& multiPolygon) {
|
||||
static auto& javaClass = jni::Class<MultiPolygon>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<MultiPolygon>(jni::Object<java::util::List>)>(
|
||||
env, "fromLngLats");
|
||||
|
||||
auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, multiPolygon.size());
|
||||
|
||||
for (size_t i = 0; i < multiPolygon.size(); i++) {
|
||||
jarray.Set(env, i, asPointsListsList(env, multiPolygon.at(i)));
|
||||
}
|
||||
|
||||
return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray));
|
||||
}
|
||||
|
||||
mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv& env, const jni::Object<MultiPolygon>& jMultiPolygon) {
|
||||
mapbox::geojson::multi_polygon multiPolygon;
|
||||
|
||||
if (jMultiPolygon) {
|
||||
auto jPointListsListList = MultiPolygon::coordinates(env, jMultiPolygon);
|
||||
auto jPointListsListArray = java::util::List::toArray<java::util::List>(env, jPointListsListList);
|
||||
|
||||
auto size = jPointListsListArray.Length(env);
|
||||
multiPolygon.reserve(size);
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
multiPolygon.push_back(Polygon::convert(env, jPointListsListArray.Get(env, i)));
|
||||
}
|
||||
}
|
||||
|
||||
return multiPolygon;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> MultiPolygon::coordinates(jni::JNIEnv& env,
|
||||
const jni::Object<MultiPolygon>& jPolygon) {
|
||||
static auto& javaClass = jni::Class<MultiPolygon>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List>()>(env, "coordinates");
|
||||
return jPolygon.Call(env, method);
|
||||
}
|
||||
|
||||
void MultiPolygon::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<MultiPolygon>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "../java/util.hpp"
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class MultiPolygon {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/MultiPolygon"; };
|
||||
static constexpr auto Type() { return "MultiPolygon"; };
|
||||
|
||||
static jni::Local<jni::Object<MultiPolygon>> New(jni::JNIEnv&, const mbgl::MultiPolygon<double>&);
|
||||
|
||||
static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, const jni::Object<MultiPolygon>&);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiPolygon>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
31
platform/android/MapLibreAndroid/src/cpp/geojson/point.cpp
Normal file
31
platform/android/MapLibreAndroid/src/cpp/geojson/point.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "point.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<Point>> Point::New(jni::JNIEnv& env, const mbgl::Point<double>& point) {
|
||||
static auto& javaClass = jni::Class<Point>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Point>(jni::jdouble, jni::jdouble)>(env, "fromLngLat");
|
||||
return javaClass.Call(env, method, point.x, point.y);
|
||||
}
|
||||
|
||||
mbgl::Point<double> Point::convert(jni::JNIEnv& env, const jni::Object<Point>& jPoint) {
|
||||
static auto& javaClass = jni::Class<Point>::Singleton(env);
|
||||
static auto longitude = javaClass.GetMethod<jni::jdouble()>(env, "longitude");
|
||||
static auto latitude = javaClass.GetMethod<jni::jdouble()>(env, "latitude");
|
||||
|
||||
if (!jPoint) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {jPoint.Call(env, longitude), jPoint.Call(env, latitude)};
|
||||
}
|
||||
|
||||
void Point::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Point>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
27
platform/android/MapLibreAndroid/src/cpp/geojson/point.hpp
Normal file
27
platform/android/MapLibreAndroid/src/cpp/geojson/point.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Point {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Point"; };
|
||||
static constexpr auto Type() { return "Point"; };
|
||||
|
||||
static jni::Local<jni::Object<Point>> New(jni::JNIEnv&, const mbgl::Point<double>&);
|
||||
static mbgl::Point<double> convert(jni::JNIEnv&, const jni::Object<Point>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
56
platform/android/MapLibreAndroid/src/cpp/geojson/polygon.cpp
Normal file
56
platform/android/MapLibreAndroid/src/cpp/geojson/polygon.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "polygon.hpp"
|
||||
|
||||
#include "multi_line_string.hpp"
|
||||
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
jni::Local<jni::Object<Polygon>> Polygon::New(jni::JNIEnv& env, const mbgl::Polygon<double>& polygon) {
|
||||
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Polygon>(jni::Object<java::util::List>)>(env,
|
||||
"fromLngLats");
|
||||
|
||||
return javaClass.Call(env, method, asPointsListsList(env, polygon));
|
||||
}
|
||||
|
||||
mapbox::geojson::polygon Polygon::convert(jni::JNIEnv& env, const jni::Object<Polygon>& jPolygon) {
|
||||
mapbox::geojson::polygon polygon;
|
||||
|
||||
if (jPolygon) {
|
||||
polygon = Polygon::convert(env, Polygon::coordinates(env, jPolygon));
|
||||
}
|
||||
|
||||
return polygon;
|
||||
}
|
||||
|
||||
mapbox::geojson::polygon Polygon::convert(
|
||||
jni::JNIEnv& env, const jni::Object<java::util::List /*<java::util::List<Point>>*/>& jPointListsList) {
|
||||
mapbox::geojson::polygon polygon;
|
||||
|
||||
if (jPointListsList) {
|
||||
auto multiLine = MultiLineString::convert(env, jPointListsList);
|
||||
polygon.reserve(multiLine.size());
|
||||
for (auto&& line : multiLine) {
|
||||
polygon.emplace_back(convertExplicit<mapbox::geojson::linear_ring>(std::move(line)));
|
||||
}
|
||||
}
|
||||
|
||||
return polygon;
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<java::util::List>> Polygon::coordinates(jni::JNIEnv& env, const jni::Object<Polygon>& jPolygon) {
|
||||
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::List>()>(env, "coordinates");
|
||||
return jPolygon.Call(env, method);
|
||||
}
|
||||
|
||||
void Polygon::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Polygon>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
35
platform/android/MapLibreAndroid/src/cpp/geojson/polygon.hpp
Normal file
35
platform/android/MapLibreAndroid/src/cpp/geojson/polygon.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/geojson.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include "geometry.hpp"
|
||||
#include "../java/util.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
class Polygon {
|
||||
public:
|
||||
using SuperTag = Geometry;
|
||||
static constexpr auto Name() { return "com/mapbox/geojson/Polygon"; };
|
||||
static constexpr auto Type() { return "Polygon"; };
|
||||
|
||||
static jni::Local<jni::Object<Polygon>> New(jni::JNIEnv &, const mbgl::Polygon<double> &);
|
||||
|
||||
static mapbox::geojson::polygon convert(jni::JNIEnv &, const jni::Object<Polygon> &);
|
||||
|
||||
static mapbox::geojson::polygon convert(jni::JNIEnv &,
|
||||
const jni::Object<java::util::List /*<java::util::List<Point>>*/> &);
|
||||
|
||||
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv &, const jni::Object<Polygon> &);
|
||||
|
||||
static void registerNative(jni::JNIEnv &);
|
||||
};
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
50
platform/android/MapLibreAndroid/src/cpp/geojson/util.hpp
Normal file
50
platform/android/MapLibreAndroid/src/cpp/geojson/util.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "point.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace geojson {
|
||||
|
||||
// Clang 3.8 fails to implicitly convert matching types, so we'll have to do it explicitly.
|
||||
template <typename To, typename From>
|
||||
To convertExplicit(From&& src) {
|
||||
static_assert(std::is_same<typename std::decay_t<From>::container_type, typename To::container_type>::value,
|
||||
"container types do not match");
|
||||
static_assert(std::is_rvalue_reference<From&&>::value, "argument must be rvalue reference");
|
||||
return *reinterpret_cast<std::add_pointer_t<To>>(&src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Geometry -> List<Point>
|
||||
*/
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<java::util::List>> asPointsList(jni::JNIEnv& env, const T& pointsList) {
|
||||
auto jarray = jni::Array<jni::Object<Point>>::New(env, pointsList.size());
|
||||
|
||||
for (jni::jsize i = 0; i < pointsList.size(); i++) {
|
||||
jarray.Set(env, i, Point::New(env, pointsList.at(i)));
|
||||
}
|
||||
|
||||
return java::util::Arrays::asList(env, jarray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Geometry -> List<List<Point>>
|
||||
*/
|
||||
template <class SHAPE>
|
||||
static jni::Local<jni::Object<java::util::List>> asPointsListsList(JNIEnv& env, const SHAPE& value) {
|
||||
auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, value.size());
|
||||
|
||||
for (size_t i = 0; i < value.size(); i++) {
|
||||
jarray.Set(env, i, asPointsList(env, value[i]));
|
||||
}
|
||||
|
||||
return java::util::Arrays::asList(env, jarray);
|
||||
}
|
||||
|
||||
} // namespace geojson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<LatLng>> LatLng::New(jni::JNIEnv& env, const mbgl::LatLng& latLng) {
|
||||
static auto& javaClass = jni::Class<LatLng>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<double, double>(env);
|
||||
return javaClass.New(env, constructor, latLng.latitude(), latLng.longitude());
|
||||
}
|
||||
|
||||
mbgl::Point<double> LatLng::getGeometry(jni::JNIEnv& env, const jni::Object<LatLng>& latLng) {
|
||||
static auto& javaClass = jni::Class<LatLng>::Singleton(env);
|
||||
static auto latitudeField = javaClass.GetField<jni::jdouble>(env, "latitude");
|
||||
static auto longitudeField = javaClass.GetField<jni::jdouble>(env, "longitude");
|
||||
return mbgl::Point<double>(latLng.Get(env, longitudeField), latLng.Get(env, latitudeField));
|
||||
}
|
||||
|
||||
mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, const jni::Object<LatLng>& latLng) {
|
||||
auto point = LatLng::getGeometry(env, latLng);
|
||||
return mbgl::LatLng(point.y, point.x);
|
||||
}
|
||||
|
||||
void LatLng::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<LatLng>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class LatLng : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/geometry/LatLng"; };
|
||||
|
||||
static jni::Local<jni::Object<LatLng>> New(jni::JNIEnv&, const mbgl::LatLng&);
|
||||
|
||||
static mbgl::Point<double> getGeometry(jni::JNIEnv&, const jni::Object<LatLng>&);
|
||||
|
||||
static mbgl::LatLng getLatLng(jni::JNIEnv&, const jni::Object<LatLng>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "lat_lng_bounds.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<LatLngBounds>> LatLngBounds::New(jni::JNIEnv& env, mbgl::LatLngBounds bounds) {
|
||||
static auto& javaClass = jni::Class<LatLngBounds>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<double, double, double, double>(env);
|
||||
return javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west());
|
||||
}
|
||||
|
||||
mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, const jni::Object<LatLngBounds>& bounds) {
|
||||
static auto& javaClass = jni::Class<LatLngBounds>::Singleton(env);
|
||||
static auto swLatField = javaClass.GetField<jni::jdouble>(env, "latitudeSouth");
|
||||
static auto swLonField = javaClass.GetField<jni::jdouble>(env, "longitudeWest");
|
||||
static auto neLatField = javaClass.GetField<jni::jdouble>(env, "latitudeNorth");
|
||||
static auto neLonField = javaClass.GetField<jni::jdouble>(env, "longitudeEast");
|
||||
|
||||
mbgl::LatLng sw = {bounds.Get(env, swLatField), bounds.Get(env, swLonField)};
|
||||
mbgl::LatLng ne = {bounds.Get(env, neLatField), bounds.Get(env, neLonField)};
|
||||
|
||||
return mbgl::LatLngBounds::hull(sw, ne);
|
||||
}
|
||||
|
||||
void LatLngBounds::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<LatLngBounds>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class LatLngBounds : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/geometry/LatLngBounds"; };
|
||||
|
||||
static jni::Local<jni::Object<LatLngBounds>> New(jni::JNIEnv&, mbgl::LatLngBounds);
|
||||
|
||||
static mbgl::LatLngBounds getLatLngBounds(jni::JNIEnv&, const jni::Object<LatLngBounds>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "lat_lng_quad.hpp"
|
||||
#include "lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<LatLngQuad>> LatLngQuad::New(jni::JNIEnv& env, std::array<mbgl::LatLng, 4> coordinates) {
|
||||
static auto& javaClass = jni::Class<LatLngQuad>::Singleton(env);
|
||||
static auto quadConstructor =
|
||||
javaClass.GetConstructor<jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>>(
|
||||
env);
|
||||
return javaClass.New(env,
|
||||
quadConstructor,
|
||||
LatLng::New(env, coordinates[0]),
|
||||
LatLng::New(env, coordinates[1]),
|
||||
LatLng::New(env, coordinates[2]),
|
||||
LatLng::New(env, coordinates[3]));
|
||||
}
|
||||
|
||||
std::array<mbgl::LatLng, 4> LatLngQuad::getLatLngArray(jni::JNIEnv& env, const jni::Object<LatLngQuad>& quad) {
|
||||
static auto& javaClass = jni::Class<LatLngQuad>::Singleton(env);
|
||||
static auto topLeftField = javaClass.GetField<jni::Object<LatLng>>(env, "topLeft");
|
||||
static auto topRightField = javaClass.GetField<jni::Object<LatLng>>(env, "topRight");
|
||||
static auto bottomRightField = javaClass.GetField<jni::Object<LatLng>>(env, "bottomRight");
|
||||
static auto bottomLeftField = javaClass.GetField<jni::Object<LatLng>>(env, "bottomLeft");
|
||||
|
||||
return std::array<mbgl::LatLng, 4>{{LatLng::getLatLng(env, quad.Get(env, topLeftField)),
|
||||
LatLng::getLatLng(env, quad.Get(env, topRightField)),
|
||||
LatLng::getLatLng(env, quad.Get(env, bottomRightField)),
|
||||
LatLng::getLatLng(env, quad.Get(env, bottomLeftField))}};
|
||||
}
|
||||
|
||||
void LatLngQuad::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<LatLngQuad>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
#include <array>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class LatLngQuad : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/geometry/LatLngQuad"; };
|
||||
|
||||
static jni::Local<jni::Object<LatLngQuad>> New(jni::JNIEnv&, std::array<mbgl::LatLng, 4>);
|
||||
|
||||
static std::array<mbgl::LatLng, 4> getLatLngArray(jni::JNIEnv&, const jni::Object<LatLngQuad>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "projected_meters.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<ProjectedMeters>> ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) {
|
||||
static auto& javaClass = jni::Class<ProjectedMeters>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<double, double>(env);
|
||||
return javaClass.New(env, constructor, northing, easting);
|
||||
}
|
||||
|
||||
void ProjectedMeters::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<ProjectedMeters>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class ProjectedMeters : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/geometry/ProjectedMeters"; };
|
||||
|
||||
static jni::Local<jni::Object<ProjectedMeters>> New(jni::JNIEnv&, double, double);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
25
platform/android/MapLibreAndroid/src/cpp/graphics/pointf.cpp
Normal file
25
platform/android/MapLibreAndroid/src/cpp/graphics/pointf.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include "pointf.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<PointF>> PointF::New(jni::JNIEnv& env, float x, float y) {
|
||||
static auto& javaClass = jni::Class<PointF>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<float, float>(env);
|
||||
return javaClass.New(env, constructor, x, y);
|
||||
}
|
||||
|
||||
mbgl::ScreenCoordinate PointF::getScreenCoordinate(jni::JNIEnv& env, const jni::Object<PointF>& point) {
|
||||
static auto& javaClass = jni::Class<PointF>::Singleton(env);
|
||||
static auto xField = javaClass.GetField<jni::jfloat>(env, "x");
|
||||
static auto yField = javaClass.GetField<jni::jfloat>(env, "y");
|
||||
return mbgl::ScreenCoordinate{point.Get(env, xField), point.Get(env, yField)};
|
||||
}
|
||||
|
||||
void PointF::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<PointF>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
22
platform/android/MapLibreAndroid/src/cpp/graphics/pointf.hpp
Normal file
22
platform/android/MapLibreAndroid/src/cpp/graphics/pointf.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class PointF : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "android/graphics/PointF"; };
|
||||
|
||||
static jni::Local<jni::Object<PointF>> New(jni::JNIEnv&, float, float);
|
||||
|
||||
static mbgl::ScreenCoordinate getScreenCoordinate(jni::JNIEnv&, const jni::Object<PointF>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
35
platform/android/MapLibreAndroid/src/cpp/graphics/rectf.cpp
Normal file
35
platform/android/MapLibreAndroid/src/cpp/graphics/rectf.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "rectf.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
float RectF::getLeft(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "left");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
float RectF::getTop(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "top");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
float RectF::getRight(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "right");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
float RectF::getBottom(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
|
||||
static auto& javaClass = jni::Class<RectF>::Singleton(env);
|
||||
static auto field = javaClass.GetField<float>(env, "bottom");
|
||||
return rectf.Get(env, field);
|
||||
}
|
||||
|
||||
void RectF::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<RectF>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
26
platform/android/MapLibreAndroid/src/cpp/graphics/rectf.hpp
Normal file
26
platform/android/MapLibreAndroid/src/cpp/graphics/rectf.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class RectF : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "android/graphics/RectF"; };
|
||||
|
||||
static float getLeft(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static float getTop(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static float getRight(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static float getBottom(jni::JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
50
platform/android/MapLibreAndroid/src/cpp/gson/json_array.cpp
Normal file
50
platform/android/MapLibreAndroid/src/cpp/gson/json_array.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "json_array.hpp"
|
||||
#include "json_element.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
jni::Local<jni::Object<JsonArray>> JsonArray::New(jni::JNIEnv& env, const std::vector<mbgl::Value>& values) {
|
||||
static auto& javaClass = jni::Class<JsonArray>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor(env);
|
||||
static auto addMethod = javaClass.GetMethod<void(jni::Object<JsonElement>)>(env, "add");
|
||||
|
||||
auto jsonArray = javaClass.New(env, constructor);
|
||||
|
||||
for (const auto& v : values) {
|
||||
jsonArray.Call(env, addMethod, JsonElement::New(env, v));
|
||||
}
|
||||
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
std::vector<mbgl::Value> JsonArray::convert(jni::JNIEnv& env, const jni::Object<JsonArray>& jsonArray) {
|
||||
std::vector<mbgl::Value> values;
|
||||
|
||||
if (jsonArray) {
|
||||
static auto& javaClass = jni::Class<JsonArray>::Singleton(env);
|
||||
static auto getMethod = javaClass.GetMethod<jni::Object<JsonElement>(jni::jint)>(env, "get");
|
||||
static auto sizeMethod = javaClass.GetMethod<jni::jint()>(env, "size");
|
||||
|
||||
int size = jsonArray.Call(env, sizeMethod);
|
||||
values.reserve(uint(size));
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
auto entry = jsonArray.Call(env, getMethod, i);
|
||||
if (entry) {
|
||||
values.push_back(JsonElement::convert(env, entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
void JsonArray::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<JsonArray>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
24
platform/android/MapLibreAndroid/src/cpp/gson/json_array.hpp
Normal file
24
platform/android/MapLibreAndroid/src/cpp/gson/json_array.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonArray {
|
||||
public:
|
||||
using SuperTag = JsonElement;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonArray"; };
|
||||
|
||||
static jni::Local<jni::Object<JsonArray>> New(jni::JNIEnv&, const std::vector<mbgl::Value>&);
|
||||
static std::vector<mbgl::Value> convert(JNIEnv&, const jni::Object<JsonArray>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "json_element.hpp"
|
||||
#include "json_array.hpp"
|
||||
#include "json_object.hpp"
|
||||
#include "json_primitive.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
jni::Local<jni::Object<JsonElement>> JsonElement::New(jni::JNIEnv& env, const mbgl::Value& value) {
|
||||
static auto& primitive = jni::Class<JsonPrimitive>::Singleton(env);
|
||||
static auto stringConstructor = primitive.GetConstructor<jni::String>(env);
|
||||
static auto numberConstructor = primitive.GetConstructor<jni::Number>(env);
|
||||
static auto booleanConstructor = primitive.GetConstructor<jni::Boolean>(env);
|
||||
|
||||
return value.match(
|
||||
[&](const mbgl::NullValue&) { return jni::Local<jni::Object<JsonElement>>(); },
|
||||
[&](const std::string& value) {
|
||||
return primitive.New(env, stringConstructor, jni::Make<jni::String>(env, value));
|
||||
},
|
||||
[&](const double value) { return primitive.New(env, numberConstructor, jni::Box(env, value)); },
|
||||
[&](const int64_t value) { return primitive.New(env, numberConstructor, jni::Box(env, value)); },
|
||||
[&](const uint64_t value) {
|
||||
return primitive.New(env, numberConstructor, jni::Box(env, int64_t(value))); // TODO: should use BigInteger
|
||||
},
|
||||
[&](const bool value) {
|
||||
return primitive.New(env, booleanConstructor, jni::Box(env, value ? jni::jni_true : jni::jni_false));
|
||||
},
|
||||
[&](const std::vector<mbgl::Value>& values) { return JsonArray::New(env, values); },
|
||||
[&](const mbgl::PropertyMap& values) { return JsonObject::New(env, values); });
|
||||
}
|
||||
|
||||
mbgl::Value JsonElement::convert(jni::JNIEnv& env, const jni::Object<JsonElement>& jsonElement) {
|
||||
if (!jsonElement) {
|
||||
return mbgl::NullValue();
|
||||
}
|
||||
|
||||
static auto& elementClass = jni::Class<JsonElement>::Singleton(env);
|
||||
static auto isJsonObject = elementClass.GetMethod<jni::jboolean()>(env, "isJsonObject");
|
||||
static auto isJsonArray = elementClass.GetMethod<jni::jboolean()>(env, "isJsonArray");
|
||||
static auto isJsonPrimitive = elementClass.GetMethod<jni::jboolean()>(env, "isJsonPrimitive");
|
||||
|
||||
static auto& primitiveClass = jni::Class<JsonPrimitive>::Singleton(env);
|
||||
static auto isBoolean = primitiveClass.GetMethod<jni::jboolean()>(env, "isBoolean");
|
||||
static auto isString = primitiveClass.GetMethod<jni::jboolean()>(env, "isString");
|
||||
static auto isNumber = primitiveClass.GetMethod<jni::jboolean()>(env, "isNumber");
|
||||
static auto getAsBoolean = primitiveClass.GetMethod<jni::jboolean()>(env, "getAsBoolean");
|
||||
static auto getAsString = primitiveClass.GetMethod<jni::String()>(env, "getAsString");
|
||||
static auto getAsDouble = primitiveClass.GetMethod<jni::jdouble()>(env, "getAsDouble");
|
||||
|
||||
if (jsonElement.Call(env, isJsonPrimitive)) {
|
||||
auto primitive = jni::Cast(env, primitiveClass, jsonElement);
|
||||
if (primitive.Call(env, isBoolean)) {
|
||||
return bool(primitive.Call(env, getAsBoolean));
|
||||
} else if (primitive.Call(env, isNumber)) {
|
||||
return primitive.Call(env, getAsDouble);
|
||||
} else if (primitive.Call(env, isString)) {
|
||||
return jni::Make<std::string>(env, primitive.Call(env, getAsString));
|
||||
} else {
|
||||
return mbgl::NullValue();
|
||||
}
|
||||
} else if (jsonElement.Call(env, isJsonObject)) {
|
||||
return JsonObject::convert(env, jni::Cast(env, jni::Class<JsonObject>::Singleton(env), jsonElement));
|
||||
} else if (jsonElement.Call(env, isJsonArray)) {
|
||||
return JsonArray::convert(env, jni::Cast(env, jni::Class<JsonArray>::Singleton(env), jsonElement));
|
||||
} else {
|
||||
return mbgl::NullValue();
|
||||
}
|
||||
}
|
||||
|
||||
void JsonElement::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<JsonElement>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/feature.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonElement {
|
||||
public:
|
||||
using SuperTag = jni::ObjectTag;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonElement"; };
|
||||
|
||||
static jni::Local<jni::Object<JsonElement>> New(jni::JNIEnv&, const mbgl::Value&);
|
||||
static mbgl::Value convert(JNIEnv&, const jni::Object<JsonElement>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "json_object.hpp"
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include "../java/util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
jni::Local<jni::Object<JsonObject>> JsonObject::New(jni::JNIEnv& env, const mbgl::PropertyMap& values) {
|
||||
static auto& javaClass = jni::Class<JsonObject>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor(env);
|
||||
static auto addMethod = javaClass.GetMethod<void(jni::String, jni::Object<JsonElement>)>(env, "add");
|
||||
|
||||
auto jsonObject = javaClass.New(env, constructor);
|
||||
|
||||
for (auto& item : values) {
|
||||
jsonObject.Call(env, addMethod, jni::Make<jni::String>(env, item.first), JsonElement::New(env, item.second));
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
template <typename F> // void (jni::String, jni::Object<gson::JsonElement>)
|
||||
static void iterateEntrySet(jni::JNIEnv& env, const jni::Object<JsonObject>& jsonObject, F callback) {
|
||||
// Get Set<Map.Entry<String, JsonElement>>
|
||||
static auto& javaClass = jni::Class<JsonObject>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<java::util::Set>()>(env, "entrySet");
|
||||
|
||||
auto entryArray = java::util::Set::toArray<java::util::Map::Entry>(env, jsonObject.Call(env, method));
|
||||
|
||||
size_t size = entryArray.Length(env);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
auto entry = entryArray.Get(env, i);
|
||||
if (entry) {
|
||||
callback(java::util::Map::Entry::getKey<jni::StringTag>(env, entry),
|
||||
java::util::Map::Entry::getValue<gson::JsonElement>(env, entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mbgl::PropertyMap JsonObject::convert(jni::JNIEnv& env, const jni::Object<JsonObject>& jsonObject) {
|
||||
mbgl::PropertyMap map;
|
||||
|
||||
if (jsonObject) {
|
||||
iterateEntrySet(
|
||||
env, jsonObject, [&map, &env](const jni::String& jId, const jni::Object<gson::JsonElement>& jsonElement) {
|
||||
map[jni::Make<std::string>(env, jId)] = JsonElement::convert(env, jsonElement);
|
||||
});
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void JsonObject::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<JsonObject>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonObject {
|
||||
public:
|
||||
using SuperTag = JsonElement;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonObject"; };
|
||||
|
||||
static jni::Local<jni::Object<JsonObject>> New(jni::JNIEnv&, const mbgl::PropertyMap&);
|
||||
static mbgl::PropertyMap convert(JNIEnv&, const jni::Object<JsonObject>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "json_primitive.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
void JsonPrimitive::registerNative(jni::JNIEnv &env) {
|
||||
jni::Class<JsonPrimitive>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "json_element.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace gson {
|
||||
|
||||
class JsonPrimitive {
|
||||
public:
|
||||
using SuperTag = JsonElement;
|
||||
static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace gson
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
237
platform/android/MapLibreAndroid/src/cpp/http_file_source.cpp
Normal file
237
platform/android/MapLibreAndroid/src/cpp/http_file_source.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
#include <mbgl/storage/http_file_source.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/resource_options.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/util/client_options.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <mbgl/util/async_request.hpp>
|
||||
#include <mbgl/util/async_task.hpp>
|
||||
#include <mbgl/util/http_header.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
#include <mbgl/util/util.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
#include "attach_env.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class HTTPFileSource::Impl {
|
||||
public:
|
||||
Impl(const ResourceOptions resourceOptions_, const ClientOptions clientOptions_)
|
||||
: resourceOptions(resourceOptions_.clone()),
|
||||
clientOptions(clientOptions_.clone()){};
|
||||
|
||||
android::UniqueEnv env{android::AttachEnv()};
|
||||
|
||||
void setResourceOptions(ResourceOptions options) { resourceOptions = options; };
|
||||
ResourceOptions getResourceOptions() { return resourceOptions.clone(); };
|
||||
|
||||
void setClientOptions(ClientOptions options) { clientOptions = options; };
|
||||
ClientOptions getClientOptions() { return clientOptions.clone(); };
|
||||
|
||||
private:
|
||||
ResourceOptions resourceOptions;
|
||||
ClientOptions clientOptions;
|
||||
};
|
||||
|
||||
class HTTPRequest : public AsyncRequest {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/http/NativeHttpRequest"; };
|
||||
|
||||
HTTPRequest(jni::JNIEnv&, const Resource&, FileSource::Callback);
|
||||
~HTTPRequest();
|
||||
|
||||
void onFailure(jni::JNIEnv&, int type, const jni::String& message);
|
||||
void onResponse(jni::JNIEnv&,
|
||||
int code,
|
||||
const jni::String& etag,
|
||||
const jni::String& modified,
|
||||
const jni::String& cacheControl,
|
||||
const jni::String& expires,
|
||||
const jni::String& retryAfter,
|
||||
const jni::String& xRateLimitReset,
|
||||
const jni::Array<jni::jbyte>& body);
|
||||
|
||||
jni::Global<jni::Object<HTTPRequest>> javaRequest;
|
||||
|
||||
private:
|
||||
Resource resource;
|
||||
FileSource::Callback callback;
|
||||
Response response;
|
||||
|
||||
util::AsyncTask async{[this] {
|
||||
// Calling `callback` may result in deleting `this`. Copy data to temporaries first.
|
||||
auto callback_ = callback;
|
||||
auto response_ = response;
|
||||
callback_(response_);
|
||||
}};
|
||||
|
||||
static const int connectionError = 0;
|
||||
static const int temporaryError = 1;
|
||||
static const int permanentError = 2;
|
||||
};
|
||||
|
||||
namespace android {
|
||||
|
||||
void RegisterNativeHTTPRequest(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
jni::RegisterNativePeer<HTTPRequest>(env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
METHOD(&HTTPRequest::onFailure, "nativeOnFailure"),
|
||||
METHOD(&HTTPRequest::onResponse, "nativeOnResponse"));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, FileSource::Callback callback_)
|
||||
: resource(resource_),
|
||||
callback(callback_) {
|
||||
std::string etagStr;
|
||||
std::string modifiedStr;
|
||||
|
||||
if (resource.priorEtag) {
|
||||
etagStr = *resource.priorEtag;
|
||||
} else if (resource.priorModified) {
|
||||
modifiedStr = util::rfc1123(*resource.priorModified);
|
||||
}
|
||||
|
||||
jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 10);
|
||||
|
||||
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(env);
|
||||
static auto constructor =
|
||||
javaClass.GetConstructor<jni::jlong, jni::String, jni::String, jni::String, jni::jboolean>(env);
|
||||
|
||||
javaRequest = jni::NewGlobal(env,
|
||||
javaClass.New(env,
|
||||
constructor,
|
||||
reinterpret_cast<jlong>(this),
|
||||
jni::Make<jni::String>(env, resource.url),
|
||||
jni::Make<jni::String>(env, etagStr),
|
||||
jni::Make<jni::String>(env, modifiedStr),
|
||||
(jboolean)(resource_.usage == Resource::Usage::Offline)));
|
||||
}
|
||||
|
||||
HTTPRequest::~HTTPRequest() {
|
||||
android::UniqueEnv env = android::AttachEnv();
|
||||
|
||||
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(*env);
|
||||
static auto cancel = javaClass.GetMethod<void()>(*env, "cancel");
|
||||
|
||||
javaRequest.Call(*env, cancel);
|
||||
}
|
||||
|
||||
void HTTPRequest::onResponse(jni::JNIEnv& env,
|
||||
int code,
|
||||
const jni::String& etag,
|
||||
const jni::String& modified,
|
||||
const jni::String& cacheControl,
|
||||
const jni::String& expires,
|
||||
const jni::String& jRetryAfter,
|
||||
const jni::String& jXRateLimitReset,
|
||||
const jni::Array<jni::jbyte>& body) {
|
||||
using Error = Response::Error;
|
||||
|
||||
if (etag) {
|
||||
response.etag = jni::Make<std::string>(env, etag);
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
response.modified = util::parseTimestamp(jni::Make<std::string>(env, modified).c_str());
|
||||
}
|
||||
|
||||
if (cacheControl) {
|
||||
const auto cc = http::CacheControl::parse(jni::Make<std::string>(env, cacheControl).c_str());
|
||||
response.expires = cc.toTimePoint();
|
||||
response.mustRevalidate = cc.mustRevalidate;
|
||||
}
|
||||
|
||||
if (expires) {
|
||||
response.expires = util::parseTimestamp(jni::Make<std::string>(env, expires).c_str());
|
||||
}
|
||||
|
||||
if (code == 200) {
|
||||
if (body) {
|
||||
auto data = std::make_shared<std::string>(body.Length(env), char());
|
||||
jni::GetArrayRegion(env, *body, 0, data->size(), reinterpret_cast<jbyte*>(&(*data)[0]));
|
||||
response.data = data;
|
||||
} else {
|
||||
response.data = std::make_shared<std::string>();
|
||||
}
|
||||
} else if (code == 204 || (code == 404 && resource.kind == Resource::Kind::Tile)) {
|
||||
response.noContent = true;
|
||||
} else if (code == 304) {
|
||||
response.notModified = true;
|
||||
} else if (code == 404) {
|
||||
response.error = std::make_unique<Error>(Error::Reason::NotFound, "HTTP status code 404");
|
||||
} else if (code == 429) {
|
||||
std::optional<std::string> retryAfter;
|
||||
std::optional<std::string> xRateLimitReset;
|
||||
if (jRetryAfter) {
|
||||
retryAfter = jni::Make<std::string>(env, jRetryAfter);
|
||||
}
|
||||
if (jXRateLimitReset) {
|
||||
xRateLimitReset = jni::Make<std::string>(env, jXRateLimitReset);
|
||||
}
|
||||
response.error = std::make_unique<Error>(
|
||||
Error::Reason::RateLimit, "HTTP status code 429", http::parseRetryHeaders(retryAfter, xRateLimitReset));
|
||||
} else if (code >= 500 && code < 600) {
|
||||
response.error = std::make_unique<Error>(Error::Reason::Server,
|
||||
std::string{"HTTP status code "} + util::toString(code));
|
||||
} else {
|
||||
response.error = std::make_unique<Error>(Error::Reason::Other,
|
||||
std::string{"HTTP status code "} + util::toString(code));
|
||||
}
|
||||
|
||||
async.send();
|
||||
}
|
||||
|
||||
void HTTPRequest::onFailure(jni::JNIEnv& env, int type, const jni::String& message) {
|
||||
std::string messageStr = jni::Make<std::string>(env, message);
|
||||
|
||||
using Error = Response::Error;
|
||||
|
||||
switch (type) {
|
||||
case connectionError:
|
||||
response.error = std::make_unique<Error>(Error::Reason::Connection, messageStr);
|
||||
break;
|
||||
case temporaryError:
|
||||
response.error = std::make_unique<Error>(Error::Reason::Server, messageStr);
|
||||
break;
|
||||
default:
|
||||
response.error = std::make_unique<Error>(Error::Reason::Other, messageStr);
|
||||
}
|
||||
|
||||
async.send();
|
||||
}
|
||||
|
||||
HTTPFileSource::HTTPFileSource(const ResourceOptions& resourceOptions, const ClientOptions& clientOptions)
|
||||
: impl(std::make_unique<Impl>(resourceOptions.clone(), clientOptions.clone())) {}
|
||||
|
||||
HTTPFileSource::~HTTPFileSource() = default;
|
||||
|
||||
std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource, Callback callback) {
|
||||
return std::make_unique<HTTPRequest>(*impl->env, resource, callback);
|
||||
}
|
||||
|
||||
void HTTPFileSource::setResourceOptions(ResourceOptions options) {
|
||||
impl->setResourceOptions(options.clone());
|
||||
}
|
||||
|
||||
ResourceOptions HTTPFileSource::getResourceOptions() {
|
||||
return impl->getResourceOptions();
|
||||
}
|
||||
|
||||
void HTTPFileSource::setClientOptions(ClientOptions options) {
|
||||
impl->setClientOptions(options.clone());
|
||||
}
|
||||
|
||||
ClientOptions HTTPFileSource::getClientOptions() {
|
||||
return impl->getClientOptions();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
195
platform/android/MapLibreAndroid/src/cpp/i18n/collator.cpp
Normal file
195
platform/android/MapLibreAndroid/src/cpp/i18n/collator.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include <mbgl/i18n/collator.hpp>
|
||||
#include <mbgl/text/language_tag.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "attach_env.hpp"
|
||||
#include "collator_jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void Collator::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Collator>::Singleton(env);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Collator>> Collator::getInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<Collator>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Collator>(jni::Object<Locale>)>(env, "getInstance");
|
||||
return javaClass.Call(env, method, locale);
|
||||
}
|
||||
|
||||
void Collator::setStrength(jni::JNIEnv& env, const jni::Object<Collator>& collator, jni::jint strength) {
|
||||
static auto& javaClass = jni::Class<Collator>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void(jni::jint)>(env, "setStrength");
|
||||
collator.Call(env, method, strength);
|
||||
}
|
||||
|
||||
jni::jint Collator::compare(jni::JNIEnv& env,
|
||||
const jni::Object<Collator>& collator,
|
||||
const jni::String& lhs,
|
||||
const jni::String& rhs) {
|
||||
static auto& javaClass = jni::Class<Collator>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::jint(jni::String, jni::String)>(env, "compare");
|
||||
return collator.Call(env, method, lhs, rhs);
|
||||
}
|
||||
|
||||
void StringUtils::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<StringUtils>::Singleton(env);
|
||||
}
|
||||
|
||||
jni::Local<jni::String> StringUtils::unaccent(jni::JNIEnv& env, const jni::String& value) {
|
||||
static auto& javaClass = jni::Class<StringUtils>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::String(jni::String)>(env, "unaccent");
|
||||
return javaClass.Call(env, method, value);
|
||||
}
|
||||
|
||||
void Locale::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Locale>::Singleton(env);
|
||||
}
|
||||
|
||||
/*
|
||||
We would prefer to use for/toLanguageTag, but they're only available in API level 21+
|
||||
|
||||
jni::Object<Locale> Locale::forLanguageTag(jni::JNIEnv& env, jni::String languageTag) {
|
||||
using Signature = jni::Object<Locale>(jni::String);
|
||||
auto method = javaClass.GetStaticMethod<Signature>(env, "forLanguageTag");
|
||||
return javaClass.Call(env, method, languageTag);
|
||||
}
|
||||
|
||||
jni::String Locale::toLanguageTag(jni::JNIEnv& env, jni::Object<Locale> locale) {
|
||||
using Signature = jni::String();
|
||||
auto static method = javaClass.GetMethod<Signature>(env, "toLanguageTag");
|
||||
return locale.Call(env, method);
|
||||
}
|
||||
*/
|
||||
|
||||
jni::Local<jni::String> Locale::getLanguage(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String()>(env, "getLanguage");
|
||||
return locale.Call(env, method);
|
||||
}
|
||||
|
||||
jni::Local<jni::String> Locale::getCountry(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String()>(env, "getCountry");
|
||||
return locale.Call(env, method);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Locale>> Locale::getDefault(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<Locale>()>(env, "getDefault");
|
||||
return javaClass.Call(env, method);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Locale>> Locale::New(jni::JNIEnv& env, const jni::String& language) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jni::String>(env);
|
||||
return javaClass.New(env, constructor, language);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<Locale>> Locale::New(jni::JNIEnv& env, const jni::String& language, const jni::String& region) {
|
||||
static auto& javaClass = jni::Class<Locale>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jni::String, jni::String>(env);
|
||||
return javaClass.New(env, constructor, language, region);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
namespace platform {
|
||||
|
||||
class Collator::Impl {
|
||||
public:
|
||||
Impl(bool caseSensitive_, bool diacriticSensitive_, std::optional<std::string> locale_)
|
||||
: caseSensitive(caseSensitive_),
|
||||
diacriticSensitive(diacriticSensitive_),
|
||||
env(android::AttachEnv()) {
|
||||
LanguageTag languageTag = locale_ ? LanguageTag::fromBCP47(*locale_) : LanguageTag();
|
||||
if (!languageTag.language) {
|
||||
locale = jni::NewGlobal(*env, android::Locale::getDefault(*env));
|
||||
} else if (!languageTag.region) {
|
||||
locale = jni::NewGlobal(*env,
|
||||
android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language)));
|
||||
} else {
|
||||
locale = jni::NewGlobal(*env,
|
||||
android::Locale::New(*env,
|
||||
jni::Make<jni::String>(*env, *languageTag.language),
|
||||
jni::Make<jni::String>(*env, *languageTag.region)));
|
||||
}
|
||||
collator = jni::NewGlobal(*env, android::Collator::getInstance(*env, locale));
|
||||
if (!diacriticSensitive && !caseSensitive) {
|
||||
android::Collator::setStrength(*env, collator, 0 /*PRIMARY*/);
|
||||
} else if (diacriticSensitive && !caseSensitive) {
|
||||
android::Collator::setStrength(*env, collator, 1 /*SECONDARY*/);
|
||||
} else if (caseSensitive) {
|
||||
// If we're case-sensitive and diacritic-sensitive, we use a
|
||||
// case-sensitive collator and a fallback implementation of
|
||||
// diacritic-insensitivity.
|
||||
android::Collator::setStrength(*env, collator, 2 /*TERTIARY*/);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Impl& other) const {
|
||||
return caseSensitive == other.caseSensitive && diacriticSensitive == other.diacriticSensitive &&
|
||||
resolvedLocale() == other.resolvedLocale();
|
||||
}
|
||||
|
||||
int compare(const std::string& lhs, const std::string& rhs) const {
|
||||
bool useUnaccent = !diacriticSensitive && caseSensitive;
|
||||
// java.text.Collator doesn't support a
|
||||
// diacritic-insensitive/case-sensitive collation order, so we have to
|
||||
// compromise here. We use Android's case-sensitive Collator against
|
||||
// strings that have been "unaccented" using non-locale-aware nunicode
|
||||
// logic. Because of the difference in locale-awareness, this means
|
||||
// turning on case-sensitivity can _potentially_ change compare results
|
||||
// for strings that don't actually have any case differences.
|
||||
jni::Local<jni::String> jlhs = useUnaccent
|
||||
? android::StringUtils::unaccent(*env, jni::Make<jni::String>(*env, lhs))
|
||||
: jni::Make<jni::String>(*env, lhs);
|
||||
jni::Local<jni::String> jrhs = useUnaccent
|
||||
? android::StringUtils::unaccent(*env, jni::Make<jni::String>(*env, rhs))
|
||||
: jni::Make<jni::String>(*env, rhs);
|
||||
|
||||
jni::jint result = android::Collator::compare(*env, collator, jlhs, jrhs);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string resolvedLocale() const {
|
||||
std::string language = jni::Make<std::string>(*env, android::Locale::getLanguage(*env, locale));
|
||||
std::string region = jni::Make<std::string>(*env, android::Locale::getCountry(*env, locale));
|
||||
|
||||
std::optional<std::string> resultLanguage;
|
||||
if (!language.empty()) resultLanguage = language;
|
||||
std::optional<std::string> resultRegion;
|
||||
if (!region.empty()) resultRegion = region;
|
||||
|
||||
return LanguageTag(resultLanguage, {}, resultRegion).toBCP47();
|
||||
}
|
||||
|
||||
private:
|
||||
bool caseSensitive;
|
||||
bool diacriticSensitive;
|
||||
|
||||
android::UniqueEnv env;
|
||||
jni::Global<jni::Object<android::Collator>> collator;
|
||||
jni::Global<jni::Object<android::Locale>> locale;
|
||||
};
|
||||
|
||||
Collator::Collator(bool caseSensitive, bool diacriticSensitive, const std::optional<std::string>& locale_)
|
||||
: impl(std::make_shared<Impl>(caseSensitive, diacriticSensitive, locale_)) {}
|
||||
|
||||
bool Collator::operator==(const Collator& other) const {
|
||||
return *impl == *(other.impl);
|
||||
}
|
||||
|
||||
int Collator::compare(const std::string& lhs, const std::string& rhs) const {
|
||||
return impl->compare(lhs, rhs);
|
||||
}
|
||||
|
||||
std::string Collator::resolvedLocale() const {
|
||||
return impl->resolvedLocale();
|
||||
}
|
||||
|
||||
} // namespace platform
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
/*
|
||||
android::Collator and android::Locale are
|
||||
the JNI wrappers of
|
||||
java/text/Collator and java/util/Locale
|
||||
|
||||
mbgl::Collator is the portable interface
|
||||
Both implementations are in collator.cpp
|
||||
*/
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Locale {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Locale"; };
|
||||
|
||||
/* Requires API level 21+ in order to support script/variant
|
||||
static jni::Object<Locale> forLanguageTag(jni::JNIEnv&, jni::String);
|
||||
static jni::String toLanguageTag(jni::JNIEnv&, jni::Object<Locale>);
|
||||
*/
|
||||
static jni::Local<jni::Object<Locale>> getDefault(jni::JNIEnv&);
|
||||
static jni::Local<jni::String> getLanguage(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
static jni::Local<jni::String> getCountry(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
|
||||
static jni::Local<jni::Object<Locale>> New(jni::JNIEnv&, const jni::String&);
|
||||
static jni::Local<jni::Object<Locale>> New(jni::JNIEnv&, const jni::String&, const jni::String&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
class Collator {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/text/Collator"; };
|
||||
|
||||
static jni::Local<jni::Object<Collator>> getInstance(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
|
||||
static void setStrength(jni::JNIEnv&, const jni::Object<Collator>&, jni::jint);
|
||||
|
||||
static jni::jint compare(jni::JNIEnv&, const jni::Object<Collator>&, const jni::String&, const jni::String&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
class StringUtils {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/utils/StringUtils"; };
|
||||
|
||||
static jni::Local<jni::String> unaccent(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,88 @@
|
||||
#include <mbgl/i18n/number_format.hpp>
|
||||
#include <mbgl/text/language_tag.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "attach_env.hpp"
|
||||
#include "number_format_jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void NumberFormat::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<NumberFormat>::Singleton(env);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<NumberFormat>> NumberFormat::getInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<NumberFormat>(jni::Object<Locale>)>(env, "getInstance");
|
||||
return javaClass.Call(env, method, locale);
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<NumberFormat>> NumberFormat::getCurrencyInstance(jni::JNIEnv& env,
|
||||
const jni::Object<Locale>& locale) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetStaticMethod<jni::Object<NumberFormat>(jni::Object<Locale>)>(
|
||||
env, "getCurrencyInstance");
|
||||
return javaClass.Call(env, method, locale);
|
||||
}
|
||||
|
||||
jni::Local<jni::String> NumberFormat::format(jni::JNIEnv& env,
|
||||
const jni::Object<NumberFormat>& nf,
|
||||
jni::jdouble number) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::String(jni::jdouble)>(env, "format");
|
||||
return nf.Call(env, method, number);
|
||||
}
|
||||
|
||||
void NumberFormat::setMinimumFractionDigits(jni::JNIEnv& env, const jni::Object<NumberFormat>& nf, jni::jint value) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void(jni::jint)>(env, "setMinimumFractionDigits");
|
||||
return nf.Call(env, method, value);
|
||||
}
|
||||
|
||||
void NumberFormat::setMaximumFractionDigits(jni::JNIEnv& env, const jni::Object<NumberFormat>& nf, jni::jint value) {
|
||||
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<void(jni::jint)>(env, "setMaximumFractionDigits");
|
||||
return nf.Call(env, method, value);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
namespace platform {
|
||||
|
||||
std::string formatNumber(double number,
|
||||
const std::string& localeId,
|
||||
const std::string& currency,
|
||||
uint8_t minFractionDigits,
|
||||
uint8_t maxFractionDigits) {
|
||||
auto env{android::AttachEnv()};
|
||||
|
||||
jni::Global<jni::Object<android::Locale>> locale;
|
||||
LanguageTag languageTag = !localeId.empty() ? LanguageTag::fromBCP47(localeId) : LanguageTag();
|
||||
if (!languageTag.language) {
|
||||
locale = jni::NewGlobal(*env, android::Locale::getDefault(*env));
|
||||
} else if (!languageTag.region) {
|
||||
locale = jni::NewGlobal(*env, android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language)));
|
||||
} else {
|
||||
locale = jni::NewGlobal(*env,
|
||||
android::Locale::New(*env,
|
||||
jni::Make<jni::String>(*env, *languageTag.language),
|
||||
jni::Make<jni::String>(*env, *languageTag.region)));
|
||||
}
|
||||
|
||||
jni::Global<jni::Object<android::NumberFormat>> formatter;
|
||||
if (currency.empty()) {
|
||||
formatter = jni::NewGlobal(*env, android::NumberFormat::getInstance(*env, locale));
|
||||
android::NumberFormat::setMinimumFractionDigits(*env, formatter, static_cast<jni::jint>(minFractionDigits));
|
||||
android::NumberFormat::setMaximumFractionDigits(*env, formatter, static_cast<jni::jint>(maxFractionDigits));
|
||||
} else {
|
||||
formatter = jni::NewGlobal(*env, android::NumberFormat::getCurrencyInstance(*env, locale));
|
||||
}
|
||||
|
||||
auto result = android::NumberFormat::format(*env, formatter, static_cast<jni::jdouble>(number));
|
||||
return jni::Make<std::string>(*env, result);
|
||||
}
|
||||
|
||||
} // namespace platform
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include "collator_jni.hpp"
|
||||
|
||||
/*
|
||||
android::NumberFormat is the JNI wrapper
|
||||
of java/text/NumberFormat.
|
||||
*/
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class NumberFormat {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/text/NumberFormat"; };
|
||||
|
||||
static jni::Local<jni::Object<NumberFormat>> getInstance(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
static jni::Local<jni::Object<NumberFormat>> getCurrencyInstance(jni::JNIEnv&, const jni::Object<Locale>&);
|
||||
static jni::Local<jni::String> format(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jdouble);
|
||||
static void setMinimumFractionDigits(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jint);
|
||||
static void setMaximumFractionDigits(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jint);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
19
platform/android/MapLibreAndroid/src/cpp/java/util.cpp
Normal file
19
platform/android/MapLibreAndroid/src/cpp/java/util.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "util.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
namespace util {
|
||||
|
||||
void registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Arrays>::Singleton(env);
|
||||
jni::Class<List>::Singleton(env);
|
||||
jni::Class<Set>::Singleton(env);
|
||||
jni::Class<Map>::Singleton(env);
|
||||
jni::Class<Map::Entry>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace java
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
81
platform/android/MapLibreAndroid/src/cpp/java/util.hpp
Normal file
81
platform/android/MapLibreAndroid/src/cpp/java/util.hpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
namespace util {
|
||||
|
||||
class List : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/List"; };
|
||||
|
||||
template <class T>
|
||||
static jni::Local<jni::Array<jni::Object<T>>> toArray(jni::JNIEnv& env, const jni::Object<List>& list) {
|
||||
static auto& javaClass = jni::Class<List>::Singleton(env);
|
||||
static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>>()>(env, "toArray");
|
||||
|
||||
return jni::Local<jni::Array<jni::Object<T>>>(env, list.Call(env, toArray).release());
|
||||
};
|
||||
};
|
||||
|
||||
class Arrays : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Arrays"; };
|
||||
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<List>> asList(jni::JNIEnv& env, const jni::Array<jni::Object<T>>& array) {
|
||||
static auto& javaClass = jni::Class<Arrays>::Singleton(env);
|
||||
static auto asList = javaClass.GetStaticMethod<jni::Object<List>(jni::Array<jni::Object<>>)>(env, "asList");
|
||||
|
||||
auto typeErasedArray = jni::Local<jni::Array<jni::Object<>>>(env, jni::NewLocal(env, array).release());
|
||||
return javaClass.Call(env, asList, typeErasedArray);
|
||||
}
|
||||
};
|
||||
|
||||
class Set : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Set"; };
|
||||
|
||||
template <class T>
|
||||
static jni::Local<jni::Array<jni::Object<T>>> toArray(jni::JNIEnv& env, const jni::Object<Set>& list) {
|
||||
static auto& javaClass = jni::Class<Set>::Singleton(env);
|
||||
static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>>()>(env, "toArray");
|
||||
|
||||
return jni::Local<jni::Array<jni::Object<T>>>(env, list.Call(env, toArray).release());
|
||||
};
|
||||
};
|
||||
|
||||
class Map : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Map"; };
|
||||
|
||||
class Entry : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "java/util/Map$Entry"; };
|
||||
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<T>> getKey(jni::JNIEnv& env, const jni::Object<Entry>& entry) {
|
||||
static auto& javaClass = jni::Class<Map::Entry>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<>()>(env, "getKey");
|
||||
return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static jni::Local<jni::Object<T>> getValue(jni::JNIEnv& env, const jni::Object<Entry>& entry) {
|
||||
static auto& javaClass = jni::Class<Map::Entry>::Singleton(env);
|
||||
static auto method = javaClass.GetMethod<jni::Object<>()>(env, "getValue");
|
||||
return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void registerNative(jni::JNIEnv&);
|
||||
|
||||
} // namespace util
|
||||
} // namespace java
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
49
platform/android/MapLibreAndroid/src/cpp/java_types.cpp
Normal file
49
platform/android/MapLibreAndroid/src/cpp/java_types.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "java_types.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
|
||||
jni::jclass* ObjectArray::jclass;
|
||||
|
||||
jni::jclass* String::jclass;
|
||||
|
||||
jni::jclass* Boolean::jclass;
|
||||
jni::jmethodID* Boolean::booleanValueMethodId;
|
||||
|
||||
jni::jclass* Number::jclass;
|
||||
jni::jmethodID* Number::floatValueMethodId;
|
||||
jni::jmethodID* Number::doubleValueMethodId;
|
||||
jni::jmethodID* Number::longValueMethodId;
|
||||
|
||||
jni::jclass* Map::jclass;
|
||||
jni::jmethodID* Map::getMethodId;
|
||||
jni::jmethodID* Map::keySetMethodId;
|
||||
|
||||
jni::jclass* Set::jclass;
|
||||
jni::jmethodID* Set::toArrayMethodId;
|
||||
|
||||
void registerNatives(JNIEnv& env) {
|
||||
ObjectArray::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "[Ljava/lang/Object;")).release();
|
||||
|
||||
String::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/String")).release();
|
||||
|
||||
Boolean::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Boolean")).release();
|
||||
Boolean::booleanValueMethodId = &jni::GetMethodID(env, *Boolean::jclass, "booleanValue", "()Z");
|
||||
|
||||
Number::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Number")).release();
|
||||
Number::floatValueMethodId = &jni::GetMethodID(env, *Number::jclass, "floatValue", "()F");
|
||||
Number::doubleValueMethodId = &jni::GetMethodID(env, *Number::jclass, "doubleValue", "()D");
|
||||
Number::longValueMethodId = &jni::GetMethodID(env, *Number::jclass, "longValue", "()J");
|
||||
|
||||
Map::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Map")).release();
|
||||
Map::getMethodId = &jni::GetMethodID(env, *Map::jclass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
Map::keySetMethodId = &jni::GetMethodID(env, *Map::jclass, "keySet", "()Ljava/util/Set;");
|
||||
|
||||
Set::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Set")).release();
|
||||
Set::toArrayMethodId = &jni::GetMethodID(env, *Set::jclass, "toArray", "()[Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
} // namespace java
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
43
platform/android/MapLibreAndroid/src/cpp/java_types.hpp
Normal file
43
platform/android/MapLibreAndroid/src/cpp/java_types.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace java {
|
||||
|
||||
struct ObjectArray {
|
||||
static jni::jclass* jclass;
|
||||
};
|
||||
|
||||
struct String {
|
||||
static jni::jclass* jclass;
|
||||
};
|
||||
|
||||
struct Boolean {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* booleanValueMethodId;
|
||||
};
|
||||
|
||||
struct Number {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* floatValueMethodId;
|
||||
static jni::jmethodID* doubleValueMethodId;
|
||||
static jni::jmethodID* longValueMethodId;
|
||||
};
|
||||
|
||||
struct Map {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* getMethodId;
|
||||
static jni::jmethodID* keySetMethodId;
|
||||
};
|
||||
|
||||
struct Set {
|
||||
static jni::jclass* jclass;
|
||||
static jni::jmethodID* toArrayMethodId;
|
||||
};
|
||||
|
||||
void registerNatives(JNIEnv&);
|
||||
} // namespace java
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
173
platform/android/MapLibreAndroid/src/cpp/jni_native.cpp
Normal file
173
platform/android/MapLibreAndroid/src/cpp/jni_native.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
#include "jni_native.hpp"
|
||||
|
||||
#include "annotation/marker.hpp"
|
||||
#include "annotation/polygon.hpp"
|
||||
#include "annotation/polyline.hpp"
|
||||
#include "bitmap.hpp"
|
||||
#include "bitmap_factory.hpp"
|
||||
#include "connectivity_listener.hpp"
|
||||
#include "conversion/collection.hpp"
|
||||
#include "conversion/conversion.hpp"
|
||||
#include "file_source.hpp"
|
||||
#include "geojson/feature.hpp"
|
||||
#include "geojson/feature_collection.hpp"
|
||||
#include "geojson/geometry.hpp"
|
||||
#include "geojson/geometry_collection.hpp"
|
||||
#include "geojson/line_string.hpp"
|
||||
#include "geojson/multi_line_string.hpp"
|
||||
#include "geojson/multi_point.hpp"
|
||||
#include "geojson/multi_polygon.hpp"
|
||||
#include "geojson/point.hpp"
|
||||
#include "geojson/polygon.hpp"
|
||||
#include "geometry/lat_lng.hpp"
|
||||
#include "geometry/lat_lng_bounds.hpp"
|
||||
#include "geometry/lat_lng_quad.hpp"
|
||||
#include "geometry/projected_meters.hpp"
|
||||
#include "graphics/pointf.hpp"
|
||||
#include "graphics/rectf.hpp"
|
||||
#include "gson/json_array.hpp"
|
||||
#include "gson/json_element.hpp"
|
||||
#include "gson/json_object.hpp"
|
||||
#include "gson/json_primitive.hpp"
|
||||
#include "java_types.hpp"
|
||||
#include "map_renderer.hpp"
|
||||
#include "map_renderer_runnable.hpp"
|
||||
#include "maplibre.hpp"
|
||||
#include "native_map_view.hpp"
|
||||
#include "util/tile_server_options.hpp"
|
||||
#ifndef MBGL_MODULE_OFFLINE_DISABLE
|
||||
#include "offline/offline_manager.hpp"
|
||||
#include "offline/offline_region.hpp"
|
||||
#include "offline/offline_region_definition.hpp"
|
||||
#include "offline/offline_region_error.hpp"
|
||||
#include "offline/offline_region_status.hpp"
|
||||
#endif
|
||||
#include "style/transition_options.hpp"
|
||||
#include "style/layers/layer_manager.hpp"
|
||||
#include "style/sources/source.hpp"
|
||||
#include "style/light.hpp"
|
||||
#include "style/formatted.hpp"
|
||||
#include "style/formatted_section.hpp"
|
||||
#ifndef MBGL_MODULE_SNAPSHOT_DISABLE
|
||||
#include "snapshotter/map_snapshotter.hpp"
|
||||
#include "snapshotter/map_snapshot.hpp"
|
||||
#endif
|
||||
#include "i18n/collator_jni.hpp"
|
||||
#include "i18n/number_format_jni.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "text/local_glyph_rasterizer_jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void RegisterNativeHTTPRequest(JNIEnv&);
|
||||
|
||||
void registerNatives(JavaVM* vm) {
|
||||
theJVM = vm;
|
||||
|
||||
jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6);
|
||||
|
||||
// For the FileSource
|
||||
static mbgl::util::RunLoop mainRunLoop;
|
||||
FileSource::registerNative(env);
|
||||
|
||||
// Basic types
|
||||
java::registerNatives(env);
|
||||
java::util::registerNative(env);
|
||||
PointF::registerNative(env);
|
||||
RectF::registerNative(env);
|
||||
|
||||
// GeoJSON
|
||||
geojson::Feature::registerNative(env);
|
||||
geojson::FeatureCollection::registerNative(env);
|
||||
geojson::Geometry::registerNative(env);
|
||||
geojson::GeometryCollection::registerNative(env);
|
||||
geojson::LineString::registerNative(env);
|
||||
geojson::MultiLineString::registerNative(env);
|
||||
geojson::MultiPoint::registerNative(env);
|
||||
geojson::MultiPolygon::registerNative(env);
|
||||
geojson::Point::registerNative(env);
|
||||
geojson::Polygon::registerNative(env);
|
||||
|
||||
// Geometry
|
||||
LatLng::registerNative(env);
|
||||
LatLngBounds::registerNative(env);
|
||||
LatLngQuad::registerNative(env);
|
||||
ProjectedMeters::registerNative(env);
|
||||
|
||||
// GSon
|
||||
gson::JsonArray::registerNative(env);
|
||||
gson::JsonElement::registerNative(env);
|
||||
gson::JsonObject::registerNative(env);
|
||||
gson::JsonPrimitive::registerNative(env);
|
||||
|
||||
// Annotation
|
||||
Marker::registerNative(env);
|
||||
Polygon::registerNative(env);
|
||||
Polyline::registerNative(env);
|
||||
|
||||
// Map
|
||||
MapRenderer::registerNative(env);
|
||||
MapRendererRunnable::registerNative(env);
|
||||
NativeMapView::registerNative(env);
|
||||
|
||||
// Http
|
||||
RegisterNativeHTTPRequest(env);
|
||||
|
||||
// Bitmap
|
||||
Bitmap::registerNative(env);
|
||||
BitmapFactory::registerNative(env);
|
||||
|
||||
// Style
|
||||
TransitionOptions::registerNative(env);
|
||||
LayerManagerAndroid::get()->registerNative(env);
|
||||
Source::registerNative(env);
|
||||
Light::registerNative(env);
|
||||
Position::registerNative(env);
|
||||
Formatted::registerNative(env);
|
||||
FormattedSection::registerNative(env);
|
||||
|
||||
// Map
|
||||
CameraPosition::registerNative(env);
|
||||
Image::registerNative(env);
|
||||
|
||||
// Connectivity
|
||||
ConnectivityListener::registerNative(env);
|
||||
|
||||
// Offline
|
||||
#ifndef MBGL_MODULE_OFFLINE_DISABLE
|
||||
OfflineManager::registerNative(env);
|
||||
OfflineRegion::registerNative(env);
|
||||
OfflineRegionDefinition::registerNative(env);
|
||||
OfflineTilePyramidRegionDefinition::registerNative(env);
|
||||
OfflineGeometryRegionDefinition::registerNative(env);
|
||||
OfflineRegionError::registerNative(env);
|
||||
OfflineRegionStatus::registerNative(env);
|
||||
#endif
|
||||
|
||||
// Snapshotter
|
||||
#ifndef MBGL_MODULE_SNAPSHOT_DISABLE
|
||||
MapSnapshotter::registerNative(env);
|
||||
MapSnapshot::registerNative(env);
|
||||
#endif
|
||||
|
||||
// text
|
||||
LocalGlyphRasterizer::registerNative(env);
|
||||
Locale::registerNative(env);
|
||||
Collator::registerNative(env);
|
||||
StringUtils::registerNative(env);
|
||||
NumberFormat::registerNative(env);
|
||||
|
||||
// Logger
|
||||
Logger::registerNative(env);
|
||||
|
||||
// AssetManager
|
||||
MapLibre::registerNative(env);
|
||||
|
||||
// Util
|
||||
DefaultStyle::registerNative(env);
|
||||
TileServerOptions::registerNative(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
13
platform/android/MapLibreAndroid/src/cpp/jni_native.hpp
Normal file
13
platform/android/MapLibreAndroid/src/cpp/jni_native.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/util.hpp>
|
||||
|
||||
#include "jni.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
MBGL_EXPORT void registerNatives(JavaVM* vm);
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
34
platform/android/MapLibreAndroid/src/cpp/logger.cpp
Normal file
34
platform/android/MapLibreAndroid/src/cpp/logger.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "logger.hpp"
|
||||
#include "java_types.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
void Logger::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Logger>::Singleton(env);
|
||||
}
|
||||
|
||||
void Logger::log(jni::JNIEnv& env, EventSeverity severity, const std::string& msg) {
|
||||
static auto& _class = jni::Class<Logger>::Singleton(env);
|
||||
|
||||
auto tag = jni::Make<jni::String>(env, "Mbgl");
|
||||
auto message = jni::Make<jni::String>(env, msg);
|
||||
using Signature = void(jni::String, jni::String);
|
||||
|
||||
if (severity == EventSeverity::Debug) {
|
||||
auto static debug = _class.GetStaticMethod<Signature>(env, "d");
|
||||
_class.Call(env, debug, tag, message);
|
||||
} else if (severity == EventSeverity::Info) {
|
||||
auto static info = _class.GetStaticMethod<Signature>(env, "i");
|
||||
_class.Call(env, info, tag, message);
|
||||
} else if (severity == EventSeverity::Warning) {
|
||||
auto static warning = _class.GetStaticMethod<Signature>(env, "w");
|
||||
_class.Call(env, warning, tag, message);
|
||||
} else {
|
||||
auto static error = _class.GetStaticMethod<Signature>(env, "e");
|
||||
_class.Call(env, error, tag, message);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
19
platform/android/MapLibreAndroid/src/cpp/logger.hpp
Normal file
19
platform/android/MapLibreAndroid/src/cpp/logger.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/event.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
#include "bitmap.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/log/Logger"; };
|
||||
static void registerNative(jni::JNIEnv &);
|
||||
|
||||
static void log(jni::JNIEnv &, EventSeverity severity, const std::string &msg);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
13
platform/android/MapLibreAndroid/src/cpp/logging_android.cpp
Normal file
13
platform/android/MapLibreAndroid/src/cpp/logging_android.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include "logger.hpp"
|
||||
#include "attach_env.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
void Log::platformRecord(EventSeverity severity, const std::string &msg) {
|
||||
auto env{android::AttachEnv()};
|
||||
android::Logger::log(*env, severity, msg);
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
9
platform/android/MapLibreAndroid/src/cpp/main.cpp
Normal file
9
platform/android/MapLibreAndroid/src/cpp/main.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "jni.hpp"
|
||||
#include "jni_native.hpp"
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *) {
|
||||
assert(vm != nullptr);
|
||||
mbgl::android::registerNatives(vm);
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#include "camera_position.hpp"
|
||||
#include "../geometry/lat_lng.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<CameraPosition>> CameraPosition::New(jni::JNIEnv& env,
|
||||
mbgl::CameraOptions options,
|
||||
float pixelRatio) {
|
||||
static auto& javaClass = jni::Class<CameraPosition>::Singleton(env);
|
||||
static auto constructor =
|
||||
javaClass.GetConstructor<jni::Object<LatLng>, double, double, double, jni::Array<jni::jdouble>>(env);
|
||||
|
||||
// wrap LatLng values coming from core
|
||||
auto center = options.center.value();
|
||||
center.wrap();
|
||||
|
||||
// convert bearing, measured in radians counterclockwise from true north.
|
||||
// Wrapped to [−π rad, π rad). Android binding from 0 to 360 degrees
|
||||
double bearing_degrees = options.bearing.value_or(0);
|
||||
while (bearing_degrees > 360) {
|
||||
bearing_degrees -= 360;
|
||||
}
|
||||
while (bearing_degrees < 0) {
|
||||
bearing_degrees += 360;
|
||||
}
|
||||
|
||||
// convert tilt, core ranges from [0 rad, 1,0472 rad], android ranges from 0 to 60
|
||||
double tilt_degrees = options.pitch.value_or(0);
|
||||
|
||||
std::vector<jdouble> paddingVect;
|
||||
auto insets = options.padding.value_or(EdgeInsets{0, 0, 0, 0});
|
||||
auto padding = jni::Array<jni::jdouble>::New(env, 4);
|
||||
paddingVect.push_back(insets.left() * pixelRatio);
|
||||
paddingVect.push_back(insets.top() * pixelRatio);
|
||||
paddingVect.push_back(insets.right() * pixelRatio);
|
||||
paddingVect.push_back(insets.bottom() * pixelRatio);
|
||||
padding.SetRegion<std::vector<jni::jdouble>>(env, 0, paddingVect);
|
||||
|
||||
return javaClass.New(
|
||||
env, constructor, LatLng::New(env, center), options.zoom.value_or(0), tilt_degrees, bearing_degrees, padding);
|
||||
}
|
||||
|
||||
mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env,
|
||||
const jni::Object<CameraPosition>& position,
|
||||
float pixelRatio) {
|
||||
static auto& javaClass = jni::Class<CameraPosition>::Singleton(env);
|
||||
static auto bearing = javaClass.GetField<jni::jdouble>(env, "bearing");
|
||||
static auto target = javaClass.GetField<jni::Object<LatLng>>(env, "target");
|
||||
static auto tilt = javaClass.GetField<jni::jdouble>(env, "tilt");
|
||||
static auto zoom = javaClass.GetField<jni::jdouble>(env, "zoom");
|
||||
static auto paddingField = javaClass.GetField<jni::Array<jni::jdouble>>(env, "padding");
|
||||
|
||||
auto padding = position.Get(env, paddingField);
|
||||
auto center = LatLng::getLatLng(env, position.Get(env, target));
|
||||
|
||||
return mbgl::CameraOptions{center,
|
||||
padding && padding.Length(env) == 4 ? EdgeInsets{padding.Get(env, 1) * pixelRatio,
|
||||
padding.Get(env, 0) * pixelRatio,
|
||||
padding.Get(env, 3) * pixelRatio,
|
||||
padding.Get(env, 2) * pixelRatio}
|
||||
: (EdgeInsets){},
|
||||
{},
|
||||
position.Get(env, zoom),
|
||||
position.Get(env, bearing),
|
||||
position.Get(env, tilt)};
|
||||
}
|
||||
|
||||
void CameraPosition::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<CameraPosition>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/map/camera.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class CameraPosition : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/camera/CameraPosition"; };
|
||||
|
||||
static jni::Local<jni::Object<CameraPosition>> New(jni::JNIEnv&, mbgl::CameraOptions, float pixelRatio);
|
||||
|
||||
static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, const jni::Object<CameraPosition>&, float pixelRatio);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
74
platform/android/MapLibreAndroid/src/cpp/map/image.cpp
Normal file
74
platform/android/MapLibreAndroid/src/cpp/map/image.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#include <mbgl/style/image.hpp>
|
||||
#include <mbgl/util/exception.hpp>
|
||||
#include "image.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
mbgl::style::Image Image::getImage(jni::JNIEnv& env, const jni::Object<Image>& image) {
|
||||
static auto& javaClass = jni::Class<Image>::Singleton(env);
|
||||
static auto widthField = javaClass.GetField<jni::jint>(env, "width");
|
||||
static auto heightField = javaClass.GetField<jni::jint>(env, "height");
|
||||
static auto pixelRatioField = javaClass.GetField<jni::jfloat>(env, "pixelRatio");
|
||||
static auto bufferField = javaClass.GetField<jni::Array<jbyte>>(env, "buffer");
|
||||
static auto nameField = javaClass.GetField<jni::String>(env, "name");
|
||||
static auto sdfField = javaClass.GetField<jni::jboolean>(env, "sdf");
|
||||
static auto contentField = javaClass.GetField<jni::Array<jfloat>>(env, "content");
|
||||
static auto stretchXField = javaClass.GetField<jni::Array<jfloat>>(env, "stretchX");
|
||||
static auto stretchYField = javaClass.GetField<jni::Array<jfloat>>(env, "stretchY");
|
||||
|
||||
auto height = image.Get(env, heightField);
|
||||
auto width = image.Get(env, widthField);
|
||||
auto pixelRatio = image.Get(env, pixelRatioField);
|
||||
auto pixels = image.Get(env, bufferField);
|
||||
auto name = jni::Make<std::string>(env, image.Get(env, nameField));
|
||||
auto sdf = (bool)image.Get(env, sdfField);
|
||||
auto content = image.Get(env, contentField);
|
||||
auto stretchX = image.Get(env, stretchXField);
|
||||
auto stretchY = image.Get(env, stretchYField);
|
||||
jni::NullCheck(env, pixels.get());
|
||||
std::size_t size = pixels.Length(env);
|
||||
|
||||
mbgl::PremultipliedImage premultipliedImage({static_cast<uint32_t>(width), static_cast<uint32_t>(height)});
|
||||
if (premultipliedImage.bytes() != uint32_t(size)) {
|
||||
throw mbgl::util::StyleImageException("Image pixel count mismatch");
|
||||
}
|
||||
|
||||
jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
|
||||
|
||||
style::ImageStretches imageStretchesX = {};
|
||||
style::ImageStretches imageStretchesY = {};
|
||||
if (stretchX.get()) {
|
||||
std::size_t sizeX = stretchX.Length(env);
|
||||
for (jni::jsize i = 0; i < sizeX - 1; i += 2) {
|
||||
imageStretchesX.push_back({stretchX.Get(env, i), stretchX.Get(env, i + 1)});
|
||||
}
|
||||
}
|
||||
if (stretchY.get()) {
|
||||
std::size_t sizeY = stretchY.Length(env);
|
||||
for (jni::jsize i = 0; i < sizeY - 1; i += 2) {
|
||||
imageStretchesY.push_back({stretchY.Get(env, i), stretchY.Get(env, i + 1)});
|
||||
}
|
||||
}
|
||||
|
||||
if (content) {
|
||||
const style::ImageContent imageContent = style::ImageContent{
|
||||
content.Get(env, 0), content.Get(env, 1), content.Get(env, 2), content.Get(env, 3)};
|
||||
return mbgl::style::Image{name,
|
||||
std::move(premultipliedImage),
|
||||
pixelRatio,
|
||||
sdf,
|
||||
imageStretchesX,
|
||||
imageStretchesY,
|
||||
std::move(imageContent)};
|
||||
}
|
||||
|
||||
return mbgl::style::Image{name, std::move(premultipliedImage), pixelRatio, sdf, imageStretchesX, imageStretchesY};
|
||||
}
|
||||
|
||||
void Image::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<Image>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
21
platform/android/MapLibreAndroid/src/cpp/map/image.hpp
Normal file
21
platform/android/MapLibreAndroid/src/cpp/map/image.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
#include <mbgl/style/image.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class Image : private mbgl::util::noncopyable {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/maps/Image"; };
|
||||
|
||||
static mbgl::style::Image getImage(jni::JNIEnv&, const jni::Object<Image>&);
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
293
platform/android/MapLibreAndroid/src/cpp/map_renderer.cpp
Normal file
293
platform/android/MapLibreAndroid/src/cpp/map_renderer.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
#include "map_renderer.hpp"
|
||||
|
||||
#include <mbgl/renderer/renderer.hpp>
|
||||
#include <mbgl/gfx/backend_scope.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "attach_env.hpp"
|
||||
#include "android_renderer_backend.hpp"
|
||||
#include "map_renderer_runnable.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
MapRenderer::MapRenderer(jni::JNIEnv& _env,
|
||||
const jni::Object<MapRenderer>& obj,
|
||||
jni::jfloat pixelRatio_,
|
||||
const jni::String& localIdeographFontFamily_)
|
||||
: javaPeer(_env, obj),
|
||||
pixelRatio(pixelRatio_),
|
||||
localIdeographFontFamily(localIdeographFontFamily_ ? jni::Make<std::string>(_env, localIdeographFontFamily_)
|
||||
: std::optional<std::string>{}),
|
||||
mailboxData(this) {}
|
||||
|
||||
MapRenderer::MailboxData::MailboxData(Scheduler* scheduler_)
|
||||
: scheduler(scheduler_) {
|
||||
assert(scheduler);
|
||||
}
|
||||
|
||||
std::shared_ptr<Mailbox> MapRenderer::MailboxData::getMailbox() const noexcept {
|
||||
if (!mailbox) {
|
||||
mailbox = std::make_shared<Mailbox>(*scheduler);
|
||||
}
|
||||
return mailbox;
|
||||
}
|
||||
|
||||
MapRenderer::~MapRenderer() = default;
|
||||
|
||||
void MapRenderer::reset() {
|
||||
try {
|
||||
destroyed = true;
|
||||
|
||||
if (renderer) {
|
||||
// Make sure to destroy the renderer on the GL Thread
|
||||
auto self = ActorRef<MapRenderer>(*this, mailboxData.getMailbox());
|
||||
self.ask(&MapRenderer::resetRenderer).wait();
|
||||
}
|
||||
|
||||
// Lock to make sure there is no concurrent initialisation on the gl thread
|
||||
std::lock_guard<std::mutex> lock(initialisationMutex);
|
||||
rendererObserver.reset();
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android, std::string("MapRenderer::reset failed: ") + exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
ActorRef<Renderer> MapRenderer::actor() const {
|
||||
return *rendererRef;
|
||||
}
|
||||
|
||||
void MapRenderer::schedule(std::function<void()>&& scheduled) {
|
||||
try {
|
||||
// Create a runnable
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
auto runnable = std::make_unique<MapRendererRunnable>(*_env, std::move(scheduled));
|
||||
|
||||
// Obtain ownership of the peer (gets transferred to the MapRenderer on the JVM for later GC)
|
||||
auto peer = runnable->peer();
|
||||
|
||||
// Queue the event on the Java Peer
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(*_env);
|
||||
static auto queueEvent = javaClass.GetMethod<void(jni::Object<MapRendererRunnable>)>(*_env, "queueEvent");
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference) {
|
||||
weakReference.Call(*_env, queueEvent, peer);
|
||||
}
|
||||
|
||||
// Release the c++ peer as it will be destroyed on GC of the Java Peer
|
||||
runnable.release();
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android, std::string("MapRenderer::schedule failed: ") + exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t MapRenderer::waitForEmpty(Milliseconds timeout) {
|
||||
try {
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(*_env);
|
||||
static auto waitForEmpty = javaClass.GetMethod<jni::jint(jni::jlong)>(*_env, "waitForEmpty");
|
||||
if (auto weakReference = javaPeer.get(*_env)) {
|
||||
return weakReference.Call(*_env, waitForEmpty, static_cast<int64_t>(timeout.count()));
|
||||
}
|
||||
// If the peer is already cleaned up, there's nothing to wait for
|
||||
return 0;
|
||||
} catch (...) {
|
||||
Log::Error(Event::Android, "MapRenderer::waitForEmpty failed");
|
||||
jni::ThrowJavaError(*android::AttachEnv(), std::current_exception());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::requestRender() {
|
||||
try {
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(*_env);
|
||||
static auto onInvalidate = javaClass.GetMethod<void()>(*_env, "requestRender");
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference) {
|
||||
weakReference.Call(*_env, onInvalidate);
|
||||
}
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android, std::string("MapRenderer::requestRender failed: ") + exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::update(std::shared_ptr<UpdateParameters> params) {
|
||||
try {
|
||||
// Lock on the parameters
|
||||
std::lock_guard<std::mutex> lock(updateMutex);
|
||||
updateParameters = std::move(params);
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android, std::string("MapRenderer::update failed: ") + exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::setObserver(std::shared_ptr<RendererObserver> _rendererObserver) {
|
||||
try {
|
||||
// Lock as the initialization can come from the main thread or the GL thread first
|
||||
std::lock_guard<std::mutex> lock(initialisationMutex);
|
||||
|
||||
rendererObserver = std::move(_rendererObserver);
|
||||
|
||||
// Set the new observer on the Renderer implementation
|
||||
if (renderer) {
|
||||
renderer->setObserver(rendererObserver.get());
|
||||
}
|
||||
} catch (const std::exception& exception) {
|
||||
Log::Error(Event::Android, std::string("MapRenderer::setObserver failed: ") + exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::requestSnapshot(SnapshotCallback callback) {
|
||||
auto self = ActorRef<MapRenderer>(*this, mailboxData.getMailbox());
|
||||
self.invoke(
|
||||
&MapRenderer::scheduleSnapshot,
|
||||
std::make_unique<SnapshotCallback>(
|
||||
[&, callback = std::move(callback), runloop = util::RunLoop::Get()](PremultipliedImage image) {
|
||||
runloop->invoke(
|
||||
[callback = std::move(callback), image = std::move(image), renderer = std::move(this)]() mutable {
|
||||
if (renderer && !renderer->destroyed) {
|
||||
callback(std::move(image));
|
||||
}
|
||||
});
|
||||
snapshotCallback.reset();
|
||||
}));
|
||||
}
|
||||
|
||||
// Called on OpenGL thread //
|
||||
|
||||
void MapRenderer::resetRenderer() {
|
||||
renderer.reset();
|
||||
backend.reset();
|
||||
}
|
||||
|
||||
void MapRenderer::scheduleSnapshot(std::unique_ptr<SnapshotCallback> callback) {
|
||||
snapshotCallback = std::move(callback);
|
||||
requestRender();
|
||||
}
|
||||
|
||||
void MapRenderer::render(JNIEnv&) {
|
||||
assert(renderer);
|
||||
|
||||
std::shared_ptr<UpdateParameters> params;
|
||||
{
|
||||
// Lock on the parameters
|
||||
std::unique_lock<std::mutex> lock(updateMutex);
|
||||
if (!updateParameters) return;
|
||||
|
||||
// Hold on to the update parameters during render
|
||||
params = updateParameters;
|
||||
}
|
||||
|
||||
// Activate the backend
|
||||
gfx::BackendScope backendGuard{*backend};
|
||||
|
||||
// Ensure that the "current" scheduler on the render thread is
|
||||
// this scheduler.
|
||||
Scheduler::SetCurrent(this);
|
||||
|
||||
if (framebufferSizeChanged) {
|
||||
backend->updateViewPort();
|
||||
framebufferSizeChanged = false;
|
||||
}
|
||||
|
||||
renderer->render(params);
|
||||
|
||||
// Deliver the snapshot if requested
|
||||
if (snapshotCallback) {
|
||||
snapshotCallback->operator()(backend->readFramebuffer());
|
||||
snapshotCallback.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::onSurfaceCreated(JNIEnv&) {
|
||||
// Lock as the initialization can come from the main thread or the GL thread first
|
||||
std::lock_guard<std::mutex> lock(initialisationMutex);
|
||||
|
||||
// The GL context is already active if get a new surface.
|
||||
gfx::BackendScope backendGuard{*backend, gfx::BackendScope::ScopeType::Implicit};
|
||||
|
||||
// The android system will have already destroyed the underlying
|
||||
// GL resources if this is not the first initialization and an
|
||||
// attempt to clean them up will fail
|
||||
if (backend) backend->markContextLost();
|
||||
if (renderer) renderer->markContextLost();
|
||||
|
||||
// Reset in opposite order
|
||||
renderer.reset();
|
||||
backend.reset();
|
||||
|
||||
// Create the new backend and renderer
|
||||
backend = std::make_unique<AndroidRendererBackend>();
|
||||
renderer = std::make_unique<Renderer>(*backend, pixelRatio, localIdeographFontFamily);
|
||||
rendererRef = std::make_unique<ActorRef<Renderer>>(*renderer, mailboxData.getMailbox());
|
||||
|
||||
// Set the observer on the new Renderer implementation
|
||||
if (rendererObserver) {
|
||||
renderer->setObserver(rendererObserver.get());
|
||||
}
|
||||
}
|
||||
|
||||
void MapRenderer::onSurfaceChanged(JNIEnv& env, jint width, jint height) {
|
||||
if (!renderer) {
|
||||
// In case the surface has been destroyed (due to app back-grounding)
|
||||
onSurfaceCreated(env);
|
||||
}
|
||||
|
||||
backend->resizeFramebuffer(width, height);
|
||||
framebufferSizeChanged = true;
|
||||
requestRender();
|
||||
}
|
||||
|
||||
void MapRenderer::onRendererReset(JNIEnv&) {
|
||||
// Make sure to destroy the renderer on the GL Thread
|
||||
auto self = ActorRef<MapRenderer>(*this, mailboxData.getMailbox());
|
||||
self.ask(&MapRenderer::resetRenderer).wait();
|
||||
}
|
||||
|
||||
// needs to be called on GL thread
|
||||
void MapRenderer::onSurfaceDestroyed(JNIEnv&) {
|
||||
resetRenderer();
|
||||
}
|
||||
|
||||
void MapRenderer::setSwapBehaviorFlush(JNIEnv&, jboolean flush) {
|
||||
backend->setSwapBehavior(flush ? gfx::Renderable::SwapBehaviour::Flush : gfx::Renderable::SwapBehaviour::NoFlush);
|
||||
}
|
||||
|
||||
// Static methods //
|
||||
|
||||
void MapRenderer::registerNative(jni::JNIEnv& env) {
|
||||
// Lookup the class
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
// Register the peer
|
||||
jni::RegisterNativePeer<MapRenderer>(
|
||||
env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
jni::MakePeer<MapRenderer, const jni::Object<MapRenderer>&, jni::jfloat, const jni::String&>,
|
||||
"nativeInitialize",
|
||||
"finalize",
|
||||
METHOD(&MapRenderer::render, "nativeRender"),
|
||||
METHOD(&MapRenderer::onRendererReset, "nativeReset"),
|
||||
METHOD(&MapRenderer::onSurfaceCreated, "nativeOnSurfaceCreated"),
|
||||
METHOD(&MapRenderer::onSurfaceChanged, "nativeOnSurfaceChanged"),
|
||||
METHOD(&MapRenderer::onSurfaceDestroyed, "nativeOnSurfaceDestroyed"),
|
||||
METHOD(&MapRenderer::setSwapBehaviorFlush, "nativeSetSwapBehaviorFlush"));
|
||||
}
|
||||
|
||||
MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, const jni::Object<MapRenderer>& jObject) {
|
||||
static auto& javaClass = jni::Class<MapRenderer>::Singleton(env);
|
||||
static auto field = javaClass.GetField<jlong>(env, "nativePtr");
|
||||
MapRenderer* mapRenderer = reinterpret_cast<MapRenderer*>(jObject.Get(env, field));
|
||||
assert(mapRenderer != nullptr);
|
||||
return *mapRenderer;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
143
platform/android/MapLibreAndroid/src/cpp/map_renderer.hpp
Normal file
143
platform/android/MapLibreAndroid/src/cpp/map_renderer.hpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/actor/actor_ref.hpp>
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/util/image.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
#include <optional>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template <class>
|
||||
class ActorRef;
|
||||
class Mailbox;
|
||||
class Renderer;
|
||||
class RendererBackend;
|
||||
class RendererObserver;
|
||||
class ThreadPool;
|
||||
class UpdateParameters;
|
||||
|
||||
namespace android {
|
||||
|
||||
class AndroidRendererBackend;
|
||||
|
||||
/**
|
||||
* The MapRenderer is a peer class that encapsulates the actions
|
||||
* performed on the GL Thread.
|
||||
*
|
||||
* The public methods are safe to call from the main thread, others are not.
|
||||
*/
|
||||
class MapRenderer : public Scheduler {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/maps/renderer/MapRenderer"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
static MapRenderer& getNativePeer(JNIEnv&, const jni::Object<MapRenderer>&);
|
||||
|
||||
MapRenderer(jni::JNIEnv& _env,
|
||||
const jni::Object<MapRenderer>&,
|
||||
jni::jfloat pixelRatio,
|
||||
const jni::String& localIdeographFontFamily);
|
||||
|
||||
~MapRenderer() override;
|
||||
|
||||
// Resets the renderer to clean up on the calling thread
|
||||
void reset();
|
||||
|
||||
// Takes the RendererObserver by shared_ptr so we
|
||||
// don't have to make the header public. Use
|
||||
// this instead of Renderer#setObserver directly
|
||||
void setObserver(std::shared_ptr<RendererObserver>);
|
||||
|
||||
// Sets the new update parameters to use on subsequent
|
||||
// renders. Be sure to trigger a render with
|
||||
// requestRender().
|
||||
void update(std::shared_ptr<UpdateParameters>);
|
||||
|
||||
// Gives a handle to the Renderer to enable actions on
|
||||
// any thread.
|
||||
ActorRef<Renderer> actor() const;
|
||||
|
||||
// From Scheduler. Schedules by using callbacks to the
|
||||
// JVM to process the mailbox on the right thread.
|
||||
void schedule(std::function<void()>&& scheduled) override;
|
||||
mapbox::base::WeakPtr<Scheduler> makeWeakPtr() override { return weakFactory.makeWeakPtr(); }
|
||||
|
||||
// Wait for the queue to be empty
|
||||
// A timeout of zero results in an unbounded wait
|
||||
std::size_t waitForEmpty(Milliseconds timeout) override;
|
||||
|
||||
void requestRender();
|
||||
|
||||
// Snapshot - requires a RunLoop on the calling thread
|
||||
using SnapshotCallback = std::function<void(PremultipliedImage)>;
|
||||
void requestSnapshot(SnapshotCallback);
|
||||
|
||||
protected:
|
||||
// Called from the GL Thread //
|
||||
|
||||
void scheduleSnapshot(std::unique_ptr<SnapshotCallback>);
|
||||
|
||||
private:
|
||||
struct MailboxData {
|
||||
explicit MailboxData(Scheduler*);
|
||||
std::shared_ptr<Mailbox> getMailbox() const noexcept;
|
||||
|
||||
private:
|
||||
Scheduler* scheduler;
|
||||
mutable std::shared_ptr<Mailbox> mailbox;
|
||||
};
|
||||
// Called from the GL Thread //
|
||||
|
||||
// Resets the renderer
|
||||
void resetRenderer();
|
||||
|
||||
// Renders a frame.
|
||||
void render(JNIEnv&);
|
||||
|
||||
void onSurfaceCreated(JNIEnv&);
|
||||
|
||||
void onSurfaceChanged(JNIEnv&, jint width, jint height);
|
||||
|
||||
void onSurfaceDestroyed(JNIEnv&);
|
||||
|
||||
private:
|
||||
// Called on either Main or GL thread //
|
||||
void onRendererReset(JNIEnv&);
|
||||
|
||||
void setSwapBehaviorFlush(JNIEnv&, jboolean flush);
|
||||
|
||||
private:
|
||||
jni::WeakReference<jni::Object<MapRenderer>, jni::EnvAttachingDeleter> javaPeer;
|
||||
|
||||
float pixelRatio;
|
||||
std::optional<std::string> localIdeographFontFamily;
|
||||
|
||||
std::shared_ptr<ThreadPool> threadPool;
|
||||
const MailboxData mailboxData;
|
||||
|
||||
std::mutex initialisationMutex;
|
||||
std::shared_ptr<RendererObserver> rendererObserver;
|
||||
|
||||
std::unique_ptr<AndroidRendererBackend> backend;
|
||||
std::unique_ptr<Renderer> renderer;
|
||||
std::unique_ptr<ActorRef<Renderer>> rendererRef;
|
||||
|
||||
std::shared_ptr<UpdateParameters> updateParameters;
|
||||
std::mutex updateMutex;
|
||||
|
||||
bool framebufferSizeChanged = false;
|
||||
std::atomic<bool> destroyed{false};
|
||||
|
||||
std::unique_ptr<SnapshotCallback> snapshotCallback;
|
||||
mapbox::base::WeakPtrFactory<Scheduler> weakFactory{this};
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "map_renderer_runnable.hpp"
|
||||
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::function<void()> function_)
|
||||
: function(std::move(function_)) {
|
||||
// Create the Java peer and hold on to a global reference
|
||||
// Not using a weak reference here as this might oerflow
|
||||
// the weak reference table on some devices
|
||||
jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 5);
|
||||
static auto& javaClass = jni::Class<MapRendererRunnable>::Singleton(env);
|
||||
static auto constructor = javaClass.GetConstructor<jlong>(env);
|
||||
auto instance = javaClass.New(env, constructor, reinterpret_cast<jlong>(this));
|
||||
javaPeer = jni::NewGlobal(env, instance);
|
||||
}
|
||||
|
||||
MapRendererRunnable::~MapRendererRunnable() = default;
|
||||
|
||||
void MapRendererRunnable::run(jni::JNIEnv&) {
|
||||
if (function) function();
|
||||
}
|
||||
|
||||
jni::Global<jni::Object<MapRendererRunnable>> MapRendererRunnable::peer() {
|
||||
return std::move(javaPeer);
|
||||
}
|
||||
|
||||
// Static methods //
|
||||
|
||||
void MapRendererRunnable::registerNative(jni::JNIEnv& env) {
|
||||
// Lookup the class
|
||||
static auto& javaClass = jni::Class<MapRendererRunnable>::Singleton(env);
|
||||
|
||||
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||
|
||||
jni::RegisterNativePeer<MapRendererRunnable>(env,
|
||||
javaClass,
|
||||
"nativePtr",
|
||||
std::make_unique<MapRendererRunnable, JNIEnv&>,
|
||||
"nativeInitialize",
|
||||
"finalize",
|
||||
METHOD(&MapRendererRunnable::run, "run"));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/actor/mailbox.hpp>
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
/**
|
||||
* The MapRendererRunnable is a peer class that encapsulates
|
||||
* a scheduled mailbox in a Java Runnable so it can be
|
||||
* scheduled on the map renderer thread.
|
||||
*
|
||||
*/
|
||||
class MapRendererRunnable {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/maps/renderer/MapRendererRunnable"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
MapRendererRunnable(jni::JNIEnv&, std::function<void()>);
|
||||
|
||||
// Only for jni registration, unused
|
||||
MapRendererRunnable(jni::JNIEnv&) { assert(false); }
|
||||
|
||||
~MapRendererRunnable();
|
||||
|
||||
void run(jni::JNIEnv&);
|
||||
|
||||
// Transfers ownership of the Peer object to the caller
|
||||
jni::Global<jni::Object<MapRendererRunnable>> peer();
|
||||
|
||||
private:
|
||||
jni::Global<jni::Object<MapRendererRunnable>> javaPeer;
|
||||
std::function<void()> function;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
23
platform/android/MapLibreAndroid/src/cpp/maplibre.cpp
Normal file
23
platform/android/MapLibreAndroid/src/cpp/maplibre.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "maplibre.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<AssetManager>> MapLibre::getAssetManager(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<MapLibre>::Singleton(env);
|
||||
auto method = javaClass.GetStaticMethod<jni::Object<AssetManager>()>(env, "getAssetManager");
|
||||
return javaClass.Call(env, method);
|
||||
}
|
||||
|
||||
jboolean MapLibre::hasInstance(jni::JNIEnv& env) {
|
||||
static auto& javaClass = jni::Class<MapLibre>::Singleton(env);
|
||||
auto method = javaClass.GetStaticMethod<jboolean()>(env, "hasInstance");
|
||||
return javaClass.Call(env, method);
|
||||
}
|
||||
|
||||
void MapLibre::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<MapLibre>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
19
platform/android/MapLibreAndroid/src/cpp/maplibre.hpp
Normal file
19
platform/android/MapLibreAndroid/src/cpp/maplibre.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "asset_manager.hpp"
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class MapLibre {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/MapLibre"; };
|
||||
static jboolean hasInstance(jni::JNIEnv&);
|
||||
static jni::Local<jni::Object<AssetManager>> getAssetManager(jni::JNIEnv&);
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
1335
platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp
Normal file
1335
platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp
Normal file
File diff suppressed because it is too large
Load Diff
318
platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp
Normal file
318
platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp
Normal file
@@ -0,0 +1,318 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/map/change.hpp>
|
||||
#include <mbgl/map/camera.hpp>
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
|
||||
#include "annotation/marker.hpp"
|
||||
#include "annotation/polygon.hpp"
|
||||
#include "annotation/polyline.hpp"
|
||||
#include "graphics/pointf.hpp"
|
||||
#include "graphics/rectf.hpp"
|
||||
#include "geojson/feature.hpp"
|
||||
#include "geojson/geometry.hpp"
|
||||
#include "geometry/lat_lng.hpp"
|
||||
#include "geometry/projected_meters.hpp"
|
||||
#include "style/layers/layer_manager.hpp"
|
||||
#include "style/sources/source.hpp"
|
||||
#include "geometry/lat_lng_bounds.hpp"
|
||||
#include "map/camera_position.hpp"
|
||||
#include "map/image.hpp"
|
||||
#include "style/light.hpp"
|
||||
#include "bitmap.hpp"
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <jni.h>
|
||||
#include <android/native_window.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class AndroidRendererFrontend;
|
||||
class FileSource;
|
||||
class MapRenderer;
|
||||
|
||||
class NativeMapView : public MapObserver {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/maps/NativeMapView"; };
|
||||
|
||||
static void registerNative(jni::JNIEnv&);
|
||||
|
||||
NativeMapView(jni::JNIEnv&,
|
||||
const jni::Object<NativeMapView>&,
|
||||
const jni::Object<FileSource>&,
|
||||
const jni::Object<MapRenderer>&,
|
||||
jni::jfloat,
|
||||
jni::jboolean);
|
||||
|
||||
virtual ~NativeMapView();
|
||||
|
||||
// mbgl::RendererBackend (mbgl::MapObserver) //
|
||||
void onCameraWillChange(MapObserver::CameraChangeMode) override;
|
||||
void onCameraIsChanging() override;
|
||||
void onCameraDidChange(MapObserver::CameraChangeMode) override;
|
||||
void onWillStartLoadingMap() override;
|
||||
void onDidFinishLoadingMap() override;
|
||||
void onDidFailLoadingMap(MapLoadError, const std::string&) override;
|
||||
void onWillStartRenderingFrame() override;
|
||||
void onDidFinishRenderingFrame(MapObserver::RenderFrameStatus) override;
|
||||
void onWillStartRenderingMap() override;
|
||||
void onDidFinishRenderingMap(MapObserver::RenderMode) override;
|
||||
void onDidBecomeIdle() override;
|
||||
void onDidFinishLoadingStyle() override;
|
||||
void onSourceChanged(mbgl::style::Source&) override;
|
||||
void onStyleImageMissing(const std::string&) override;
|
||||
bool onCanRemoveUnusedStyleImage(const std::string&) override;
|
||||
|
||||
// JNI //
|
||||
|
||||
void resizeView(jni::JNIEnv&, int, int);
|
||||
|
||||
jni::Local<jni::String> getStyleUrl(jni::JNIEnv&);
|
||||
|
||||
void setStyleUrl(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
jni::Local<jni::String> getStyleJson(jni::JNIEnv&);
|
||||
|
||||
void setStyleJson(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
void setLatLngBounds(jni::JNIEnv&, const jni::Object<mbgl::android::LatLngBounds>&);
|
||||
|
||||
void cancelTransitions(jni::JNIEnv&);
|
||||
|
||||
void setGestureInProgress(jni::JNIEnv&, jni::jboolean);
|
||||
|
||||
void moveBy(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jlong);
|
||||
|
||||
void jumpTo(jni::JNIEnv&,
|
||||
jni::jdouble,
|
||||
jni::jdouble,
|
||||
jni::jdouble,
|
||||
jni::jdouble,
|
||||
jni::jdouble,
|
||||
const jni::Array<jni::jdouble>&);
|
||||
|
||||
void easeTo(jni::JNIEnv&,
|
||||
jni::jdouble,
|
||||
jni::jdouble,
|
||||
jni::jdouble,
|
||||
jni::jlong,
|
||||
jni::jdouble,
|
||||
jni::jdouble,
|
||||
const jni::Array<jni::jdouble>&,
|
||||
jni::jboolean);
|
||||
|
||||
void flyTo(jni::JNIEnv&,
|
||||
jni::jdouble,
|
||||
jni::jdouble,
|
||||
jni::jdouble,
|
||||
jni::jlong,
|
||||
jni::jdouble,
|
||||
jni::jdouble,
|
||||
const jni::Array<jni::jdouble>&);
|
||||
|
||||
jni::Local<jni::Object<LatLng>> getLatLng(JNIEnv&);
|
||||
|
||||
void setLatLng(jni::JNIEnv&, jni::jdouble, jni::jdouble, const jni::Array<jni::jdouble>&, jni::jlong);
|
||||
|
||||
jni::Local<jni::Object<CameraPosition>> getCameraForLatLngBounds(jni::JNIEnv&,
|
||||
const jni::Object<mbgl::android::LatLngBounds>&,
|
||||
double top,
|
||||
double left,
|
||||
double bottom,
|
||||
double right,
|
||||
double bearing,
|
||||
double tilt);
|
||||
|
||||
jni::Local<jni::Object<CameraPosition>> getCameraForGeometry(jni::JNIEnv&,
|
||||
const jni::Object<geojson::Geometry>&,
|
||||
double top,
|
||||
double left,
|
||||
double bottom,
|
||||
double right,
|
||||
double bearing,
|
||||
double tilt);
|
||||
|
||||
void setReachability(jni::JNIEnv&, jni::jboolean);
|
||||
|
||||
void resetPosition(jni::JNIEnv&);
|
||||
|
||||
jni::jdouble getPitch(jni::JNIEnv&);
|
||||
|
||||
void setPitch(jni::JNIEnv&, jni::jdouble, jni::jlong);
|
||||
|
||||
void setZoom(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong);
|
||||
|
||||
jni::jdouble getZoom(jni::JNIEnv&);
|
||||
|
||||
void resetZoom(jni::JNIEnv&);
|
||||
|
||||
void setMinZoom(jni::JNIEnv&, jni::jdouble);
|
||||
|
||||
jni::jdouble getMinZoom(jni::JNIEnv&);
|
||||
|
||||
void setMaxZoom(jni::JNIEnv&, jni::jdouble);
|
||||
|
||||
jni::jdouble getMaxZoom(jni::JNIEnv&);
|
||||
|
||||
void setMinPitch(jni::JNIEnv&, jni::jdouble);
|
||||
|
||||
jni::jdouble getMinPitch(jni::JNIEnv&);
|
||||
|
||||
void setMaxPitch(jni::JNIEnv&, jni::jdouble);
|
||||
|
||||
jni::jdouble getMaxPitch(jni::JNIEnv&);
|
||||
|
||||
void rotateBy(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong);
|
||||
|
||||
void setBearing(jni::JNIEnv&, jni::jdouble, jni::jlong);
|
||||
|
||||
void setBearingXY(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong);
|
||||
|
||||
jni::jdouble getBearing(jni::JNIEnv&);
|
||||
|
||||
void resetNorth(jni::JNIEnv&);
|
||||
|
||||
void setVisibleCoordinateBounds(
|
||||
JNIEnv&, const jni::Array<jni::Object<LatLng>>&, const jni::Object<RectF>&, jni::jdouble, jni::jlong);
|
||||
|
||||
void getVisibleCoordinateBounds(JNIEnv& env, jni::Array<jdouble>& output);
|
||||
|
||||
void scheduleSnapshot(jni::JNIEnv&);
|
||||
|
||||
jni::Local<jni::Object<CameraPosition>> getCameraPosition(jni::JNIEnv&);
|
||||
|
||||
void updateMarker(jni::JNIEnv&, jni::jlong, jni::jdouble, jni::jdouble, const jni::String&);
|
||||
|
||||
jni::Local<jni::Array<jni::jlong>> addMarkers(jni::JNIEnv&, const jni::Array<jni::Object<Marker>>&);
|
||||
|
||||
void onLowMemory(JNIEnv& env);
|
||||
|
||||
void setDebug(JNIEnv&, jni::jboolean);
|
||||
|
||||
jni::jboolean getDebug(JNIEnv&);
|
||||
|
||||
jni::jboolean isFullyLoaded(JNIEnv&);
|
||||
|
||||
jni::jdouble getMetersPerPixelAtLatitude(JNIEnv&, jni::jdouble, jni::jdouble);
|
||||
|
||||
jni::Local<jni::Object<ProjectedMeters>> projectedMetersForLatLng(JNIEnv&, jni::jdouble, jni::jdouble);
|
||||
|
||||
jni::Local<jni::Object<PointF>> pixelForLatLng(JNIEnv&, jdouble, jdouble);
|
||||
|
||||
void pixelsForLatLngs(JNIEnv&, const jni::Array<jdouble>&, jni::Array<jdouble>&, jfloat);
|
||||
|
||||
jni::Local<jni::Object<LatLng>> latLngForProjectedMeters(JNIEnv&, jdouble, jdouble);
|
||||
|
||||
jni::Local<jni::Object<LatLng>> latLngForPixel(JNIEnv&, jfloat, jfloat);
|
||||
|
||||
void latLngsForPixels(JNIEnv&, const jni::Array<jdouble>&, jni::Array<jdouble>&, jfloat);
|
||||
|
||||
jni::Local<jni::Array<jlong>> addPolylines(JNIEnv&, const jni::Array<jni::Object<Polyline>>&);
|
||||
|
||||
jni::Local<jni::Array<jlong>> addPolygons(JNIEnv&, const jni::Array<jni::Object<Polygon>>&);
|
||||
|
||||
void updatePolyline(JNIEnv&, jlong, const jni::Object<Polyline>&);
|
||||
|
||||
void updatePolygon(JNIEnv&, jlong, const jni::Object<Polygon>&);
|
||||
|
||||
void removeAnnotations(JNIEnv&, const jni::Array<jlong>&);
|
||||
|
||||
void addAnnotationIcon(JNIEnv&, const jni::String&, jint, jint, jfloat, const jni::Array<jbyte>&);
|
||||
|
||||
void removeAnnotationIcon(JNIEnv&, const jni::String&);
|
||||
|
||||
jni::jdouble getTopOffsetPixelsForAnnotationSymbol(JNIEnv&, const jni::String&);
|
||||
|
||||
jni::Local<jni::Object<TransitionOptions>> getTransitionOptions(JNIEnv&);
|
||||
|
||||
void setTransitionOptions(JNIEnv&, const jni::Object<TransitionOptions>&);
|
||||
|
||||
jni::Local<jni::Array<jlong>> queryPointAnnotations(JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
jni::Local<jni::Array<jlong>> queryShapeAnnotations(JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
jni::Local<jni::Array<jni::Object<geojson::Feature>>> queryRenderedFeaturesForPoint(
|
||||
JNIEnv&, jni::jfloat, jni::jfloat, const jni::Array<jni::String>&, const jni::Array<jni::Object<>>& jfilter);
|
||||
|
||||
jni::Local<jni::Array<jni::Object<geojson::Feature>>> queryRenderedFeaturesForBox(
|
||||
JNIEnv&,
|
||||
jni::jfloat,
|
||||
jni::jfloat,
|
||||
jni::jfloat,
|
||||
jni::jfloat,
|
||||
const jni::Array<jni::String>&,
|
||||
const jni::Array<jni::Object<>>& jfilter);
|
||||
|
||||
jni::Local<jni::Object<Light>> getLight(JNIEnv&);
|
||||
|
||||
jni::Local<jni::Array<jni::Object<Layer>>> getLayers(JNIEnv&);
|
||||
|
||||
jni::Local<jni::Object<Layer>> getLayer(JNIEnv&, const jni::String&);
|
||||
|
||||
void addLayer(JNIEnv&, jlong, const jni::String&);
|
||||
|
||||
void addLayerAbove(JNIEnv&, jlong, const jni::String&);
|
||||
|
||||
void addLayerAt(JNIEnv&, jni::jlong, jni::jint);
|
||||
|
||||
jni::jboolean removeLayerAt(JNIEnv&, jni::jint);
|
||||
|
||||
jni::jboolean removeLayer(JNIEnv&, jlong);
|
||||
|
||||
jni::Local<jni::Array<jni::Object<Source>>> getSources(JNIEnv&);
|
||||
|
||||
jni::Local<jni::Object<Source>> getSource(JNIEnv&, const jni::String&);
|
||||
|
||||
void addSource(JNIEnv&, const jni::Object<Source>&, jlong nativePtr);
|
||||
|
||||
jni::jboolean removeSource(JNIEnv&, const jni::Object<Source>&, jlong nativePtr);
|
||||
|
||||
void addImage(JNIEnv&, const jni::String&, const jni::Object<Bitmap>& bitmap, jni::jfloat, jni::jboolean);
|
||||
|
||||
void addImages(JNIEnv&, const jni::Array<jni::Object<mbgl::android::Image>>&);
|
||||
|
||||
void removeImage(JNIEnv&, const jni::String&);
|
||||
|
||||
jni::Local<jni::Object<Bitmap>> getImage(JNIEnv&, const jni::String&);
|
||||
|
||||
void setPrefetchTiles(JNIEnv&, jni::jboolean);
|
||||
|
||||
jni::jboolean getPrefetchTiles(JNIEnv&);
|
||||
|
||||
void setPrefetchZoomDelta(JNIEnv&, jni::jint);
|
||||
|
||||
jni::jint getPrefetchZoomDelta(JNIEnv&);
|
||||
|
||||
mbgl::Map& getMap();
|
||||
|
||||
void triggerRepaint(JNIEnv&);
|
||||
|
||||
private:
|
||||
std::unique_ptr<AndroidRendererFrontend> rendererFrontend;
|
||||
|
||||
JavaVM* vm = nullptr;
|
||||
jni::WeakReference<jni::Object<NativeMapView>> javaPeer;
|
||||
|
||||
MapRenderer& mapRenderer;
|
||||
|
||||
std::string styleUrl;
|
||||
|
||||
float pixelRatio;
|
||||
|
||||
// Minimum texture size according to OpenGL ES 2.0 specification.
|
||||
int width = 64;
|
||||
int height = 64;
|
||||
|
||||
// Ensure these are initialised last
|
||||
std::unique_ptr<mbgl::Map> map;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user