summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/.gitignore5
-rw-r--r--platform/android/MapboxGLAndroidSDK/build.gradle60
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle.properties4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java45
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java47
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java22
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/README.md14
-rw-r--r--platform/android/bitrise.yml69
-rw-r--r--platform/android/build.gradle3
-rw-r--r--platform/android/config.cmake23
-rwxr-xr-xplatform/android/scripts/debug.sh42
-rwxr-xr-xplatform/android/scripts/metrics.sh14
-rwxr-xr-xplatform/android/scripts/ndk.sh111
-rwxr-xr-xplatform/android/src/native_map_view.cpp64
-rwxr-xr-xplatform/android/src/native_map_view.hpp20
-rw-r--r--platform/android/tests/docs/UI_TESTS.md4
-rw-r--r--platform/android/tests/docs/UNIT_TESTS.md4
-rw-r--r--platform/darwin/src/MGLTypes.h4
-rw-r--r--platform/default/async_task.cpp8
-rw-r--r--platform/default/mbgl/gl/headless_backend.cpp6
-rw-r--r--platform/default/mbgl/gl/headless_backend.hpp5
-rw-r--r--platform/default/run_loop.cpp15
-rw-r--r--platform/default/timer.cpp8
-rw-r--r--platform/glfw/glfw_view.cpp10
-rw-r--r--platform/glfw/glfw_view.hpp5
-rw-r--r--platform/ios/CHANGELOG.md8
-rw-r--r--platform/ios/INSTALL.md14
-rw-r--r--platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec30
-rw-r--r--platform/ios/bitrise.yml35
-rw-r--r--platform/ios/resources/Base.lproj/Localizable.strings13
-rwxr-xr-xplatform/ios/scripts/deploy-nightly.sh20
-rwxr-xr-xplatform/ios/scripts/publish.sh15
-rw-r--r--platform/ios/src/MGLMapView.mm368
-rw-r--r--platform/macos/CHANGELOG.md4
-rw-r--r--platform/macos/bitrise.yml58
-rw-r--r--platform/macos/sdk/Base.lproj/Localizable.strings12
-rw-r--r--platform/macos/src/MGLMapView.mm329
-rw-r--r--platform/node/CHANGELOG.md13
-rw-r--r--platform/node/bitrise.yml96
-rwxr-xr-xplatform/node/scripts/after_success.sh2
-rw-r--r--platform/node/src/node_map.cpp22
-rw-r--r--platform/node/src/node_map.hpp10
-rw-r--r--platform/node/src/node_request.cpp10
-rw-r--r--platform/node/src/node_request.hpp6
-rw-r--r--platform/node/src/util/async_queue.hpp8
-rw-r--r--platform/node/test/js/map.test.js6
-rw-r--r--platform/node/test/memory.test.js41
-rw-r--r--platform/node/test/mockfs.js53
-rw-r--r--platform/qt/bitrise-qt4.yml16
-rw-r--r--platform/qt/bitrise-qt5.yml17
-rw-r--r--platform/qt/include/qmapboxgl.hpp1
-rw-r--r--platform/qt/src/qmapbox.cpp1
-rw-r--r--platform/qt/src/qmapboxgl.cpp106
-rw-r--r--platform/qt/src/qmapboxgl_p.hpp15
58 files changed, 1131 insertions, 819 deletions
diff --git a/platform/android/.gitignore b/platform/android/.gitignore
index 81eeaad167..7a3db0aafd 100644
--- a/platform/android/.gitignore
+++ b/platform/android/.gitignore
@@ -7,17 +7,16 @@
# Build files
build/
+.externalNativeBuild
*.so
*.apk
-# JNI
-MapboxGLAndroidSDK/src/main/jniLibs/
-
# Lib assets
MapboxGLAndroidSDK/src/main/assets/
# Local settings
local.properties
+/configuration.gradle
# Token file
MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml
diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle
index 2ce3780421..f2d28e53d1 100644
--- a/platform/android/MapboxGLAndroidSDK/build.gradle
+++ b/platform/android/MapboxGLAndroidSDK/build.gradle
@@ -31,6 +31,66 @@ android {
buildConfigField "String", "MAPBOX_EVENTS_USER_AGENT", String.format("\"MapboxEventsAndroid/%s\"", project.VERSION_NAME)
}
+ defaultPublishConfig project.hasProperty("mapbox.buildtype") ? project.getProperty("mapbox.buildtype") : "debug"
+
+ // We sometimes want to invoke Gradle without building a native dependency, e.g. when we just want
+ // to invoke the Java tests. When we explicitly specify an ABI of 'none', no native dependencies are
+ // added. When another ABI is specified explicitly, we're just going to build that ABI. In all other
+ // cases, all ABIs are built.
+ // When invoking from the command line, set `-Pmapbox.abis=...` to only build the desired architectures.
+ // When building from Android Studio, gradle.properties sets `android.buildOnlyTargetAbi=true` so that
+ // only the architecture for the device you're running on gets built.
+ def abi = 'all'
+ if (!project.hasProperty('android.injected.invoked.from.ide')) {
+ // Errors when the user invokes Gradle from the command line and didn't set mapbox.abis
+ abi = project.getProperty("mapbox.abis")
+ }
+
+ if (abi != 'none') {
+ externalNativeBuild {
+ cmake {
+ path "../../../CMakeLists.txt"
+ }
+ }
+ }
+
+ defaultConfig {
+ if (abi != 'none') {
+ externalNativeBuild {
+ cmake {
+ arguments "-DANDROID_TOOLCHAIN=clang"
+ arguments "-DANDROID_STL=c++_static"
+ arguments "-DANDROID_CPP_FEATURES=rtti;exceptions"
+ arguments "-DMBGL_PLATFORM=android"
+ arguments "-DMASON_PLATFORM=android"
+ arguments "-DNodeJS_EXECUTABLE=" + rootProject.ext.node
+ arguments "-Dnpm_EXECUTABLE=" + rootProject.ext.npm
+
+ // Enable ccache if the user has installed it.
+ if (rootProject.ext.ccache?.trim()) {
+ arguments "-DANDROID_CCACHE=" + rootProject.ext.ccache
+ // ccache splits up the compile command until multiple invocations and uses -E
+ // with one of them, and clang doesn't like unused arguments in that case.
+ cFlags "-Qunused-arguments"
+ cppFlags "-Qunused-arguments"
+ }
+
+ targets "mapbox-gl"
+ targets "example-custom-layer"
+ if (project.hasProperty("mapbox.with_test")) {
+ targets "mbgl-test"
+ }
+
+ if (abi != 'all') {
+ abiFilters abi.split(' ')
+ } else {
+ abiFilters "armeabi", "armeabi-v7a", "mips", "x86", "arm64-v8a", "x86_64"
+ }
+ }
+ }
+ }
+ }
+
// avoid naming conflicts, force usage of prefix
resourcePrefix 'mapbox_'
diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties
index 7a6f777a3b..9f555da5f8 100644
--- a/platform/android/MapboxGLAndroidSDK/gradle.properties
+++ b/platform/android/MapboxGLAndroidSDK/gradle.properties
@@ -14,3 +14,7 @@ POM_DEVELOPER_NAME=Mapbox
POM_NAME=Mapbox Android SDK
POM_ARTIFACT_ID=mapbox-android-sdk
POM_PACKAGING=aar
+
+# Only build native dependencies for the current ABI
+# See https://code.google.com/p/android/issues/detail?id=221098#c20
+android.buildOnlyTargetAbi=true
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
index 0bd9523f4f..9adefa3221 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
@@ -121,6 +121,7 @@ public class MapboxConstants {
public static final String STATE_COMPASS_MARGIN_RIGHT = "mapbox_compassMarginRight";
public static final String STATE_COMPASS_MARGIN_BOTTOM = "mapbox_compassMarginBottom";
public static final String STATE_COMPASS_FADE_WHEN_FACING_NORTH = "mapbox_compassFade";
+ public static final String STATE_COMPASS_IMAGE_BITMAP = "mapbox_compassImage";
public static final String STATE_LOGO_GRAVITY = "mapbox_logoGravity";
public static final String STATE_LOGO_MARGIN_LEFT = "mapbox_logoMarginLeft";
public static final String STATE_LOGO_MARGIN_TOP = "mapbox_logoMarginTop";
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
index 6467033ead..2fd02c76e5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
@@ -47,6 +47,7 @@ public class MapboxMapOptions implements Parcelable {
private boolean fadeCompassFacingNorth = true;
private int compassGravity = Gravity.TOP | Gravity.END;
private int[] compassMargins;
+ private Drawable compassImage;
private boolean logoEnabled = true;
private int logoGravity = Gravity.BOTTOM | Gravity.START;
@@ -100,6 +101,11 @@ public class MapboxMapOptions implements Parcelable {
compassMargins = in.createIntArray();
fadeCompassFacingNorth = in.readByte() != 0;
+ Bitmap compassBitmap = in.readParcelable(getClass().getClassLoader());
+ if (compassBitmap != null) {
+ compassImage = new BitmapDrawable(compassBitmap);
+ }
+
logoEnabled = in.readByte() != 0;
logoGravity = in.readInt();
logoMargins = in.createIntArray();
@@ -147,7 +153,7 @@ public class MapboxMapOptions implements Parcelable {
textureMode = in.readByte() != 0;
}
- public static Bitmap getBitmapFromDrawable(Drawable drawable) {
+ static Bitmap getBitmapFromDrawable(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else {
@@ -208,6 +214,12 @@ public class MapboxMapOptions implements Parcelable {
DIMENSION_TEN_DP * pxlRatio))});
mapboxMapOptions.compassFadesWhenFacingNorth(typedArray.getBoolean(
R.styleable.mapbox_MapView_mapbox_uiCompassFadeFacingNorth, true));
+ Drawable compassDrawable = typedArray.getDrawable(
+ R.styleable.mapbox_MapView_mapbox_uiCompassDrawable);
+ if (compassDrawable == null) {
+ compassDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_compass_icon);
+ }
+ mapboxMapOptions.compassImage(compassDrawable);
mapboxMapOptions.logoEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiLogo, true));
mapboxMapOptions.logoGravity(typedArray.getInt(R.styleable.mapbox_MapView_mapbox_uiLogoGravity,
@@ -401,6 +413,20 @@ public class MapboxMapOptions implements Parcelable {
}
/**
+ * Specifies the image of the CompassView.
+ * <p>
+ * By default this value is R.drawable.mapbox_compass_icon.
+ * </p>
+ *
+ * @param compass the drawable to show as image compass
+ * @return This
+ */
+ public MapboxMapOptions compassImage(Drawable compass) {
+ this.compassImage = compass;
+ return this;
+ }
+
+ /**
* Specifies the visibility state of a logo for a map view.
*
* @param enabled True and logo is shown
@@ -743,6 +769,15 @@ public class MapboxMapOptions implements Parcelable {
}
/**
+ * Get the current configured CompassView image.
+ *
+ * @return the drawable used as compass image
+ */
+ public Drawable getCompassImage() {
+ return compassImage;
+ }
+
+ /**
* Get the current configured visibility state for mapbox_compass_icon for a map view.
*
* @return Visibility state of the mapbox_compass_icon
@@ -993,6 +1028,8 @@ public class MapboxMapOptions implements Parcelable {
dest.writeInt(compassGravity);
dest.writeIntArray(compassMargins);
dest.writeByte((byte) (fadeCompassFacingNorth ? 1 : 0));
+ dest.writeParcelable(compassImage != null
+ ? getBitmapFromDrawable(compassImage) : null, flags);
dest.writeByte((byte) (logoEnabled ? 1 : 0));
dest.writeInt(logoGravity);
@@ -1052,6 +1089,11 @@ public class MapboxMapOptions implements Parcelable {
if (fadeCompassFacingNorth != options.fadeCompassFacingNorth) {
return false;
}
+ if (compassImage != null
+ ? !compassImage.equals(options.compassImage)
+ : options.compassImage != null) {
+ return false;
+ }
if (compassGravity != options.compassGravity) {
return false;
}
@@ -1157,6 +1199,7 @@ public class MapboxMapOptions implements Parcelable {
result = 31 * result + (compassEnabled ? 1 : 0);
result = 31 * result + (fadeCompassFacingNorth ? 1 : 0);
result = 31 * result + compassGravity;
+ result = 31 * result + (compassImage != null ? compassImage.hashCode() : 0);
result = 31 * result + Arrays.hashCode(compassMargins);
result = 31 * result + (logoEnabled ? 1 : 0);
result = 31 * result + logoGravity;
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 1460f08e10..c5eaf2deb9 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
@@ -938,7 +938,11 @@ final class NativeMapView {
protected void onMapChanged(int rawChange) {
if (onMapChangedListeners != null) {
for (MapView.OnMapChangedListener onMapChangedListener : onMapChangedListeners) {
- onMapChangedListener.onMapChanged(rawChange);
+ try {
+ onMapChangedListener.onMapChanged(rawChange);
+ } catch (RuntimeException err) {
+ Timber.e("Exception (%s) in MapView.OnMapChangedListener: %s", err.getClass(), err.getMessage());
+ }
}
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
index 8a3ae1e4f3..bcb4ca4afc 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
@@ -3,8 +3,12 @@ package com.mapbox.mapboxsdk.maps;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.PointF;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
@@ -22,6 +26,8 @@ import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.maps.widgets.CompassView;
import com.mapbox.mapboxsdk.utils.ColorUtils;
+import java.io.ByteArrayOutputStream;
+
/**
* Settings for the user interface of a MapboxMap. To obtain this interface, call getUiSettings().
*/
@@ -143,6 +149,7 @@ public final class UiSettings {
setCompassMargins(tenDp, tenDp, tenDp, tenDp);
}
setCompassFadeFacingNorth(options.getCompassFadeFacingNorth());
+ setCompassImage(options.getCompassImage());
}
private void saveCompass(Bundle outState) {
@@ -153,6 +160,16 @@ public final class UiSettings {
outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM, getCompassMarginBottom());
outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT, getCompassMarginRight());
outState.putBoolean(MapboxConstants.STATE_COMPASS_FADE_WHEN_FACING_NORTH, isCompassFadeWhenFacingNorth());
+ outState.putByteArray(MapboxConstants.STATE_COMPASS_IMAGE_BITMAP,
+ convert(MapboxMapOptions.getBitmapFromDrawable(getCompassImage())));
+ }
+
+ private byte[] convert(Bitmap resource) {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ resource.compress(Bitmap.CompressFormat.PNG, 100, stream);
+ byte[] byteArray = stream.toByteArray();
+
+ return byteArray;
}
private void restoreCompass(Bundle savedInstanceState) {
@@ -163,6 +180,15 @@ public final class UiSettings {
savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT),
savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM));
setCompassFadeFacingNorth(savedInstanceState.getBoolean(MapboxConstants.STATE_COMPASS_FADE_WHEN_FACING_NORTH));
+ setCompassImage(decode(savedInstanceState.getByteArray(MapboxConstants.STATE_COMPASS_IMAGE_BITMAP)));
+ }
+
+ private Drawable decode(byte[] bitmap) {
+ Bitmap compass = BitmapFactory.decodeByteArray(bitmap, 0, bitmap.length);
+
+ Drawable compassImage = new BitmapDrawable(compassView.getResources(), compass);
+
+ return compassImage;
}
private void initialiseLogo(MapboxMapOptions options, Resources resources) {
@@ -297,6 +323,18 @@ public final class UiSettings {
}
/**
+ * Specifies the CompassView image.
+ * <p>
+ * By default this value is R.drawable.mapbox_compass_icon.
+ * </p>
+ *
+ * @param compass the drawable to show as image compass
+ */
+ public void setCompassImage(Drawable compass) {
+ compassView.setCompassImage(compass);
+ }
+
+ /**
* Returns whether the compass performs a fading animation out when facing north.
*
* @return True if the compass will fade, false if it remains visible
@@ -364,6 +402,15 @@ public final class UiSettings {
return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).bottomMargin;
}
+ /**
+ * Get the current configured CompassView image.
+ *
+ * @return the drawable used as compass image
+ */
+ public Drawable getCompassImage() {
+ return compassView.getCompassImage();
+ }
+
void update(@NonNull CameraPosition cameraPosition) {
if (!isCompassEnabled()) {
return;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
index 5c9cf93ebc..48bfae4a6e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
@@ -2,9 +2,9 @@ package com.mapbox.mapboxsdk.maps.widgets;
import android.content.Context;
import android.graphics.PointF;
+import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorCompat;
import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
@@ -13,7 +13,6 @@ import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
-import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.maps.FocalPointChangeListener;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -55,7 +54,6 @@ public final class CompassView extends AppCompatImageView implements Runnable, F
}
private void initialize(Context context) {
- setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.mapbox_compass_icon));
setEnabled(false);
// Layout params
@@ -140,6 +138,24 @@ public final class CompassView extends AppCompatImageView implements Runnable, F
return fadeCompassViewFacingNorth;
}
+ /**
+ * Set the CompassView image.
+ *
+ * @param compass the drawable to use as compass image
+ */
+ public void setCompassImage(Drawable compass) {
+ setImageDrawable(compass);
+ }
+
+ /**
+ * Get the current configured CompassView image.
+ *
+ * @return the drawable used as compass image
+ */
+ public Drawable getCompassImage() {
+ return getDrawable();
+ }
+
@Override
public void run() {
if (isFacingNorth() && fadeCompassViewFacingNorth) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
index 641020906a..7283aced5f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
@@ -54,6 +54,7 @@
<public name="mapbox_uiCompassMarginRight" type="attr" />
<public name="mapbox_uiCompassMarginBottom" type="attr" />
<public name="mapbox_uiCompassFadeFacingNorth" type="attr" />
+ <public name="mapbox_uiCompassDrawable" type="attr" />
<!--Logo-->
<public name="mapbox_uiLogo" type="attr" />
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
index 738cae07be..e17f01d075 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
@@ -64,6 +64,7 @@
<attr name="mapbox_uiCompassMarginRight" format="dimension"/>
<attr name="mapbox_uiCompassMarginBottom" format="dimension"/>
<attr name="mapbox_uiCompassFadeFacingNorth" format="boolean"/>
+ <attr name="mapbox_uiCompassDrawable" format="reference"/>
<!--Logo-->
<attr name="mapbox_uiLogo" format="boolean"/>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/README.md b/platform/android/MapboxGLAndroidSDKTestApp/README.md
index 0acb509b3e..c7a918cd48 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/README.md
+++ b/platform/android/MapboxGLAndroidSDKTestApp/README.md
@@ -1,5 +1,15 @@
# Mapbox GL Test App
+## Building
+
+To be able to run any Gradle commands, you'll need to create the configuration file by running
+
+```
+$ make android-configuration
+```
+
+from the root folder.
+
## Testing
### Running Espresso tests on a device
@@ -28,7 +38,7 @@ On a terminal, within `mapbox-gl-native/android/java`,
run the tests (`cC` stands for `connectedCheck`):
```
-$ ./gradlew cC -p MapboxGLAndroidSDKTestApp
+$ ./gradlew -Pmapbox.abis=all cC -p MapboxGLAndroidSDKTestApp
```
Then:
@@ -63,7 +73,7 @@ You can also have a run configuration:
You can also run the tests from the command line with:
```
-$ ./gradlew test --continue -p MapboxGLAndroidSDKTestApp
+$ ./gradlew -Pmapbox.abis=none test -p MapboxGLAndroidSDKTestApp
```
### Running the UI/Application Exerciser Monkey
diff --git a/platform/android/bitrise.yml b/platform/android/bitrise.yml
index de1095409e..53637fd498 100644
--- a/platform/android/bitrise.yml
+++ b/platform/android/bitrise.yml
@@ -14,30 +14,7 @@ workflows:
primary:
steps:
- script:
- title: Check for skipping CI
- inputs:
- - content: |-
- #!/bin/bash
-
- if [[ -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[ci skip\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[ci skip\]/p')" ]]; then
- envman add --key SKIPCI --value true
- else
- envman add --key SKIPCI --value false
- fi
- - script:
- title: Run Checkstyle
- run_if: '{{enveq "SKIPCI" "false"}}'
- inputs:
- - content: |-
- #!/bin/bash
- # Run checkstyle gradle task on all modules
- cd platform/android && ./gradlew checkstyle
- - script:
title: Configure Google Cloud SDK
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
@@ -58,16 +35,17 @@ workflows:
wget -O secret.json "$BITRISEIO_GCLOUD_SERVICE_ACCOUNT_JSON_URL"
- script:
title: Build libmapbox-gl.so for armeabi-v7a
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
+ # Accept Android SDK license
+ echo "Accepting Android SDK license..."
+ mkdir -p "${ANDROID_HOME}/licenses"
+ echo "8933bad161af4178b1185d1a37fbf41ea5269c55" > "${ANDROID_HOME}/licenses/android-sdk-license"
echo "Compile libmapbox-gl.so for armeabi-v7a abi:"
- export BUILDTYPE=Debug
- make android-lib-arm-v7
+ BUILDTYPE=Debug make android-lib-arm-v7
- script:
title: Compile Core tests
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
@@ -75,7 +53,6 @@ workflows:
BUILDTYPE=Debug make android-test-lib-arm-v7
- script:
title: Run local JVM Unit tests on phone module
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
@@ -83,7 +60,6 @@ workflows:
make run-android-unit-test
- script:
title: Run local JVM Unit tests on wear module
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
@@ -91,15 +67,20 @@ workflows:
make run-android-wear-unit-test
- script:
title: Generate Espresso sanity tests
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
echo "Generate these test locally by executing:"
make test-code-android
- script:
+ title: Run Checkstyle
+ inputs:
+ - content: |-
+ #!/bin/bash
+ # Run checkstyle gradle task on all modules
+ make android-checkstyle
+ - script:
title: Run Firebase instrumentation tests
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
@@ -107,7 +88,7 @@ workflows:
wget -O platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml "$BITRISEIO_TEST_ACCESS_TOKEN_UI_TEST_URL"
echo "Build seperate test apk:"
- make android-ui-test
+ make android-ui-test-arm-v7
echo "Run tests on firebase:"
gcloud auth activate-service-account --key-file secret.json --project android-gl-native
@@ -115,7 +96,6 @@ workflows:
gcloud beta test android run --type instrumentation --app platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug.apk --test platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug-androidTest.apk --device-ids shamu --os-version-ids 22 --locales en --orientations portrait --timeout 15m --test-targets "class com.mapbox.mapboxsdk.testapp.maps.widgets.AttributionTest"
- script:
title: Download Firebase results
- run_if: '{{enveq "SKIPCI" "false"}}'
is_always_run: true
inputs:
- content: |-
@@ -131,13 +111,11 @@ workflows:
find platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk -type f -name "logcat" -print0 | xargs -0 -Imylogcat mv -i mylogcat ./
cat logcat | ndk-stack -sym build/android-arm-v7/Debug
- deploy-to-bitrise-io:
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- deploy_path: platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk
- is_compress: 'true'
- notify_user_groups: none
- slack:
- run_if: '{{enveq "SKIPCI" "false"}}'
title: Post to Slack
inputs:
- webhook_url: "$SLACK_HOOK_URL"
@@ -181,15 +159,19 @@ workflows:
inputs:
- content: |-
#!/bin/bash
- echo "Compile libmapbox-gl.so for all supported abi's and create an aar file:"
- BUILDTYPE=Release make apackage
+ # Accept Android SDK license
+ echo "Accepting Android SDK license..."
+ mkdir -p "${ANDROID_HOME}/licenses"
+ echo "8933bad161af4178b1185d1a37fbf41ea5269c55" > "${ANDROID_HOME}/licenses/android-sdk-license"
+ echo "Compile libmapbox-gl.so for all supportd abi's:"
+ export BUILDTYPE=Release make apackage
- script:
title: Publish to maven
inputs:
- content: |-
#!/bin/bash
echo "Upload aar file to maven:"
- cd platform/android && ./gradlew :MapboxGLAndroidSDK:uploadArchives
+ make run-android-upload-archives
- slack:
title: Post to Slack
inputs:
@@ -208,6 +190,10 @@ workflows:
inputs:
- content: |-
#!/bin/bash
+ # Accept Android SDK license
+ echo "Accepting Android SDK license..."
+ mkdir -p "${ANDROID_HOME}/licenses"
+ echo "8933bad161af4178b1185d1a37fbf41ea5269c55" > "${ANDROID_HOME}/licenses/android-sdk-license"
echo "Compile libmapbox-gl.so for all supportd abi's:"
export BUILDTYPE=Release
make apackage
@@ -231,7 +217,7 @@ workflows:
- content: |-
#!/bin/bash
echo "Run tests on device farm:"
- cd platform/android && ./gradlew devicefarmUpload
+ make run-android-ui-test-aws
- slack:
title: Post to Slack
inputs:
@@ -257,10 +243,13 @@ workflows:
inputs:
- content: |-
#!/bin/bash
+ # Accept Android SDK license
+ echo "Accepting Android SDK license..."
+ mkdir -p "${ANDROID_HOME}/licenses"
+ echo "8933bad161af4178b1185d1a37fbf41ea5269c55" > "${ANDROID_HOME}/licenses/android-sdk-license"
echo "Compile libmapbox-gl.so for all supportd abi's:"
export BUILDTYPE=Release
make apackage
- cd platform/android && ./gradlew :MapboxGLAndroidSDK:assembleRelease
- script:
title: Log metrics
inputs:
diff --git a/platform/android/build.gradle b/platform/android/build.gradle
index 4219f2bdee..5e45232716 100644
--- a/platform/android/build.gradle
+++ b/platform/android/build.gradle
@@ -21,3 +21,6 @@ task wrapper(type: Wrapper) {
apply from: rootProject.file('dependencies.gradle')
+// Load build system information. If this file does not exist, run
+// `make platform/android/configuration.gradle`
+apply from: rootProject.file('configuration.gradle')
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index fdf03b4ec8..1a68ee065d 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -22,15 +22,6 @@ mason_use(sqlite VERSION 3.14.2)
mason_use(gtest VERSION 1.8.0)
mason_use(icu VERSION 58.1-min-size)
-set(ANDROID_SDK_PROJECT_DIR ${CMAKE_SOURCE_DIR}/platform/android/MapboxGLAndroidSDK)
-set(ANDROID_JNI_TARGET_DIR ${ANDROID_SDK_PROJECT_DIR}/src/main/jniLibs/${ANDROID_ABI})
-set(ANDROID_ASSETS_TARGET_DIR ${ANDROID_SDK_PROJECT_DIR}/src/main/assets)
-set(ANDROID_TEST_APP_JNI_TARGET_DIR ${CMAKE_SOURCE_DIR}/platform/android/MapboxGLAndroidSDKTestApp/src/main/jniLibs/${ANDROID_ABI})
-
-if (NOT DEFINED ANDROID_TOOLCHAIN_PREFIX)
- set(ANDROID_TOOLCHAIN_PREFIX "${MASON_XC_ROOT}/bin/${ANDROID_TOOLCHAIN}-")
-endif()
-
## mbgl core ##
macro(mbgl_platform_core)
@@ -251,11 +242,6 @@ target_link_libraries(mapbox-gl
PUBLIC -Wl,--version-script=${CMAKE_SOURCE_DIR}/platform/android/version-script
)
-# Create a stripped version of the library and copy it to the JNIDIR.
-add_custom_command(TARGET mapbox-gl POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E make_directory ${ANDROID_JNI_TARGET_DIR}
- COMMAND ${ANDROID_TOOLCHAIN_PREFIX}strip $<TARGET_FILE:mapbox-gl> -o ${ANDROID_JNI_TARGET_DIR}/$<TARGET_FILE_NAME:mapbox-gl>)
-
## Test library ##
add_library(mbgl-test SHARED
@@ -312,11 +298,6 @@ target_add_mason_package(mbgl-test PRIVATE boost)
target_add_mason_package(mbgl-test PRIVATE geojson)
target_add_mason_package(mbgl-test PRIVATE geojsonvt)
-add_custom_command(TARGET mbgl-test POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/stripped
- COMMAND ${ANDROID_TOOLCHAIN_PREFIX}strip $<TARGET_FILE:mapbox-gl> -o ${CMAKE_CURRENT_BINARY_DIR}/stripped/$<TARGET_FILE_NAME:mapbox-gl>
- COMMAND ${ANDROID_TOOLCHAIN_PREFIX}strip $<TARGET_FILE:mbgl-test> -o ${CMAKE_CURRENT_BINARY_DIR}/stripped/$<TARGET_FILE_NAME:mbgl-test>)
-
## Custom layer example ##
add_library(example-custom-layer SHARED
@@ -334,7 +315,3 @@ target_link_libraries(example-custom-layer
PUBLIC -Wl,--gc-sections
PUBLIC -Wl,--version-script=${CMAKE_SOURCE_DIR}/platform/android/version-script
)
-
-add_custom_command(TARGET example-custom-layer POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E make_directory ${ANDROID_TEST_APP_JNI_TARGET_DIR}
- COMMAND ${ANDROID_TOOLCHAIN_PREFIX}strip $<TARGET_FILE:example-custom-layer> -o ${ANDROID_TEST_APP_JNI_TARGET_DIR}/$<TARGET_FILE_NAME:example-custom-layer>)
diff --git a/platform/android/scripts/debug.sh b/platform/android/scripts/debug.sh
deleted file mode 100755
index c3390b4ce1..0000000000
--- a/platform/android/scripts/debug.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -o pipefail
-
-# Automation of https://github.com/mapbox/mapbox-gl-native/wiki/Android-debugging-with-remote-GDB
-
-export MASON_ANDROID_ARCH=x86
-export MASON_ANDROID_PLATFORM=9
-export MASON_ANDROID_NDK_VERSION=r13b
-
-export MASON_XC_ROOT=`scripts/mason.sh PREFIX android-ndk VERSION ${MASON_ANDROID_ARCH}-${MASON_ANDROID_PLATFORM}-${MASON_ANDROID_NDK_VERSION}`
-source ${MASON_XC_ROOT}/toolchain.sh
-
-if [[ $1 == '--prepare' ]]; then
- mkdir -p ~/.android/debugging/{vendor,system}_lib
- adb pull /system/lib ~/.android/debugging/system_lib
- adb pull /vendor/lib ~/.android/debugging/vendor_lib
- adb pull /system/bin/app_process ~/.android/debugging
- adb pull /system/bin/app_process32 ~/.android/debugging
- adb pull /system/bin/linker ~/.android/debugging
-
- if [[ ${MASON_ANDROID_ARCH} == 'arm-v8' || ${MASON_ANDROID_ARCH} == 'x86-64' || ${MASON_ANDROID_ARCH} == 'mips-64' ]]; then
- adb pull /system/bin/app_process64 ~/.android/debugging
- adb pull /system/bin/linker64 ~/.android/debugging
- fi
-
- cp ${MASON_XC_ROOT}/prebuilt/gdbserver/gdbserver \
- platform/android/MapboxGLAndroidSDK/src/main/jniLibs/${ANDROID_ABI}/gdbserver.so
-fi
-
-adb install -r -t -d -g platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug.apk
-adb shell am start -n "com.mapbox.mapboxsdk.testapp/com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity" \
- -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
-
-adb forward tcp:5039 tcp:5039
-adb shell run-as com.mapbox.mapboxsdk.testapp '/data/data/com.mapbox.mapboxsdk.testapp/lib/gdbserver.so \
- --attach :5039 `pgrep com.mapbox.mapboxsdk.testapp`' &
-
-${MASON_XC_ROOT}/bin/gdb \
- -ex "target remote :5039" \
- -ex "set solib-search-path ~/.android/debugging:~/.android/debugging/system_lib:~/.android/debugging/vendor_lib:~/.android/debugging/vendor_lib/egl:./build/android-${MASON_ANDROID_ARCH}-${MASON_ANDROID_PLATFORM}/Debug/lib.target/"
diff --git a/platform/android/scripts/metrics.sh b/platform/android/scripts/metrics.sh
index 37d8c1de65..974ee5e8db 100755
--- a/platform/android/scripts/metrics.sh
+++ b/platform/android/scripts/metrics.sh
@@ -4,12 +4,12 @@ set -e
set -o pipefail
# Track individual architectures
-scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/armeabi/libmapbox-gl.so" "Platform=Android,Arch=arm-v5"
-scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/armeabi-v7a/libmapbox-gl.so" "Platform=Android,Arch=arm-v7"
-scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/arm64-v8a/libmapbox-gl.so" "Platform=Android,Arch=arm-v8"
-scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/x86/libmapbox-gl.so" "Platform=Android,Arch=x86"
-scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/x86_64/libmapbox-gl.so" "Platform=Android,Arch=x86_64"
-scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/src/main/jniLibs/mips/libmapbox-gl.so" "Platform=Android,Arch=mips"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/build/intermediates/bundles/default/jni/armeabi/libmapbox-gl.so" "Platform=Android,Arch=arm-v5"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/build/intermediates/bundles/default/jni/armeabi-v7a/libmapbox-gl.so" "Platform=Android,Arch=arm-v7"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/build/intermediates/bundles/default/jni/arm64-v8a/libmapbox-gl.so" "Platform=Android,Arch=arm-v8"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/build/intermediates/bundles/default/jni/x86/libmapbox-gl.so" "Platform=Android,Arch=x86"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/build/intermediates/bundles/default/jni/x86_64/libmapbox-gl.so" "Platform=Android,Arch=x86_64"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/build/intermediates/bundles/default/jni/mips/libmapbox-gl.so" "Platform=Android,Arch=mips"
# Track overall library size
-scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/build/outputs/aar/MapboxGLAndroidSDK-release.aar" "Platform=Android,Arch=Archive"
+scripts/log_binary_size.sh "platform/android/MapboxGLAndroidSDK/build/outputs/aar/MapboxGLAndroidSDK-release.aar" "Platform=Android,Arch=Archive"
diff --git a/platform/android/scripts/ndk.sh b/platform/android/scripts/ndk.sh
deleted file mode 100755
index 96a314a3c2..0000000000
--- a/platform/android/scripts/ndk.sh
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -o pipefail
-set -u
-
-# This script produces an env.sh file, which contains the paths to CMake, and the flags required to
-# create a build. It first tries to use the Android NDK, but falls back to installing it via Mason.
-
-function error { >&2 echo -e "\033[1m\033[31m$@\033[0m"; }
-function warning { >&2 echo -e "\033[1m\033[33m$@\033[0m"; }
-function status { >&2 echo -e "\033[1m\033[36m$@\033[0m"; }
-function info { >&2 echo -e "\033[1m\033[32m$@\033[0m"; }
-
-if [ "$#" -ne 3 ]; then
- error "Usage: $0 <short arch> <long arch> <api level>"
-fi
-
-NDK_ANDROID_VERSION=$1-$3
-ANDROID_NATIVE_API_LEVEL=$3
-ANDROID_ABI=$2
-
-function mason_ndk {
- local CMAKE=${CMAKE:-cmake}
- MASON_XC_ROOT="`${CMAKE} -P cmake/mason.cmake PREFIX android-ndk VERSION ${NDK_ANDROID_VERSION}-r13b`"
-
- local TOOLCHAIN="${MASON_XC_ROOT}/toolchain.cmake"
- if [ ! -f "${TOOLCHAIN}" ]; then
- error "Can't find CMake toolchain file at ${TOOLCHAIN}."
- exit 1
- fi
-
- info "Using Mason-provided Android NDK at ${MASON_XC_ROOT}"
- echo CMAKE=\"${CMAKE}\"
- echo CMAKE_GENERATOR=\"Ninja\"
- echo CMAKE_ARGS=\" \
- -DCMAKE_MAKE_PROGRAM=`pwd`/${NINJA} \
- -DMASON_XC_ROOT=${MASON_XC_ROOT} \
- -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN} \
- \"
-}
-
-function system_ndk {
- if [[ ${USE_MASON_NDK:-} ]]; then
- return 1
- fi
-
- if [ -f platform/android/local.properties ]; then
- local SDK_DIR=$(sed -n -e 's/^sdk.dir=\(.*\)$/\1/p' platform/android/local.properties)
- fi
-
- if [ ! -d "${SDK_DIR:-}" ]; then
- if [ ! -z "${ANDROID_HOME:-}" ]; then
- local SDK_DIR="${ANDROID_HOME}"
- else
- error "Can't find the Android SDK. Set \$ANDROID_HOME to the SDK path."
- exit 1
- fi
- fi
-
- local NDK_DIR="${ANDROID_NDK_HOME:-${SDK_DIR}/ndk-bundle}"
- if [ ! -d "${NDK_DIR}" ]; then
- warning "Can't find the Android NDK. If it is installed, set \$ANDROID_NDK_HOME to the NDK path."
- return 1
- fi
-
- # Try to install CMake if it's not installed yet.
- mkdir -p "${SDK_DIR}/cmake"
- local CMAKE_VERSION=/$(ls "${SDK_DIR}/cmake" | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n | tail -n 1)
- local CMAKE="${SDK_DIR}/cmake${CMAKE_VERSION:-}/bin/cmake"
- if [ ! -f "${CMAKE}" ]; then
- status "Trying to install CMake..."
- mkdir -p "${SDK_DIR}/licenses"
- echo "8933bad161af4178b1185d1a37fbf41ea5269c55" > "${SDK_DIR}/licenses/android-sdk-license"
- "${SDK_DIR}/tools/bin/sdkmanager" --list | grep cmake | tail -n 1 | cut -d \| -f 1 | xargs "${SDK_DIR}/tools/bin/sdkmanager" >&2
- CMAKE_VERSION=/$(ls "${SDK_DIR}/cmake" | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n | tail -n 1)
- CMAKE="${SDK_DIR}/cmake${CMAKE_VERSION:-}/bin/cmake"
- if [ ! -f "${CMAKE}" ]; then
- error "Can't find CMake at ${CMAKE}."
- return 1
- fi
- fi
-
- local NINJA="${SDK_DIR}/cmake${CMAKE_VERSION:-}/bin/ninja"
- if [ ! -f "${NINJA}" ]; then
- error "Can't find Ninja at ${NINJA}."
- return 1
- fi
-
- local TOOLCHAIN="${NDK_DIR}/build/cmake/android.toolchain.cmake"
- if [ ! -f "${TOOLCHAIN}" ]; then
- error "Can't find CMake toolchain file at ${TOOLCHAIN}."
- return 1
- fi
-
- info "Using system-provided Android NDK at ${NDK_DIR}"
- echo CMAKE=\"${CMAKE}\"
- echo CMAKE_GENERATOR=\"Android Gradle - Ninja\"
- echo CMAKE_ARGS=\" \
- -DANDROID_ABI=${ANDROID_ABI} \
- -DANDROID_NDK=${NDK_DIR} \
- -DCMAKE_MAKE_PROGRAM=${NINJA} \
- -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN} \
- -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \
- -DANDROID_TOOLCHAIN=clang \
- -DANDROID_STL=c++_static \
- -DANDROID_CPP_FEATURES=rtti\;exceptions \
- \"
-}
-
-system_ndk || mason_ndk
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 696849b11b..af8ae16bf6 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -181,6 +181,70 @@ void NativeMapView::notifyMapChange(mbgl::MapChange change) {
javaPeer->Call(*_env, onMapChanged, (int) change);
}
+void NativeMapView::onCameraWillChange(MapObserver::CameraChangeMode mode) {
+ if (mode == MapObserver::CameraChangeMode::Immediate) {
+ notifyMapChange(MapChange::MapChangeRegionWillChange);
+ } else {
+ notifyMapChange(MapChange::MapChangeRegionWillChangeAnimated);
+ }
+}
+
+void NativeMapView::onCameraIsChanging() {
+ notifyMapChange(MapChange::MapChangeRegionIsChanging);
+}
+
+void NativeMapView::onCameraDidChange(MapObserver::CameraChangeMode mode) {
+ if (mode == MapObserver::CameraChangeMode::Immediate) {
+ notifyMapChange(MapChange::MapChangeRegionDidChange);
+ } else {
+ notifyMapChange(MapChange::MapChangeRegionDidChangeAnimated);
+ }
+}
+
+void NativeMapView::onWillStartLoadingMap() {
+ notifyMapChange(MapChange::MapChangeWillStartLoadingMap);
+}
+
+void NativeMapView::onDidFinishLoadingMap() {
+ notifyMapChange(MapChange::MapChangeDidFinishLoadingMap);
+}
+
+void NativeMapView::onDidFailLoadingMap(std::exception_ptr) {
+ notifyMapChange(MapChange::MapChangeDidFailLoadingMap);
+}
+
+void NativeMapView::onWillStartRenderingFrame() {
+ notifyMapChange(MapChange::MapChangeWillStartRenderingFrame);
+}
+
+void NativeMapView::onDidFinishRenderingFrame(MapObserver::RenderMode mode) {
+ if (mode == MapObserver::RenderMode::Partial) {
+ notifyMapChange(MapChange::MapChangeDidFinishRenderingFrame);
+ } else {
+ notifyMapChange(MapChange::MapChangeDidFinishRenderingFrameFullyRendered);
+ }
+}
+
+void NativeMapView::onWillStartRenderingMap() {
+ notifyMapChange(MapChange::MapChangeWillStartRenderingMap);
+}
+
+void NativeMapView::onDidFinishRenderingMap(MapObserver::RenderMode mode) {
+ if (mode == MapObserver::RenderMode::Partial) {
+ notifyMapChange(MapChange::MapChangeDidFinishRenderingMap);
+ } else {
+ notifyMapChange(MapChange::MapChangeDidFinishRenderingMapFullyRendered);
+ }
+}
+
+void NativeMapView::onDidFinishLoadingStyle() {
+ notifyMapChange(MapChange::MapChangeDidFinishLoadingStyle);
+}
+
+void NativeMapView::onSourceChanged(mbgl::style::Source&) {
+ notifyMapChange(MapChange::MapChangeSourceDidChange);
+}
+
// JNI Methods //
void NativeMapView::initializeDisplay(jni::JNIEnv&) {
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index 4afea036bf..fbfe69040e 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/map/backend.hpp>
+#include <mbgl/map/change.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/map/view.hpp>
@@ -22,6 +23,7 @@
#include "style/layers/layers.hpp"
#include "style/sources/sources.hpp"
+#include <exception>
#include <string>
#include <jni.h>
#include <android/native_window.h>
@@ -51,7 +53,23 @@ public:
// mbgl::Backend //
void invalidate() override;
- void notifyMapChange(mbgl::MapChange) override;
+
+ // Deprecated //
+ void notifyMapChange(mbgl::MapChange);
+
+ // mbgl::Backend (mbgl::MapObserver) //
+ void onCameraWillChange(MapObserver::CameraChangeMode) override;
+ void onCameraIsChanging() override;
+ void onCameraDidChange(MapObserver::CameraChangeMode) override;
+ void onWillStartLoadingMap() override;
+ void onDidFinishLoadingMap() override;
+ void onDidFailLoadingMap(std::exception_ptr) override;
+ void onWillStartRenderingFrame() override;
+ void onDidFinishRenderingFrame(MapObserver::RenderMode) override;
+ void onWillStartRenderingMap() override;
+ void onDidFinishRenderingMap(MapObserver::RenderMode) override;
+ void onDidFinishLoadingStyle() override;
+ void onSourceChanged(mbgl::style::Source&) override;
// JNI //
diff --git a/platform/android/tests/docs/UI_TESTS.md b/platform/android/tests/docs/UI_TESTS.md
index 9341cf1e1e..6d8541a406 100644
--- a/platform/android/tests/docs/UI_TESTS.md
+++ b/platform/android/tests/docs/UI_TESTS.md
@@ -25,7 +25,7 @@ On a terminal, within `mapbox-gl-native/android/java`,
run the tests (`cC` stands for `connectedCheck`):
```
-$ ./gradlew cC -p MapboxGLAndroidSDKTestApp
+$ ./gradlew -Pmapbox.abis=all cC -p MapboxGLAndroidSDKTestApp
```
Then:
@@ -59,7 +59,7 @@ You can generate JaCoCo reports from espresso tests by
- running the gradle task `createMockDebugCoverageReport` when executing tests.
## Running Espresso test automatically on AWS Device Farm
-To run tests on AWS device farm you need to execute `./gradlew devicefarmUpload`.
+To run tests on AWS device farm you need to execute `./gradlew -Pmapbox.abis=none devicefarmUpload`.
You can configure the different steps in the testapp `build.gradle`.
AWS credentials are found in bitrise.
diff --git a/platform/android/tests/docs/UNIT_TESTS.md b/platform/android/tests/docs/UNIT_TESTS.md
index e32a36ef78..fefb435684 100644
--- a/platform/android/tests/docs/UNIT_TESTS.md
+++ b/platform/android/tests/docs/UNIT_TESTS.md
@@ -69,7 +69,7 @@ If you like, you can also run with test coverage enabled. This will show you the
You can also run the tests from the command line with:
```
-$ ./gradlew test --continue -p MapboxGLAndroidSDKTestApp
+$ ./gradlew -Pmapbox.abis=none test -p MapboxGLAndroidSDKTestApp
```
## Running Unit tests on CI
@@ -80,7 +80,7 @@ fails, this will fail and stop the build.
You can find this gradle command in our [buildscript](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/bitrise.yml#L48):
```
-$ ./gradlew testReleaseUnitTest --continue
+$ ./gradlew -Pmapbox.abis=none testReleaseUnitTest
```
diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h
index 5216e921f1..c06fd8b0e7 100644
--- a/platform/darwin/src/MGLTypes.h
+++ b/platform/darwin/src/MGLTypes.h
@@ -42,6 +42,10 @@ typedef NS_ENUM(NSInteger, MGLErrorCode) {
MGLErrorCodeBadServerResponse = 2,
/** An attempt to establish a connection failed. */
MGLErrorCodeConnectionFailed = 3,
+ /** A style parse error occurred while attempting to load the map. */
+ MGLErrorCodeParseStyleFailed = 4,
+ /** An attempt to load the style failed. */
+ MGLErrorCodeLoadStyleFailed = 5,
};
/** Options for enabling debugging features in an `MGLMapView` instance. */
diff --git a/platform/default/async_task.cpp b/platform/default/async_task.cpp
index 05cf759863..5fa9db8d33 100644
--- a/platform/default/async_task.cpp
+++ b/platform/default/async_task.cpp
@@ -7,12 +7,6 @@
#include <uv.h>
-#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
-#define UV_ASYNC_PARAMS(handle) uv_async_t *handle, int
-#else
-#define UV_ASYNC_PARAMS(handle) uv_async_t *handle
-#endif
-
namespace mbgl {
namespace util {
@@ -45,7 +39,7 @@ public:
}
private:
- static void asyncCallback(UV_ASYNC_PARAMS(handle)) {
+ static void asyncCallback(uv_async_t* handle) {
reinterpret_cast<Impl*>(handle->data)->task();
}
diff --git a/platform/default/mbgl/gl/headless_backend.cpp b/platform/default/mbgl/gl/headless_backend.cpp
index c105fd6b84..6ae19356fb 100644
--- a/platform/default/mbgl/gl/headless_backend.cpp
+++ b/platform/default/mbgl/gl/headless_backend.cpp
@@ -50,10 +50,4 @@ void HeadlessBackend::invalidate() {
assert(false);
}
-void HeadlessBackend::notifyMapChange(MapChange change) {
- if (mapChangeCallback) {
- mapChangeCallback(change);
- }
-}
-
} // namespace mbgl
diff --git a/platform/default/mbgl/gl/headless_backend.hpp b/platform/default/mbgl/gl/headless_backend.hpp
index e632d0feb6..63e3cec9ee 100644
--- a/platform/default/mbgl/gl/headless_backend.hpp
+++ b/platform/default/mbgl/gl/headless_backend.hpp
@@ -18,9 +18,6 @@ public:
~HeadlessBackend() override;
void invalidate() override;
- void notifyMapChange(MapChange) override;
-
- void setMapChangeCallback(std::function<void(MapChange)>&& cb) { mapChangeCallback = std::move(cb); }
struct Impl {
virtual ~Impl() {}
@@ -45,8 +42,6 @@ private:
bool extensionsLoaded = false;
bool active = false;
-
- std::function<void(MapChange)> mapChangeCallback;
};
} // namespace mbgl
diff --git a/platform/default/run_loop.cpp b/platform/default/run_loop.cpp
index 1ebbade7ab..98d1badcb5 100644
--- a/platform/default/run_loop.cpp
+++ b/platform/default/run_loop.cpp
@@ -13,11 +13,7 @@ namespace {
using namespace mbgl::util;
static ThreadLocal<RunLoop>& current = *new ThreadLocal<RunLoop>;
-#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
-void dummyCallback(uv_async_t*, int) {}
-#else
void dummyCallback(uv_async_t*) {}
-#endif
} // namespace
@@ -84,13 +80,8 @@ public:
RunLoop::RunLoop(Type type) : impl(std::make_unique<Impl>()) {
switch (type) {
case Type::New:
-#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
- impl->loop = uv_loop_new();
- if (impl->loop == nullptr) {
-#else
impl->loop = new uv_loop_t;
if (uv_loop_init(impl->loop) != 0) {
-#endif
throw std::runtime_error("Failed to initialize loop.");
}
break;
@@ -129,14 +120,10 @@ RunLoop::~RunLoop() {
impl->async.reset();
runOnce();
-#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
- uv_loop_delete(impl->loop);
-#else
if (uv_loop_close(impl->loop) == UV_EBUSY) {
- throw std::runtime_error("Failed to close loop.");
+ assert(false && "Failed to close loop.");
}
delete impl->loop;
-#endif
}
LOOP_HANDLE RunLoop::getLoopHandle() {
diff --git a/platform/default/timer.cpp b/platform/default/timer.cpp
index 473f059133..cd0e6da6aa 100644
--- a/platform/default/timer.cpp
+++ b/platform/default/timer.cpp
@@ -4,12 +4,6 @@
#include <uv.h>
-#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
-#define UV_TIMER_PARAMS(timer) uv_timer_t *timer, int
-#else
-#define UV_TIMER_PARAMS(timer) uv_timer_t *timer
-#endif
-
namespace mbgl {
namespace util {
@@ -46,7 +40,7 @@ public:
}
private:
- static void timerCallback(UV_TIMER_PARAMS(handle)) {
+ static void timerCallback(uv_timer_t* handle) {
reinterpret_cast<Impl*>(handle->data)->cb();
}
diff --git a/platform/glfw/glfw_view.cpp b/platform/glfw/glfw_view.cpp
index 4070a0fe9b..39dca8080b 100644
--- a/platform/glfw/glfw_view.cpp
+++ b/platform/glfw/glfw_view.cpp
@@ -538,16 +538,6 @@ void GLFWView::setWindowTitle(const std::string& title) {
glfwSetWindowTitle(window, (std::string { "Mapbox GL: " } + title).c_str());
}
-void GLFWView::setMapChangeCallback(std::function<void(mbgl::MapChange)> callback) {
- this->mapChangeCallback = callback;
-}
-
-void GLFWView::notifyMapChange(mbgl::MapChange change) {
- if (mapChangeCallback) {
- mapChangeCallback(change);
- }
-}
-
namespace mbgl {
namespace platform {
diff --git a/platform/glfw/glfw_view.hpp b/platform/glfw/glfw_view.hpp
index a426e58a94..bfabf6cc68 100644
--- a/platform/glfw/glfw_view.hpp
+++ b/platform/glfw/glfw_view.hpp
@@ -60,9 +60,6 @@ private:
// Internal
void report(float duration);
- void setMapChangeCallback(std::function<void(mbgl::MapChange)> callback);
- void notifyMapChange(mbgl::MapChange change) override;
-
mbgl::Color makeRandomColor() const;
mbgl::Point<double> makeRandomPoint() const;
static std::shared_ptr<const mbgl::SpriteImage>
@@ -81,8 +78,6 @@ private:
mbgl::AnnotationIDs annotationIDs;
std::vector<std::string> spriteIDs;
- std::function<void(mbgl::MapChange)> mapChangeCallback;
-
private:
mbgl::Map* map = nullptr;
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index 40795a2aef..e75f90dd5d 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -2,6 +2,10 @@
Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started.
+## master
+
+* The error passed into `-[MGLMapViewDelegate mapViewDidFailLoadingMap:withError:]` now includes a more specific description and failure reason. ([#8418](https://github.com/mapbox/mapbox-gl-native/pull/8418))
+
## 3.5.0
### Packaging
@@ -68,6 +72,8 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Fixed an issue that sometimes caused crashes when the SDK interacted with the file system in the background. ([#8125](https://github.com/mapbox/mapbox-gl-native/pull/8125))
* Added a `MGLDistanceFormatter` class for formatting geographic distances. ([#7888](https://github.com/mapbox/mapbox-gl-native/pull/7888))
* Fixed an issue that was causing the system location indicator to stay on in background after telemetry was disabled. ([#7833](https://github.com/mapbox/mapbox-gl-native/pull/7833))
+* Added support for predicates in rendered feature querying [8256](https://github.com/mapbox/mapbox-gl-native/pull/8246)
+* Added a nightly build of the dynamic framework. ([#8337](https://github.com/mapbox/mapbox-gl-native/pull/8337))
## 3.4.2 - February 21, 2017
@@ -117,7 +123,7 @@ This is the final scheduled version of the Mapbox iOS SDK that supports iOS 7. (
* A source’s tiles are no longer rendered when the map is outside the source’s supported zoom levels. ([#6345](https://github.com/mapbox/mapbox-gl-native/pull/6345))
* Improved style parsing performance. ([#6170](https://github.com/mapbox/mapbox-gl-native/pull/6170))
* Improved feature querying performance. ([#6514](https://github.com/mapbox/mapbox-gl-native/pull/6514))
-* Fixed an issue where shapes that cannot currently be visually represented as annotations were still shown on the map as point annotations. ([#6764](https://github.com/mapbox/mapbox-gl-native/issues/6764))
+* Fixed an issue where shapes that cannot currently be visually represented as annotations were still shown on the map as point annotations. ([#6764](https://github.com/mapbox/mapbox-gl-native/issues/6764))
### User location
diff --git a/platform/ios/INSTALL.md b/platform/ios/INSTALL.md
index c93ab6b698..e0df7c48f6 100644
--- a/platform/ios/INSTALL.md
+++ b/platform/ios/INSTALL.md
@@ -50,6 +50,10 @@ bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Mapbox.framework/strip-fra
(The last step, courtesy of [Realm](https://github.com/realm/realm-cocoa/), is required for working around an [iOS App Store bug](http://www.openradar.me/radar?id=6409498411401216) when archiving universal binaries.)
+##### Nightly builds
+
+A nightly build of the dynamic framework, based on the master branch, is available for download [here](https://mapbox.s3.amazonaws.com/mapbox-gl-native/ios/builds/mapbox-ios-sdk-nightly-dynamic.zip).
+
#### Static framework
You can alternatively install the SDK as a static framework:
@@ -82,7 +86,15 @@ You can alternatively install the SDK as a static framework:
To test pre-releases and/or betas, you can reference the pre-release like so in your Podfile:
```rb
-pod 'Mapbox-iOS-SDK', podspec: 'https://raw.githubusercontent.com/mapbox/mapbox-gl-native/<insert branch or tag>/ios/Mapbox-iOS-SDK.podspec'
+pod 'Mapbox-iOS-SDK', podspec: 'https://raw.githubusercontent.com/mapbox/mapbox-gl-native/<insert branch or tag>/platform/ios/Mapbox-iOS-SDK.podspec'
+```
+
+##### Testing nightly releases with CocoaPods
+
+To test a nightly dynamic framework build, update your app’s `Podfile` to point to:
+
+```rb
+pod 'Mapbox-iOS-SDK-nightly-dynamic', podspec: 'https://raw.githubusercontent.com/mapbox/mapbox-gl-native/master/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec'
```
##### Using your own build with CocoaPods
diff --git a/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec b/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec
new file mode 100644
index 0000000000..62d76d4897
--- /dev/null
+++ b/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec
@@ -0,0 +1,30 @@
+Pod::Spec.new do |m|
+
+ version = '3.5.0-beta.2'
+
+ m.name = 'Mapbox-iOS-SDK-nightly-dynamic'
+ m.version = "#{version}-nightly"
+
+ m.summary = 'Open source vector map solution for iOS with full styling capabilities.'
+ m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.'
+ m.homepage = 'https://www.mapbox.com/ios-sdk/'
+ m.license = { :type => 'BSD', :file => 'LICENSE.md' }
+ m.author = { 'Mapbox' => 'mobile@mapbox.com' }
+ m.screenshot = "https://www.mapbox.com/ios-sdk/api/#{version}/img/screenshot.png"
+ m.social_media_url = 'https://twitter.com/mapbox'
+ m.documentation_url = 'https://www.mapbox.com/ios-sdk/api/'
+
+ m.source = {
+ :http => "https://mapbox.s3.amazonaws.com/mapbox-gl-native/ios/builds/mapbox-ios-sdk-nightly-dynamic.zip",
+ :flatten => true
+ }
+
+ m.platform = :ios
+ m.ios.deployment_target = '8.0'
+
+ m.requires_arc = true
+
+ m.vendored_frameworks = 'dynamic/Mapbox.framework'
+ m.module_name = 'Mapbox'
+
+end
diff --git a/platform/ios/bitrise.yml b/platform/ios/bitrise.yml
index 93d1d4afd8..53287ec06d 100644
--- a/platform/ios/bitrise.yml
+++ b/platform/ios/bitrise.yml
@@ -11,22 +11,7 @@ workflows:
primary:
steps:
- script:
- title: Check for skipping CI
- inputs:
- - content: |-
- #!/bin/bash
-
- if [[ -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[ci skip\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[ci skip\]/p')" ]]; then
- envman add --key SKIPCI --value true
- else
- envman add --key SKIPCI --value false
- fi
- - script:
title: Install Dependencies
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
@@ -37,7 +22,6 @@ workflows:
- is_debug: 'yes'
- script:
title: Generate Workspace
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
@@ -47,18 +31,15 @@ workflows:
- is_debug: 'yes'
- xcode-test:
title: Run SDK Unit Tests
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- project_path: platform/ios/ios.xcworkspace
- scheme: CI
- deploy-to-bitrise-io:
title: Deploy to Bitrise.io
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- notify_user_groups: none
- slack:
title: Post to Slack
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- webhook_url: "$SLACK_HOOK_URL"
- channel: "#gl-bots"
@@ -102,4 +83,20 @@ workflows:
export FORMAT=dynamic
make ipackage-strip
CLOUDWATCH=true platform/ios/scripts/metrics.sh
+ platform/ios/scripts/deploy-nightly.sh
- is_debug: 'yes'
+ - slack:
+ title: Post to Slack
+ inputs:
+ - webhook_url: "$SLACK_HOOK_URL"
+ - channel: "#gl-bots"
+ - from_username: 'Bitrise iOS Nightly \U0001F31D'
+ - from_username_on_error: 'Bitrise iOS Nightly \U0001F31D'
+ - message: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}>
+ for <https://github.com/mapbox/mapbox-gl-native/compare/${BITRISE_GIT_BRANCH}@%7B1day%7D...${BITRISE_GIT_BRANCH}|mapbox/mapbox-gl-native@${BITRISE_GIT_BRANCH}>
+ completed successfully.'
+ - message_on_error: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}>
+ for <https://github.com/mapbox/mapbox-gl-native/compare/${BITRISE_GIT_BRANCH}@%7B1day%7D...${BITRISE_GIT_BRANCH}|mapbox/mapbox-gl-native@${BITRISE_GIT_BRANCH}>
+ failed.'
+ - icon_url: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-icon-128.png
+ - icon_url_on_error: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-error-icon-128.png
diff --git a/platform/ios/resources/Base.lproj/Localizable.strings b/platform/ios/resources/Base.lproj/Localizable.strings
index ab071a4505..fc2e8c8fec 100644
--- a/platform/ios/resources/Base.lproj/Localizable.strings
+++ b/platform/ios/resources/Base.lproj/Localizable.strings
@@ -31,6 +31,12 @@
/* Accessibility label */
"INFO_A11Y_LABEL" = "About this map";
+/* User-friendly error description */
+"LOAD_MAP_FAILED_DESC" = "The map failed to load because an unknown error occurred.";
+
+/* User-friendly error description */
+"LOAD_STYLE_FAILED_DESC" = "The map failed to load because the style can't be loaded.";
+
/* Accessibility label */
"LOGO_A11Y_LABEL" = "Mapbox";
@@ -40,9 +46,16 @@
/* Map accessibility value */
"MAP_A11Y_VALUE" = "Zoom %1$dx\n%2$ld annotation(s) visible";
+/* User-friendly error description */
+"PARSE_STYLE_FAILED_DESC" = "The map failed to load because the style is corrupted.";
+
/* Action sheet title */
"SDK_NAME" = "Mapbox iOS SDK";
+
+/* User-friendly error description */
+"STYLE_NOT_FOUND_DESC" = "The map failed to load because the style can’t be found or is incompatible.";
+
/* Developer-only SDK update notification; {latest version, in format x.x.x} */
"SDK_UPDATE_AVAILABLE" = "Mapbox iOS SDK version %@ is now available:";
diff --git a/platform/ios/scripts/deploy-nightly.sh b/platform/ios/scripts/deploy-nightly.sh
new file mode 100755
index 0000000000..9fec4df58a
--- /dev/null
+++ b/platform/ios/scripts/deploy-nightly.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -e
+set -o pipefail
+set -u
+
+function step { >&2 echo -e "\033[1m\033[36m* $@\033[0m"; }
+function finish { >&2 echo -en "\033[0m"; }
+trap finish EXIT
+
+export TRAVIS_REPO_SLUG=mapbox-gl-native
+
+DATE=`date +%Y-%m-%d`
+NIGHTLY_TYPE="nightly-dynamic"
+
+step "Uploading ${NIGHTLY_TYPE} build for ${DATE} to s3…"
+
+./platform/ios/scripts/publish.sh "${NIGHTLY_TYPE}" "${DATE}"
+
+step "Finished deploying ${NIGHTLY_TYPE} build in $(($SECONDS / 60)) minutes and $(($SECONDS % 60)) seconds"
diff --git a/platform/ios/scripts/publish.sh b/platform/ios/scripts/publish.sh
index e080ee825c..2934e10217 100755
--- a/platform/ios/scripts/publish.sh
+++ b/platform/ios/scripts/publish.sh
@@ -24,7 +24,7 @@ fi
# zip
#
cd build/ios/pkg
-ZIP=mapbox-ios-sdk-${PUBLISH_VERSION}${PUBLISH_STYLE}.zip
+ZIP="mapbox-ios-sdk-${PUBLISH_VERSION}${PUBLISH_STYLE}.zip"
step "Compressing ${ZIP}…"
rm -f ../${ZIP}
zip -r ../${ZIP} *
@@ -35,4 +35,15 @@ zip -r ../${ZIP} *
step "Uploading ${ZIP} to s3…"
REPO_NAME=$(basename $TRAVIS_REPO_SLUG)
aws s3 cp ../${ZIP} s3://mapbox/$REPO_NAME/ios/builds/ --acl public-read
-echo http://mapbox.s3.amazonaws.com/$REPO_NAME/ios/builds/${ZIP}
+echo "URL: https://mapbox.s3.amazonaws.com/$REPO_NAME/ios/builds/${ZIP}"
+
+#
+# update nightly
+#
+if [[ ${PUBLISH_VERSION} =~ "nightly" ]]; then
+ step "Updating ${PUBLISH_VERSION} to ${PUBLISH_STYLE}…"
+ GENERIC_NIGHTLY_FILENAME="mapbox-ios-sdk-${PUBLISH_VERSION}.zip"
+ aws s3 cp \
+ s3://mapbox/$REPO_NAME/ios/builds/${ZIP} \
+ s3://mapbox/$REPO_NAME/ios/builds/${GENERIC_NIGHTLY_FILENAME} --acl public-read
+fi
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 1baebf60bc..1ccd5ce355 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -22,6 +22,7 @@
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/map/backend.hpp>
#include <mbgl/math/wrap.hpp>
+#include <mbgl/util/exception.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/image.hpp>
@@ -30,6 +31,7 @@
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/shared_thread_pool.hpp>
+#include <mbgl/util/string.hpp>
#import "Mapbox.h"
#import "MGLFeature_Private.h"
@@ -1173,7 +1175,8 @@ public:
}
- (void)notifyGestureDidBegin {
- [self notifyMapChange:mbgl::MapChangeRegionWillChange];
+ BOOL animated = NO;
+ [self cameraWillChangeAnimated:animated];
_mbglMap->setGestureInProgress(true);
_changeDelimiterSuppressionDepth++;
}
@@ -1187,7 +1190,8 @@ public:
}
if ( ! drift)
{
- [self notifyMapChange:mbgl::MapChangeRegionDidChange];
+ BOOL animated = NO;
+ [self cameraDidChangeAnimated:animated];
}
}
@@ -1224,7 +1228,7 @@ public:
[pan setTranslation:CGPointZero inView:pan.view];
}
- [self notifyMapChange:mbgl::MapChangeRegionIsChanging];
+ [self cameraIsChanging];
}
else if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled)
{
@@ -1307,7 +1311,7 @@ public:
_mbglMap->setLatLng(MGLLatLngFromLocationCoordinate2D(centerCoordinate),
mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
}
- [self notifyMapChange:mbgl::MapChangeRegionIsChanging];
+ [self cameraIsChanging];
}
else if (pinch.state == UIGestureRecognizerStateEnded || pinch.state == UIGestureRecognizerStateCancelled)
{
@@ -1406,9 +1410,8 @@ public:
{
_mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
}
-
- [self notifyMapChange:mbgl::MapChangeRegionIsChanging];
-
+
+ [self cameraIsChanging];
}
else if (rotate.state == UIGestureRecognizerStateEnded || rotate.state == UIGestureRecognizerStateCancelled)
{
@@ -1661,7 +1664,7 @@ public:
_mbglMap->scaleBy(scale, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
}
- [self notifyMapChange:mbgl::MapChangeRegionIsChanging];
+ [self cameraIsChanging];
}
else if (quickZoom.state == UIGestureRecognizerStateEnded || quickZoom.state == UIGestureRecognizerStateCancelled)
{
@@ -1700,7 +1703,7 @@ public:
_mbglMap->setPitch(pitchNew, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
}
- [self notifyMapChange:mbgl::MapChangeRegionIsChanging];
+ [self cameraIsChanging];
}
else if (twoFingerDrag.state == UIGestureRecognizerStateEnded || twoFingerDrag.state == UIGestureRecognizerStateCancelled)
{
@@ -4737,150 +4740,160 @@ public:
}
}
-- (void)notifyMapChange:(mbgl::MapChange)change
-{
- // Ignore map updates when the Map object isn't set.
+- (void)cameraWillChangeAnimated:(BOOL)animated {
if (!_mbglMap) {
return;
}
- switch (change)
+ if ( ! _userLocationAnnotationIsSelected
+ || self.userTrackingMode == MGLUserTrackingModeNone
+ || self.userTrackingState != MGLUserTrackingStateChanged)
{
- case mbgl::MapChangeRegionWillChange:
- case mbgl::MapChangeRegionWillChangeAnimated:
+ UIView<MGLCalloutView> *calloutView = self.calloutViewForSelectedAnnotation;
+ BOOL dismissesAutomatically = (calloutView
+ && [calloutView respondsToSelector:@selector(dismissesAutomatically)]
+ && calloutView.dismissesAutomatically);
+ // dismissesAutomatically is an optional property and we want to dismiss
+ // the callout view if it's unimplemented.
+ if (dismissesAutomatically || (calloutView && ![calloutView respondsToSelector:@selector(dismissesAutomatically)]))
{
- if ( ! _userLocationAnnotationIsSelected
- || self.userTrackingMode == MGLUserTrackingModeNone
- || self.userTrackingState != MGLUserTrackingStateChanged)
- {
- UIView<MGLCalloutView> *calloutView = self.calloutViewForSelectedAnnotation;
- BOOL dismissesAutomatically = (calloutView
- && [calloutView respondsToSelector:@selector(dismissesAutomatically)]
- && calloutView.dismissesAutomatically);
- // dismissesAutomatically is an optional property and we want to dismiss
- // the callout view if it's unimplemented.
- if (dismissesAutomatically || (calloutView && ![calloutView respondsToSelector:@selector(dismissesAutomatically)]))
- {
- [self deselectAnnotation:self.selectedAnnotation animated:NO];
- }
- }
-
- if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)])
- {
- BOOL animated = change == mbgl::MapChangeRegionWillChangeAnimated;
- [self.delegate mapView:self regionWillChangeAnimated:animated];
- }
- break;
+ [self deselectAnnotation:self.selectedAnnotation animated:NO];
}
- case mbgl::MapChangeRegionIsChanging:
- {
- [self updateCompass];
+ }
- if ([self.delegate respondsToSelector:@selector(mapViewRegionIsChanging:)])
- {
- [self.delegate mapViewRegionIsChanging:self];
- }
- break;
- }
- case mbgl::MapChangeRegionDidChange:
- case mbgl::MapChangeRegionDidChangeAnimated:
- {
- [self updateCompass];
+ if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)])
+ {
+ [self.delegate mapView:self regionWillChangeAnimated:animated];
+ }
+}
- if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)])
- {
- if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
- {
- UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
- }
- BOOL animated = change == mbgl::MapChangeRegionDidChangeAnimated;
- [self.delegate mapView:self regionDidChangeAnimated:animated];
- }
- break;
- }
- case mbgl::MapChangeWillStartLoadingMap:
- {
- if ([self.delegate respondsToSelector:@selector(mapViewWillStartLoadingMap:)])
- {
- [self.delegate mapViewWillStartLoadingMap:self];
- }
- break;
- }
- case mbgl::MapChangeDidFinishLoadingMap:
- {
- [self.style willChangeValueForKey:@"sources"];
- [self.style didChangeValueForKey:@"sources"];
- [self.style willChangeValueForKey:@"layers"];
- [self.style didChangeValueForKey:@"layers"];
- if ([self.delegate respondsToSelector:@selector(mapViewDidFinishLoadingMap:)])
- {
- [self.delegate mapViewDidFinishLoadingMap:self];
- }
- break;
- }
- case mbgl::MapChangeDidFailLoadingMap:
- {
- if ([self.delegate respondsToSelector:@selector(mapViewDidFailLoadingMap:withError:)])
- {
- NSError *error = [NSError errorWithDomain:MGLErrorDomain code:0 userInfo:nil];
- [self.delegate mapViewDidFailLoadingMap:self withError:error];
- }
- break;
- }
- case mbgl::MapChangeWillStartRenderingMap:
- {
- if ([self.delegate respondsToSelector:@selector(mapViewWillStartRenderingMap:)])
- {
- [self.delegate mapViewWillStartRenderingMap:self];
- }
- break;
- }
- case mbgl::MapChangeDidFinishRenderingMap:
- case mbgl::MapChangeDidFinishRenderingMapFullyRendered:
- {
- if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingMap:fullyRendered:)])
- {
- [self.delegate mapViewDidFinishRenderingMap:self fullyRendered:(change == mbgl::MapChangeDidFinishRenderingMapFullyRendered)];
- }
- break;
- }
- case mbgl::MapChangeWillStartRenderingFrame:
- {
- if ([self.delegate respondsToSelector:@selector(mapViewWillStartRenderingFrame:)])
- {
- [self.delegate mapViewWillStartRenderingFrame:self];
- }
- break;
- }
- case mbgl::MapChangeDidFinishRenderingFrame:
- case mbgl::MapChangeDidFinishRenderingFrameFullyRendered:
- {
- if (_isChangingAnnotationLayers)
- {
- _isChangingAnnotationLayers = NO;
- [self.style didChangeValueForKey:@"layers"];
- }
- [self updateAnnotationViews];
- [self updateCalloutView];
- if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)])
- {
- [self.delegate mapViewDidFinishRenderingFrame:self fullyRendered:(change == mbgl::MapChangeDidFinishRenderingFrameFullyRendered)];
- }
- break;
- }
- case mbgl::MapChangeDidFinishLoadingStyle:
- {
- self.style = [[MGLStyle alloc] initWithMapView:self];
- if ([self.delegate respondsToSelector:@selector(mapView:didFinishLoadingStyle:)])
- {
- [self.delegate mapView:self didFinishLoadingStyle:self.style];
- }
- break;
- }
- case mbgl::MapChangeSourceDidChange:
+- (void)cameraIsChanging {
+ if (!_mbglMap) {
+ return;
+ }
+
+ [self updateCompass];
+
+ if ([self.delegate respondsToSelector:@selector(mapViewRegionIsChanging:)])
+ {
+ [self.delegate mapViewRegionIsChanging:self];
+ }
+}
+
+- (void)cameraDidChangeAnimated:(BOOL)animated {
+ if (!_mbglMap) {
+ return;
+ }
+
+ [self updateCompass];
+
+ if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)])
+ {
+ if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
{
- break;
+ UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
}
+ [self.delegate mapView:self regionDidChangeAnimated:animated];
+ }
+}
+
+- (void)mapViewWillStartLoadingMap {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if ([self.delegate respondsToSelector:@selector(mapViewWillStartLoadingMap:)])
+ {
+ [self.delegate mapViewWillStartLoadingMap:self];
+ }
+}
+
+- (void)mapViewDidFinishLoadingMap {
+ if (!_mbglMap) {
+ return;
+ }
+
+ [self.style willChangeValueForKey:@"sources"];
+ [self.style didChangeValueForKey:@"sources"];
+ [self.style willChangeValueForKey:@"layers"];
+ [self.style didChangeValueForKey:@"layers"];
+ if ([self.delegate respondsToSelector:@selector(mapViewDidFinishLoadingMap:)])
+ {
+ [self.delegate mapViewDidFinishLoadingMap:self];
+ }
+}
+
+- (void)mapViewDidFailLoadingMapWithError:(NSError *)error {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if ([self.delegate respondsToSelector:@selector(mapViewDidFailLoadingMap:withError:)])
+ {
+ [self.delegate mapViewDidFailLoadingMap:self withError:error];
+ }
+}
+
+- (void)mapViewWillStartRenderingFrame {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if ([self.delegate respondsToSelector:@selector(mapViewWillStartRenderingFrame:)])
+ {
+ [self.delegate mapViewWillStartRenderingFrame:self];
+ }
+}
+
+- (void)mapViewDidFinishRenderingFrameFullyRendered:(BOOL)fullyRendered {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if (_isChangingAnnotationLayers)
+ {
+ _isChangingAnnotationLayers = NO;
+ [self.style didChangeValueForKey:@"layers"];
+ }
+ [self updateAnnotationViews];
+ [self updateCalloutView];
+ if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)])
+ {
+ [self.delegate mapViewDidFinishRenderingFrame:self fullyRendered:fullyRendered];
+ }
+}
+
+- (void)mapViewWillStartRenderingMap {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if ([self.delegate respondsToSelector:@selector(mapViewWillStartRenderingMap:)])
+ {
+ [self.delegate mapViewWillStartRenderingMap:self];
+ }
+}
+
+- (void)mapViewDidFinishRenderingMapFullyRendered:(BOOL)fullyRendered {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingMap:fullyRendered:)])
+ {
+ [self.delegate mapViewDidFinishRenderingMap:self fullyRendered:fullyRendered];
+ }
+}
+
+- (void)didFinishLoadingStyle {
+ if (!_mbglMap) {
+ return;
+ }
+
+ self.style = [[MGLStyle alloc] initWithMapView:self];
+ if ([self.delegate respondsToSelector:@selector(mapView:didFinishLoadingStyle:)])
+ {
+ [self.delegate mapView:self didFinishLoadingStyle:self.style];
}
}
@@ -5349,9 +5362,74 @@ public:
}
}
- void notifyMapChange(mbgl::MapChange change) override
- {
- [nativeView notifyMapChange:change];
+ void onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) override {
+ bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
+ [nativeView cameraWillChangeAnimated:animated];
+ }
+
+ void onCameraIsChanging() override {
+ [nativeView cameraIsChanging];
+ }
+
+ void onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode) override {
+ bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
+ [nativeView cameraDidChangeAnimated:animated];
+ }
+
+ void onWillStartLoadingMap() override {
+ [nativeView mapViewWillStartLoadingMap];
+ }
+
+ void onDidFinishLoadingMap() override {
+ [nativeView mapViewDidFinishLoadingMap];
+ }
+
+ void onDidFailLoadingMap(std::exception_ptr exception) override {
+ NSString *description;
+ MGLErrorCode code;
+ try {
+ std::rethrow_exception(exception);
+ } catch (const mbgl::util::StyleParseException&) {
+ code = MGLErrorCodeParseStyleFailed;
+ description = NSLocalizedStringWithDefaultValue(@"PARSE_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style is corrupted.", @"User-friendly error description");
+ } catch (const mbgl::util::StyleLoadException&) {
+ code = MGLErrorCodeLoadStyleFailed;
+ description = NSLocalizedStringWithDefaultValue(@"LOAD_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style can't be loaded.", @"User-friendly error description");
+ } catch (const mbgl::util::NotFoundException&) {
+ code = MGLErrorCodeNotFound;
+ description = NSLocalizedStringWithDefaultValue(@"STYLE_NOT_FOUND_DESC", nil, nil, @"The map failed to load because the style can’t be found or is incompatible.", @"User-friendly error description");
+ } catch (...) {
+ code = MGLErrorCodeUnknown;
+ description = NSLocalizedStringWithDefaultValue(@"LOAD_MAP_FAILED_DESC", nil, nil, @"The map failed to load because an unknown error occurred.", @"User-friendly error description");
+ }
+ NSDictionary *userInfo = @{
+ NSLocalizedDescriptionKey: description,
+ NSLocalizedFailureReasonErrorKey: @(mbgl::util::toString(exception).c_str()),
+ };
+ NSError *error = [NSError errorWithDomain:MGLErrorDomain code:code userInfo:userInfo];
+ [nativeView mapViewDidFailLoadingMapWithError:error];
+ }
+
+ void onWillStartRenderingFrame() override {
+ [nativeView mapViewWillStartRenderingFrame];
+ }
+
+ void onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode mode) override {
+ bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
+ [nativeView mapViewDidFinishRenderingFrameFullyRendered:fullyRendered];
+ }
+
+ void onWillStartRenderingMap() override {
+ [nativeView mapViewWillStartRenderingMap];
+ }
+
+ void onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode) override {
+ bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
+ [nativeView mapViewDidFinishRenderingMapFullyRendered:fullyRendered];
+ }
+
+ void onDidFinishLoadingStyle() override {
+ [nativeView didFinishLoadingStyle];
}
void invalidate() override
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index 7e3eac9877..152fdc382b 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog for Mapbox macOS SDK
+## master
+
+* The error passed into `-[MGLMapViewDelegate mapViewDidFailLoadingMap:withError:]` now includes a more specific description and failure reason. ([#8418](https://github.com/mapbox/mapbox-gl-native/pull/8418))
+
## 0.4.0
### Internationalization
diff --git a/platform/macos/bitrise.yml b/platform/macos/bitrise.yml
index 2de6bce1fc..1f2495dab2 100644
--- a/platform/macos/bitrise.yml
+++ b/platform/macos/bitrise.yml
@@ -12,59 +12,24 @@ workflows:
primary:
steps:
- script:
- title: Check for skipping CI
- inputs:
- - content: |-
- #!/bin/bash
- if [[ -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[ci skip\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[ci skip\]/p')" ]]; then
- envman add --key SKIPCI --value true
- else
- envman add --key SKIPCI --value false
- fi
- - script:
- title: Install Dependencies
- run_if: '{{enveq "SKIPCI" "false"}}'
+ title: Build
inputs:
- content: |-
#!/bin/bash
set -eu -o pipefail
brew install cmake
gem install xcpretty --no-rdoc --no-ri
- - is_debug: 'yes'
- - script:
- title: Generate Workspace
- run_if: '{{enveq "SKIPCI" "false"}}'
- inputs:
- - content: |-
- #!/bin/bash
- set -eu -o pipefail
- export BUILDTYPE=Debug
- make xproj
- - is_debug: 'yes'
- - script:
- title: Run Core and SDK Unit Tests
- run_if: '{{enveq "SKIPCI" "false"}}'
- inputs:
- - content: |-
- #!/bin/bash
- set -eu -o pipefail
export BUILDTYPE=Debug
export XCPRETTY="| tee ${BITRISE_DEPLOY_DIR}/raw-xcodebuild-output.txt | xcpretty --color --report html --output ${BITRISE_DEPLOY_DIR}/xcode-test-results.html"
make run-test
- - is_debug: 'yes'
- deploy-to-bitrise-io:
title: Deploy to Bitrise.io
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- deploy_path: "test/fixtures"
- notify_user_groups: none
- is_compress: 'true'
- slack:
title: Post to Slack
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- webhook_url: "$SLACK_HOOK_URL"
- channel: "#gl-bots"
@@ -83,28 +48,13 @@ workflows:
nightly-release:
steps:
- script:
- title: Install Dependencies
+ title: Build
inputs:
- content: |-
#!/bin/bash
set -eu -o pipefail
brew install cmake
- - is_debug: 'yes'
- - script:
- title: Configure AWS-CLI
- inputs:
- - content: |-
- #!/bin/bash
- apt-get install -y python-pip python-dev build-essential
pip install awscli
- - script:
- title: Build package
- inputs:
- - content: |-
- #!/bin/bash
- set -eu -o pipefail
- export BUILDTYPE=Release
- export SYMBOLS=NO
- make xpackage
+ gem install xcpretty --no-rdoc --no-ri
+ BUILDTYPE=Release SYMBOLS=NO make xpackage
CLOUDWATCH=true platform/macos/scripts/metrics.sh
- - is_debug: 'yes'
diff --git a/platform/macos/sdk/Base.lproj/Localizable.strings b/platform/macos/sdk/Base.lproj/Localizable.strings
index b7a4a21173..68360320eb 100644
--- a/platform/macos/sdk/Base.lproj/Localizable.strings
+++ b/platform/macos/sdk/Base.lproj/Localizable.strings
@@ -1,6 +1,18 @@
+/* User-friendly error description */
+"LOAD_MAP_FAILED_DESC" = "The map failed to load because an unknown error occurred.";
+
+/* User-friendly error description */
+"LOAD_STYLE_FAILED_DESC" = "The map failed to load because the style can't be loaded.";
+
/* Accessibility title */
"MAP_A11Y_TITLE" = "Mapbox";
+/* User-friendly error description */
+"PARSE_STYLE_FAILED_DESC" = "The map failed to load because the style is corrupted.";
+
+/* User-friendly error description */
+"STYLE_NOT_FOUND_DESC" = "The map failed to load because the style can’t be found or is incompatible.";
+
/* Label of Zoom In button */
"ZOOM_IN_LABEL" = "+";
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index 8711950554..028d41ceda 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -35,8 +35,10 @@
#import <mbgl/math/wrap.hpp>
#import <mbgl/util/constants.hpp>
#import <mbgl/util/chrono.hpp>
+#import <mbgl/util/exception.hpp>
#import <mbgl/util/run_loop.hpp>
#import <mbgl/util/shared_thread_pool.hpp>
+#import <mbgl/util/string.hpp>
#import <map>
#import <unordered_map>
@@ -813,133 +815,150 @@ public:
[self.layer setNeedsDisplay];
}
-- (void)notifyMapChange:(mbgl::MapChange)change {
- // Ignore map updates when the Map object isn't set.
+- (void)cameraWillChangeAnimated:(BOOL)animated {
if (!_mbglMap) {
return;
}
- switch (change) {
- case mbgl::MapChangeRegionWillChange:
- case mbgl::MapChangeRegionWillChangeAnimated:
- {
- if ([self.delegate respondsToSelector:@selector(mapView:cameraWillChangeAnimated:)]) {
- BOOL animated = change == mbgl::MapChangeRegionWillChangeAnimated;
- [self.delegate mapView:self cameraWillChangeAnimated:animated];
- }
- break;
- }
- case mbgl::MapChangeRegionIsChanging:
- {
- // Update a minimum of UI that needs to stay attached to the map
- // while animating.
- [self updateCompass];
- [self updateAnnotationCallouts];
+ if ([self.delegate respondsToSelector:@selector(mapView:cameraWillChangeAnimated:)]) {
+ [self.delegate mapView:self cameraWillChangeAnimated:animated];
+ }
+}
- if ([self.delegate respondsToSelector:@selector(mapViewCameraIsChanging:)]) {
- [self.delegate mapViewCameraIsChanging:self];
- }
- break;
- }
- case mbgl::MapChangeRegionDidChange:
- case mbgl::MapChangeRegionDidChangeAnimated:
- {
- // Update all UI at the end of an animation or atomic change to the
- // viewport. More expensive updates can happen here, but care should
- // still be taken to minimize the work done here because scroll
- // gesture recognition and momentum scrolling is performed as a
- // series of atomic changes, not an animation.
- [self updateZoomControls];
- [self updateCompass];
- [self updateAnnotationCallouts];
- [self updateAnnotationTrackingAreas];
+- (void)cameraIsChanging {
+ if (!_mbglMap) {
+ return;
+ }
- if ([self.delegate respondsToSelector:@selector(mapView:cameraDidChangeAnimated:)]) {
- BOOL animated = change == mbgl::MapChangeRegionDidChangeAnimated;
- [self.delegate mapView:self cameraDidChangeAnimated:animated];
- }
- break;
- }
- case mbgl::MapChangeWillStartLoadingMap:
- {
- if ([self.delegate respondsToSelector:@selector(mapViewWillStartLoadingMap:)]) {
- [self.delegate mapViewWillStartLoadingMap:self];
- }
- break;
- }
- case mbgl::MapChangeDidFinishLoadingMap:
- {
- [self.style willChangeValueForKey:@"sources"];
- [self.style didChangeValueForKey:@"sources"];
- [self.style willChangeValueForKey:@"layers"];
- [self.style didChangeValueForKey:@"layers"];
- if ([self.delegate respondsToSelector:@selector(mapViewDidFinishLoadingMap:)]) {
- [self.delegate mapViewDidFinishLoadingMap:self];
- }
- break;
- }
- case mbgl::MapChangeDidFailLoadingMap:
- {
- if ([self.delegate respondsToSelector:@selector(mapViewDidFailLoadingMap:withError:)]) {
- NSError *error = [NSError errorWithDomain:MGLErrorDomain code:0 userInfo:nil];
- [self.delegate mapViewDidFailLoadingMap:self withError:error];
- }
- break;
- }
- case mbgl::MapChangeWillStartRenderingMap:
- {
- if ([self.delegate respondsToSelector:@selector(mapViewWillStartRenderingMap:)]) {
- [self.delegate mapViewWillStartRenderingMap:self];
- }
- break;
- }
- case mbgl::MapChangeDidFinishRenderingMap:
- case mbgl::MapChangeDidFinishRenderingMapFullyRendered:
- {
- if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingMap:fullyRendered:)]) {
- BOOL fullyRendered = change == mbgl::MapChangeDidFinishRenderingMapFullyRendered;
- [self.delegate mapViewDidFinishRenderingMap:self fullyRendered:fullyRendered];
- }
- break;
- }
- case mbgl::MapChangeWillStartRenderingFrame:
- {
- if ([self.delegate respondsToSelector:@selector(mapViewWillStartRenderingFrame:)]) {
- [self.delegate mapViewWillStartRenderingFrame:self];
- }
- break;
- }
- case mbgl::MapChangeDidFinishRenderingFrame:
- case mbgl::MapChangeDidFinishRenderingFrameFullyRendered:
- {
- if (_isChangingAnnotationLayers) {
- _isChangingAnnotationLayers = NO;
- [self.style didChangeValueForKey:@"layers"];
- }
- if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)]) {
- BOOL fullyRendered = change == mbgl::MapChangeDidFinishRenderingFrameFullyRendered;
- [self.delegate mapViewDidFinishRenderingFrame:self fullyRendered:fullyRendered];
- }
- break;
- }
- case mbgl::MapChangeDidFinishLoadingStyle:
- {
- self.style = [[MGLStyle alloc] initWithMapView:self];
- if ([self.delegate respondsToSelector:@selector(mapView:didFinishLoadingStyle:)])
- {
- [self.delegate mapView:self didFinishLoadingStyle:self.style];
- }
- break;
- }
- case mbgl::MapChangeSourceDidChange:
- {
- [self installAttributionView];
- self.needsUpdateConstraints = YES;
- break;
- }
+ // Update a minimum of UI that needs to stay attached to the map
+ // while animating.
+ [self updateCompass];
+ [self updateAnnotationCallouts];
+
+ if ([self.delegate respondsToSelector:@selector(mapViewCameraIsChanging:)]) {
+ [self.delegate mapViewCameraIsChanging:self];
+ }
+}
+
+- (void)cameraDidChangeAnimated:(BOOL)animated {
+ if (!_mbglMap) {
+ return;
+ }
+
+ // Update all UI at the end of an animation or atomic change to the
+ // viewport. More expensive updates can happen here, but care should
+ // still be taken to minimize the work done here because scroll
+ // gesture recognition and momentum scrolling is performed as a
+ // series of atomic changes, not an animation.
+ [self updateZoomControls];
+ [self updateCompass];
+ [self updateAnnotationCallouts];
+ [self updateAnnotationTrackingAreas];
+
+ if ([self.delegate respondsToSelector:@selector(mapView:cameraDidChangeAnimated:)]) {
+ [self.delegate mapView:self cameraDidChangeAnimated:animated];
+ }
+}
+
+- (void)mapViewWillStartLoadingMap {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if ([self.delegate respondsToSelector:@selector(mapViewWillStartLoadingMap:)]) {
+ [self.delegate mapViewWillStartLoadingMap:self];
+ }
+}
+
+- (void)mapViewDidFinishLoadingMap {
+ if (!_mbglMap) {
+ return;
+ }
+
+ [self.style willChangeValueForKey:@"sources"];
+ [self.style didChangeValueForKey:@"sources"];
+ [self.style willChangeValueForKey:@"layers"];
+ [self.style didChangeValueForKey:@"layers"];
+ if ([self.delegate respondsToSelector:@selector(mapViewDidFinishLoadingMap:)]) {
+ [self.delegate mapViewDidFinishLoadingMap:self];
+ }
+}
+
+- (void)mapViewDidFailLoadingMapWithError:(NSError *)error {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if ([self.delegate respondsToSelector:@selector(mapViewDidFailLoadingMap:withError:)]) {
+ [self.delegate mapViewDidFailLoadingMap:self withError:error];
+ }
+}
+
+- (void)mapViewWillStartRenderingFrame {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if ([self.delegate respondsToSelector:@selector(mapViewWillStartRenderingFrame:)]) {
+ [self.delegate mapViewWillStartRenderingFrame:self];
+ }
+}
+
+- (void)mapViewDidFinishRenderingFrameFullyRendered:(BOOL)fullyRendered {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if (_isChangingAnnotationLayers) {
+ _isChangingAnnotationLayers = NO;
+ [self.style didChangeValueForKey:@"layers"];
+ }
+ if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)]) {
+ [self.delegate mapViewDidFinishRenderingFrame:self fullyRendered:fullyRendered];
+ }
+}
+
+- (void)mapViewWillStartRenderingMap {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if ([self.delegate respondsToSelector:@selector(mapViewWillStartRenderingMap:)]) {
+ [self.delegate mapViewWillStartRenderingMap:self];
+ }
+}
+
+- (void)mapViewDidFinishRenderingMapFullyRendered:(BOOL)fullyRendered {
+ if (!_mbglMap) {
+ return;
+ }
+
+ if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingMap:fullyRendered:)]) {
+ [self.delegate mapViewDidFinishRenderingMap:self fullyRendered:fullyRendered];
}
}
+- (void)mapViewDidFinishLoadingStyle {
+ if (!_mbglMap) {
+ return;
+ }
+
+ self.style = [[MGLStyle alloc] initWithMapView:self];
+ if ([self.delegate respondsToSelector:@selector(mapView:didFinishLoadingStyle:)])
+ {
+ [self.delegate mapView:self didFinishLoadingStyle:self.style];
+ }
+}
+
+- (void)sourceDidChange {
+ if (!_mbglMap) {
+ return;
+ }
+
+ [self installAttributionView];
+ self.needsUpdateConstraints = YES;
+}
+
#pragma mark Printing
- (void)print:(__unused id)sender {
@@ -2750,8 +2769,78 @@ public:
MGLMapViewImpl(MGLMapView *nativeView_)
: nativeView(nativeView_) {}
- void notifyMapChange(mbgl::MapChange change) override {
- [nativeView notifyMapChange:change];
+ void onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) override {
+ bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
+ [nativeView cameraWillChangeAnimated:animated];
+ }
+
+ void onCameraIsChanging() override {
+ [nativeView cameraIsChanging];
+ }
+
+ void onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode) override {
+ bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
+ [nativeView cameraDidChangeAnimated:animated];
+ }
+
+ void onWillStartLoadingMap() override {
+ [nativeView mapViewWillStartLoadingMap];
+ }
+
+ void onDidFinishLoadingMap() override {
+ [nativeView mapViewDidFinishLoadingMap];
+ }
+
+ void onDidFailLoadingMap(std::exception_ptr exception) override {
+ NSString *description;
+ MGLErrorCode code;
+ try {
+ std::rethrow_exception(exception);
+ } catch (const mbgl::util::StyleParseException&) {
+ code = MGLErrorCodeParseStyleFailed;
+ description = NSLocalizedStringWithDefaultValue(@"PARSE_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style is corrupted.", @"User-friendly error description");
+ } catch (const mbgl::util::StyleLoadException&) {
+ code = MGLErrorCodeLoadStyleFailed;
+ description = NSLocalizedStringWithDefaultValue(@"LOAD_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style can't be loaded.", @"User-friendly error description");
+ } catch (const mbgl::util::NotFoundException&) {
+ code = MGLErrorCodeNotFound;
+ description = NSLocalizedStringWithDefaultValue(@"STYLE_NOT_FOUND_DESC", nil, nil, @"The map failed to load because the style can’t be found or is incompatible.", @"User-friendly error description");
+ } catch (...) {
+ code = MGLErrorCodeUnknown;
+ description = NSLocalizedStringWithDefaultValue(@"LOAD_MAP_FAILED_DESC", nil, nil, @"The map failed to load because an unknown error occurred.", @"User-friendly error description");
+ }
+ NSDictionary *userInfo = @{
+ NSLocalizedDescriptionKey: description,
+ NSLocalizedFailureReasonErrorKey: @(mbgl::util::toString(exception).c_str()),
+ };
+ NSError *error = [NSError errorWithDomain:MGLErrorDomain code:code userInfo:userInfo];
+ [nativeView mapViewDidFailLoadingMapWithError:error];
+ }
+
+ void onWillStartRenderingFrame() override {
+ [nativeView mapViewWillStartRenderingFrame];
+ }
+
+ void onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode mode) override {
+ bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
+ [nativeView mapViewDidFinishRenderingFrameFullyRendered:fullyRendered];
+ }
+
+ void onWillStartRenderingMap() override {
+ [nativeView mapViewWillStartRenderingMap];
+ }
+
+ void onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode) override {
+ bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
+ [nativeView mapViewDidFinishRenderingMapFullyRendered:fullyRendered];
+ }
+
+ void onDidFinishLoadingStyle() override {
+ [nativeView mapViewDidFinishLoadingStyle];
+ }
+
+ void onSourceChanged(mbgl::style::Source&) override {
+ [nativeView sourceDidChange];
}
void invalidate() override {
diff --git a/platform/node/CHANGELOG.md b/platform/node/CHANGELOG.md
index 6f5afbbd6c..12032b4037 100644
--- a/platform/node/CHANGELOG.md
+++ b/platform/node/CHANGELOG.md
@@ -1,3 +1,16 @@
+# 3.4.7 - March 15, 2017
+
+- Fixed MacOS Release builds ([8409](https://github.com/mapbox/mapbox-gl-native/pull/8409))
+
+# 3.4.6 - March 14, 2017
+
+- Publishes `Release` build on Mac ([#8407](https://github.com/mapbox/mapbox-gl-native/pull/8407))
+- Fixes the publish binary build process ([#8406](https://github.com/mapbox/mapbox-gl-native/pull/8406))
+
+# 3.4.5 - March 14, 2017
+
+- Fixed a memory hang issue after GlyphAtlas was refactored ([#8394](https://github.com/mapbox/mapbox-gl-native/pull/8394))
+
# 3.4.4 - January 10, 2017
- Updates the node binary publish location on s3 to reflect new package name ([#7653](https://github.com/mapbox/mapbox-gl-native/pull/7653))
diff --git a/platform/node/bitrise.yml b/platform/node/bitrise.yml
index 20dcfb1908..68829d966e 100644
--- a/platform/node/bitrise.yml
+++ b/platform/node/bitrise.yml
@@ -3,85 +3,65 @@ default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
trigger_map:
- tag: "node-v*"
- workflow: primary
+ workflow: publish
- push_branch: "*"
workflow: primary
- pull_request_target_branch: "*"
workflow: primary
+shortcuts:
+ slack: &slack
+ title: Post to Slack
+ inputs:
+ - webhook_url: "$SLACK_HOOK_URL"
+ - channel: "#gl-bots"
+ - from_username: 'Bitrise Node macOS'
+ - from_username_on_error: 'Bitrise Node macOS'
+ - message: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}>
+ for <https://github.com/mapbox/mapbox-gl-native/compare/${BITRISE_GIT_BRANCH}|mapbox/mapbox-gl-native@${BITRISE_GIT_BRANCH}>
+ by ${GIT_CLONE_COMMIT_COMMITER_NAME}
+ passed'
+ - message_on_error: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}>
+ for <https://github.com/mapbox/mapbox-gl-native/compare/${BITRISE_GIT_BRANCH}|mapbox/mapbox-gl-native@${BITRISE_GIT_BRANCH}>
+ by ${GIT_CLONE_COMMIT_COMMITER_NAME}
+ failed'
+ - icon_url: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-icon-128.png
+ - icon_url_on_error: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-error-icon-128.png
+
workflows:
primary:
steps:
- script:
- title: Check for skipping CI
- inputs:
- - content: |-
- #!/bin/bash
- if [[ -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[ci skip\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[ci skip\]/p')" ]]; then
- envman add --key SKIPCI --value true
- else
- envman add --key SKIPCI --value false
- fi
- - script:
- title: Check for publishing
- run_if: '{{enveq "SKIPCI" "false"}}'
- inputs:
- - content: |-
- #!/bin/bash
- PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
- if [[ "${BITRISE_GIT_TAG:-}" == "node-v${PACKAGE_JSON_VERSION}" ]]; then
- envman add --key PUBLISH --value true
- fi
- - script:
- title: Run build script
- run_if: '{{enveq "SKIPCI" "false"}}'
+ title: Test
inputs:
- content: |-
#!/bin/bash
set -eu -o pipefail
brew update
- brew install cmake
brew unlink node
- brew install awscli node@4
+ brew install cmake awscli node@4
brew link node@4 --force
gem install xcpretty --no-rdoc --no-ri
- make node
- - script:
- title: Run test script
- run_if: '{{and (enveq "SKIPCI" "false") (enveq "PUBLISH" "")}}'
- inputs:
- - content: |-
- #!/bin/bash
- set -eu -o pipefail
- make test-node || envman add --key RESULT --value $?
+ make test-node || RESULT=$?
./platform/node/scripts/after_script.sh ${BITRISE_BUILD_NUMBER}
+ exit ${RESULT:-0}
+ - slack: *slack
+
+ publish:
+ steps:
- script:
- title: Run publish script
- run_if: '{{enveq "SKIPCI" "false"}}'
+ title: Publish
inputs:
- content: |-
#!/bin/bash
set -eu -o pipefail
+ brew update
+ brew unlink node
+ brew install cmake awscli node@4
+ brew link node@4 --force
+ gem install xcpretty --no-rdoc --no-ri
+ export BUILDTYPE=Release
+ export PUBLISH=true
+ make test-node
./platform/node/scripts/after_success.sh
- exit ${RESULT:-0}
- - slack:
- title: Post to Slack
- run_if: '{{enveq "SKIPCI" "false"}}'
- inputs:
- - webhook_url: "$SLACK_HOOK_URL"
- - channel: "#gl-bots"
- - from_username: 'Bitrise Node macOS'
- - from_username_on_error: 'Bitrise Node macOS'
- - message: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}>
- for <https://github.com/mapbox/mapbox-gl-native/compare/${BITRISE_GIT_BRANCH}|mapbox/mapbox-gl-native@${BITRISE_GIT_BRANCH}>
- by ${GIT_CLONE_COMMIT_COMMITER_NAME}
- passed'
- - message_on_error: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}>
- for <https://github.com/mapbox/mapbox-gl-native/compare/${BITRISE_GIT_BRANCH}|mapbox/mapbox-gl-native@${BITRISE_GIT_BRANCH}>
- by ${GIT_CLONE_COMMIT_COMMITER_NAME}
- failed'
- - icon_url: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-icon-128.png
- - icon_url_on_error: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-error-icon-128.png
+ - slack: *slack
diff --git a/platform/node/scripts/after_success.sh b/platform/node/scripts/after_success.sh
index 7ef8f53545..95921a42c2 100755
--- a/platform/node/scripts/after_success.sh
+++ b/platform/node/scripts/after_success.sh
@@ -4,7 +4,7 @@ set -e
set -o pipefail
if [[ -n ${PUBLISH:-} ]]; then
- if [[ "${BUILDTYPE}" == "Debug" ]]; then
+ if [[ "${BUILDTYPE}" != "Release" ]]; then
echo "Please run this script in release mode (BUILDTYPE=Release)."
exit 1
else
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index f6b672efee..a3a11a1907 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -14,12 +14,6 @@
#include <unistd.h>
-#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
-#define UV_ASYNC_PARAMS(handle) uv_async_t *handle, int
-#else
-#define UV_ASYNC_PARAMS(handle) uv_async_t *handle
-#endif
-
namespace node_mbgl {
struct NodeMap::RenderOptions {
@@ -45,6 +39,13 @@ static const char* releasedMessage() {
return "Map resources have already been released";
}
+NodeBackend::NodeBackend()
+ : HeadlessBackend(sharedDisplay()) {}
+
+void NodeBackend::onDidFailLoadingMap(std::exception_ptr error) {
+ std::rethrow_exception(error);
+}
+
void NodeMap::Init(v8::Local<v8::Object> target) {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
@@ -959,7 +960,6 @@ NodeMap::NodeMap(v8::Local<v8::Object> options)
->NumberValue()
: 1.0;
}()),
- backend(sharedDisplay()),
map(std::make_unique<mbgl::Map>(backend,
mbgl::Size{ 256, 256 },
pixelRatio,
@@ -968,14 +968,8 @@ NodeMap::NodeMap(v8::Local<v8::Object> options)
mbgl::MapMode::Still)),
async(new uv_async_t) {
- backend.setMapChangeCallback([&](mbgl::MapChange change) {
- if (change == mbgl::MapChangeDidFailLoadingMap) {
- throw std::runtime_error("Requires a map style to be a valid style JSON");
- }
- });
-
async->data = this;
- uv_async_init(uv_default_loop(), async, [](UV_ASYNC_PARAMS(h)) {
+ uv_async_init(uv_default_loop(), async, [](uv_async_t* h) {
reinterpret_cast<NodeMap *>(h->data)->renderFinished();
});
diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp
index 47a5385ad6..bfc0a7eab6 100644
--- a/platform/node/src/node_map.hpp
+++ b/platform/node/src/node_map.hpp
@@ -7,6 +7,8 @@
#include <mbgl/gl/headless_backend.hpp>
#include <mbgl/gl/offscreen_view.hpp>
+#include <exception>
+
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wshadow"
@@ -15,6 +17,12 @@
namespace node_mbgl {
+class NodeBackend : public mbgl::HeadlessBackend {
+public:
+ NodeBackend();
+ void onDidFailLoadingMap(std::exception_ptr) final;
+};
+
class NodeMap : public Nan::ObjectWrap,
public mbgl::FileSource {
public:
@@ -59,7 +67,7 @@ public:
std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback);
const float pixelRatio;
- mbgl::HeadlessBackend backend;
+ NodeBackend backend;
std::unique_ptr<mbgl::OffscreenView> view;
NodeThreadPool threadpool;
std::unique_ptr<mbgl::Map> map;
diff --git a/platform/node/src/node_request.cpp b/platform/node/src/node_request.cpp
index de16710f78..09373b1779 100644
--- a/platform/node/src/node_request.cpp
+++ b/platform/node/src/node_request.cpp
@@ -122,9 +122,19 @@ void NodeRequest::HandleCallback(const Nan::FunctionCallbackInfo<v8::Value>& inf
}
void NodeRequest::Execute() {
+ asyncExecute = std::make_unique<mbgl::util::AsyncTask>([this] { doExecute(); Unref(); });
+ asyncExecute->send();
+
+ Ref();
+}
+
+void NodeRequest::doExecute() {
+ Nan::HandleScope scope;
+
v8::Local<v8::Value> argv[] = { handle() };
Nan::MakeCallback(Nan::To<v8::Object>(target->handle()->GetInternalField(1)).ToLocalChecked(), "request", 1, argv);
+ asyncExecute.reset();
}
NodeRequest::NodeAsyncRequest::NodeAsyncRequest(NodeRequest* request_) : request(request_) {
diff --git a/platform/node/src/node_request.hpp b/platform/node/src/node_request.hpp
index 7d7679a3c7..356566132b 100644
--- a/platform/node/src/node_request.hpp
+++ b/platform/node/src/node_request.hpp
@@ -8,6 +8,9 @@
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/file_source.hpp>
+#include <mbgl/util/async_task.hpp>
+
+#include <memory>
namespace node_mbgl {
@@ -35,9 +38,12 @@ public:
void Execute();
private:
+ void doExecute();
+
NodeMap* target;
mbgl::FileSource::Callback callback;
NodeAsyncRequest* asyncRequest = nullptr;
+ std::unique_ptr<mbgl::util::AsyncTask> asyncExecute;
};
}
diff --git a/platform/node/src/util/async_queue.hpp b/platform/node/src/util/async_queue.hpp
index 87737437c3..a084b866ae 100644
--- a/platform/node/src/util/async_queue.hpp
+++ b/platform/node/src/util/async_queue.hpp
@@ -8,12 +8,6 @@
#include <queue>
#include <string>
-#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
-#define UV_ASYNC_PARAMS(handle) uv_async_t *handle, int
-#else
-#define UV_ASYNC_PARAMS(handle) uv_async_t *handle
-#endif
-
namespace node_mbgl {
namespace util {
@@ -23,7 +17,7 @@ public:
AsyncQueue(uv_loop_t *loop, std::function<void(T &)> fn) :
callback(fn) {
async.data = this;
- uv_async_init(loop, &async, [](UV_ASYNC_PARAMS(handle)) {
+ uv_async_init(loop, &async, [](uv_async_t* handle) {
auto q = reinterpret_cast<AsyncQueue *>(handle->data);
q->process();
});
diff --git a/platform/node/test/js/map.test.js b/platform/node/test/js/map.test.js
index 145f62ef5f..e5c756adb6 100644
--- a/platform/node/test/js/map.test.js
+++ b/platform/node/test/js/map.test.js
@@ -311,11 +311,11 @@ test('Map', function(t) {
t.throws(function() {
map.load('foo bar');
- }, /Requires a map style to be a valid style JSON/);
+ }, /Failed to parse style: 1 - Invalid value./);
t.throws(function() {
map.load('""');
- }, /Requires a map style to be a valid style JSON/);
+ }, /Failed to parse style: style must be an object/);
map.release();
t.end();
@@ -335,7 +335,7 @@ test('Map', function(t) {
t.throws(function() {
map.load('invalid');
- }, /Requires a map style to be a valid style JSON/);
+ }, /Failed to parse style: 0 - Invalid value./);
});
t.test('accepts an empty stylesheet string', function(t) {
diff --git a/platform/node/test/memory.test.js b/platform/node/test/memory.test.js
index e23cb60f89..997ccdbbe1 100644
--- a/platform/node/test/memory.test.js
+++ b/platform/node/test/memory.test.js
@@ -1,8 +1,7 @@
'use strict';
-var fs = require('fs');
+var mockfs = require('./mockfs');
var mbgl = require('../index');
-var path = require('path');
var test = require('tape');
var testParams = {
@@ -12,20 +11,6 @@ var testParams = {
ratio: 2
};
-function readFixture(file) {
- return fs.readFileSync(path.join('test/fixtures/resources', file));
-}
-
-var style_raster = readFixture('style_raster.json').toString('utf8');
-var style_vector = readFixture('style_vector.json').toString('utf8');
-var sprite_json = readFixture('sprite.json');
-var sprite_png = readFixture('sprite.png');
-var glyph = readFixture('glyphs.pbf');
-var source_raster = readFixture('source_raster.json');
-var source_vector = readFixture('source_vector.json');
-var tile_raster = readFixture('raster.tile');
-var tile_vector = readFixture('vector.tile');
-
test('Memory', function(t) {
// Trigger garbage collection before starting test, then initialize
// heap size
@@ -34,25 +19,7 @@ test('Memory', function(t) {
var options = {
request: function(req, callback) {
- if (req.url == null) {
- t.fail('invalid file request');
- } else if (req.url.indexOf('sprite') > -1 && req.url.endsWith('json')) {
- callback(null, { data: sprite_json });
- } else if (req.url.indexOf('sprite') > -1 && req.url.endsWith('png')) {
- callback(null, { data: sprite_png });
- } else if (req.url.indexOf('fonts') > -1 && req.url.endsWith('pbf')) {
- callback(null, { data: glyph });
- } else if (req.url.endsWith('mapbox.satellite')) {
- callback(null, { data: source_raster });
- } else if (req.url.indexOf('satellite') > -1 && (req.url.endsWith('png') || req.url.endsWith('webp'))) {
- callback(null, { data: tile_raster });
- } else if (req.url.endsWith('mapbox.mapbox-streets-v7')) {
- callback(null, { data: source_vector });
- } else if (req.url.indexOf('streets') > -1 && req.url.endsWith('pbf')) {
- callback(null, { data: tile_vector });
- } else {
- t.fail('unhandled file request: ' + req.url);
- }
+ callback(null, { data: mockfs.dataForRequest(req) });
},
ratio: testParams.ratio,
};
@@ -75,9 +42,9 @@ test('Memory', function(t) {
var map = mapPool.shift();
if (Math.floor(Math.random() * 2)) {
- map.load(style_raster);
+ map.load(mockfs.style_raster);
} else {
- map.load(style_vector);
+ map.load(mockfs.style_vector);
}
map.render({ zoom: 16 }, function(err, pixels) {
diff --git a/platform/node/test/mockfs.js b/platform/node/test/mockfs.js
new file mode 100644
index 0000000000..dfa5a425e3
--- /dev/null
+++ b/platform/node/test/mockfs.js
@@ -0,0 +1,53 @@
+"use strict";
+
+var fs = require('fs');
+var path = require('path');
+
+function readFixture(file) {
+ return fs.readFileSync(path.join('test/fixtures/resources', file));
+};
+
+var style_raster = readFixture('style_raster.json').toString('utf8');
+var style_vector = readFixture('style_vector.json').toString('utf8');
+var sprite_json = readFixture('sprite.json');
+var sprite_png = readFixture('sprite.png');
+var glyph = readFixture('glyphs.pbf');
+var source_raster = readFixture('source_raster.json');
+var source_vector = readFixture('source_vector.json');
+var tile_raster = readFixture('raster.tile');
+var tile_vector = readFixture('vector.tile');
+
+function dataForRequest(req) {
+ if (req.url == null) {
+ return null;
+ } else if (req.url.indexOf('sprite') > -1 && req.url.endsWith('json')) {
+ return sprite_json;
+ } else if (req.url.indexOf('sprite') > -1 && req.url.endsWith('png')) {
+ return sprite_png;
+ } else if (req.url.indexOf('fonts') > -1 && req.url.endsWith('pbf')) {
+ return glyph;
+ } else if (req.url.endsWith('mapbox.satellite')) {
+ return source_raster;
+ } else if (req.url.indexOf('satellite') > -1 && (req.url.endsWith('png') || req.url.endsWith('webp'))) {
+ return tile_raster;
+ } else if (req.url.endsWith('mapbox.mapbox-streets-v7')) {
+ return source_vector;
+ } else if (req.url.indexOf('streets') > -1 && req.url.endsWith('pbf')) {
+ return tile_vector;
+ } else {
+ return null;
+ }
+};
+
+module.exports = {
+ dataForRequest: dataForRequest,
+ style_raster: style_raster,
+ style_vector: style_vector,
+ sprite_json: sprite_json,
+ sprite_png: sprite_png,
+ glyph: glyph,
+ source_raster: source_raster,
+ source_vector: source_vector,
+ tile_raster: tile_raster,
+ tile_vector: tile_vector
+};
diff --git a/platform/qt/bitrise-qt4.yml b/platform/qt/bitrise-qt4.yml
index 8b327d0974..0a08d684fc 100644
--- a/platform/qt/bitrise-qt4.yml
+++ b/platform/qt/bitrise-qt4.yml
@@ -9,22 +9,7 @@ workflows:
primary:
steps:
- script:
- title: Check for skipping CI
- inputs:
- - content: |-
- #!/bin/bash
-
- if [[ -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[ci skip\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[ci skip\]/p')" ]]; then
- envman add --key SKIPCI --value true
- else
- envman add --key SKIPCI --value false
- fi
- - script:
title: Run build
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
@@ -40,7 +25,6 @@ workflows:
- is_debug: 'yes'
- slack:
title: Post to Slack
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- webhook_url: "$SLACK_HOOK_URL"
- channel: "#gl-bots"
diff --git a/platform/qt/bitrise-qt5.yml b/platform/qt/bitrise-qt5.yml
index 036ec044c5..4438b50a8f 100644
--- a/platform/qt/bitrise-qt5.yml
+++ b/platform/qt/bitrise-qt5.yml
@@ -9,22 +9,7 @@ workflows:
primary:
steps:
- script:
- title: Check for skipping CI
- inputs:
- - content: |-
- #!/bin/bash
-
- if [[ -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[ci skip\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[skip ci\]/p')" ||
- -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[ci skip\]/p')" ]]; then
- envman add --key SKIPCI --value true
- else
- envman add --key SKIPCI --value false
- fi
- - script:
title: Run build
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
@@ -43,14 +28,12 @@ workflows:
- is_debug: 'yes'
- deploy-to-bitrise-io:
title: Deploy to Bitrise.io
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- deploy_path: "test/fixtures"
- notify_user_groups: none
- is_compress: 'true'
- slack:
title: Post to Slack
- run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- webhook_url: "$SLACK_HOOK_URL"
- channel: "#gl-bots"
diff --git a/platform/qt/include/qmapboxgl.hpp b/platform/qt/include/qmapboxgl.hpp
index af7ed6275f..117fce515c 100644
--- a/platform/qt/include/qmapboxgl.hpp
+++ b/platform/qt/include/qmapboxgl.hpp
@@ -94,7 +94,6 @@ class Q_DECL_EXPORT QMapboxGL : public QObject
Q_PROPERTY(QMargins margins READ margins WRITE setMargins)
public:
- // Reflects mbgl::MapChange.
enum MapChange {
MapChangeRegionWillChange = 0,
MapChangeRegionWillChangeAnimated,
diff --git a/platform/qt/src/qmapbox.cpp b/platform/qt/src/qmapbox.cpp
index 62bfde4fa8..126ece1efa 100644
--- a/platform/qt/src/qmapbox.cpp
+++ b/platform/qt/src/qmapbox.cpp
@@ -1,7 +1,6 @@
#include "qmapbox.hpp"
#include <mbgl/gl/extension.hpp>
-#include <mbgl/map/change.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/util/default_styles.hpp>
#include <mbgl/util/geometry.hpp>
diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp
index 55470a65e1..ab727a62e7 100644
--- a/platform/qt/src/qmapboxgl.cpp
+++ b/platform/qt/src/qmapboxgl.cpp
@@ -57,24 +57,6 @@ static_assert(mbgl::underlying_type(QMapboxGLSettings::ConstrainWidthAndHeight)
static_assert(mbgl::underlying_type(QMapboxGLSettings::DefaultViewport) == mbgl::underlying_type(mbgl::ViewportMode::Default), "error");
static_assert(mbgl::underlying_type(QMapboxGLSettings::FlippedYViewport) == mbgl::underlying_type(mbgl::ViewportMode::FlippedY), "error");
-// mbgl::MapChange
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeRegionWillChange) == mbgl::underlying_type(mbgl::MapChangeRegionWillChange), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeRegionWillChangeAnimated) == mbgl::underlying_type(mbgl::MapChangeRegionWillChangeAnimated), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeRegionIsChanging) == mbgl::underlying_type(mbgl::MapChangeRegionIsChanging), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeRegionDidChange) == mbgl::underlying_type(mbgl::MapChangeRegionDidChange), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeRegionDidChangeAnimated) == mbgl::underlying_type(mbgl::MapChangeRegionDidChangeAnimated), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeWillStartLoadingMap) == mbgl::underlying_type(mbgl::MapChangeWillStartLoadingMap), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishLoadingMap) == mbgl::underlying_type(mbgl::MapChangeDidFinishLoadingMap), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFailLoadingMap) == mbgl::underlying_type(mbgl::MapChangeDidFailLoadingMap), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeWillStartRenderingFrame) == mbgl::underlying_type(mbgl::MapChangeWillStartRenderingFrame), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishRenderingFrame) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingFrame), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishRenderingFrameFullyRendered) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingFrameFullyRendered), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeWillStartRenderingMap) == mbgl::underlying_type(mbgl::MapChangeWillStartRenderingMap), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishRenderingMap) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingMap), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishRenderingMapFullyRendered) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingMapFullyRendered), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishLoadingStyle) == mbgl::underlying_type(mbgl::MapChangeDidFinishLoadingStyle), "error");
-static_assert(mbgl::underlying_type(QMapboxGL::MapChangeSourceDidChange) == mbgl::underlying_type(mbgl::MapChangeSourceDidChange), "error");
-
// mbgl::NorthOrientation
static_assert(mbgl::underlying_type(QMapboxGL::NorthUpwards) == mbgl::underlying_type(mbgl::NorthOrientation::Upwards), "error");
static_assert(mbgl::underlying_type(QMapboxGL::NorthRightwards) == mbgl::underlying_type(mbgl::NorthOrientation::Rightwards), "error");
@@ -1587,19 +1569,87 @@ void QMapboxGLPrivate::invalidate()
}
}
-void QMapboxGLPrivate::notifyMapChange(mbgl::MapChange change)
+void QMapboxGLPrivate::onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode)
{
- if (change == mbgl::MapChangeSourceDidChange) {
- std::string attribution;
- for (const auto& source : mapObj->getSources()) {
- // Avoid duplicates by using the most complete attribution HTML snippet.
- if (source->getAttribution() && (attribution.size() < source->getAttribution()->size()))
- attribution = *source->getAttribution();
- }
- emit copyrightsChanged(QString::fromStdString(attribution));
+ if (mode == mbgl::MapObserver::CameraChangeMode::Immediate) {
+ emit mapChanged(QMapboxGL::MapChangeRegionWillChange);
+ } else {
+ emit mapChanged(QMapboxGL::MapChangeRegionWillChangeAnimated);
+ }
+}
+
+void QMapboxGLPrivate::onCameraIsChanging()
+{
+ emit mapChanged(QMapboxGL::MapChangeRegionIsChanging);
+}
+
+void QMapboxGLPrivate::onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode)
+{
+ if (mode == mbgl::MapObserver::CameraChangeMode::Immediate) {
+ emit mapChanged(QMapboxGL::MapChangeRegionDidChange);
+ } else {
+ emit mapChanged(QMapboxGL::MapChangeRegionDidChangeAnimated);
+ }
+}
+
+void QMapboxGLPrivate::onWillStartLoadingMap()
+{
+ emit mapChanged(QMapboxGL::MapChangeWillStartLoadingMap);
+}
+
+void QMapboxGLPrivate::onDidFinishLoadingMap()
+{
+ emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingMap);
+}
+
+void QMapboxGLPrivate::onDidFailLoadingMap(std::exception_ptr)
+{
+ emit mapChanged(QMapboxGL::MapChangeDidFailLoadingMap);
+}
+
+void QMapboxGLPrivate::onWillStartRenderingFrame()
+{
+ emit mapChanged(QMapboxGL::MapChangeWillStartRenderingFrame);
+}
+
+void QMapboxGLPrivate::onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode mode)
+{
+ if (mode == mbgl::MapObserver::RenderMode::Partial) {
+ emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingFrame);
+ } else {
+ emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingFrameFullyRendered);
}
+}
+
+void QMapboxGLPrivate::onWillStartRenderingMap()
+{
+ emit mapChanged(QMapboxGL::MapChangeWillStartLoadingMap);
+}
- emit mapChanged(static_cast<QMapboxGL::MapChange>(change));
+void QMapboxGLPrivate::onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode)
+{
+ if (mode == mbgl::MapObserver::RenderMode::Partial) {
+ emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingMap);
+ } else {
+ emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingMapFullyRendered);
+ }
+}
+
+void QMapboxGLPrivate::onDidFinishLoadingStyle()
+{
+ emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingStyle);
+}
+
+void QMapboxGLPrivate::onSourceChanged(mbgl::style::Source&)
+{
+ std::string attribution;
+ for (const auto& source : mapObj->getSources()) {
+ // Avoid duplicates by using the most complete attribution HTML snippet.
+ if (source->getAttribution() && (attribution.size() < source->getAttribution()->size()))
+ attribution = *source->getAttribution();
+ }
+ emit copyrightsChanged(QString::fromStdString(attribution));
+ emit mapChanged(QMapboxGL::MapChangeSourceDidChange);
}
void QMapboxGLPrivate::connectionEstablished()
diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp
index ee7bff0872..2d8bfaaf53 100644
--- a/platform/qt/src/qmapboxgl_p.hpp
+++ b/platform/qt/src/qmapboxgl_p.hpp
@@ -29,7 +29,20 @@ public:
void activate() final {}
void deactivate() final {}
void invalidate() final;
- void notifyMapChange(mbgl::MapChange) final;
+
+ // mbgl::Backend (mbgl::MapObserver) implementation.
+ void onCameraWillChange(mbgl::MapObserver::CameraChangeMode) final;
+ void onCameraIsChanging() final;
+ void onCameraDidChange(mbgl::MapObserver::CameraChangeMode) final;
+ void onWillStartLoadingMap() final;
+ void onDidFinishLoadingMap() final;
+ void onDidFailLoadingMap(std::exception_ptr) final;
+ void onWillStartRenderingFrame() final;
+ void onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode) final;
+ void onWillStartRenderingMap() final;
+ void onDidFinishRenderingMap(mbgl::MapObserver::RenderMode) final;
+ void onDidFinishLoadingStyle() final;
+ void onSourceChanged(mbgl::style::Source&) final;
mbgl::EdgeInsets margins;
QSize size { 0, 0 };