summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobrun <tobrun.van.nuland@gmail.com>2017-10-24 17:43:53 -0700
committerTobrun <tobrun@mapbox.com>2017-10-31 13:47:12 -0700
commitf578b262820c02b0621b7c512118f92b755cc06d (patch)
tree151716e3be50f4cc92b8a3912bbb8136e1782fae
parentebe6a30821d244a95f7e631636a25b283b5430be (diff)
downloadqtlocation-mapboxgl-f578b262820c02b0621b7c512118f92b755cc06d.tar.gz
[android] - add bulk addImages api on MapboxMap
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java17
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java14
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java65
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java141
-rw-r--r--platform/android/config.cmake2
-rwxr-xr-xplatform/android/src/jni.cpp1
-rw-r--r--platform/android/src/map/image.cpp44
-rw-r--r--platform/android/src/map/image.hpp26
-rwxr-xr-xplatform/android/src/native_map_view.cpp14
-rwxr-xr-xplatform/android/src/native_map_view.hpp3
10 files changed, 278 insertions, 49 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java
new file mode 100644
index 0000000000..b2f6cef3b0
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java
@@ -0,0 +1,17 @@
+package com.mapbox.mapboxsdk.maps;
+
+class Image {
+ private final byte[] buffer;
+ private final float pixelRatio;
+ private final String name;
+ private final int width;
+ private final int height;
+
+ public Image(byte[] buffer, float pixelRatio, String name, int width, int height) {
+ this.buffer = buffer;
+ this.pixelRatio = pixelRatio;
+ this.name = name;
+ this.width = width;
+ this.height = height;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
index f3d4a5b3c2..ee21ddaaa5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
@@ -47,6 +47,7 @@ import com.mapbox.services.commons.geojson.Feature;
import com.mapbox.services.commons.geojson.Geometry;
import java.lang.reflect.ParameterizedType;
+import java.util.HashMap;
import java.util.List;
import timber.log.Timber;
@@ -467,6 +468,13 @@ public final class MapboxMap {
}
/**
+ * Adds an images to be used in the map's style
+ */
+ public void addImages(@NonNull HashMap<String, Bitmap> images) {
+ nativeMapView.addImages(images);
+ }
+
+ /**
* Removes an image from the map's style
*
* @param name the name of the image to remove
@@ -1674,9 +1682,9 @@ public final class MapboxMap {
/**
* Get a camera position that fits a provided shape with a given bearing and padding.
*
- * @param geometry the geometry to constrain the map with
- * @param bearing the bearing at which to compute the geometry's bounds
- * @param padding the padding to apply to the bounds
+ * @param geometry the geometry to constrain the map with
+ * @param bearing the bearing at which to compute the geometry's bounds
+ * @param padding the padding to apply to the bounds
* @return the camera position that fits the bounds and padding
*/
public CameraPosition getCameraForGeometry(Geometry geometry, double bearing, int[] padding) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
index db0b14a4c7..8b6bce69e2 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -4,6 +4,7 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.RectF;
+import android.os.AsyncTask;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -34,7 +35,9 @@ import com.mapbox.services.commons.geojson.Geometry;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import timber.log.Timber;
@@ -753,6 +756,7 @@ final class NativeMapView {
if (isDestroyedOn("addImage")) {
return;
}
+
// Check/correct config
if (image.getConfig() != Bitmap.Config.ARGB_8888) {
image = image.copy(Bitmap.Config.ARGB_8888, false);
@@ -769,6 +773,14 @@ final class NativeMapView {
nativeAddImage(name, image.getWidth(), image.getHeight(), pixelRatio, buffer.array());
}
+ public void addImages(@NonNull HashMap<String, Bitmap> bitmapHashMap) {
+ if (isDestroyedOn("addImages")) {
+ return;
+ }
+ //noinspection unchecked
+ new BitmapImageConversionTask(this).execute(bitmapHashMap);
+ }
+
public void removeImage(String name) {
if (isDestroyedOn("removeImage")) {
return;
@@ -1024,6 +1036,8 @@ final class NativeMapView {
private native void nativeAddImage(String name, int width, int height, float pixelRatio,
byte[] array);
+ private native void nativeAddImages(Image[] images);
+
private native void nativeRemoveImage(String name);
private native Bitmap nativeGetImage(String name);
@@ -1111,4 +1125,55 @@ final class NativeMapView {
});
}
+
+
+ //
+ // Image conversion
+ //
+
+ private static class BitmapImageConversionTask extends AsyncTask<HashMap<String, Bitmap>, Void, List<Image>> {
+
+ private NativeMapView nativeMapView;
+
+ BitmapImageConversionTask(NativeMapView nativeMapView) {
+ this.nativeMapView = nativeMapView;
+ }
+
+ @Override
+ protected List<Image> doInBackground(HashMap<String, Bitmap>... params) {
+ HashMap<String, Bitmap> bitmapHashMap = params[0];
+
+ List<Image> images = new ArrayList<>();
+ ByteBuffer buffer;
+ String name;
+ Bitmap bitmap;
+
+ for (Map.Entry<String, Bitmap> stringBitmapEntry : bitmapHashMap.entrySet()) {
+ name = stringBitmapEntry.getKey();
+ bitmap = stringBitmapEntry.getValue();
+
+ if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
+ bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
+ }
+
+ buffer = ByteBuffer.allocate(bitmap.getByteCount());
+ bitmap.copyPixelsToBuffer(buffer);
+
+ float density = bitmap.getDensity() == Bitmap.DENSITY_NONE ? Bitmap.DENSITY_NONE : bitmap.getDensity();
+ float pixelRatio = density / DisplayMetrics.DENSITY_DEFAULT;
+
+ images.add(new Image(buffer.array(), pixelRatio, name, bitmap.getWidth(), bitmap.getHeight()));
+ }
+
+ return images;
+ }
+
+ @Override
+ protected void onPostExecute(List<Image> images) {
+ super.onPostExecute(images);
+ if (nativeMapView != null && !nativeMapView.isDestroyedOn("nativeAddImages")) {
+ nativeMapView.nativeAddImages(images.toArray(new Image[images.size()]));
+ }
+ }
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
index 0eaccfef0c..6e9e45cfaa 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
@@ -1,13 +1,14 @@
package com.mapbox.mapboxsdk.testapp.activity.style;
+import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.support.v7.app.AppCompatActivity;
import android.graphics.Color;
import android.graphics.PointF;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
-
+import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -32,7 +33,7 @@ import com.mapbox.services.commons.geojson.custom.PositionDeserializer;
import com.mapbox.services.commons.models.Position;
import java.io.IOException;
-
+import java.util.HashMap;
import java.util.List;
import timber.log.Timber;
@@ -64,49 +65,10 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
}
@Override
- public void onMapReady(MapboxMap map) {
+ public void onMapReady(final MapboxMap map) {
mapboxMap = map;
- try {
- // read local geojson from raw folder
- String tinyCountriesJson = ResourceUtils.readRawResource(this, R.raw.tiny_countries);
-
- // convert geojson to a model
- FeatureCollection featureCollection = new GsonBuilder()
- .registerTypeAdapter(Geometry.class, new GeometryDeserializer())
- .registerTypeAdapter(Position.class, new PositionDeserializer())
- .create().fromJson(tinyCountriesJson, FeatureCollection.class);
-
- // add a geojson to the map
- Source source = new GeoJsonSource(SOURCE_ID, featureCollection);
- mapboxMap.addSource(source);
-
- // for each feature add a symbolLayer
- for (Feature feature : featureCollection.getFeatures()) {
- String countryName = feature.getStringProperty(FEATURE_ID);
-
- // create View
- TextView textView = new TextView(this);
- textView.setBackgroundColor(getResources().getColor(R.color.blueAccent));
- textView.setPadding(10, 5, 10, 5);
- textView.setTextColor(Color.WHITE);
- textView.setText(countryName);
-
- // create bitmap from view
- mapboxMap.addImage(countryName, SymbolGenerator.generate(textView));
- }
-
- // create layer use
- mapboxMap.addLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
- .withProperties(
- iconImage("{" + FEATURE_ID + "}"), // { } is a token notation
- iconAllowOverlap(false)
- )
- );
-
- addSymbolClickListener();
- } catch (IOException exception) {
- Timber.e(exception);
- }
+ addSymbolClickListener();
+ new LoadDataTask(map, SymbolGeneratorActivity.this).execute();
}
private void addSymbolClickListener() {
@@ -213,4 +175,91 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
return bitmap;
}
}
-}
+
+ private static class LoadDataTask extends AsyncTask<Void, Void, FeatureCollection> {
+
+ private final MapboxMap mapboxMap;
+ private final Context context;
+
+ LoadDataTask(MapboxMap mapboxMap, Context context) {
+ this.mapboxMap = mapboxMap;
+ this.context = context;
+ }
+
+ @Override
+ protected FeatureCollection doInBackground(Void... params) {
+ try {
+ // read local geojson from raw folder
+ String tinyCountriesJson = ResourceUtils.readRawResource(context, R.raw.tiny_countries);
+
+ // convert geojson to a model
+ FeatureCollection featureCollection = new GsonBuilder()
+ .registerTypeAdapter(Geometry.class, new GeometryDeserializer())
+ .registerTypeAdapter(Position.class, new PositionDeserializer())
+ .create().fromJson(tinyCountriesJson, FeatureCollection.class);
+
+ return featureCollection;
+ } catch (IOException exception) {
+ return null;
+ }
+ }
+
+
+ @Override
+ protected void onPostExecute(FeatureCollection featureCollection) {
+ super.onPostExecute(featureCollection);
+ if (featureCollection == null) {
+ return;
+ }
+
+ // add a geojson to the map
+ Source source = new GeoJsonSource(SOURCE_ID, featureCollection);
+ mapboxMap.addSource(source);
+
+ // create layer use
+ mapboxMap.addLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
+ .withProperties(
+ iconImage("{" + FEATURE_ID + "}"), // { } is a token notation
+ iconAllowOverlap(false)
+ )
+ );
+
+ new GenerateSymbolTask(mapboxMap, context).execute(featureCollection);
+ }
+ }
+
+ private static class GenerateSymbolTask extends AsyncTask<FeatureCollection, Void, HashMap<String, Bitmap>> {
+
+ private MapboxMap mapboxMap;
+ private Context context;
+
+ GenerateSymbolTask(MapboxMap mapboxMap, Context context) {
+ this.mapboxMap = mapboxMap;
+ this.context = context;
+ }
+
+ @SuppressWarnings("WrongThread")
+ @Override
+ protected HashMap<String, Bitmap> doInBackground(FeatureCollection... params) {
+ FeatureCollection featureCollection = params[0];
+
+ HashMap<String, Bitmap> imagesMap = new HashMap<>();
+ for (Feature feature : featureCollection.getFeatures()) {
+ String countryName = feature.getStringProperty(FEATURE_ID);
+ TextView textView = new TextView(context);
+ textView.setBackgroundColor(context.getResources().getColor(R.color.blueAccent));
+ textView.setPadding(10, 5, 10, 5);
+ textView.setTextColor(Color.WHITE);
+ textView.setText(countryName);
+ imagesMap.put(countryName, SymbolGenerator.generate(textView));
+ }
+ return imagesMap;
+ }
+
+ @Override
+ protected void onPostExecute(HashMap<String, Bitmap> bitmapHashMap) {
+ super.onPostExecute(bitmapHashMap);
+ mapboxMap.addImages(bitmapHashMap);
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index 8dd537d36e..e6813d5a22 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -143,6 +143,8 @@ add_library(mbgl-android STATIC
platform/android/src/style/conversion/types_string_values.hpp
platform/android/src/map/camera_position.cpp
platform/android/src/map/camera_position.hpp
+ platform/android/src/map/image.cpp
+ platform/android/src/map/image.hpp
# Style conversion Java -> C++
platform/android/src/style/android_conversion.hpp
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index 6acb6a3664..f6ddb8b6ee 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -171,6 +171,7 @@ void registerNatives(JavaVM *vm) {
// Map
CameraPosition::registerNative(env);
+ Image::registerNative(env);
// Connectivity
ConnectivityListener::registerNative(env);
diff --git a/platform/android/src/map/image.cpp b/platform/android/src/map/image.cpp
new file mode 100644
index 0000000000..5f5c90eddd
--- /dev/null
+++ b/platform/android/src/map/image.cpp
@@ -0,0 +1,44 @@
+#include <mbgl/style/image.hpp>
+#include <mbgl/util/exception.hpp>
+#include "image.hpp"
+
+namespace mbgl {
+namespace android {
+
+mbgl::style::Image Image::getImage(jni::JNIEnv& env, jni::Object<Image> image) {
+ static auto widthField = Image::javaClass.GetField<jni::jint>(env, "width");
+ static auto heightField = Image::javaClass.GetField<jni::jint>(env, "height");
+ static auto pixelRatioField = Image::javaClass.GetField<jni::jfloat>(env, "pixelRatio");
+ static auto bufferField = Image::javaClass.GetField<jni::Array<jbyte>>(env, "buffer");
+ static auto nameField = Image::javaClass.GetField<jni::String>(env, "name");
+
+ auto height = image.Get(env, heightField);
+ auto width = image.Get(env, widthField);
+ auto pixelRatio = image.Get(env, pixelRatioField);
+ auto pixels = image.Get(env, bufferField);
+ auto name = jni::Make<std::string>(env, image.Get(env, nameField));
+
+ jni::NullCheck(env, &pixels);
+ std::size_t size = pixels.Length(env);
+
+ mbgl::PremultipliedImage premultipliedImage({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
+ if (premultipliedImage.bytes() != uint32_t(size)) {
+ throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
+ }
+
+ jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
+
+ return mbgl::style::Image {name, std::move(premultipliedImage), pixelRatio};
+}
+
+void Image::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ Image::javaClass = *jni::Class<Image>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<Image> Image::javaClass;
+
+
+} // namespace android
+} // namespace mb
+
diff --git a/platform/android/src/map/image.hpp b/platform/android/src/map/image.hpp
new file mode 100644
index 0000000000..1513e13ee7
--- /dev/null
+++ b/platform/android/src/map/image.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+
+#include <jni/jni.hpp>
+#include <mbgl/style/image.hpp>
+
+namespace mbgl {
+namespace android {
+
+class Image : private mbgl::util::noncopyable {
+public:
+
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/Image"; };
+
+ static mbgl::style::Image getImage(jni::JNIEnv&, jni::Object<Image>);
+
+ static jni::Class<Image> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 7372ecdf71..04cbb21927 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -49,6 +49,7 @@
#include "java/util.hpp"
#include "geometry/lat_lng_bounds.hpp"
#include "map/camera_position.hpp"
+#include "map/image.hpp"
#include "style/light.hpp"
#include "bitmap_factory.hpp"
@@ -924,6 +925,18 @@ void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::jint w, jni::ji
float(scale)));
}
+void NativeMapView::addImages(JNIEnv& env, jni::Array<jni::Object<mbgl::android::Image>> jimages) {
+ jni::NullCheck(env, &jimages);
+ std::size_t len = jimages.Length(env);
+
+ for (std::size_t i = 0; i < len; i++) {
+ jni::Object<mbgl::android::Image> jimage = jimages.Get(env, i);
+ auto image = mbgl::android::Image::getImage(env, jimage);
+ map->getStyle().addImage(std::make_unique<mbgl::style::Image>(image));
+ jni::DeleteLocalRef(env, jimage);
+ }
+}
+
void NativeMapView::removeImage(JNIEnv& env, jni::String name) {
map->getStyle().removeImage(jni::Make<std::string>(env, name));
}
@@ -1038,6 +1051,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
METHOD(&NativeMapView::removeSourceById, "nativeRemoveSourceById"),
METHOD(&NativeMapView::removeSource, "nativeRemoveSource"),
METHOD(&NativeMapView::addImage, "nativeAddImage"),
+ METHOD(&NativeMapView::addImages, "nativeAddImages"),
METHOD(&NativeMapView::removeImage, "nativeRemoveImage"),
METHOD(&NativeMapView::getImage, "nativeGetImage"),
METHOD(&NativeMapView::setLatLngBounds, "nativeSetLatLngBounds"),
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index 11b12a9f6f..d7e3b17b99 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -22,6 +22,7 @@
#include "style/sources/sources.hpp"
#include "geometry/lat_lng_bounds.hpp"
#include "map/camera_position.hpp"
+#include "map/image.hpp"
#include "style/light.hpp"
#include "bitmap.hpp"
@@ -237,6 +238,8 @@ public:
void addImage(JNIEnv&, jni::String, jni::jint, jni::jint, jni::jfloat, jni::Array<jbyte>);
+ void addImages(JNIEnv&, jni::Array<jni::Object<mbgl::android::Image>>);
+
void removeImage(JNIEnv&, jni::String);
jni::Object<Bitmap> getImage(JNIEnv&, jni::String);