summaryrefslogtreecommitdiff
path: root/platform/android/src
diff options
context:
space:
mode:
authorWilhelm Berg <wb@BergWerk-GIS.at>2018-08-22 16:56:32 +0200
committerWilhelm Berg <wb@BergWerk-GIS.at>2018-08-22 16:56:32 +0200
commit797f622a26b34db5a30e7f1728d87c6700a2ec1e (patch)
tree75ea93979db2baf3eb2234c6fbb3d1a9c5b70329 /platform/android/src
parent86fc3f525e42d042f239876b93525ff411ad7182 (diff)
parent520df7f02049cdbbb9e68041e755d6c3a8d5b21f (diff)
downloadqtlocation-mapboxgl-797f622a26b34db5a30e7f1728d87c6700a2ec1e.tar.gz
Merge branch 'master' of github.com:mapbox/mapbox-gl-native into bwg-vs2017
Diffstat (limited to 'platform/android/src')
-rw-r--r--platform/android/src/android_renderer_frontend.cpp11
-rw-r--r--platform/android/src/android_renderer_frontend.hpp8
-rw-r--r--platform/android/src/conversion/collection.cpp24
-rw-r--r--platform/android/src/conversion/collection.hpp43
-rw-r--r--platform/android/src/conversion/color.cpp17
-rw-r--r--platform/android/src/conversion/color.hpp8
-rw-r--r--platform/android/src/conversion/constant.cpp70
-rw-r--r--platform/android/src/conversion/constant.hpp93
-rw-r--r--platform/android/src/geojson/conversion/feature.cpp191
-rw-r--r--platform/android/src/geojson/conversion/feature.hpp194
-rw-r--r--platform/android/src/geojson/conversion/geometry.hpp24
-rwxr-xr-xplatform/android/src/jni.cpp1
-rwxr-xr-xplatform/android/src/native_map_view.cpp6
-rw-r--r--platform/android/src/offline/offline_manager.cpp29
-rw-r--r--platform/android/src/offline/offline_region.cpp29
-rw-r--r--platform/android/src/offline/offline_region_definition.cpp68
-rw-r--r--platform/android/src/offline/offline_region_definition.hpp17
-rw-r--r--platform/android/src/style/android_conversion.hpp2
-rw-r--r--platform/android/src/style/conversion/filter.cpp26
-rw-r--r--platform/android/src/style/conversion/filter.hpp21
-rw-r--r--platform/android/src/style/conversion/latlngquad.hpp24
-rw-r--r--platform/android/src/style/conversion/position.cpp24
-rw-r--r--platform/android/src/style/conversion/position.hpp26
-rw-r--r--platform/android/src/style/conversion/property_expression.hpp16
-rw-r--r--platform/android/src/style/conversion/property_value.hpp17
-rw-r--r--platform/android/src/style/conversion/transition_options.cpp16
-rw-r--r--platform/android/src/style/conversion/transition_options.hpp19
-rw-r--r--platform/android/src/style/conversion/types.hpp119
-rw-r--r--platform/android/src/style/conversion/types.hpp.ejs40
-rw-r--r--platform/android/src/style/conversion/types_string_values.hpp257
-rw-r--r--platform/android/src/style/conversion/types_string_values.hpp.ejs48
-rw-r--r--platform/android/src/style/conversion/url_or_tileset.cpp30
-rw-r--r--platform/android/src/style/conversion/url_or_tileset.hpp27
-rw-r--r--platform/android/src/style/layers/layer.cpp6
-rw-r--r--platform/android/src/style/sources/custom_geometry_source.cpp39
-rw-r--r--platform/android/src/style/sources/custom_geometry_source.hpp5
-rw-r--r--platform/android/src/style/sources/geojson_source.cpp130
-rw-r--r--platform/android/src/style/sources/geojson_source.hpp30
-rw-r--r--platform/android/src/style/sources/image_source.cpp2
-rw-r--r--platform/android/src/style/sources/source.cpp13
-rw-r--r--platform/android/src/style/sources/source.hpp6
41 files changed, 769 insertions, 1007 deletions
diff --git a/platform/android/src/android_renderer_frontend.cpp b/platform/android/src/android_renderer_frontend.cpp
index 2a03d9de9e..8b4a25a4d9 100644
--- a/platform/android/src/android_renderer_frontend.cpp
+++ b/platform/android/src/android_renderer_frontend.cpp
@@ -4,6 +4,7 @@
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/renderer_observer.hpp>
#include <mbgl/storage/file_source.hpp>
+#include <mbgl/util/async_task.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/util/run_loop.hpp>
@@ -56,7 +57,11 @@ private:
AndroidRendererFrontend::AndroidRendererFrontend(MapRenderer& mapRenderer_)
: mapRenderer(mapRenderer_)
- , mapRunLoop(util::RunLoop::Get()) {
+ , mapRunLoop(util::RunLoop::Get())
+ , updateAsyncTask(std::make_unique<util::AsyncTask>([this]() {
+ mapRenderer.update(std::move(updateParams));
+ mapRenderer.requestRender();
+ })) {
}
AndroidRendererFrontend::~AndroidRendererFrontend() = default;
@@ -73,8 +78,8 @@ void AndroidRendererFrontend::setObserver(RendererObserver& observer) {
}
void AndroidRendererFrontend::update(std::shared_ptr<UpdateParameters> params) {
- mapRenderer.update(std::move(params));
- mapRenderer.requestRender();
+ updateParams = std::move(params);
+ updateAsyncTask->send();
}
void AndroidRendererFrontend::reduceMemoryUse() {
diff --git a/platform/android/src/android_renderer_frontend.hpp b/platform/android/src/android_renderer_frontend.hpp
index b61904e388..9bd64e4819 100644
--- a/platform/android/src/android_renderer_frontend.hpp
+++ b/platform/android/src/android_renderer_frontend.hpp
@@ -18,6 +18,12 @@ namespace mbgl {
class RenderedQueryOptions;
class SourceQueryOptions;
+namespace util {
+
+class AsyncTask;
+
+} // namespace util
+
namespace android {
class AndroidRendererFrontend : public RendererFrontend {
@@ -44,6 +50,8 @@ public:
private:
MapRenderer& mapRenderer;
util::RunLoop* mapRunLoop;
+ std::unique_ptr<util::AsyncTask> updateAsyncTask;
+ std::shared_ptr<UpdateParameters> updateParams;
};
} // namespace android
diff --git a/platform/android/src/conversion/collection.cpp b/platform/android/src/conversion/collection.cpp
new file mode 100644
index 0000000000..27b614e8cd
--- /dev/null
+++ b/platform/android/src/conversion/collection.cpp
@@ -0,0 +1,24 @@
+#include "collection.hpp"
+#include "constant.hpp"
+
+namespace mbgl {
+namespace android {
+namespace conversion {
+
+std::vector<std::string> toVector(JNIEnv& env, 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++) {
+ jni::String jstr = array.Get(env, i);
+ vector.push_back(*convert<std::string, jni::String>(env, jstr));
+ jni::DeleteLocalRef(env, jstr);
+ }
+
+ return vector;
+}
+
+}
+}
+}
diff --git a/platform/android/src/conversion/collection.hpp b/platform/android/src/conversion/collection.hpp
index 2b953e73f4..bb8941c984 100644
--- a/platform/android/src/conversion/collection.hpp
+++ b/platform/android/src/conversion/collection.hpp
@@ -1,9 +1,7 @@
#pragma once
#include "conversion.hpp"
-#include "constant.hpp"
-#include <mbgl/util/optional.hpp>
#include <jni/jni.hpp>
#include <vector>
@@ -12,46 +10,7 @@ namespace mbgl {
namespace android {
namespace conversion {
-/**
- * Convert jarray -> ArrayList
- */
-template <class T>
-inline jni::jobject* toArrayList(JNIEnv& env, jni::jarray<T>& array) {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Arrays")).release();
- static jni::jmethodID* asList = &jni::GetStaticMethodID(env, *javaClass, "asList", "([Ljava/lang/Object;)Ljava/util/List;");
- return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *asList, array));
-}
-
-// Java -> C++
-
-
-inline std::vector<std::string> toVector(JNIEnv& env, jni::jarray<jni::jobject>& array) {
- std::vector<std::string> vector;
- std::size_t len = jni::GetArrayLength(env, array);
- vector.reserve(len);
-
- for (std::size_t i = 0; i < len; i++) {
- jni::jstring* jstr = reinterpret_cast<jni::jstring*>(jni::GetObjectArrayElement(env, array, i));
- vector.push_back(*convert<std::string, jni::String>(env, jni::String(jstr)));
- jni::DeleteLocalRef(env, jstr);
- }
-
- return vector;
-}
-
-inline std::vector<std::string> toVector(JNIEnv& env, 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++) {
- jni::String jstr = array.Get(env, i);
- vector.push_back(*convert<std::string, jni::String>(env, jstr));
- jni::DeleteLocalRef(env, jstr);
- }
-
- return vector;
-}
+std::vector<std::string> toVector(JNIEnv& env, jni::Array<jni::String> array);
}
}
diff --git a/platform/android/src/conversion/color.cpp b/platform/android/src/conversion/color.cpp
new file mode 100644
index 0000000000..ce85943e61
--- /dev/null
+++ b/platform/android/src/conversion/color.cpp
@@ -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 style
+} // namespace mbgl
diff --git a/platform/android/src/conversion/color.hpp b/platform/android/src/conversion/color.hpp
index 40aa68d4a9..2b4144b933 100644
--- a/platform/android/src/conversion/color.hpp
+++ b/platform/android/src/conversion/color.hpp
@@ -10,13 +10,7 @@ namespace conversion {
template <>
struct Converter<mbgl::Color, int> {
- Result<mbgl::Color> 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 ) };
- }
+ Result<mbgl::Color> operator()(jni::JNIEnv&, const int& color) const;
};
} // namespace conversion
diff --git a/platform/android/src/conversion/constant.cpp b/platform/android/src/conversion/constant.cpp
new file mode 100644
index 0000000000..16e8b32943
--- /dev/null
+++ b/platform/android/src/conversion/constant.cpp
@@ -0,0 +1,70 @@
+#include "constant.hpp"
+
+#include <sstream>
+
+namespace mbgl {
+namespace android {
+namespace conversion {
+
+Result<jni::jobject*> Converter<jni::jobject*, bool>::operator()(jni::JNIEnv& env, const bool& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Boolean")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Z)V");
+ return {&jni::NewObject(env, *javaClass, *constructor, (jboolean) value)};
+}
+
+Result<jni::jobject*> Converter<jni::jobject*, float>::operator()(jni::JNIEnv& env, const float& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Float")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(F)V");
+ return {&jni::NewObject(env, *javaClass, *constructor, (jfloat) value)};
+}
+
+Result<jni::jobject*> Converter<jni::jobject*, double>::operator()(jni::JNIEnv& env, const double& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Double")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(D)V");
+ return {&jni::NewObject(env, *javaClass, *constructor, (jfloat) value)};
+}
+
+Result<jni::jobject*> Converter<jni::jobject*, std::string>::operator()(jni::JNIEnv& env, const std::string& value) const {
+ return {jni::Make<jni::String>(env, value).Get()};
+}
+
+Result<jni::jobject*> Converter<jni::jobject*, Color>::operator()(jni::JNIEnv& env, const Color& value) const {
+ std::stringstream sstream;
+ sstream << "rgba(" << value.r << ", " << value.g << ", " << value.b << ", " << value.a << ")";
+ std::string result = sstream.str();
+ return convert<jni::jobject*, std::string>(env, result);
+}
+
+Result<jni::jobject*> Converter<jni::jobject*, std::vector<std::string>>::operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const {
+ static jni::jclass* stringCass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/String")).release();
+ jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *stringCass);
+
+ for(size_t i = 0; i < value.size(); i = i + 1) {
+ Result<jni::jobject*> converted = convert<jni::jobject*, std::string>(env, value.at(i));
+ jni::SetObjectArrayElement(env, jarray, i, *converted);
+ }
+
+ return &jarray;
+}
+
+Result<jni::jobject*> Converter<jni::jobject*, std::vector<float>>::operator()(jni::JNIEnv& env, const std::vector<float>& value) const {
+ static jni::jclass* floatClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Float")).release();
+ jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *floatClass);
+
+ for(size_t i = 0; i < value.size(); i = i + 1) {
+ Result<jni::jobject*> converted = convert<jni::jobject*, float>(env, value.at(i));
+ jni::SetObjectArrayElement(env, jarray, i, *converted);
+ }
+
+ return &jarray;
+}
+
+// Java -> C++
+
+Result<std::string> Converter<std::string, jni::String>::operator()(jni::JNIEnv& env, const jni::String& value) const {
+ return { jni::Make<std::string>(env, value) };
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/platform/android/src/conversion/constant.hpp b/platform/android/src/conversion/constant.hpp
index f1c72eb5dd..0e665cf56a 100644
--- a/platform/android/src/conversion/constant.hpp
+++ b/platform/android/src/conversion/constant.hpp
@@ -2,14 +2,14 @@
#include "conversion.hpp"
-#include <mbgl/util/optional.hpp>
#include <mbgl/util/color.hpp>
+#include <mbgl/util/enum.hpp>
+
#include <jni/jni.hpp>
#include <string>
#include <array>
#include <vector>
-#include <sstream>
namespace mbgl {
namespace android {
@@ -17,51 +17,17 @@ namespace conversion {
template <>
struct Converter<jni::jobject*, bool> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const bool& value) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Boolean")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Z)V");
- return {&jni::NewObject(env, *javaClass, *constructor, (jboolean) value)};
- }
-};
-
-template <>
-struct Converter<jni::jboolean, bool> {
- Result<jni::jboolean> operator()(jni::JNIEnv&, const bool& value) const {
- return {(jni::jboolean) value};
- }
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const bool& value) const;
};
template <>
struct Converter<jni::jobject*, float> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const float& value) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Float")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(F)V");
- return {&jni::NewObject(env, *javaClass, *constructor, (jfloat) value)};
- }
-};
-
-template <>
-struct Converter<jni::jfloat, float> {
- Result<jni::jfloat> operator()(jni::JNIEnv&, const float& value) const {
- return {(jni::jfloat) value};
- }
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const float& value) const;
};
-
template <>
struct Converter<jni::jobject*, double> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const double& value) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Double")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(D)V");
- return {&jni::NewObject(env, *javaClass, *constructor, (jfloat) value)};
- }
-};
-
-template <>
-struct Converter<jni::jdouble, float> {
- Result<jni::jdouble> operator()(jni::JNIEnv&, const double& value) const {
- return {(jni::jdouble) value};
- }
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const double& value) const;
};
/**
@@ -81,26 +47,12 @@ struct Converter<jni::jobject*, T, typename std::enable_if<std::is_integral<T>::
template <>
struct Converter<jni::jobject*, std::string> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::string& value) const {
- return {jni::Make<jni::String>(env, value).Get()};
- }
-};
-
-template <>
-struct Converter<jni::jstring*, std::string> {
- Result<jni::jstring*> operator()(jni::JNIEnv& env, const std::string& value) const {
- return {jni::Make<jni::String>(env, value).Get()};
- }
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::string& value) const;
};
template <>
struct Converter<jni::jobject*, Color> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const Color& value) const {
- std::stringstream sstream;
- sstream << "rgba(" << value.r << ", " << value.g << ", " << value.b << ", " << value.a << ")";
- std::string result = sstream.str();
- return convert<jni::jobject*, std::string>(env, result);
- }
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const Color& value) const;
};
template <std::size_t N>
@@ -116,31 +68,18 @@ struct Converter<jni::jobject*, std::array<float, N>> {
template <>
struct Converter<jni::jobject*, std::vector<std::string>> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const {
- static jni::jclass* stringCass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/String")).release();
- jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *stringCass);
-
- for(size_t i = 0; i < value.size(); i = i + 1) {
- Result<jni::jobject*> converted = convert<jni::jobject*, std::string>(env, value.at(i));
- jni::SetObjectArrayElement(env, jarray, i, *converted);
- }
-
- return &jarray;
- }
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const;
};
template <>
struct Converter<jni::jobject*, std::vector<float>> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::vector<float>& value) const {
- static jni::jclass* floatClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Float")).release();
- jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *floatClass);
-
- for(size_t i = 0; i < value.size(); i = i + 1) {
- Result<jni::jobject*> converted = convert<jni::jobject*, float>(env, value.at(i));
- jni::SetObjectArrayElement(env, jarray, i, *converted);
- }
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::vector<float>& value) const;
+};
- return &jarray;
+template <class T>
+struct Converter<jni::jobject*, T, typename std::enable_if_t<std::is_enum<T>::value>> {
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const T& value) const {
+ return convert<jni::jobject*, std::string>(env, Enum<T>::toString(value));
}
};
@@ -148,9 +87,7 @@ struct Converter<jni::jobject*, std::vector<float>> {
template <>
struct Converter<std::string, jni::String> {
- Result<std::string> operator()(jni::JNIEnv& env, const jni::String& value) const {
- return { jni::Make<std::string>(env, value) };
- }
+ Result<std::string> operator()(jni::JNIEnv& env, const jni::String& value) const;
};
} // namespace conversion
diff --git a/platform/android/src/geojson/conversion/feature.cpp b/platform/android/src/geojson/conversion/feature.cpp
new file mode 100644
index 0000000000..3cb6d37b17
--- /dev/null
+++ b/platform/android/src/geojson/conversion/feature.cpp
@@ -0,0 +1,191 @@
+#include "feature.hpp"
+
+#include "../../conversion/constant.hpp"
+#include "../../conversion/conversion.hpp"
+#include "../../jni/local_object.hpp"
+
+namespace mbgl {
+namespace android {
+namespace conversion {
+
+/**
+ * Turn feature identifier into std::string
+ */
+class FeatureIdVisitor {
+public:
+
+ template<class T>
+ std::string operator()(const T& i) const {
+ return std::to_string(i);
+ }
+
+ std::string operator()(const std::string& i) const {
+ return i;
+ }
+
+ std::string operator()(const std::nullptr_t&) const {
+ return "";
+ }
+
+};
+
+/**
+ * Turn properties into Java GSON JsonObject's
+ */
+class PropertyValueEvaluator {
+public:
+ jni::JNIEnv& env;
+
+ /**
+ * null
+ */
+ jni::jobject* operator()(const mapbox::geometry::null_value_t &) const {
+ return (jni::jobject*) nullptr;
+ }
+
+ /**
+ * Boolean primitive
+ */
+ jni::jobject* operator()(const bool& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/Boolean;)V");
+
+ // Create JsonPrimitive
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, bool>(env, value));
+ jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, *converted);
+
+ return object;
+ }
+
+ /**
+ * String primitive
+ */
+ jni::jobject* operator()(const std::string& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/String;)V");
+
+ // Create JsonPrimitive
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, value));
+ jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get());
+
+ return object;
+ }
+
+ /**
+ * Number primitives
+ */
+ template <class Number>
+ jni::jobject* operator()(const Number& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/Number;)V");
+
+ // Create JsonPrimitive
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, Number>(env, value));
+ jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get());
+
+ return object;
+ }
+
+
+ /**
+ * Json Array
+ */
+ jni::jobject* operator()(const std::vector<mbgl::Value> &values) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonArray")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
+ static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Lcom/google/gson/JsonElement;)V");
+
+ // Create json array
+ jni::jobject* jarray = &jni::NewObject(env, *javaClass, *constructor);
+
+ // Add values
+ for (const auto &v : values) {
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(v, *this));
+ jni::CallMethod<void>(env, jarray, *add, converted.get());
+ }
+
+ return jarray;
+ }
+
+ /**
+ * Json Object
+ */
+ jni::jobject* operator()(const std::unordered_map<std::string, mbgl::Value> &value) const {
+ // TODO: clean up duplication here
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
+ static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V");
+
+ // Create json object
+ jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor);
+
+ // Add items
+ for (auto &item : value) {
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, *this));
+ jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first));
+ jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get());
+ }
+
+ return jsonObject;
+ }
+};
+
+Result<jni::jobject*> Converter<jni::jobject*, std::unordered_map<std::string, mbgl::Value>>::operator()(jni::JNIEnv& env, const std::unordered_map<std::string, mbgl::Value>& value) const {
+ static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release();
+ static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
+ static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V");
+
+ // Create json object
+ jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor);
+
+ // Add items
+ PropertyValueEvaluator evaluator {env};
+ for (auto &item : value) {
+ jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, evaluator));
+ jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first));
+ jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get());
+ }
+
+ return {jsonObject};
+}
+
+Result<jni::Object<android::geojson::Feature>> Converter<jni::Object<android::geojson::Feature>, mbgl::Feature>::operator()(jni::JNIEnv& env, const mbgl::Feature& value) const {
+
+ // Convert Id
+ FeatureIdVisitor idEvaluator;
+ std::string id = (value.id) ? mapbox::geometry::identifier::visit(value.id.value(), idEvaluator) : "";
+ auto jid = jni::Make<jni::String>(env, id);
+
+ // Convert properties
+ auto properties = jni::Object<gson::JsonObject>(*convert<jni::jobject*>(env, value.properties));
+
+ // Convert geometry
+ auto geometry = android::geojson::Geometry::New(env, value.geometry);
+
+ // Create feature
+ auto feature = android::geojson::Feature::fromGeometry(env, geometry, properties, jid);
+
+ //Cleanup
+ jni::DeleteLocalRef(env, jid);
+ jni::DeleteLocalRef(env, geometry);
+ jni::DeleteLocalRef(env, properties);
+
+ return feature;
+}
+
+Result<jni::Array<jni::Object<android::geojson::Feature>>> Converter<jni::Array<jni::Object<android::geojson::Feature>>, std::vector<mbgl::Feature>>::operator()(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) const {
+ using namespace mbgl::android::geojson;
+ auto features = jni::Array<jni::Object<Feature>>::New(env, value.size(), Feature::javaClass);
+
+ for(size_t i = 0; i < value.size(); i = i + 1) {
+ auto converted = *convert<jni::Object<android::geojson::Feature>, mbgl::Feature>(env, value.at(i));
+ features.Set(env, i, converted);
+ jni::DeleteLocalRef(env, converted);
+ }
+
+ return {features};
+}
+
+} // namespace conversion
+} // namespace android
+} // namespace mbgl
diff --git a/platform/android/src/geojson/conversion/feature.hpp b/platform/android/src/geojson/conversion/feature.hpp
index 8fc62a2789..031449cd23 100644
--- a/platform/android/src/geojson/conversion/feature.hpp
+++ b/platform/android/src/geojson/conversion/feature.hpp
@@ -1,215 +1,31 @@
#pragma once
-#include "../../conversion/constant.hpp"
#include "../../conversion/conversion.hpp"
-#include "geometry.hpp"
-#include "../../gson/json_object.hpp"
+#include "../feature.hpp"
#include <mbgl/util/feature.hpp>
-#include <mapbox/variant.hpp>
-#include <mapbox/geometry.hpp>
-
#include <jni/jni.hpp>
-#include "../../jni/local_object.hpp"
-#include "../feature.hpp"
-#include <string>
-#include <array>
#include <vector>
-#include <sstream>
-
-#include <mbgl/util/logging.hpp>
+#include <unordered_map>
namespace mbgl {
namespace android {
namespace conversion {
-/**
- * Turn feature identifier into std::string
- */
-class FeatureIdVisitor {
-public:
-
- template<class T>
- std::string operator()(const T& i) const {
- return std::to_string(i);
- }
-
- std::string operator()(const std::string& i) const {
- return i;
- }
-
- std::string operator()(const std::nullptr_t&) const {
- return "";
- }
-
-};
-
-/**
- * Turn properties into Java GSON JsonObject's
- */
-class PropertyValueEvaluator {
-public:
- jni::JNIEnv& env;
-
- /**
- * null
- */
- jni::jobject* operator()(const mapbox::geometry::null_value_t &) const {
- return (jni::jobject*) nullptr;
- }
-
- /**
- * Boolean primitive
- */
- jni::jobject* operator()(const bool& value) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/Boolean;)V");
-
- // Create JsonPrimitive
- jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, bool>(env, value));
- jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, *converted);
-
- return object;
- }
-
- /**
- * String primitive
- */
- jni::jobject* operator()(const std::string& value) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/String;)V");
-
- // Create JsonPrimitive
- jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, value));
- jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get());
-
- return object;
- }
-
- /**
- * Number primitives
- */
- template <class Number>
- jni::jobject* operator()(const Number& value) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/Number;)V");
-
- // Create JsonPrimitive
- jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, Number>(env, value));
- jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get());
-
- return object;
- }
-
-
- /**
- * Json Array
- */
- jni::jobject* operator()(const std::vector<mbgl::Value> &values) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonArray")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
- static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Lcom/google/gson/JsonElement;)V");
-
- // Create json array
- jni::jobject* jarray = &jni::NewObject(env, *javaClass, *constructor);
-
- // Add values
- for (const auto &v : values) {
- jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(v, *this));
- jni::CallMethod<void>(env, jarray, *add, converted.get());
- }
-
- return jarray;
- }
-
- /**
- * Json Object
- */
- jni::jobject* operator()(const std::unordered_map<std::string, mbgl::Value> &value) const {
- // TODO: clean up duplication here
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
- static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V");
-
- // Create json object
- jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor);
-
- // Add items
- for (auto &item : value) {
- jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, *this));
- jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first));
- jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get());
- }
-
- return jsonObject;
- }
-};
-
template <>
struct Converter<jni::jobject*, std::unordered_map<std::string, mbgl::Value>> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::unordered_map<std::string, mbgl::Value>& value) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
- static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V");
-
- // Create json object
- jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor);
-
- // Add items
- PropertyValueEvaluator evaluator {env};
- for (auto &item : value) {
- jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, evaluator));
- jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first));
- jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get());
- }
-
- return {jsonObject};
- }
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::unordered_map<std::string, mbgl::Value>& value) const;
};
-
template <>
struct Converter<jni::Object<android::geojson::Feature>, mbgl::Feature> {
- Result<jni::Object<android::geojson::Feature>> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const {
-
- // Convert Id
- FeatureIdVisitor idEvaluator;
- std::string id = (value.id) ? mapbox::geometry::identifier::visit(value.id.value(), idEvaluator) : "";
- auto jid = jni::Make<jni::String>(env, id);
-
- // Convert properties
- auto properties = jni::Object<gson::JsonObject>(*convert<jni::jobject*>(env, value.properties));
-
- // Convert geometry
- auto geometry = *convert<jni::Object<android::geojson::Geometry>>(env, value.geometry);
-
- // Create feature
- auto feature = android::geojson::Feature::fromGeometry(env, geometry, properties, jid);
-
- //Cleanup
- jni::DeleteLocalRef(env, jid);
- jni::DeleteLocalRef(env, geometry);
- jni::DeleteLocalRef(env, properties);
-
- return feature;
- }
+ Result<jni::Object<android::geojson::Feature>> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const;
};
template <>
struct Converter<jni::Array<jni::Object<android::geojson::Feature>>, std::vector<mbgl::Feature>> {
- Result<jni::Array<jni::Object<android::geojson::Feature>>> operator()(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) const {
- using namespace mbgl::android::geojson;
- auto features = jni::Array<jni::Object<Feature>>::New(env, value.size(), Feature::javaClass);
-
- for(size_t i = 0; i < value.size(); i = i + 1) {
- auto converted = *convert<jni::Object<android::geojson::Feature>, mbgl::Feature>(env, value.at(i));
- features.Set(env, i, converted);
- jni::DeleteLocalRef(env, converted);
- }
-
- return {features};
- }
+ Result<jni::Array<jni::Object<android::geojson::Feature>>> operator()(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) const;
};
} // namespace conversion
diff --git a/platform/android/src/geojson/conversion/geometry.hpp b/platform/android/src/geojson/conversion/geometry.hpp
deleted file mode 100644
index 242a68df02..0000000000
--- a/platform/android/src/geojson/conversion/geometry.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include <mapbox/geometry.hpp>
-#include "../geometry.hpp"
-#include <jni/jni.hpp>
-
-namespace mbgl {
-namespace android {
-namespace conversion {
-
-/**
- * mapbox::geometry::geometry<T> -> Java GeoJson Geometry
- */
-template <class T>
-struct Converter<jni::Object<android::geojson::Geometry>, mapbox::geometry::geometry<T>> {
- Result<jni::Object<android::geojson::Geometry>> operator()(jni::JNIEnv& env, const mapbox::geometry::geometry<T>& value) const {
- return { android::geojson::Geometry::New(env, value) };
- }
-};
-
-
-} // conversion
-} // android
-} // mbgl
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index beb2c14eb3..18b966e261 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -180,6 +180,7 @@ void registerNatives(JavaVM *vm) {
OfflineRegion::registerNative(env);
OfflineRegionDefinition::registerNative(env);
OfflineTilePyramidRegionDefinition::registerNative(env);
+ OfflineGeometryRegionDefinition::registerNative(env);
OfflineRegionError::registerNative(env);
OfflineRegionStatus::registerNative(env);
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 44b04fc538..8c76332b39 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -30,8 +30,8 @@
// Java -> C++ conversion
#include "style/android_conversion.hpp"
-#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/filter.hpp>
+#include <mbgl/style/conversion_impl.hpp>
// C++ -> Java conversion
#include "conversion/conversion.hpp"
@@ -892,7 +892,9 @@ void NativeMapView::removeSource(JNIEnv& env, jni::Object<Source> obj, jlong sou
assert(sourcePtr != 0);
mbgl::android::Source *source = reinterpret_cast<mbgl::android::Source *>(sourcePtr);
- source->removeFromMap(env, obj, *map);
+ if (source->removeFromMap(env, obj, *map)) {
+ source->releaseJavaPeer();
+ }
}
void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::Object<Bitmap> bitmap, jni::jfloat scale, jni::jboolean sdf) {
diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp
index 4960ae2845..e96ed7e4d2 100644
--- a/platform/android/src/offline/offline_manager.cpp
+++ b/platform/android/src/offline/offline_manager.cpp
@@ -26,15 +26,18 @@ void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, jni::Object<FileSourc
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()),
jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
- ](std::exception_ptr error, mbgl::optional<std::vector<mbgl::OfflineRegion>> regions) mutable {
+ ](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> regions) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
- if (error) {
- OfflineManager::ListOfflineRegionsCallback::onError(*env, jni::Object<ListOfflineRegionsCallback>(*callback), error);
- } else if (regions) {
- OfflineManager::ListOfflineRegionsCallback::onList(*env, jni::Object<FileSource>(*jFileSource), jni::Object<ListOfflineRegionsCallback>(*callback), std::move(regions));
+ if (regions) {
+ OfflineManager::ListOfflineRegionsCallback::onList(
+ *env, jni::Object<FileSource>(*jFileSource),
+ jni::Object<ListOfflineRegionsCallback>(*callback), std::move(*regions));
+ } else {
+ OfflineManager::ListOfflineRegionsCallback::onError(
+ *env, jni::Object<ListOfflineRegionsCallback>(*callback), regions.error());
}
});
}
@@ -45,9 +48,7 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_,
jni::Array<jni::jbyte> metadata_,
jni::Object<CreateOfflineRegionCallback> callback_) {
// Convert
-
- // XXX hardcoded cast for now as we only support OfflineTilePyramidRegionDefinition
- auto definition = OfflineTilePyramidRegionDefinition::getDefinition(env_, jni::Object<OfflineTilePyramidRegionDefinition>(*definition_));
+ auto definition = OfflineRegionDefinition::getDefinition(env_, definition_);
mbgl::OfflineRegionMetadata metadata;
if (metadata_) {
@@ -59,19 +60,19 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_,
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()),
jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
- ](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegion> region) mutable {
+ ](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> region) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
- if (error) {
- OfflineManager::CreateOfflineRegionCallback::onError(*env, jni::Object<CreateOfflineRegionCallback>(*callback), error);
- } else if (region) {
+ if (region) {
OfflineManager::CreateOfflineRegionCallback::onCreate(
*env,
jni::Object<FileSource>(*jFileSource),
- jni::Object<CreateOfflineRegionCallback>(*callback), std::move(region)
+ jni::Object<CreateOfflineRegionCallback>(*callback), std::move(*region)
);
+ } else {
+ OfflineManager::CreateOfflineRegionCallback::onError(*env, jni::Object<CreateOfflineRegionCallback>(*callback), region.error());
}
});
}
@@ -149,7 +150,7 @@ void OfflineManager::CreateOfflineRegionCallback::onCreate(jni::JNIEnv& env,
jni::Object<FileSource> jFileSource,
jni::Object<OfflineManager::CreateOfflineRegionCallback> callback,
mbgl::optional<mbgl::OfflineRegion> region) {
- //Convert the region to java peer object
+ // Convert the region to java peer object
auto jregion = OfflineRegion::New(env, jFileSource, std::move(*region));
// Trigger callback
diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp
index 27de76fb00..5ed37eda73 100644
--- a/platform/android/src/offline/offline_region.cpp
+++ b/platform/android/src/offline/offline_region.cpp
@@ -107,14 +107,14 @@ void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, jni::Object<Offlin
fileSource.getOfflineRegionStatus(*region, [
//Ensure the object is not gc'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
- ](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegionStatus> status) mutable {
+ ](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
- if (error) {
- OfflineRegionStatusCallback::onError(*env, jni::Object<OfflineRegionStatusCallback>(*callback), error);
- } else if (status) {
- OfflineRegionStatusCallback::onStatus(*env, jni::Object<OfflineRegionStatusCallback>(*callback), std::move(status));
+ if (status) {
+ OfflineRegionStatusCallback::onStatus(*env, jni::Object<OfflineRegionStatusCallback>(*callback), std::move(*status));
+ } else {
+ OfflineRegionStatusCallback::onError(*env, jni::Object<OfflineRegionStatusCallback>(*callback), status.error());
}
});
}
@@ -144,14 +144,14 @@ void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::Array<jn
fileSource.updateOfflineMetadata(region->getID(), metadata, [
//Ensure the object is not gc'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
- ](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegionMetadata> data) mutable {
+ ](mbgl::expected<mbgl::OfflineRegionMetadata, std::exception_ptr> data) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
- if (error) {
- OfflineRegionUpdateMetadataCallback::onError(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), error);
- } else if (data) {
- OfflineRegionUpdateMetadataCallback::onUpdate(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), std::move(data));
+ if (data) {
+ OfflineRegionUpdateMetadataCallback::onUpdate(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), std::move(*data));
+ } else {
+ OfflineRegionUpdateMetadataCallback::onError(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), data.error());
}
});
}
@@ -159,7 +159,14 @@ void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::Array<jn
jni::Object<OfflineRegion> OfflineRegion::New(jni::JNIEnv& env, jni::Object<FileSource> jFileSource, mbgl::OfflineRegion region) {
// Definition
- auto definition = jni::Object<OfflineRegionDefinition>(*OfflineTilePyramidRegionDefinition::New(env, region.getDefinition()));
+ auto definition = region.getDefinition().match(
+ [&](const mbgl::OfflineTilePyramidRegionDefinition def) {
+ return jni::Object<OfflineRegionDefinition>(
+ *OfflineTilePyramidRegionDefinition::New(env, def));
+ }, [&](const mbgl::OfflineGeometryRegionDefinition def) {
+ return jni::Object<OfflineRegionDefinition>(
+ *OfflineGeometryRegionDefinition::New(env, def));
+ });
// Metadata
auto metadata = OfflineRegion::metadata(env, region.getMetadata());
diff --git a/platform/android/src/offline/offline_region_definition.cpp b/platform/android/src/offline/offline_region_definition.cpp
index 66a9bdf99d..a856672902 100644
--- a/platform/android/src/offline/offline_region_definition.cpp
+++ b/platform/android/src/offline/offline_region_definition.cpp
@@ -1,6 +1,9 @@
#include "offline_region_definition.hpp"
#include "../geometry/lat_lng_bounds.hpp"
+#include "../geojson/geometry.hpp"
+
+#include <exception>
namespace mbgl {
namespace android {
@@ -13,9 +16,21 @@ void OfflineRegionDefinition::registerNative(jni::JNIEnv& env) {
javaClass = *jni::Class<OfflineRegionDefinition>::Find(env).NewGlobalRef(env).release();
}
+mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env,
+ jni::Object<OfflineRegionDefinition> jDefinition) {
+
+ if (jDefinition.IsInstanceOf(env, OfflineTilePyramidRegionDefinition::javaClass)) {
+ return OfflineTilePyramidRegionDefinition::getDefinition(env, jni::Object<OfflineTilePyramidRegionDefinition>(*jDefinition));
+ } else if (jDefinition.IsInstanceOf(env, OfflineGeometryRegionDefinition::javaClass)) {
+ return OfflineGeometryRegionDefinition::getDefinition(env, jni::Object<OfflineGeometryRegionDefinition>(*jDefinition));
+ }
+
+ throw std::runtime_error("Unknown offline region definition java class");
+}
+
// OfflineTilePyramidRegionDefinition //
-jni::Object<OfflineTilePyramidRegionDefinition> OfflineTilePyramidRegionDefinition::New(jni::JNIEnv& env, mbgl::OfflineTilePyramidRegionDefinition definition) {
+jni::Object<OfflineTilePyramidRegionDefinition> OfflineTilePyramidRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineTilePyramidRegionDefinition& definition) {
//Convert objects
auto styleURL = jni::Make<jni::String>(env, definition.styleURL);
@@ -65,5 +80,56 @@ void OfflineTilePyramidRegionDefinition::registerNative(jni::JNIEnv& env) {
javaClass = *jni::Class<OfflineTilePyramidRegionDefinition>::Find(env).NewGlobalRef(env).release();
}
+// OfflineGeometryRegionDefinition //
+
+jni::Object<OfflineGeometryRegionDefinition> OfflineGeometryRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineGeometryRegionDefinition& definition) {
+ //Convert objects
+ auto styleURL = jni::Make<jni::String>(env, definition.styleURL);
+ auto geometry = geojson::Geometry::New(env, definition.geometry);
+
+ static auto constructor = javaClass.GetConstructor<jni::String, jni::Object<geojson::Geometry>, jni::jdouble, jni::jdouble, jni::jfloat>(env);
+ auto jdefinition = javaClass.New(env, constructor, styleURL, geometry, definition.minZoom, definition.maxZoom, definition.pixelRatio);
+
+ //Delete References
+ jni::DeleteLocalRef(env, styleURL);
+ jni::DeleteLocalRef(env, geometry);
+
+ return jdefinition;
+}
+
+mbgl::OfflineGeometryRegionDefinition OfflineGeometryRegionDefinition::getDefinition(jni::JNIEnv& env, jni::Object<OfflineGeometryRegionDefinition> jDefinition) {
+ // Field references
+ static auto styleURLF = javaClass.GetField<jni::String>(env, "styleURL");
+ static auto geometryF = javaClass.GetField<jni::Object<geojson::Geometry>>(env, "geometry");
+ static auto minZoomF = javaClass.GetField<jni::jdouble>(env, "minZoom");
+ static auto maxZoomF = javaClass.GetField<jni::jdouble>(env, "maxZoom");
+ static auto pixelRatioF = javaClass.GetField<jni::jfloat>(env, "pixelRatio");
+
+ // Get objects
+ auto jStyleURL = jDefinition.Get(env, styleURLF);
+ auto jGeometry = jDefinition.Get(env, geometryF);
+
+ // Create definition
+ mbgl::OfflineGeometryRegionDefinition definition(
+ jni::Make<std::string>(env, jStyleURL),
+ geojson::Geometry::convert(env, jGeometry),
+ jDefinition.Get(env, minZoomF),
+ jDefinition.Get(env, maxZoomF),
+ jDefinition.Get(env, pixelRatioF)
+ );
+
+ // Delete references
+ jni::DeleteLocalRef(env, jStyleURL);
+ jni::DeleteLocalRef(env, jGeometry);
+
+ return definition;
+}
+
+jni::Class<OfflineGeometryRegionDefinition> OfflineGeometryRegionDefinition::javaClass;
+
+void OfflineGeometryRegionDefinition::registerNative(jni::JNIEnv& env) {
+ javaClass = *jni::Class<OfflineGeometryRegionDefinition>::Find(env).NewGlobalRef(env).release();
+}
+
} // namespace android
} // namespace mbgl
diff --git a/platform/android/src/offline/offline_region_definition.hpp b/platform/android/src/offline/offline_region_definition.hpp
index 2ca82a4d96..a9dfb54634 100644
--- a/platform/android/src/offline/offline_region_definition.hpp
+++ b/platform/android/src/offline/offline_region_definition.hpp
@@ -14,13 +14,14 @@ public:
static void registerNative(jni::JNIEnv&);
+ static mbgl::OfflineRegionDefinition getDefinition(JNIEnv& env, jni::Object<OfflineRegionDefinition> jDefinition);
};
class OfflineTilePyramidRegionDefinition: public OfflineRegionDefinition {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition"; };
- static jni::Object<OfflineTilePyramidRegionDefinition> New(jni::JNIEnv&, mbgl::OfflineTilePyramidRegionDefinition);
+ static jni::Object<OfflineTilePyramidRegionDefinition> New(jni::JNIEnv&, const mbgl::OfflineTilePyramidRegionDefinition&);
static mbgl::OfflineTilePyramidRegionDefinition getDefinition(jni::JNIEnv&, jni::Object<OfflineTilePyramidRegionDefinition>);
@@ -30,5 +31,19 @@ public:
};
+class OfflineGeometryRegionDefinition: public OfflineRegionDefinition {
+public:
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineGeometryRegionDefinition"; };
+
+ static jni::Object<OfflineGeometryRegionDefinition> New(jni::JNIEnv&, const mbgl::OfflineGeometryRegionDefinition&);
+
+ static mbgl::OfflineGeometryRegionDefinition getDefinition(jni::JNIEnv&, jni::Object<OfflineGeometryRegionDefinition>);
+
+ static jni::Class<OfflineGeometryRegionDefinition> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+
+};
+
} // namespace android
} // namespace mbgl
diff --git a/platform/android/src/style/android_conversion.hpp b/platform/android/src/style/android_conversion.hpp
index 510a9f8444..8559720b2f 100644
--- a/platform/android/src/style/android_conversion.hpp
+++ b/platform/android/src/style/android_conversion.hpp
@@ -5,8 +5,8 @@
#include <mbgl/util/feature.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/optional.hpp>
-#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/geojson.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <jni/jni.hpp>
diff --git a/platform/android/src/style/conversion/filter.cpp b/platform/android/src/style/conversion/filter.cpp
new file mode 100644
index 0000000000..4eac0cf82b
--- /dev/null
+++ b/platform/android/src/style/conversion/filter.cpp
@@ -0,0 +1,26 @@
+#include "filter.hpp"
+#include "../android_conversion.hpp"
+
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/filter.hpp>
+
+namespace mbgl {
+namespace android {
+namespace conversion {
+
+optional<mbgl::style::Filter> toFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter) {
+ mbgl::optional<mbgl::style::Filter> filter;
+ if (jfilter) {
+ mbgl::style::conversion::Error error;
+ auto converted = mbgl::style::conversion::convert<mbgl::style::Filter>(Value(env, jfilter), error);
+ if (!converted) {
+ mbgl::Log::Error(mbgl::Event::JNI, "Error converting filter: " + error.message);
+ }
+ filter = std::move(*converted);
+ }
+ return filter;
+}
+
+} // namespace conversion
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/style/conversion/filter.hpp b/platform/android/src/style/conversion/filter.hpp
index c154e88e7c..df482de8f3 100644
--- a/platform/android/src/style/conversion/filter.hpp
+++ b/platform/android/src/style/conversion/filter.hpp
@@ -1,30 +1,15 @@
#pragma once
-#include "../android_conversion.hpp"
-#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/conversion/filter.hpp>
+#include <mbgl/style/filter.hpp>
+#include <mbgl/util/optional.hpp>
#include <jni/jni.hpp>
-#include <tuple>
-#include <map>
-
namespace mbgl {
namespace android {
namespace conversion {
-inline optional<mbgl::style::Filter> toFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter) {
- mbgl::optional<mbgl::style::Filter> filter;
- if (jfilter) {
- mbgl::style::conversion::Error error;
- auto converted = mbgl::style::conversion::convert<mbgl::style::Filter>(Value(env, jfilter), error);
- if (!converted) {
- mbgl::Log::Error(mbgl::Event::JNI, "Error converting filter: " + error.message);
- }
- filter = std::move(*converted);
- }
- return filter;
-}
+optional<mbgl::style::Filter> toFilter(jni::JNIEnv&, jni::Array<jni::Object<>>);
} // namespace conversion
} // namespace android
diff --git a/platform/android/src/style/conversion/latlngquad.hpp b/platform/android/src/style/conversion/latlngquad.hpp
deleted file mode 100644
index 9d1a83e164..0000000000
--- a/platform/android/src/style/conversion/latlngquad.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include <mapbox/geojson.hpp>
-#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/conversion/geojson.hpp>
-#include <jni/jni.hpp>
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-template <>
-optional<std::array<LatLng, 4>> Converter<std::array<LatLng, 4>>::operator()(const mbgl::android::Value& value, Error& error) const {
- if (value.isNull() || !value.isArray()) {
- error = { "value cannot be converted to LatLng array" };
- return {};
- }
-
- return convert<GeoJSON>(value.toString(), error);
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/platform/android/src/style/conversion/position.cpp b/platform/android/src/style/conversion/position.cpp
new file mode 100644
index 0000000000..9b3925914e
--- /dev/null
+++ b/platform/android/src/style/conversion/position.cpp
@@ -0,0 +1,24 @@
+#include "position.hpp"
+
+namespace mbgl {
+namespace android {
+namespace conversion {
+
+Result<jni::Object<Position>> Converter<jni::Object<Position>, mbgl::style::Position>::operator()(jni::JNIEnv &env, const mbgl::style::Position &value) const {
+ std::array<float, 3> cartPosition = value.getSpherical();
+ return Position::fromPosition(env, cartPosition[0], cartPosition[1], cartPosition[2]);
+}
+
+Result<mbgl::style::Position> Converter<mbgl::style::Position, jni::Object<Position>>::operator()(jni::JNIEnv &env, const jni::Object<Position> &value) const {
+ float radialCoordinate = Position::getRadialCoordinate(env, value);
+ float azimuthalAngle = Position::getAzimuthalAngle(env, value);
+ float polarAngle = Position::getPolarAngle(env, value);
+ std::array<float, 3> cartPosition {{radialCoordinate, azimuthalAngle, polarAngle}};
+ mbgl::style::Position position{};
+ position.set(cartPosition);
+ return position;
+}
+
+}
+}
+}
diff --git a/platform/android/src/style/conversion/position.hpp b/platform/android/src/style/conversion/position.hpp
index f32a892c0c..2ef4bf4395 100644
--- a/platform/android/src/style/conversion/position.hpp
+++ b/platform/android/src/style/conversion/position.hpp
@@ -1,37 +1,25 @@
#pragma once
#include "../../conversion/conversion.hpp"
+#include "../position.hpp"
-#include <jni/jni.hpp>
#include <mbgl/style/position.hpp>
-#include "../../jni/local_object.hpp"
-#include "../position.hpp"
+#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace conversion {
-template<>
+template <>
struct Converter<jni::Object<Position>, mbgl::style::Position> {
- Result<jni::Object<Position>> operator()(jni::JNIEnv &env, const mbgl::style::Position &value) const {
- std::array<float, 3> cartPosition = value.getSpherical();
- return Position::fromPosition(env, cartPosition[0], cartPosition[1], cartPosition[2]);
- }
+ Result<jni::Object<Position>> operator()(jni::JNIEnv &env, const mbgl::style::Position &value) const;
};
-template<>
+template <>
struct Converter<mbgl::style::Position, jni::Object<Position>> {
- Result<mbgl::style::Position> operator()(jni::JNIEnv &env, const jni::Object<Position> &value) const {
- float radialCoordinate = Position::getRadialCoordinate(env, value);
- float azimuthalAngle = Position::getAzimuthalAngle(env, value);
- float polarAngle = Position::getPolarAngle(env, value);
- std::array<float, 3> cartPosition {{radialCoordinate, azimuthalAngle, polarAngle}};
- mbgl::style::Position position{};
- position.set(cartPosition);
- return position;
- }
+ Result<mbgl::style::Position> operator()(jni::JNIEnv &env, const jni::Object<Position> &value) const;
};
}
}
-} \ No newline at end of file
+}
diff --git a/platform/android/src/style/conversion/property_expression.hpp b/platform/android/src/style/conversion/property_expression.hpp
index ae9d4ea41c..08429960cb 100644
--- a/platform/android/src/style/conversion/property_expression.hpp
+++ b/platform/android/src/style/conversion/property_expression.hpp
@@ -1,16 +1,11 @@
#pragma once
-#include <mbgl/style/property_value.hpp>
#include "../../conversion/conversion.hpp"
-#include "../../conversion/constant.hpp"
-#include "types.hpp"
-#include "../../java/lang.hpp"
-
-#include <jni/jni.hpp>
#include "../../gson/json_element.hpp"
-#include <tuple>
-#include <map>
+#include <mbgl/style/property_expression.hpp>
+
+#include <jni/jni.hpp>
namespace mbgl {
namespace android {
@@ -18,11 +13,8 @@ namespace conversion {
template <class T>
struct Converter<jni::Object<android::gson::JsonElement>, mbgl::style::PropertyExpression<T>> {
-
Result<jni::Object<android::gson::JsonElement>> operator()(jni::JNIEnv& env, const mbgl::style::PropertyExpression<T>& value) const {
- // Convert expressions
- mbgl::Value expressionValue = value.getExpression().serialize();
- return gson::JsonElement::New(env, expressionValue);
+ return gson::JsonElement::New(env, value.getExpression().serialize());
}
};
diff --git a/platform/android/src/style/conversion/property_value.hpp b/platform/android/src/style/conversion/property_value.hpp
index 256647cddf..8150285c85 100644
--- a/platform/android/src/style/conversion/property_value.hpp
+++ b/platform/android/src/style/conversion/property_value.hpp
@@ -2,10 +2,10 @@
#include <mbgl/style/color_ramp_property_value.hpp>
#include <mbgl/style/property_value.hpp>
+
#include "../../conversion/conversion.hpp"
#include "../../conversion/constant.hpp"
#include "property_expression.hpp"
-#include "types.hpp"
namespace mbgl {
namespace android {
@@ -17,25 +17,22 @@ namespace conversion {
template <typename T>
class PropertyValueEvaluator {
public:
-
PropertyValueEvaluator(jni::JNIEnv& _env) : env(_env) {}
jni::jobject* operator()(const mbgl::style::Undefined) const {
return nullptr;
}
- jni::jobject* operator()(const T &value) const {
- Result<jni::jobject*> result = convert<jni::jobject*>(env, value);
- return *result;
+ jni::jobject* operator()(const T& value) const {
+ return *convert<jni::jobject*>(env, value);
}
- jni::jobject* operator()(const mbgl::style::PropertyExpression<T> &value) const {
- return *convert<jni::Object<android::gson::JsonElement>, mbgl::style::PropertyExpression<T>>(env, value);
+ jni::jobject* operator()(const mbgl::style::PropertyExpression<T>& value) const {
+ return *convert<jni::Object<android::gson::JsonElement>>(env, value);
}
private:
jni::JNIEnv& env;
-
};
/**
@@ -43,7 +40,6 @@ private:
*/
template <class T>
struct Converter<jni::jobject*, mbgl::style::PropertyValue<T>> {
-
Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::PropertyValue<T>& value) const {
PropertyValueEvaluator<T> evaluator(env);
return value.evaluate(evaluator);
@@ -55,8 +51,7 @@ struct Converter<jni::jobject*, mbgl::style::PropertyValue<T>> {
*/
template <>
struct Converter<jni::jobject*, mbgl::style::ColorRampPropertyValue> {
-
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::ColorRampPropertyValue value) const {
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::ColorRampPropertyValue& value) const {
PropertyValueEvaluator<mbgl::style::ColorRampPropertyValue> evaluator(env);
return *convert<jni::jobject*>(env, value.evaluate(evaluator));
}
diff --git a/platform/android/src/style/conversion/transition_options.cpp b/platform/android/src/style/conversion/transition_options.cpp
new file mode 100644
index 0000000000..313333ad17
--- /dev/null
+++ b/platform/android/src/style/conversion/transition_options.cpp
@@ -0,0 +1,16 @@
+#include "transition_options.hpp"
+
+namespace mbgl {
+namespace android {
+namespace conversion {
+
+Result<jni::Object<TransitionOptions>> Converter<jni::Object<TransitionOptions>, mbgl::style::TransitionOptions>::operator()(jni::JNIEnv& env, const mbgl::style::TransitionOptions& value) const {
+ return TransitionOptions::fromTransitionOptions(env,
+ std::chrono::duration_cast<std::chrono::milliseconds>(value.duration.value_or(mbgl::Duration::zero())).count(),
+ std::chrono::duration_cast<std::chrono::milliseconds>(value.delay.value_or(mbgl::Duration::zero())).count()
+ );
+}
+
+}
+}
+}
diff --git a/platform/android/src/style/conversion/transition_options.hpp b/platform/android/src/style/conversion/transition_options.hpp
index ae65a32194..6630456d37 100644
--- a/platform/android/src/style/conversion/transition_options.hpp
+++ b/platform/android/src/style/conversion/transition_options.hpp
@@ -1,11 +1,11 @@
#pragma once
#include "../../conversion/conversion.hpp"
+#include "../transition_options.hpp"
-#include <jni/jni.hpp>
#include <mbgl/style/transition_options.hpp>
-#include "../../jni/local_object.hpp"
-#include "../transition_options.hpp"
+
+#include <jni/jni.hpp>
namespace mbgl {
namespace android {
@@ -13,18 +13,9 @@ namespace conversion {
template<>
struct Converter<jni::Object<TransitionOptions>, mbgl::style::TransitionOptions> {
- Result<jni::Object<TransitionOptions>> operator()(jni::JNIEnv &env, const mbgl::style::TransitionOptions &value) const {
-
- // Convert duration
- jlong duration = std::chrono::duration_cast<std::chrono::milliseconds>(value.duration.value_or(mbgl::Duration::zero())).count();
- // Convert delay
- jlong delay = std::chrono::duration_cast<std::chrono::milliseconds>(value.delay.value_or(mbgl::Duration::zero())).count();
-
- // Create transition options
- return TransitionOptions::fromTransitionOptions(env, duration, delay);
- }
+ Result<jni::Object<TransitionOptions>> operator()(jni::JNIEnv&, const mbgl::style::TransitionOptions&) const;
};
}
}
-} \ No newline at end of file
+}
diff --git a/platform/android/src/style/conversion/types.hpp b/platform/android/src/style/conversion/types.hpp
deleted file mode 100644
index e87782fad0..0000000000
--- a/platform/android/src/style/conversion/types.hpp
+++ /dev/null
@@ -1,119 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
-#pragma once
-
-#include "types_string_values.hpp"
-#include "../../conversion/conversion.hpp"
-#include "../../conversion/constant.hpp"
-
-#include <mbgl/style/types.hpp>
-#include <mbgl/util/optional.hpp>
-#include <jni/jni.hpp>
-
-#include <string>
-
-namespace mbgl {
-namespace android {
-namespace conversion {
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::VisibilityType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::VisibilityType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::LineCapType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::LineCapType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::LineJoinType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::LineJoinType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::SymbolPlacementType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::SymbolPlacementType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::AlignmentType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::AlignmentType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::IconTextFitType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::IconTextFitType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::SymbolAnchorType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::SymbolAnchorType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::TextJustifyType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::TextJustifyType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::TextTransformType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::TextTransformType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::TranslateAnchorType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::TranslateAnchorType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::CirclePitchScaleType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::CirclePitchScaleType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::RasterResamplingType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::RasterResamplingType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::HillshadeIlluminationAnchorType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::HillshadeIlluminationAnchorType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::LightAnchorType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::LightAnchorType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-
-} // namespace conversion
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/conversion/types.hpp.ejs b/platform/android/src/style/conversion/types.hpp.ejs
deleted file mode 100644
index 3cd4764015..0000000000
--- a/platform/android/src/style/conversion/types.hpp.ejs
+++ /dev/null
@@ -1,40 +0,0 @@
-<%
- const properties = locals.properties;
--%>
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
-#pragma once
-
-#include "types_string_values.hpp"
-#include "../../conversion/conversion.hpp"
-#include "../../conversion/constant.hpp"
-
-#include <mbgl/style/types.hpp>
-#include <mbgl/util/optional.hpp>
-#include <jni/jni.hpp>
-
-#include <string>
-
-namespace mbgl {
-namespace android {
-namespace conversion {
-
-template <>
-struct Converter<jni::jobject*, mbgl::style::VisibilityType> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::VisibilityType& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-<% for (const property of properties) { -%>
-template <>
-struct Converter<jni::jobject*, mbgl::style::<%- propertyNativeType(property) %>> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::<%- propertyNativeType(property) %>& value) const {
- return convert<jni::jobject*, std::string>(env, toString(value));
- }
-};
-
-<% } -%>
-
-} // namespace conversion
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/conversion/types_string_values.hpp b/platform/android/src/style/conversion/types_string_values.hpp
deleted file mode 100644
index 9f6696d181..0000000000
--- a/platform/android/src/style/conversion/types_string_values.hpp
+++ /dev/null
@@ -1,257 +0,0 @@
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
-#pragma once
-
-#include <mbgl/style/types.hpp>
-
-#include <string>
-#include <stdexcept>
-
-namespace mbgl {
-namespace android {
-namespace conversion {
-
- // visibility
- inline std::string toString(mbgl::style::VisibilityType value) {
- switch (value) {
- case mbgl::style::VisibilityType::Visible:
- return "visible";
- break;
- case mbgl::style::VisibilityType::None:
- return "none";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // line-cap
- inline std::string toString(mbgl::style::LineCapType value) {
- switch (value) {
- case mbgl::style::LineCapType::Butt:
- return "butt";
- break;
- case mbgl::style::LineCapType::Round:
- return "round";
- break;
- case mbgl::style::LineCapType::Square:
- return "square";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // line-join
- inline std::string toString(mbgl::style::LineJoinType value) {
- switch (value) {
- case mbgl::style::LineJoinType::Bevel:
- return "bevel";
- break;
- case mbgl::style::LineJoinType::Round:
- return "round";
- break;
- case mbgl::style::LineJoinType::Miter:
- return "miter";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // symbol-placement
- inline std::string toString(mbgl::style::SymbolPlacementType value) {
- switch (value) {
- case mbgl::style::SymbolPlacementType::Point:
- return "point";
- break;
- case mbgl::style::SymbolPlacementType::Line:
- return "line";
- break;
- case mbgl::style::SymbolPlacementType::LineCenter:
- return "line-center";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // icon-rotation-alignment
- inline std::string toString(mbgl::style::AlignmentType value) {
- switch (value) {
- case mbgl::style::AlignmentType::Map:
- return "map";
- break;
- case mbgl::style::AlignmentType::Viewport:
- return "viewport";
- break;
- case mbgl::style::AlignmentType::Auto:
- return "auto";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // icon-text-fit
- inline std::string toString(mbgl::style::IconTextFitType value) {
- switch (value) {
- case mbgl::style::IconTextFitType::None:
- return "none";
- break;
- case mbgl::style::IconTextFitType::Width:
- return "width";
- break;
- case mbgl::style::IconTextFitType::Height:
- return "height";
- break;
- case mbgl::style::IconTextFitType::Both:
- return "both";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // icon-anchor
- inline std::string toString(mbgl::style::SymbolAnchorType value) {
- switch (value) {
- case mbgl::style::SymbolAnchorType::Center:
- return "center";
- break;
- case mbgl::style::SymbolAnchorType::Left:
- return "left";
- break;
- case mbgl::style::SymbolAnchorType::Right:
- return "right";
- break;
- case mbgl::style::SymbolAnchorType::Top:
- return "top";
- break;
- case mbgl::style::SymbolAnchorType::Bottom:
- return "bottom";
- break;
- case mbgl::style::SymbolAnchorType::TopLeft:
- return "top-left";
- break;
- case mbgl::style::SymbolAnchorType::TopRight:
- return "top-right";
- break;
- case mbgl::style::SymbolAnchorType::BottomLeft:
- return "bottom-left";
- break;
- case mbgl::style::SymbolAnchorType::BottomRight:
- return "bottom-right";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // text-justify
- inline std::string toString(mbgl::style::TextJustifyType value) {
- switch (value) {
- case mbgl::style::TextJustifyType::Left:
- return "left";
- break;
- case mbgl::style::TextJustifyType::Center:
- return "center";
- break;
- case mbgl::style::TextJustifyType::Right:
- return "right";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // text-transform
- inline std::string toString(mbgl::style::TextTransformType value) {
- switch (value) {
- case mbgl::style::TextTransformType::None:
- return "none";
- break;
- case mbgl::style::TextTransformType::Uppercase:
- return "uppercase";
- break;
- case mbgl::style::TextTransformType::Lowercase:
- return "lowercase";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // fill-translate-anchor
- inline std::string toString(mbgl::style::TranslateAnchorType value) {
- switch (value) {
- case mbgl::style::TranslateAnchorType::Map:
- return "map";
- break;
- case mbgl::style::TranslateAnchorType::Viewport:
- return "viewport";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // circle-pitch-scale
- inline std::string toString(mbgl::style::CirclePitchScaleType value) {
- switch (value) {
- case mbgl::style::CirclePitchScaleType::Map:
- return "map";
- break;
- case mbgl::style::CirclePitchScaleType::Viewport:
- return "viewport";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // raster-resampling
- inline std::string toString(mbgl::style::RasterResamplingType value) {
- switch (value) {
- case mbgl::style::RasterResamplingType::Linear:
- return "linear";
- break;
- case mbgl::style::RasterResamplingType::Nearest:
- return "nearest";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // hillshade-illumination-anchor
- inline std::string toString(mbgl::style::HillshadeIlluminationAnchorType value) {
- switch (value) {
- case mbgl::style::HillshadeIlluminationAnchorType::Map:
- return "map";
- break;
- case mbgl::style::HillshadeIlluminationAnchorType::Viewport:
- return "viewport";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
- // anchor
- inline std::string toString(mbgl::style::LightAnchorType value) {
- switch (value) {
- case mbgl::style::LightAnchorType::Map:
- return "map";
- break;
- case mbgl::style::LightAnchorType::Viewport:
- return "viewport";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
-
-} // namespace conversion
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/conversion/types_string_values.hpp.ejs b/platform/android/src/style/conversion/types_string_values.hpp.ejs
deleted file mode 100644
index bf52919741..0000000000
--- a/platform/android/src/style/conversion/types_string_values.hpp.ejs
+++ /dev/null
@@ -1,48 +0,0 @@
-<%
- const properties = locals.properties;
--%>
-// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
-#pragma once
-
-#include <mbgl/style/types.hpp>
-
-#include <string>
-#include <stdexcept>
-
-namespace mbgl {
-namespace android {
-namespace conversion {
-
- // visibility
- inline std::string toString(mbgl::style::VisibilityType value) {
- switch (value) {
- case mbgl::style::VisibilityType::Visible:
- return "visible";
- break;
- case mbgl::style::VisibilityType::None:
- return "none";
- break;
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
-<% for (const property of properties) { -%>
- // <%- property.name %>
- inline std::string toString(mbgl::style::<%- propertyNativeType(property) %> value) {
- switch (value) {
-<% for (const value in property.values) { -%>
- case mbgl::style::<%- propertyNativeType(property) %>::<%- camelize(value) %>:
- return "<%- value %>";
- break;
-<% } -%>
- default:
- throw std::runtime_error("Not implemented");
- }
- }
-
-<% } -%>
-
-} // namespace conversion
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/conversion/url_or_tileset.cpp b/platform/android/src/style/conversion/url_or_tileset.cpp
new file mode 100644
index 0000000000..2ec5856751
--- /dev/null
+++ b/platform/android/src/style/conversion/url_or_tileset.cpp
@@ -0,0 +1,30 @@
+#include "url_or_tileset.hpp"
+#include "../android_conversion.hpp"
+
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/tileset.hpp>
+
+namespace mbgl {
+namespace android {
+
+// This conversion is expected not to fail because it's used only in contexts where
+// the value was originally a String or TileSet object on the Java side. If it fails
+// to convert, it's a bug in our serialization or Java-side static typing.
+variant<std::string, Tileset> convertURLOrTileset(mbgl::android::Value&& value) {
+ using namespace mbgl::style::conversion;
+
+ const Convertible convertible(std::move(value));
+ if (isObject(convertible)) {
+ Error error;
+ optional<Tileset> tileset = convert<Tileset>(convertible, error);
+ if (!tileset) {
+ throw std::logic_error(error.message);
+ }
+ return { *tileset };
+ } else {
+ return { *toString(convertible) };
+ }
+}
+
+}
+}
diff --git a/platform/android/src/style/conversion/url_or_tileset.hpp b/platform/android/src/style/conversion/url_or_tileset.hpp
index 92c1182a63..f42a9b9a2a 100644
--- a/platform/android/src/style/conversion/url_or_tileset.hpp
+++ b/platform/android/src/style/conversion/url_or_tileset.hpp
@@ -1,37 +1,16 @@
#pragma once
-#include <mbgl/util/optional.hpp>
#include <mbgl/util/variant.hpp>
-
#include <mbgl/util/tileset.hpp>
-#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/conversion/tileset.hpp>
-
-#include <jni/jni.hpp>
#include <string>
+#include "../value.hpp"
+
namespace mbgl {
namespace android {
-// This conversion is expected not to fail because it's used only in contexts where
-// the value was originally a String or TileSet object on the Java side. If it fails
-// to convert, it's a bug in our serialization or Java-side static typing.
-inline variant<std::string, Tileset> convertURLOrTileset(mbgl::android::Value&& value) {
- using namespace mbgl::style::conversion;
-
- const Convertible convertible(std::move(value));
- if (isObject(convertible)) {
- Error error;
- optional<Tileset> tileset = convert<Tileset>(convertible, error);
- if (!tileset) {
- throw std::logic_error(error.message);
- }
- return { *tileset };
- } else {
- return { *toString(convertible) };
- }
-}
+variant<std::string, Tileset> convertURLOrTileset(mbgl::android::Value&& value);
}
}
diff --git a/platform/android/src/style/layers/layer.cpp b/platform/android/src/style/layers/layer.cpp
index c7a6bcd3a3..6c08893411 100644
--- a/platform/android/src/style/layers/layer.cpp
+++ b/platform/android/src/style/layers/layer.cpp
@@ -18,10 +18,10 @@
#include <mbgl/util/logging.hpp>
// Java -> C++ conversion
-#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/filter.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/source.hpp>
+#include <mbgl/style/conversion_impl.hpp>
// C++ -> Java conversion
#include "../conversion/property_value.hpp"
@@ -91,7 +91,7 @@ namespace android {
void Layer::setLayoutProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) {
// Convert and set property
- optional<mbgl::style::conversion::Error> error = mbgl::style::conversion::setLayoutProperty(layer, jni::Make<std::string>(env, jname), Value(env, jvalue));
+ optional<mbgl::style::conversion::Error> error = layer.setLayoutProperty(jni::Make<std::string>(env, jname), Value(env, jvalue));
if (error) {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make<std::string>(env, jname) + " " + error->message);
return;
@@ -100,7 +100,7 @@ namespace android {
void Layer::setPaintProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) {
// Convert and set property
- optional<mbgl::style::conversion::Error> error = mbgl::style::conversion::setPaintProperty(layer, jni::Make<std::string>(env, jname), Value(env, jvalue));
+ optional<mbgl::style::conversion::Error> error = layer.setPaintProperty(jni::Make<std::string>(env, jname), Value(env, jvalue));
if (error) {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make<std::string>(env, jname) + " " + error->message);
return;
diff --git a/platform/android/src/style/sources/custom_geometry_source.cpp b/platform/android/src/style/sources/custom_geometry_source.cpp
index b38405a3b1..9c51f70ab5 100644
--- a/platform/android/src/style/sources/custom_geometry_source.cpp
+++ b/platform/android/src/style/sources/custom_geometry_source.cpp
@@ -54,7 +54,9 @@ namespace android {
: Source(env, coreSource, createJavaPeer(env), frontend) {
}
- CustomGeometrySource::~CustomGeometrySource() = default;
+ CustomGeometrySource::~CustomGeometrySource() {
+ releaseThreads();
+ }
void CustomGeometrySource::fetchTile (const mbgl::CanonicalTileID& tileID) {
android::UniqueEnv _env = android::AttachEnv();
@@ -78,6 +80,28 @@ namespace android {
peer.Call(*_env, cancelTile, (int)tileID.z, (int)tileID.x, (int)tileID.y);
};
+ void CustomGeometrySource::startThreads() {
+ android::UniqueEnv _env = android::AttachEnv();
+
+ static auto startThreads = javaClass.GetMethod<void ()>(*_env, "startThreads");
+
+ assert(javaPeer);
+
+ auto peer = jni::Cast(*_env, *javaPeer, javaClass);
+ peer.Call(*_env, startThreads);
+ }
+
+ void CustomGeometrySource::releaseThreads() {
+ android::UniqueEnv _env = android::AttachEnv();
+
+ static auto releaseThreads = javaClass.GetMethod<void ()>(*_env, "releaseThreads");
+
+ assert(javaPeer);
+
+ auto peer = jni::Cast(*_env, *javaPeer, javaClass);
+ peer.Call(*_env, releaseThreads);
+ };
+
void CustomGeometrySource::setTileData(jni::JNIEnv& env,
jni::jint z,
jni::jint x,
@@ -120,6 +144,19 @@ namespace android {
return jni::Object<Source>(CustomGeometrySource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get());
}
+ void CustomGeometrySource::addToMap(JNIEnv& env, jni::Object<Source> obj, mbgl::Map& map, AndroidRendererFrontend& frontend) {
+ Source::addToMap(env, obj, map, frontend);
+ startThreads();
+ }
+
+ bool CustomGeometrySource::removeFromMap(JNIEnv& env, jni::Object<Source> source, mbgl::Map& map) {
+ bool successfullyRemoved = Source::removeFromMap(env, source, map);
+ if (successfullyRemoved) {
+ releaseThreads();
+ }
+ return successfullyRemoved;
+ }
+
void CustomGeometrySource::registerNative(jni::JNIEnv& env) {
// Lookup the class
CustomGeometrySource::javaClass = *jni::Class<CustomGeometrySource>::Find(env).NewGlobalRef(env).release();
diff --git a/platform/android/src/style/sources/custom_geometry_source.hpp b/platform/android/src/style/sources/custom_geometry_source.hpp
index 1dc1c07b4f..c38926a5b9 100644
--- a/platform/android/src/style/sources/custom_geometry_source.hpp
+++ b/platform/android/src/style/sources/custom_geometry_source.hpp
@@ -28,8 +28,13 @@ public:
~CustomGeometrySource();
+ bool removeFromMap(JNIEnv&, jni::Object<Source>, mbgl::Map&) override;
+ void addToMap(JNIEnv&, jni::Object<Source>, mbgl::Map&, AndroidRendererFrontend&) override;
+
void fetchTile(const mbgl::CanonicalTileID& tileID);
void cancelTile(const mbgl::CanonicalTileID& tileID);
+ void startThreads();
+ void releaseThreads();
void setTileData(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y, jni::Object<geojson::FeatureCollection> jf);
void invalidateTile(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y);
diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp
index 6d9ab9e22c..e526231763 100644
--- a/platform/android/src/style/sources/geojson_source.cpp
+++ b/platform/android/src/style/sources/geojson_source.cpp
@@ -5,9 +5,9 @@
// Java -> C++ conversion
#include "../android_conversion.hpp"
#include "../conversion/filter.hpp"
-#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion/geojson_options.hpp>
+#include <mbgl/style/conversion_impl.hpp>
// C++ -> Java conversion
#include "../../conversion/conversion.hpp"
@@ -16,7 +16,13 @@
#include "../conversion/url_or_tileset.hpp"
#include <string>
+#include <mbgl/util/shared_thread_pool.hpp>
+// GeoJSONSource uses a "coalescing" model for high frequency asynchronous data update calls,
+// which in practice means, that any update that started processing is going to finish
+// and the last scheduled update is going to finish as well. Any updates scheduled during processing can be canceled.
+// Conversion from Java features to core ones is done on a worker thread and once finished,
+// the ownership of the converted features is returned to the calling thread.
namespace mbgl {
namespace android {
@@ -40,60 +46,39 @@ namespace android {
: Source(env, std::make_unique<mbgl::style::GeoJSONSource>(
jni::Make<std::string>(env, sourceId),
convertGeoJSONOptions(env, options))
- ) {
+ ), converter(std::make_unique<Actor<FeatureConverter>>(*sharedThreadPool())) {
}
GeoJSONSource::GeoJSONSource(jni::JNIEnv& env,
mbgl::style::Source& coreSource,
AndroidRendererFrontend& frontend)
- : Source(env, coreSource, createJavaPeer(env), frontend) {
+ : Source(env, coreSource, createJavaPeer(env), frontend)
+ , converter(std::make_unique<Actor<FeatureConverter>>(*sharedThreadPool())) {
}
GeoJSONSource::~GeoJSONSource() = default;
- void GeoJSONSource::setGeoJSONString(jni::JNIEnv& env, jni::String json) {
- using namespace mbgl::style::conversion;
+ void GeoJSONSource::setGeoJSONString(jni::JNIEnv& env, jni::String jString) {
- // Convert the jni object
- Error error;
- optional<GeoJSON> converted = convert<GeoJSON>(mbgl::android::Value(env, json), error);
- if(!converted) {
- mbgl::Log::Error(mbgl::Event::JNI, "Error setting geo json: " + error.message);
- return;
- }
+ std::shared_ptr<std::string> json = std::make_shared<std::string>(jni::Make<std::string>(env, jString));
- // Update the core source
- source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setGeoJSON(*converted);
+ Update::Converter converterFn = [this, json](ActorRef<Callback> _callback) {
+ converter->self().invoke(&FeatureConverter::convertJson, json, _callback);
+ };
+
+ setAsync(converterFn);
}
void GeoJSONSource::setFeatureCollection(jni::JNIEnv& env, jni::Object<geojson::FeatureCollection> jFeatures) {
- using namespace mbgl::android::geojson;
-
- // Convert the jni object
- auto features = FeatureCollection::convert(env, jFeatures);
-
- // Update the core source
- source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setGeoJSON(GeoJSON(features));
+ setCollectionAsync(env, jFeatures);
}
void GeoJSONSource::setFeature(jni::JNIEnv& env, jni::Object<geojson::Feature> jFeature) {
- using namespace mbgl::android::geojson;
-
- // Convert the jni object
- auto feature = Feature::convert(env, jFeature);
-
- // Update the core source
- source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setGeoJSON(GeoJSON(feature));
+ setCollectionAsync(env, jFeature);
}
void GeoJSONSource::setGeometry(jni::JNIEnv& env, jni::Object<geojson::Geometry> jGeometry) {
- using namespace mbgl::android::geojson;
-
- // Convert the jni object
- auto geometry = Geometry::convert(env, jGeometry);
-
- // Update the core source
- source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setGeoJSON(GeoJSON(geometry));
+ setCollectionAsync(env, jGeometry);
}
void GeoJSONSource::setURL(jni::JNIEnv& env, jni::String url) {
@@ -125,6 +110,50 @@ namespace android {
return jni::Object<Source>(GeoJSONSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get());
}
+ template <class JNIType>
+ void GeoJSONSource::setCollectionAsync(jni::JNIEnv& env, jni::Object<JNIType> jObject) {
+
+ std::shared_ptr<jni::jobject> object = std::shared_ptr<jni::jobject>(jObject.NewGlobalRef(env).release()->Get(), GenericGlobalRefDeleter());
+
+ Update::Converter converterFn = [this, object](ActorRef<Callback> _callback) {
+ converter->self().invoke(&FeatureConverter::convertObject<JNIType>, jni::Object<JNIType>(*object), _callback);
+ };
+
+ setAsync(converterFn);
+ }
+
+ void GeoJSONSource::setAsync(Update::Converter converterFn) {
+ awaitingUpdate = std::make_unique<Update>(
+ std::move(converterFn),
+ std::make_unique<Actor<Callback>>(
+ *Scheduler::GetCurrent(),
+ [this](GeoJSON geoJSON) {
+ // conversion from Java features to core ones finished
+ android::UniqueEnv _env = android::AttachEnv();
+
+ // Update the core source
+ source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setGeoJSON(geoJSON);
+
+ // if there is an awaiting update, execute it, otherwise, release resources
+ if (awaitingUpdate) {
+ update = std::move(awaitingUpdate);
+ update->converterFn(update->callback->self());
+ } else {
+ update.reset();
+ }
+ })
+ );
+
+ // If another update is running, wait
+ if (update) {
+ return;
+ }
+
+ // no updates are being processed, execute this one
+ update = std::move(awaitingUpdate);
+ update->converterFn(update->callback->self());
+ }
+
void GeoJSONSource::registerNative(jni::JNIEnv& env) {
// Lookup the class
GeoJSONSource::javaClass = *jni::Class<GeoJSONSource>::Find(env).NewGlobalRef(env).release();
@@ -147,5 +176,36 @@ namespace android {
);
}
+ void FeatureConverter::convertJson(std::shared_ptr<std::string> json,
+ ActorRef<Callback> callback) {
+ using namespace mbgl::style::conversion;
+
+ android::UniqueEnv _env = android::AttachEnv();
+
+ // Convert the jni object
+ Error error;
+ optional<GeoJSON> converted = parseGeoJSON(*json, error);
+ if(!converted) {
+ mbgl::Log::Error(mbgl::Event::JNI, "Error setting geo json: " + error.message);
+ return;
+ }
+
+ callback.invoke(&Callback::operator(), *converted);
+ }
+
+ template<class JNIType>
+ void FeatureConverter::convertObject(jni::Object<JNIType> jObject, ActorRef<Callback> callback) {
+ using namespace mbgl::android::geojson;
+
+ android::UniqueEnv _env = android::AttachEnv();
+ // Convert the jni object
+ auto geometry = JNIType::convert(*_env, jObject);
+ callback.invoke(&Callback::operator(), GeoJSON(geometry));
+ }
+
+ Update::Update(Converter _converterFn, std::unique_ptr<Actor<Callback>> _callback)
+ : converterFn(std::move(_converterFn))
+ , callback(std::move(_callback)) {}
+
} // namespace android
} // namespace mbgl
diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp
index c46519b04a..b9c360c67c 100644
--- a/platform/android/src/style/sources/geojson_source.hpp
+++ b/platform/android/src/style/sources/geojson_source.hpp
@@ -10,6 +10,24 @@
namespace mbgl {
namespace android {
+using Callback = std::function<void (GeoJSON)>;
+
+struct FeatureConverter {
+ void convertJson(std::shared_ptr<std::string>, ActorRef<Callback>);
+
+ template <class JNIType>
+ void convertObject(jni::Object<JNIType>, ActorRef<Callback>);
+};
+
+struct Update {
+ using Converter = std::function<void (ActorRef<Callback>)>;
+ Converter converterFn;
+
+ std::unique_ptr<Actor<Callback>> callback;
+
+ Update(Converter, std::unique_ptr<Actor<Callback>>);
+};
+
class GeoJSONSource : public Source {
public:
@@ -35,13 +53,21 @@ public:
void setURL(jni::JNIEnv&, jni::String);
+ jni::String getURL(jni::JNIEnv&);
+
jni::Array<jni::Object<geojson::Feature>> querySourceFeatures(jni::JNIEnv&,
jni::Array<jni::Object<>> jfilter);
- jni::String getURL(jni::JNIEnv&);
-
private:
jni::Object<Source> createJavaPeer(jni::JNIEnv&);
+ std::unique_ptr<Update> awaitingUpdate;
+ std::unique_ptr<Update> update;
+ std::unique_ptr<Actor<FeatureConverter>> converter;
+
+ template <class JNIType>
+ void setCollectionAsync(jni::JNIEnv&, jni::Object<JNIType>);
+
+ void setAsync(Update::Converter);
}; // class GeoJSONSource
diff --git a/platform/android/src/style/sources/image_source.cpp b/platform/android/src/style/sources/image_source.cpp
index 249387ea51..278564485d 100644
--- a/platform/android/src/style/sources/image_source.cpp
+++ b/platform/android/src/style/sources/image_source.cpp
@@ -5,7 +5,7 @@
// C++ -> Java conversion
#include "../../conversion/conversion.hpp"
-#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/premultiply.hpp>
#include "../../bitmap.hpp"
diff --git a/platform/android/src/style/sources/source.cpp b/platform/android/src/style/sources/source.cpp
index 413530a5ec..d2e2426c0b 100644
--- a/platform/android/src/style/sources/source.cpp
+++ b/platform/android/src/style/sources/source.cpp
@@ -7,8 +7,8 @@
#include <mbgl/util/logging.hpp>
// Java -> C++ conversion
-#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/source.hpp>
+#include <mbgl/style/conversion_impl.hpp>
// C++ -> Java conversion
#include "../conversion/property_value.hpp"
@@ -51,7 +51,7 @@ namespace android {
if (!coreSource.peer.has_value()) {
coreSource.peer = createSourcePeer(env, coreSource, frontend);
}
- return *mbgl::util::any_cast<std::unique_ptr<Source>>(&coreSource.peer)->get()->javaPeer;
+ return *coreSource.peer.get<std::unique_ptr<Source>>()->javaPeer;
}
Source::Source(jni::JNIEnv& env, mbgl::style::Source& coreSource, jni::Object<Source> obj, AndroidRendererFrontend& frontend)
@@ -109,7 +109,7 @@ namespace android {
rendererFrontend = &frontend;
}
- void Source::removeFromMap(JNIEnv&, jni::Object<Source>, mbgl::Map& map) {
+ bool Source::removeFromMap(JNIEnv&, jni::Object<Source>, mbgl::Map& map) {
// Cannot remove if not attached yet
if (ownedSource) {
throw std::runtime_error("Cannot remove detached source");
@@ -119,13 +119,18 @@ namespace android {
ownedSource = map.getStyle().removeSource(source.getID());
// The source may not be removed if any layers still reference it
+ return ownedSource != nullptr;
+ }
+
+ void Source::releaseJavaPeer() {
+ // We can't release the peer if the source was not removed from the map
if (!ownedSource) {
return;
}
// Release the peer relationships. These will be re-established when the source is added to a map
assert(ownedSource->peer.has_value());
- util::any_cast<std::unique_ptr<Source>>(&(ownedSource->peer))->release();
+ ownedSource->peer.get<std::unique_ptr<Source>>().release();
ownedSource->peer.reset();
// Release the strong reference to the java peer
diff --git a/platform/android/src/style/sources/source.hpp b/platform/android/src/style/sources/source.hpp
index 718f60b381..6b906eb9c0 100644
--- a/platform/android/src/style/sources/source.hpp
+++ b/platform/android/src/style/sources/source.hpp
@@ -35,9 +35,11 @@ public:
virtual ~Source();
- void addToMap(JNIEnv&, jni::Object<Source>, mbgl::Map&, AndroidRendererFrontend&);
+ virtual void addToMap(JNIEnv&, jni::Object<Source>, mbgl::Map&, AndroidRendererFrontend&);
- void removeFromMap(JNIEnv&, jni::Object<Source>, mbgl::Map&);
+ virtual bool removeFromMap(JNIEnv&, jni::Object<Source>, mbgl::Map&);
+
+ void releaseJavaPeer();
jni::String getId(jni::JNIEnv&);