diff options
author | Ivo van Dongen <info@ivovandongen.nl> | 2017-08-22 16:32:45 +0300 |
---|---|---|
committer | Ivo van Dongen <ivovandongen@users.noreply.github.com> | 2017-08-30 17:18:37 +0300 |
commit | 966bf8824d8d0a33bc0f99d4978a10126fc61b6a (patch) | |
tree | febbb7f0dc90ec64d4e39426b84e90f53d30a099 /platform | |
parent | a90e2f3a2c7d5cadd857ef65922ec8b1b70de964 (diff) | |
download | qtlocation-mapboxgl-966bf8824d8d0a33bc0f99d4978a10126fc61b6a.tar.gz |
[android] map snapshotter
Diffstat (limited to 'platform')
11 files changed, 620 insertions, 0 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java new file mode 100644 index 0000000000..5db5f5f4b9 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java @@ -0,0 +1,259 @@ +package com.mapbox.mapboxsdk.snapshotter; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.UiThread; + +import com.mapbox.mapboxsdk.R; +import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.constants.Style; +import com.mapbox.mapboxsdk.geometry.LatLngBounds; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.storage.FileSource; + +/** + * The map snapshotter creates a bitmap of the map, rendered + * off the UI thread. The snapshotter itself must be used on + * the UI thread (for access to the main looper) + */ +@UiThread +public class MapSnapshotter { + + /** + * Can be used to get notified of errors + * in snapshot generation + * + * @see MapSnapshotter#start(MapboxMap.SnapshotReadyCallback, ErrorHandler) + */ + public static interface ErrorHandler { + + /** + * Called on error. Snapshotting will not + * continue + * + * @param error the error message + */ + void onError(String error); + } + + private static final int LOGO_MARGIN_PX = 4; + + // Holds the pointer to JNI NativeMapView + private long nativePtr = 0; + + private final Context context; + private MapboxMap.SnapshotReadyCallback callback; + private ErrorHandler errorHandler; + + /** + * MapSnapshotter options + */ + public static class Options { + private int pixelRatio = 1; + private int width; + private int height; + private String styleUrl = Style.MAPBOX_STREETS; + private LatLngBounds region; + private CameraPosition cameraPosition; + + /** + * @param width the width of the image + * @param height the height of the image + */ + public Options(int width, int height) { + this.width = width; + this.height = height; + } + + /** + * @param url The style URL to use + * @return the mutated {@link Options} + */ + public Options withStyle(String url) { + this.styleUrl = url; + return this; + } + + /** + * @param region the region to show in the snapshot. + * This is applied after the camera position + * @return the mutated {@link Options} + */ + public Options withRegion(LatLngBounds region) { + this.region = region; + return this; + } + + /** + * @param pixelRatio the pixel ratio to use (default: 1) + * @return the mutated {@link Options} + */ + public Options withPixelRatio(int pixelRatio) { + this.pixelRatio = pixelRatio; + return this; + } + + /** + * @param cameraPosition The camera position to use, + * the {@link CameraPosition#target} is overridden + * by region if set in conjunction. + * @return the mutated {@link Options} + */ + public Options withCameraPosition(CameraPosition cameraPosition) { + this.cameraPosition = cameraPosition; + return this; + } + + /** + * @return the width of the image + */ + public int getWidth() { + return width; + } + + /** + * @return the height of the image + */ + public int getHeight() { + return height; + } + + /** + * @return the pixel ratio + */ + public int getPixelRatio() { + return pixelRatio; + } + + /** + * @return the region + */ + @Nullable + public LatLngBounds getRegion() { + return region; + } + + /** + * @return the style url + */ + public String getStyleUrl() { + return styleUrl; + } + + /** + * @return the camera position + */ + @Nullable + public CameraPosition getCameraPosition() { + return cameraPosition; + } + } + + /** + * Creates the Map snapshotter, but doesn't start rendering or + * loading yet. + * + * @param context the Context that is or contains the Application context + * @param options the options to use for the snapshot + */ + public MapSnapshotter(@NonNull Context context, @NonNull Options options) { + this.context = context.getApplicationContext(); + FileSource fileSource = FileSource.getInstance(context); + String programCacheDir = context.getCacheDir().getAbsolutePath(); + + nativeInitialize(this, fileSource, options.pixelRatio, options.width, + options.height, options.styleUrl, options.region, options.cameraPosition, + programCacheDir); + } + + /** + * Starts loading and rendering the snapshot. The callback will be fired + * on the calling thread. + * + * @param callback the callback to use when the snapshot is ready + */ + public void start(@NonNull MapboxMap.SnapshotReadyCallback callback) { + this.start(callback, null); + } + + /** + * Starts loading and rendering the snapshot. The callbacks will be fired + * on the calling thread. + * + * @param callback the callback to use when the snapshot is ready + * @param errorHandler the error handler to use on snapshot errors + */ + public void start(@NonNull MapboxMap.SnapshotReadyCallback callback, ErrorHandler errorHandler) { + if (this.callback != null) { + throw new IllegalStateException("Snapshotter was already started"); + } + + this.callback = callback; + nativeStart(); + } + + /** + * Must be called in on the thread + * the object was created on. + */ + public void cancel() { + callback = null; + nativeCancel(); + } + + protected void addOverlay(Bitmap original) { + float margin = context.getResources().getDisplayMetrics().density * LOGO_MARGIN_PX; + Canvas canvas = new Canvas(original); + Bitmap logo = BitmapFactory.decodeResource(context.getResources(), R.drawable.mapbox_logo_icon, null); + canvas.drawBitmap(logo, margin, original.getHeight() - (logo.getHeight() + margin), null); + } + + /** + * Called by JNI peer when snapshot is ready. + * Always called on the origin (main) thread. + * + * @param bitmap the generated snapshot + */ + protected void onSnapshotReady(Bitmap bitmap) { + if (callback != null) { + addOverlay(bitmap); + callback.onSnapshotReady(bitmap); + reset(); + } + } + + /** + * Called by JNI peer when snapshot has failed. + * Always called on the origin (main) thread. + * + * @param reason the exception string + */ + protected void onSnapshotFailed(String reason) { + if (errorHandler != null) { + errorHandler.onError(reason); + reset(); + } + } + + protected void reset() { + callback = null; + errorHandler = null; + } + + protected native void nativeInitialize(MapSnapshotter mapSnapshotter, + FileSource fileSource, float pixelRatio, + int width, int height, String styleUrl, + LatLngBounds region, CameraPosition position, + String programCacheDir); + + protected native void nativeStart(); + + protected native void nativeCancel(); + + @Override + protected native void finalize() throws Throwable; +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml index 5dc322a530..24de706bdb 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml @@ -358,6 +358,13 @@ android:name="android.support.PARENT_ACTIVITY" android:value=".activity.FeatureOverviewActivity"/> </activity> + <activity android:name=".activity.snapshot.MapSnapshotterActivity" + android:description="@string/description_map_snapshotter" + android:label="@string/activity_map_snapshotter"> + <meta-data + android:name="@string/category" + android:value="@string/category_imagegenerator"/> + </activity> <activity android:name=".activity.maplayout.DoubleMapActivity" android:description="@string/description_doublemap" diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java new file mode 100644 index 0000000000..6b1cb920fc --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java @@ -0,0 +1,131 @@ +package com.mapbox.mapboxsdk.testapp.activity.snapshot; + +import android.graphics.Bitmap; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.ViewTreeObserver; +import android.widget.GridLayout; +import android.widget.ImageView; + +import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.constants.Style; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.geometry.LatLngBounds; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter; +import com.mapbox.mapboxsdk.testapp.R; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import timber.log.Timber; + +/** + * Test activity showing how to use a the {@link com.mapbox.mapboxsdk.snapshotter.MapSnapshotter} + */ +public class MapSnapshotterActivity extends AppCompatActivity { + + private GridLayout grid; + private List<MapSnapshotter> snapshotters = new ArrayList<>(); + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_map_snapshotter); + + // Find the grid view and start snapshotting as soon + // as the view is measured + grid = (GridLayout) findViewById(R.id.snapshot_grid); + grid.getViewTreeObserver() + .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + //noinspection deprecation + grid.getViewTreeObserver().removeGlobalOnLayoutListener(this); + addSnapshots(); + } + }); + } + + private void addSnapshots() { + Timber.i("Creating snapshotters"); + + for (int row = 0; row < grid.getRowCount(); row++) { + for (int column = 0; column < grid.getColumnCount(); column++) { + startSnapShot(row, column); + } + } + } + + private void startSnapShot(final int row, final int column) { + + // Define the dimensions + MapSnapshotter.Options options = new MapSnapshotter.Options( + grid.getMeasuredWidth() / grid.getColumnCount(), + grid.getMeasuredHeight() / grid.getRowCount() + ) + // Optionally the pixel ratio + .withPixelRatio(1) + + // Optionally the style + .withStyle((column + row) % 2 == 0 ? Style.TRAFFIC_DAY : Style.DARK); + + // Optionally the visible region + if (row % 2 == 0) { + options.withRegion(new LatLngBounds.Builder() + .include(new LatLng(randomInRange(-80, 80), randomInRange(-160, 160))) + .include(new LatLng(randomInRange(-80, 80), randomInRange(-160, 160))) + .build() + ); + } + + // Optionally the camera options + if (column % 2 == 0) { + options.withCameraPosition(new CameraPosition.Builder() + .target(options.getRegion() != null + ? options.getRegion().getCenter() + : new LatLng(randomInRange(-80, 80), randomInRange(-160, 160))) + .bearing(randomInRange(0, 360)) + .tilt(randomInRange(0, 60)) + .zoom(randomInRange(0, 20)) + .build() + ); + } + + MapSnapshotter snapshotter = new MapSnapshotter(MapSnapshotterActivity.this, options); + + snapshotter.start(new MapboxMap.SnapshotReadyCallback() { + @Override + public void onSnapshotReady(Bitmap snapshot) { + Timber.i("Got the snapshot"); + ImageView imageView = new ImageView(MapSnapshotterActivity.this); + imageView.setImageBitmap(snapshot); + grid.addView( + imageView, + new GridLayout.LayoutParams(GridLayout.spec(row), GridLayout.spec(column)) + ); + } + }); + snapshotters.add(snapshotter); + } + + @Override + public void onPause() { + super.onPause(); + + // Make sure to stop the snapshotters on pause + for (MapSnapshotter snapshotter : snapshotters) { + snapshotter.cancel(); + } + snapshotters.clear(); + } + + private static Random random = new Random(); + + public static float randomInRange(float min, float max) { + return (random.nextFloat() * (max - min)) + min; + } + +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_snapshotter.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_snapshotter.xml new file mode 100644 index 0000000000..30ad494dca --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_snapshotter.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <GridLayout + android:id="@+id/snapshot_grid" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:columnCount="3" + android:orientation="horizontal" + android:rowCount="3"/> + +</RelativeLayout> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml index 0fbf9754c5..b1f354aad5 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml @@ -63,6 +63,7 @@ <string name="activity_building_fill_extrusion_layer">Building layer</string> <string name="activity_animated_image_source">Animated Image Source</string> <string name="activity_bottom_sheet">Bottom sheet</string> + <string name="activity_map_snapshotter">Map Snapshotter</string> <!--Description--> <string name="description_user_location_tracking">Tracks the location of the user</string> @@ -125,6 +126,7 @@ <string name="description_building_fill_extrusion_layer">Shows how to show 3D extruded buildings</string> <string name="description_animated_image_source">Shows how to animate georeferenced images</string> <string name="description_bottom_sheet">Show 2 MapView on screen with a bottom sheet</string> + <string name="description_map_snapshotter">Show a static bitmap taken with the MapSnapshotter</string> <!--Categories--> <string name="category">category</string> diff --git a/platform/android/config.cmake b/platform/android/config.cmake index 390e4842f4..dc6b1c80a6 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -75,6 +75,18 @@ macro(mbgl_platform_core) # Rendering PRIVATE platform/android/src/android_renderer_frontend.cpp PRIVATE platform/android/src/android_renderer_frontend.hpp + + # Snapshots + PRIVATE platform/default/mbgl/gl/headless_backend.cpp + PRIVATE platform/default/mbgl/gl/headless_backend.hpp + PRIVATE platform/default/mbgl/gl/headless_frontend.cpp + PRIVATE platform/default/mbgl/gl/headless_frontend.hpp + PRIVATE platform/default/mbgl/map/map_snapshotter.cpp + PRIVATE platform/default/mbgl/map/map_snapshotter.hpp + PRIVATE platform/linux/src/headless_backend_egl.cpp + PRIVATE platform/linux/src/headless_display_egl.cpp + PRIVATE platform/android/src/snapshotter/map_snapshotter.cpp + PRIVATE platform/android/src/snapshotter/map_snapshotter.hpp ) target_include_directories(mbgl-core diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index db8dd1dbdf..f7d1e4afbc 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -47,6 +47,7 @@ #include "style/layers/layers.hpp" #include "style/sources/sources.hpp" #include "style/light.hpp" +#include "snapshotter/map_snapshotter.hpp" namespace mbgl { namespace android { @@ -177,6 +178,9 @@ void registerNatives(JavaVM *vm) { OfflineTilePyramidRegionDefinition::registerNative(env); OfflineRegionError::registerNative(env); OfflineRegionStatus::registerNative(env); + + // Snapshotter + MapSnapshotter::registerNative(env); } } // namespace android diff --git a/platform/android/src/map/camera_position.cpp b/platform/android/src/map/camera_position.cpp index d6f2cb83e8..1fc5f9789f 100644 --- a/platform/android/src/map/camera_position.cpp +++ b/platform/android/src/map/camera_position.cpp @@ -27,6 +27,24 @@ jni::Object<CameraPosition> CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOp return CameraPosition::javaClass.New(env, constructor, LatLng::New(env, center), options.zoom.value_or(0), tilt_degrees, bearing_degrees); } +mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env, jni::Object<CameraPosition> position) { + static auto bearing = CameraPosition::javaClass.GetField<jni::jdouble>(env, "bearing"); + static auto target = CameraPosition::javaClass.GetField<jni::Object<LatLng>>(env, "target"); + static auto tilt = CameraPosition::javaClass.GetField<jni::jdouble>(env, "tilt"); + static auto zoom = CameraPosition::javaClass.GetField<jni::jdouble>(env, "zoom"); + + auto center = LatLng::getLatLng(env, position.Get(env, target)); + + return mbgl::CameraOptions { + center, + {}, + {}, + position.Get(env, zoom), + position.Get(env, bearing) * util::DEG2RAD, + position.Get(env, tilt) + }; +} + void CameraPosition::registerNative(jni::JNIEnv &env) { // Lookup the class CameraPosition::javaClass = *jni::Class<CameraPosition>::Find(env).NewGlobalRef(env).release(); diff --git a/platform/android/src/map/camera_position.hpp b/platform/android/src/map/camera_position.hpp index b9f1646cc9..4eee8be758 100644 --- a/platform/android/src/map/camera_position.hpp +++ b/platform/android/src/map/camera_position.hpp @@ -15,6 +15,8 @@ public: static jni::Object<CameraPosition> New(jni::JNIEnv&, mbgl::CameraOptions); + static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, jni::Object<CameraPosition>); + static jni::Class<CameraPosition> javaClass; static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/snapshotter/map_snapshotter.cpp b/platform/android/src/snapshotter/map_snapshotter.cpp new file mode 100644 index 0000000000..d64218d11a --- /dev/null +++ b/platform/android/src/snapshotter/map_snapshotter.cpp @@ -0,0 +1,110 @@ +#include "map_snapshotter.hpp" + +#include <mbgl/renderer/renderer.hpp> +#include <mbgl/style/style.hpp> +#include <mbgl/util/shared_thread_pool.hpp> +#include <mbgl/util/logging.hpp> +#include <mbgl/util/string.hpp> +#include <mbgl/actor/scheduler.hpp> + +#include "../attach_env.hpp" +#include "../bitmap.hpp" + +namespace mbgl { +namespace android { + +MapSnapshotter::MapSnapshotter(jni::JNIEnv& _env, + jni::Object<MapSnapshotter> _obj, + jni::Object<FileSource> jFileSource, + jni::jfloat _pixelRatio, + jni::jint width, + jni::jint height, + jni::String styleURL, + jni::Object<LatLngBounds> region, + jni::Object<CameraPosition> position, + jni::String _programCacheDir) + : javaPeer(SeizeGenericWeakRef(_env, jni::Object<MapSnapshotter>(jni::NewWeakGlobalRef(_env, _obj.Get()).release()))) + , pixelRatio(_pixelRatio) + , threadPool(sharedThreadPool()) { + + // Get a reference to the JavaVM for callbacks + if (_env.GetJavaVM(&vm) < 0) { + _env.ExceptionDescribe(); + return; + } + + auto& fileSource = mbgl::android::FileSource::getDefaultFileSource(_env, jFileSource); + auto size = mbgl::Size { static_cast<uint32_t>(width), static_cast<uint32_t>(height) }; + auto cameraOptions = position ? CameraPosition::getCameraOptions(_env, position) : CameraOptions(); + optional<mbgl::LatLngBounds> bounds; + if (region) { + bounds = LatLngBounds::getLatLngBounds(_env, region); + } + + // Create the core snapshotter + snapshotter = std::make_unique<mbgl::MapSnapshotter>(fileSource, + *threadPool, + jni::Make<std::string>(_env, styleURL), + size, + pixelRatio, + cameraOptions, + bounds, + jni::Make<std::string>(_env, _programCacheDir)); + +} + +MapSnapshotter::~MapSnapshotter() = default; + +void MapSnapshotter::start(JNIEnv&) { + MBGL_VERIFY_THREAD(tid); + + snapshotCallback = std::make_unique<Actor<mbgl::MapSnapshotter::Callback>>(*Scheduler::GetCurrent(), [this](std::exception_ptr err, PremultipliedImage image) { + MBGL_VERIFY_THREAD(tid); + android::UniqueEnv _env = android::AttachEnv(); + + if (err) { + // error handler callback + static auto onSnapshotFailed = javaClass.GetMethod<void (jni::String)>(*_env, "onSnapshotFailed"); + javaPeer->Call(*_env, onSnapshotFailed, jni::Make<jni::String>(*_env, util::toString(err))); + } else { + // Create the bitmap + auto bitmap = Bitmap::CreateBitmap(*_env, std::move(image)); + + // invoke callback + static auto onSnapshotReady = javaClass.GetMethod<void (jni::Object<Bitmap>)>(*_env, "onSnapshotReady"); + javaPeer->Call(*_env, onSnapshotReady, bitmap); + } + }); + + snapshotter->snapshot(snapshotCallback->self()); +} + +void MapSnapshotter::cancel(JNIEnv&) { + MBGL_VERIFY_THREAD(tid); + + snapshotCallback.reset(); + snapshotter.reset(); +} + +// Static methods // + +jni::Class<MapSnapshotter> MapSnapshotter::javaClass; + +void MapSnapshotter::registerNative(jni::JNIEnv& env) { + // Lookup the class + MapSnapshotter::javaClass = *jni::Class<MapSnapshotter>::Find(env).NewGlobalRef(env).release(); + +#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + // Register the peer + jni::RegisterNativePeer<MapSnapshotter>(env, MapSnapshotter::javaClass, "nativePtr", + std::make_unique<MapSnapshotter, JNIEnv&, jni::Object<MapSnapshotter>, jni::Object<FileSource>, jni::jfloat, jni::jint, jni::jint, jni::String, jni::Object<LatLngBounds>, jni::Object<CameraPosition>, jni::String>, + "nativeInitialize", + "finalize", + METHOD(&MapSnapshotter::start, "nativeStart"), + METHOD(&MapSnapshotter::cancel, "nativeCancel") + ); +} + +} // namespace android +} // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/snapshotter/map_snapshotter.hpp b/platform/android/src/snapshotter/map_snapshotter.hpp new file mode 100644 index 0000000000..093f589c05 --- /dev/null +++ b/platform/android/src/snapshotter/map_snapshotter.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include <mbgl/map/map_snapshotter.hpp> +#include <mbgl/util/default_thread_pool.hpp> +#include <mbgl/util/util.hpp> + +#include "../file_source.hpp" +#include "../geometry/lat_lng_bounds.hpp" +#include "../map/camera_position.hpp" + +#include <jni/jni.hpp> +#include "../jni/generic_global_ref_deleter.hpp" + +#include <memory> + +namespace mbgl { +namespace android { + +class SnapshotterRendererFrontend; + +class MapSnapshotter { +public: + + static constexpr auto Name() { return "com/mapbox/mapboxsdk/snapshotter/MapSnapshotter"; }; + + static jni::Class<MapSnapshotter> javaClass; + + static void registerNative(jni::JNIEnv&); + + MapSnapshotter(jni::JNIEnv&, + jni::Object<MapSnapshotter>, + jni::Object<FileSource>, + jni::jfloat pixelRatio, + jni::jint width, + jni::jint height, + jni::String styleURL, + jni::Object<LatLngBounds> region, + jni::Object<CameraPosition> position, + jni::String programCacheDir); + + ~MapSnapshotter(); + + void start(JNIEnv&); + + void cancel(JNIEnv&); + +private: + MBGL_STORE_THREAD(tid); + + JavaVM *vm = nullptr; + GenericUniqueWeakObject<MapSnapshotter> javaPeer; + + float pixelRatio; + + std::shared_ptr<mbgl::ThreadPool> threadPool; + std::unique_ptr<Actor<mbgl::MapSnapshotter::Callback>> snapshotCallback; + std::unique_ptr<mbgl::MapSnapshotter> snapshotter; +}; + +} // namespace android +} // namespace mbgl
\ No newline at end of file |