diff options
author | Wilhelm Berg <wb@BergWerk-GIS.at> | 2018-09-12 15:07:57 +0200 |
---|---|---|
committer | Wilhelm Berg <wb@BergWerk-GIS.at> | 2018-09-12 15:07:57 +0200 |
commit | 98b34cb0dbf5c50d7f319724c93021418140b15f (patch) | |
tree | 11cd51f86b5c672dda6bfe087f40f77df1553971 | |
parent | ee17d79f9420eb859303d977955454dacc470db6 (diff) | |
parent | 079ba0209ed383c15123902f0810e658c2b0abf4 (diff) |
Merge remote-tracking branch 'origin' into bwg-vs2017upstream/bwg-vs2017
# Conflicts:
# cmake/mason-dependencies.cmake
332 files changed, 94929 insertions, 3963 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index bb315916b..b37a69a83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,6 +142,8 @@ else() message(STATUS "Can't find ccache — consider installing ccache to improve recompilation performance") endif() +include(cmake/codecvt.cmake) + if(NOT EXISTS ${CMAKE_SOURCE_DIR}/platform/${MBGL_PLATFORM}/config.cmake) message(ERROR "Can't find config.cmake file for platform ${MBGL_PLATFORM}") endif() @@ -522,7 +522,8 @@ MBGL_ANDROID_LIBDIR = lib$(if $(filter arm-v8 x86-64,$1),64) MBGL_ANDROID_DALVIKVM = dalvikvm$(if $(filter arm-v8 x86-64,$1),64,32) MBGL_ANDROID_APK_SUFFIX = $(if $(filter Release,$(BUILDTYPE)),release-unsigned,debug) MBGL_ANDROID_CORE_TEST_DIR = platform/android/MapboxGLAndroidSDK/.externalNativeBuild/cmake/$(buildtype)/$2/core-tests -MBGL_ANDROID_GRADLE = ./gradlew --parallel --max-workers=$(JOBS) -Pmapbox.buildtype=$(buildtype) +MBGL_ANDROID_STL ?= c++_static +MBGL_ANDROID_GRADLE = ./gradlew --parallel --max-workers=$(JOBS) -Pmapbox.buildtype=$(buildtype) -Pmapbox.stl=$(MBGL_ANDROID_STL) # Lists all devices, and extracts the identifiers, then obtains the ABI for every one. # Some devices return \r\n, so we'll have to remove the carriage return before concatenating. @@ -20,9 +20,7 @@ Additional Mapbox GL Native–based libraries for **hybrid applications** are de | Toolkit | Android | iOS | Developer | | ---------------------------------------- | --------|-----|------------ | | [React Native](https://github.com/mapbox/react-native-mapbox-gl/) ([npm](https://www.npmjs.com/package/@mapbox/react-native-mapbox-gl)) | :white_check_mark: | :white_check_mark: | Mapbox | -| [Apache Cordova](http://plugins.telerik.com/cordova/plugin/mapbox/) ([npm](https://www.npmjs.com/package/cordova-plugin-mapbox)) | :white_check_mark: | :white_check_mark: | Telerik | | [NativeScript](https://market.nativescript.org/plugins/nativescript-mapbox/) ([npm](https://www.npmjs.com/package/nativescript-mapbox/)) | :white_check_mark: | :white_check_mark: | Telerik | -| [Xamarin](https://components.xamarin.com/view/mapboxsdk/) | :white_check_mark: | :white_check_mark: | Xamarin | If your platform or hybrid application framework isn’t listed here, consider embedding [Mapbox GL JS](https://github.com/mapbox/mapbox-gl-js) using the standard Web capabilities on your platform. diff --git a/circle.yml b/circle.yml index c03b52e12..190578b1d 100644 --- a/circle.yml +++ b/circle.yml @@ -10,6 +10,7 @@ workflows: branches: ignore: master - android-debug-arm-v7 + - android-gnustl-arm-v7 - android-release: filters: tags: @@ -469,6 +470,86 @@ jobs: path: platform/android/MapboxGLAndroidSDKTestApp/lint-baseline.xml # ------------------------------------------------------------------------------ + android-gnustl-arm-v7: + docker: + - image: mbgl/feb0443038:android-ndk-r17 + resource_class: large + working_directory: /src + environment: + LIBSYSCONFCPUS: 4 + JOBS: 4 + BUILDTYPE: Debug + IS_LOCAL_DEVELOPMENT: false + MBGL_ANDROID_STL: gnustl_shared + steps: + - checkout + - *restore-node_modules-cache + - *npm-install + - *prepare-environment + - *prepare-ccache + - *restore-mason_packages-cache + - *restore-ccache + - *restore-gradle-cache + - *reset-ccache-stats + - run: + name: Check code style + command: make android-check + - run: + name: Build libmapbox-gl.so for arm-v7 + command: make android-lib-arm-v7 + - run: + name: Compile Core tests for arm-v7 + command: make android-test-lib-arm-v7 + - run: + name: Test phone module + command: make run-android-unit-test + - run: + name: Generate Espresso sanity tests + command: make test-code-android + - run: + name: Build Test APK + command: | + echo "${MAPBOX_DEVELOPER_CONFIG_XML}" > platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml + make android-ui-test-arm-v7 + - *show-ccache-stats + - *save-node_modules-cache + - *save-mason_packages-cache + - *save-ccache + - *save-gradle-cache + - run: + name: Log in to Google Cloud Platform + shell: /bin/bash -euo pipefail + command: | + echo "${GCLOUD_SERVICE_ACCOUNT_JSON}" > secret.json + gcloud auth activate-service-account --key-file secret.json --project android-gl-native + rm secret.json + - run: + name: Run instrumentation tests on Firebase + no_output_timeout: 1200 + shell: /bin/bash -euo pipefail + command: | + gcloud firebase test android models list + gcloud firebase test android run --type instrumentation \ + --app platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/debug/MapboxGLAndroidSDKTestApp-debug.apk \ + --test platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/androidTest/debug/MapboxGLAndroidSDKTestApp-debug-androidTest.apk \ + --device-ids sailfish --os-version-ids 26 --locales en --orientations portrait --timeout 20m + - store_artifacts: + path: platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/debug + destination: . + - store_artifacts: + path: platform/android/MapboxGLAndroidSDK/build/reports/lint-results.html + - store_artifacts: + path: platform/android/MapboxGLAndroidSDK/build/reports/lint-results.xml + - store_artifacts: + path: platform/android/MapboxGLAndroidSDK/lint-baseline.xml + - store_artifacts: + path: platform/android/MapboxGLAndroidSDKTestApp/build/reports/lint-results.html + - store_artifacts: + path: platform/android/MapboxGLAndroidSDKTestApp/build/reports/lint-results.xml + - store_artifacts: + path: platform/android/MapboxGLAndroidSDKTestApp/lint-baseline.xml + +# ------------------------------------------------------------------------------ android-release: docker: - image: mbgl/feb0443038:android-ndk-r17 diff --git a/cmake/codecvt.cmake b/cmake/codecvt.cmake new file mode 100644 index 000000000..8228a6df6 --- /dev/null +++ b/cmake/codecvt.cmake @@ -0,0 +1,19 @@ +add_library(codecvt INTERFACE) + +# Determine if the STL has codecvt +file(WRITE "${CMAKE_BINARY_DIR}/features/codecvt/main.cpp" "#include <codecvt>\nint main() {}") +try_compile(STL_SUPPORTS_CODECVT + "${CMAKE_BINARY_DIR}/features/codecvt" + SOURCES "${CMAKE_BINARY_DIR}/features/codecvt/main.cpp" + CMAKE_FLAGS "-DCMAKE_MACOSX_BUNDLE:STRING=YES" "-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED:STRING=NO" + COMPILE_DEFINITIONS "-std=c++14" # CXX_STANDARD wasn't added to try_compile until CMake 3.8 + OUTPUT_VARIABLE CODECVT_TEST_OUTPUT +) + +if (NOT STL_SUPPORTS_CODECVT) + if ($ENV{V}) + message("codecvt support not detected: ${CODECVT_TEST_OUTPUT}") + endif() + target_include_directories(codecvt INTERFACE platform/default/codecvt) + target_add_mason_package(codecvt INTERFACE boost) +endif() diff --git a/cmake/core.cmake b/cmake/core.cmake index 32e77f5d5..1b29b4fb0 100644 --- a/cmake/core.cmake +++ b/cmake/core.cmake @@ -7,6 +7,8 @@ target_include_directories(mbgl-core PRIVATE src ) +target_link_libraries(mbgl-core PRIVATE codecvt) + target_add_mason_package(mbgl-core PUBLIC geometry) target_add_mason_package(mbgl-core PUBLIC variant) target_add_mason_package(mbgl-core PRIVATE unique_resource) diff --git a/cmake/mason-dependencies.cmake b/cmake/mason-dependencies.cmake index c953981fd..3c6a535fc 100644 --- a/cmake/mason-dependencies.cmake +++ b/cmake/mason-dependencies.cmake @@ -4,8 +4,8 @@ mason_use(geometry VERSION 0.9.3 HEADER_ONLY) mason_use(variant VERSION 1.1.4 HEADER_ONLY) mason_use(unique_resource VERSION cba309e HEADER_ONLY) mason_use(rapidjson VERSION 1.1.0 HEADER_ONLY) -mason_use(boost VERSION 1.67.0 HEADER_ONLY) -mason_use(geojsonvt VERSION 6.6.0 HEADER_ONLY) +mason_use(boost VERSION 1.65.1 HEADER_ONLY) +mason_use(geojsonvt VERSION 6.6.1 HEADER_ONLY) mason_use(supercluster VERSION 0.2.2 HEADER_ONLY) mason_use(kdbush VERSION 0.1.1-1 HEADER_ONLY) mason_use(earcut VERSION 0.12.4 HEADER_ONLY) @@ -19,9 +19,9 @@ mason_use(cheap-ruler VERSION 2.5.3 HEADER_ONLY) mason_use(vector-tile VERSION 1.0.2 HEADER_ONLY) if(MBGL_PLATFORM STREQUAL "android") - mason_use(jni.hpp VERSION 3.0.0 HEADER_ONLY) + mason_use(jni.hpp VERSION 4.0.0 HEADER_ONLY) elseif(MBGL_PLATFORM STREQUAL "ios") - mason_use(icu VERSION 58.1-min-size) + # noop elseif(MBGL_PLATFORM STREQUAL "linux") mason_use(glfw VERSION 2018-06-27-0be4f3f) mason_use(libuv VERSION 1.9.1) diff --git a/cmake/mason.cmake b/cmake/mason.cmake index 76d02b95b..c0795d962 100644 --- a/cmake/mason.cmake +++ b/cmake/mason.cmake @@ -208,8 +208,8 @@ endif() mason_detect_platform() -# Execute commands if CMake is run in command mode -if (CMAKE_ARGC) +# Execute commands if CMake is run in command mode\ +if (CMAKE_ARGC AND "${CMAKE_SCRIPT_MODE_FILE}" STREQUAL "${CMAKE_CURRENT_LIST_DIR}/mason.cmake") # Collect remaining arguments for passing to mason_use set(_MASON_ARGS) foreach(I RANGE 4 ${CMAKE_ARGC}) diff --git a/cmake/sqlite.cmake b/cmake/sqlite.cmake index 03841ea9b..b099210c8 100644 --- a/cmake/sqlite.cmake +++ b/cmake/sqlite.cmake @@ -33,4 +33,5 @@ target_compile_definitions(sqlite target_compile_options(sqlite PRIVATE "-Wno-int-conversion" + PRIVATE "-Wno-implicit-fallthrough" ) diff --git a/include/mbgl/math/log2.hpp b/include/mbgl/math/log2.hpp index 3136ac22b..4f5fde60d 100644 --- a/include/mbgl/math/log2.hpp +++ b/include/mbgl/math/log2.hpp @@ -15,6 +15,17 @@ namespace util { // (== number of bits required to store x) uint32_t ceil_log2(uint64_t x); +template <typename T> +T log2(T x) { +// log2() is producing wrong results on ARMv5 binaries +// running on ARMv7+ CPUs. +#if defined(__ANDROID__) + return ::log(x) / M_LN2; +#else + return ::log2(x); +#endif +} + } // namespace util } // namespace mbgl diff --git a/include/mbgl/style/expression/interpolator.hpp b/include/mbgl/style/expression/interpolator.hpp index f37fb2c9c..62b48c175 100644 --- a/include/mbgl/style/expression/interpolator.hpp +++ b/include/mbgl/style/expression/interpolator.hpp @@ -33,7 +33,13 @@ public: CubicBezierInterpolator(double x1_, double y1_, double x2_, double y2_) : ub(x1_, y1_, x2_, y2_) {} double interpolationFactor(const Range<double>& inputLevels, const double input) const { - return ub.solve(input / (inputLevels.max - inputLevels.min), 1e-6); + return ub.solve(util::interpolationFactor(1.0, + Range<float> { + static_cast<float>(inputLevels.min), + static_cast<float>(inputLevels.max) + }, + input), + 1e-6); } bool operator==(const CubicBezierInterpolator& rhs) const { diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp index fa0b0c4e4..aabda0d79 100644 --- a/include/mbgl/style/layers/symbol_layer.hpp +++ b/include/mbgl/style/layers/symbol_layer.hpp @@ -53,6 +53,10 @@ public: PropertyValue<bool> getSymbolAvoidEdges() const; void setSymbolAvoidEdges(PropertyValue<bool>); + static PropertyValue<SymbolZOrderType> getDefaultSymbolZOrder(); + PropertyValue<SymbolZOrderType> getSymbolZOrder() const; + void setSymbolZOrder(PropertyValue<SymbolZOrderType>); + static PropertyValue<bool> getDefaultIconAllowOverlap(); PropertyValue<bool> getIconAllowOverlap() const; void setIconAllowOverlap(PropertyValue<bool>); diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp index 805cff118..ed875733c 100644 --- a/include/mbgl/style/types.hpp +++ b/include/mbgl/style/types.hpp @@ -68,6 +68,11 @@ enum class SymbolPlacementType : uint8_t { Line, LineCenter }; + +enum class SymbolZOrderType : uint8_t { + ViewportY, + Source +}; enum class AlignmentType : uint8_t { Map, diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 13162c0b4..1db3140b6 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -3,6 +3,11 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. ## master +- Add `symbol-z-order` symbol layout property to style spec [#12783](https://github.com/mapbox/mapbox-gl-native/pull/12783) + +## 6.5.0 - September 11, 2018 + - Fixed a cubic-bezier interpolation bug. [#12812](https://github.com/mapbox/mapbox-gl-native/issues/12812) + - Fixed an issue that could cause "allow-overlap" symbols to fade in during pan operations instead of always showing. [#12683](https://github.com/mapbox/mapbox-gl-native/issues/12683) ## 6.5.0-beta.1 - September 5, 2018 - Retain shared thread pool reference [#12811](https://github.com/mapbox/mapbox-gl-native/pull/12811) diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle index e796c35ce..f91df8a8a 100644 --- a/platform/android/MapboxGLAndroidSDK/build.gradle +++ b/platform/android/MapboxGLAndroidSDK/build.gradle @@ -1,22 +1,25 @@ apply plugin: 'com.android.library' apply plugin: "com.jaredsburrows.license" +apply plugin: 'kotlin-android' dependencies { lintChecks project(":MapboxGLAndroidSDKLint") - api (dependenciesList.mapboxAndroidTelemetry) { + api(dependenciesList.mapboxAndroidTelemetry) { exclude group: 'com.android.support', module: 'appcompat-v7' } api dependenciesList.mapboxJavaGeoJSON - api (dependenciesList.mapboxAndroidGestures) { + api(dependenciesList.mapboxAndroidGestures) { exclude group: 'com.android.support', module: 'appcompat-v7' } implementation dependenciesList.mapboxJavaTurf + implementation dependenciesList.supportAppcompatV7 implementation dependenciesList.supportAnnotations implementation dependenciesList.supportFragmentV4 implementation dependenciesList.okhttp3 testImplementation dependenciesList.junit testImplementation dependenciesList.mockito testImplementation dependenciesList.robolectric + testImplementation dependenciesList.kotlinLib } android { @@ -24,6 +27,7 @@ android { buildToolsVersion androidVersions.buildToolsVersion defaultConfig { + vectorDrawables.useSupportLibrary = true minSdkVersion androidVersions.minSdkVersion targetSdkVersion androidVersions.targetSdkVersion buildConfigField "String", "GIT_REVISION_SHORT", String.format("\"%s\"", getGitRevision()) @@ -59,12 +63,18 @@ android { } } + // Allow determining the C++ STL we're using when building Mapbox GL. + def stl = 'c++_static' + if (project.hasProperty("mapbox.stl")) { + stl = project.getProperty("mapbox.stl") + } + defaultConfig { if (abi != 'none') { externalNativeBuild { cmake { arguments "-DANDROID_TOOLCHAIN=clang" - arguments "-DANDROID_STL=c++_static" + arguments "-DANDROID_STL=" + stl arguments "-DANDROID_CPP_FEATURES=rtti;exceptions" arguments "-DMBGL_PLATFORM=android" arguments "-DMASON_PLATFORM=android" diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraCompassBearingAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraCompassBearingAnimator.java new file mode 100644 index 000000000..ea1817ab5 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraCompassBearingAnimator.java @@ -0,0 +1,24 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.ValueAnimator; + +import java.util.List; + +class CameraCompassBearingAnimator extends MapboxFloatAnimator<MapboxAnimator.OnCameraAnimationsValuesChangeListener> { + CameraCompassBearingAnimator(Float previous, Float target, + List<OnCameraAnimationsValuesChangeListener> updateListeners) { + super(previous, target, updateListeners); + } + + @Override + int provideAnimatorType() { + return ANIMATOR_CAMERA_COMPASS_BEARING; + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + for (OnCameraAnimationsValuesChangeListener listener : updateListeners) { + listener.onNewCompassBearingValue((Float) animation.getAnimatedValue()); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraGpsBearingAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraGpsBearingAnimator.java new file mode 100644 index 000000000..f46cf805f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraGpsBearingAnimator.java @@ -0,0 +1,23 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.ValueAnimator; + +import java.util.List; + +class CameraGpsBearingAnimator extends MapboxFloatAnimator<MapboxAnimator.OnCameraAnimationsValuesChangeListener> { + CameraGpsBearingAnimator(Float previous, Float target, List<OnCameraAnimationsValuesChangeListener> updateListeners) { + super(previous, target, updateListeners); + } + + @Override + int provideAnimatorType() { + return ANIMATOR_CAMERA_GPS_BEARING; + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + for (OnCameraAnimationsValuesChangeListener listener : updateListeners) { + listener.onNewGpsBearingValue((Float) animation.getAnimatedValue()); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraLatLngAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraLatLngAnimator.java new file mode 100644 index 000000000..533abfc33 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraLatLngAnimator.java @@ -0,0 +1,25 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.ValueAnimator; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.util.List; + +class CameraLatLngAnimator extends MapboxLatLngAnimator<MapboxAnimator.OnCameraAnimationsValuesChangeListener> { + CameraLatLngAnimator(LatLng previous, LatLng target, List<OnCameraAnimationsValuesChangeListener> updateListeners) { + super(previous, target, updateListeners); + } + + @Override + int provideAnimatorType() { + return ANIMATOR_CAMERA_LATLNG; + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + for (OnCameraAnimationsValuesChangeListener listener : updateListeners) { + listener.onNewLatLngValue((LatLng) animation.getAnimatedValue()); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CompassEngine.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CompassEngine.java new file mode 100644 index 000000000..3691bdc0e --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CompassEngine.java @@ -0,0 +1,65 @@ +package com.mapbox.mapboxsdk.location; + +import android.support.annotation.NonNull; + +import com.mapbox.mapboxsdk.location.modes.CameraMode; +import com.mapbox.mapboxsdk.location.modes.RenderMode; + +/** + * Interface defining the source of compass heading data that is + * consumed by the {@link LocationComponent} when in compass related + * {@link RenderMode} or + * {@link CameraMode}s. + */ +public interface CompassEngine { + + /** + * Adds a {@link CompassListener} that can be used to + * receive heading and state changes. + * + * @param compassListener to be added + */ + void addCompassListener(@NonNull CompassListener compassListener); + + /** + * Removes a {@link CompassListener} that can be used to + * receive heading and state changes. + * + * @param compassListener to be removed + */ + void removeCompassListener(@NonNull CompassListener compassListener); + + /** + * Returns the last heading value produced and pushed via + * a compass listener. + * + * @return last heading value + */ + float getLastHeading(); + + /** + * Provides the last know accuracy status from the sensor manager. + * <p> + * An integer value which is identical to the {@code SensorManager} class constants: + * <ul> + * <li>{@link android.hardware.SensorManager#SENSOR_STATUS_NO_CONTACT}</li> + * <li>{@link android.hardware.SensorManager#SENSOR_STATUS_UNRELIABLE}</li> + * <li>{@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_LOW}</li> + * <li>{@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_MEDIUM}</li> + * <li>{@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_HIGH}</li> + * </ul> + * + * @return last accuracy status + */ + int getLastAccuracySensorStatus(); + + /** + * Lifecycle method that can be used for adding or releasing resources. + */ + void onStart(); + + /** + * Lifecycle method that can be used for adding or releasing resources. + */ + void onStop(); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CompassListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CompassListener.java new file mode 100644 index 000000000..3e5eb7f25 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CompassListener.java @@ -0,0 +1,33 @@ +package com.mapbox.mapboxsdk.location; + +/** + * Callbacks related to the compass + */ +public interface CompassListener { + + /** + * Callback's invoked when a new compass update occurs. You can listen into the compass updates + * using {@link LocationComponent#addCompassListener(CompassListener)} and implementing these + * callbacks. Note that this interface is also used internally to to update the UI chevron/arrow. + * + * @param userHeading the new compass heading + */ + void onCompassChanged(float userHeading); + + /** + * This gets invoked when the compass accuracy status changes from one value to another. It + * provides an integer value which is identical to the {@code SensorManager} class constants: + * <ul> + * <li>{@link android.hardware.SensorManager#SENSOR_STATUS_NO_CONTACT}</li> + * <li>{@link android.hardware.SensorManager#SENSOR_STATUS_UNRELIABLE}</li> + * <li>{@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_LOW}</li> + * <li>{@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_MEDIUM}</li> + * <li>{@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_HIGH}</li> + * </ul> + * + * @param compassStatus the new accuracy of this sensor, one of + * {@code SensorManager.SENSOR_STATUS_*} + */ + void onCompassAccuracyChange(int compassStatus); +} + diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LatLngEvaluator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LatLngEvaluator.java new file mode 100644 index 000000000..fa966641f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LatLngEvaluator.java @@ -0,0 +1,19 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.TypeEvaluator; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +class LatLngEvaluator implements TypeEvaluator<LatLng> { + + private final LatLng latLng = new LatLng(); + + @Override + public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) { + latLng.setLatitude(startValue.getLatitude() + + ((endValue.getLatitude() - startValue.getLatitude()) * fraction)); + latLng.setLongitude(startValue.getLongitude() + + ((endValue.getLongitude() - startValue.getLongitude()) * fraction)); + return latLng; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerAccuracyAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerAccuracyAnimator.java new file mode 100644 index 000000000..e893f0fee --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerAccuracyAnimator.java @@ -0,0 +1,24 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.ValueAnimator; + +import java.util.List; + +class LayerAccuracyAnimator extends MapboxFloatAnimator<MapboxAnimator.OnLayerAnimationsValuesChangeListener> { + + LayerAccuracyAnimator(Float previous, Float target, List<OnLayerAnimationsValuesChangeListener> updateListeners) { + super(previous, target, updateListeners); + } + + @Override + int provideAnimatorType() { + return ANIMATOR_LAYER_ACCURACY; + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + for (OnLayerAnimationsValuesChangeListener listener : updateListeners) { + listener.onNewAccuracyRadiusValue((Float) animation.getAnimatedValue()); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerBitmapProvider.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerBitmapProvider.java new file mode 100644 index 000000000..6c9f063c1 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerBitmapProvider.java @@ -0,0 +1,33 @@ +package com.mapbox.mapboxsdk.location; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.support.annotation.ColorInt; +import android.support.annotation.DrawableRes; +import android.support.v4.content.ContextCompat; + +import com.mapbox.mapboxsdk.R; + +import static com.mapbox.mapboxsdk.location.Utils.generateShadow; +import static com.mapbox.mapboxsdk.location.Utils.getBitmapFromDrawable; +import static com.mapbox.mapboxsdk.location.Utils.getDrawable; + +class LayerBitmapProvider { + + private final Context context; + + LayerBitmapProvider(Context context) { + this.context = context; + } + + Bitmap generateBitmap(@DrawableRes int drawableRes, @ColorInt Integer tintColor) { + Drawable drawable = getDrawable(context, drawableRes, tintColor); + return getBitmapFromDrawable(drawable); + } + + Bitmap generateShadowBitmap(LocationComponentOptions options) { + Drawable shadowDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_user_icon_shadow); + return generateShadow(shadowDrawable, options.elevation()); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerCompassBearingAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerCompassBearingAnimator.java new file mode 100644 index 000000000..e75eaca2b --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerCompassBearingAnimator.java @@ -0,0 +1,24 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.ValueAnimator; + +import java.util.List; + +class LayerCompassBearingAnimator extends MapboxFloatAnimator<MapboxAnimator.OnLayerAnimationsValuesChangeListener> { + LayerCompassBearingAnimator(Float previous, + Float target, List<OnLayerAnimationsValuesChangeListener> updateListeners) { + super(previous, target, updateListeners); + } + + @Override + int provideAnimatorType() { + return ANIMATOR_LAYER_COMPASS_BEARING; + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + for (OnLayerAnimationsValuesChangeListener listener : updateListeners) { + listener.onNewCompassBearingValue((Float) animation.getAnimatedValue()); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerFeatureProvider.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerFeatureProvider.java new file mode 100644 index 000000000..0be38dc4d --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerFeatureProvider.java @@ -0,0 +1,26 @@ +package com.mapbox.mapboxsdk.location; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.mapbox.geojson.Feature; +import com.mapbox.geojson.Point; + +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_GPS_BEARING; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_LOCATION_STALE; + +class LayerFeatureProvider { + + @NonNull + Feature generateLocationFeature(@Nullable Feature locationFeature, LocationComponentOptions options) { + if (locationFeature != null) { + return locationFeature; + } + locationFeature = Feature.fromGeometry(Point.fromLngLat(0.0, 0.0)); + locationFeature.addNumberProperty(PROPERTY_GPS_BEARING, 0f); + locationFeature.addNumberProperty(PROPERTY_COMPASS_BEARING, 0f); + locationFeature.addBooleanProperty(PROPERTY_LOCATION_STALE, options.enableStaleState()); + return locationFeature; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerGpsBearingAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerGpsBearingAnimator.java new file mode 100644 index 000000000..75cea1375 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerGpsBearingAnimator.java @@ -0,0 +1,23 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.ValueAnimator; + +import java.util.List; + +class LayerGpsBearingAnimator extends MapboxFloatAnimator<MapboxAnimator.OnLayerAnimationsValuesChangeListener> { + LayerGpsBearingAnimator(Float previous, Float target, List<OnLayerAnimationsValuesChangeListener> updateListeners) { + super(previous, target, updateListeners); + } + + @Override + int provideAnimatorType() { + return ANIMATOR_LAYER_GPS_BEARING; + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + for (OnLayerAnimationsValuesChangeListener listener : updateListeners) { + listener.onNewGpsBearingValue((Float) animation.getAnimatedValue()); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerLatLngAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerLatLngAnimator.java new file mode 100644 index 000000000..f4dc2861c --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerLatLngAnimator.java @@ -0,0 +1,25 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.ValueAnimator; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.util.List; + +class LayerLatLngAnimator extends MapboxLatLngAnimator<MapboxAnimator.OnLayerAnimationsValuesChangeListener> { + LayerLatLngAnimator(LatLng previous, LatLng target, List<OnLayerAnimationsValuesChangeListener> updateListeners) { + super(previous, target, updateListeners); + } + + @Override + int provideAnimatorType() { + return ANIMATOR_LAYER_LATLNG; + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + for (OnLayerAnimationsValuesChangeListener listener : updateListeners) { + listener.onNewLatLngValue((LatLng) animation.getAnimatedValue()); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerSourceProvider.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerSourceProvider.java new file mode 100644 index 000000000..d6198a7da --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerSourceProvider.java @@ -0,0 +1,107 @@ +package com.mapbox.mapboxsdk.location; + +import com.mapbox.geojson.Feature; +import com.mapbox.mapboxsdk.style.layers.CircleLayer; +import com.mapbox.mapboxsdk.style.layers.Layer; +import com.mapbox.mapboxsdk.style.layers.Property; +import com.mapbox.mapboxsdk.style.layers.SymbolLayer; +import com.mapbox.mapboxsdk.style.sources.GeoJsonOptions; +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; + +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.ACCURACY_LAYER; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BACKGROUND_LAYER; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BEARING_LAYER; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.FOREGROUND_LAYER; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.LOCATION_SOURCE; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_ACCURACY_ALPHA; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_ACCURACY_COLOR; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_ACCURACY_RADIUS; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_BACKGROUND_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_BACKGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_BEARING_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_FOREGROUND_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_FOREGROUND_ICON_OFFSET; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_FOREGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_GPS_BEARING; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_LOCATION_STALE; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_SHADOW_ICON_OFFSET; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.SHADOW_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.SHADOW_LAYER; +import static com.mapbox.mapboxsdk.style.expressions.Expression.get; +import static com.mapbox.mapboxsdk.style.expressions.Expression.literal; +import static com.mapbox.mapboxsdk.style.expressions.Expression.match; +import static com.mapbox.mapboxsdk.style.expressions.Expression.stop; +import static com.mapbox.mapboxsdk.style.expressions.Expression.switchCase; +import static com.mapbox.mapboxsdk.style.layers.Property.ICON_ROTATION_ALIGNMENT_MAP; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleOpacity; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circlePitchAlignment; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleStrokeColor; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOffset; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconRotate; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconRotationAlignment; + +class LayerSourceProvider { + + private static final String EMPTY_STRING = ""; + + GeoJsonSource generateSource(Feature locationFeature) { + return new GeoJsonSource( + LOCATION_SOURCE, + locationFeature, + new GeoJsonOptions().withMaxZoom(16) + ); + } + + Layer generateLayer(String layerId) { + SymbolLayer layer = new SymbolLayer(layerId, LOCATION_SOURCE); + layer.setProperties( + iconAllowOverlap(true), + iconIgnorePlacement(true), + iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP), + iconRotate( + match(literal(layerId), literal(0f), + stop(FOREGROUND_LAYER, get(PROPERTY_GPS_BEARING)), + stop(BACKGROUND_LAYER, get(PROPERTY_GPS_BEARING)), + stop(SHADOW_LAYER, get(PROPERTY_GPS_BEARING)), + stop(BEARING_LAYER, get(PROPERTY_COMPASS_BEARING)) + ) + ), + iconImage( + match(literal(layerId), literal(EMPTY_STRING), + stop(FOREGROUND_LAYER, switchCase( + get(PROPERTY_LOCATION_STALE), get(PROPERTY_FOREGROUND_STALE_ICON), + get(PROPERTY_FOREGROUND_ICON))), + stop(BACKGROUND_LAYER, switchCase( + get(PROPERTY_LOCATION_STALE), get(PROPERTY_BACKGROUND_STALE_ICON), + get(PROPERTY_BACKGROUND_ICON))), + stop(SHADOW_LAYER, literal(SHADOW_ICON)), + stop(BEARING_LAYER, get(PROPERTY_BEARING_ICON)) + ) + ), + iconOffset( + match(literal(layerId), literal(new Float[] {0f, 0f}), + stop(literal(FOREGROUND_LAYER), get(PROPERTY_FOREGROUND_ICON_OFFSET)), + stop(literal(SHADOW_LAYER), get(PROPERTY_SHADOW_ICON_OFFSET)) + ) + ) + ); + return layer; + } + + Layer generateAccuracyLayer() { + return new CircleLayer(ACCURACY_LAYER, LOCATION_SOURCE) + .withProperties( + circleRadius(get(PROPERTY_ACCURACY_RADIUS)), + circleColor(get(PROPERTY_ACCURACY_COLOR)), + circleOpacity(get(PROPERTY_ACCURACY_ALPHA)), + circleStrokeColor(get(PROPERTY_ACCURACY_COLOR)), + circlePitchAlignment(Property.CIRCLE_PITCH_ALIGNMENT_MAP) + ); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinator.java new file mode 100644 index 000000000..b8baa0d49 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinator.java @@ -0,0 +1,373 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.location.Location; +import android.os.SystemClock; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.SparseArray; +import android.view.animation.LinearInterpolator; + +import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.maps.MapboxMap; + +import java.util.ArrayList; +import java.util.List; + +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.ACCURACY_RADIUS_ANIMATION_DURATION; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.COMPASS_UPDATE_RATE_MS; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.MAX_ANIMATION_DURATION_MS; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.TRANSITION_ANIMATION_DURATION_MS; +import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_CAMERA_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_CAMERA_GPS_BEARING; +import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_CAMERA_LATLNG; +import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_ACCURACY; +import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_GPS_BEARING; +import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_LATLNG; +import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_TILT; +import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_ZOOM; + +final class LocationAnimatorCoordinator { + + final SparseArray<MapboxAnimator> animatorArray = new SparseArray<>(); + + final List<MapboxAnimator.OnLayerAnimationsValuesChangeListener> layerListeners = new ArrayList<>(); + final List<MapboxAnimator.OnCameraAnimationsValuesChangeListener> cameraListeners = new ArrayList<>(); + + private Location previousLocation; + private float previousAccuracyRadius = -1; + private float previousCompassBearing = -1; + private long locationUpdateTimestamp = -1; + + void addLayerListener(MapboxAnimator.OnLayerAnimationsValuesChangeListener listener) { + layerListeners.add(listener); + } + + void removeLayerListener(MapboxAnimator.OnLayerAnimationsValuesChangeListener listener) { + layerListeners.remove(listener); + } + + void addCameraListener(MapboxAnimator.OnCameraAnimationsValuesChangeListener listener) { + cameraListeners.add(listener); + } + + void removeCameraListener(MapboxAnimator.OnCameraAnimationsValuesChangeListener listener) { + cameraListeners.remove(listener); + } + + void feedNewLocation(@NonNull Location newLocation, @NonNull CameraPosition currentCameraPosition, + boolean isGpsNorth) { + if (previousLocation == null) { + previousLocation = newLocation; + locationUpdateTimestamp = SystemClock.elapsedRealtime() - TRANSITION_ANIMATION_DURATION_MS; + } + + LatLng previousLayerLatLng = getPreviousLayerLatLng(); + float previousLayerBearing = getPreviousLayerGpsBearing(); + LatLng previousCameraLatLng = currentCameraPosition.target; + float previousCameraBearing = (float) currentCameraPosition.bearing; + + LatLng targetLatLng = new LatLng(newLocation); + float targetLayerBearing = newLocation.getBearing(); + float targetCameraBearing = newLocation.getBearing(); + targetCameraBearing = checkGpsNorth(isGpsNorth, targetCameraBearing); + + updateLayerAnimators(previousLayerLatLng, targetLatLng, previousLayerBearing, targetLayerBearing); + updateCameraAnimators(previousCameraLatLng, previousCameraBearing, targetLatLng, targetCameraBearing); + + playLocationAnimators(getAnimationDuration()); + + previousLocation = newLocation; + } + + void feedNewCompassBearing(float targetCompassBearing, @NonNull CameraPosition currentCameraPosition) { + if (previousCompassBearing < 0) { + previousCompassBearing = targetCompassBearing; + } + + float previousLayerBearing = getPreviousLayerCompassBearing(); + float previousCameraBearing = (float) currentCameraPosition.bearing; + + updateCompassAnimators(targetCompassBearing, previousLayerBearing, previousCameraBearing); + playCompassAnimators(COMPASS_UPDATE_RATE_MS); + + previousCompassBearing = targetCompassBearing; + } + + void feedNewAccuracyRadius(float targetAccuracyRadius, boolean noAnimation) { + if (previousAccuracyRadius < 0) { + previousAccuracyRadius = targetAccuracyRadius; + } + + float previousAccuracyRadius = getPreviousAccuracyRadius(); + updateAccuracyAnimators(targetAccuracyRadius, previousAccuracyRadius); + playAccuracyAnimator(noAnimation ? 0 : ACCURACY_RADIUS_ANIMATION_DURATION); + + this.previousAccuracyRadius = targetAccuracyRadius; + } + + void feedNewZoomLevel(double targetZoomLevel, @NonNull CameraPosition currentCameraPosition, long animationDuration, + @Nullable MapboxMap.CancelableCallback callback) { + updateZoomAnimator((float) targetZoomLevel, (float) currentCameraPosition.zoom, callback); + playZoomAnimator(animationDuration); + } + + void feedNewTilt(double targetTilt, @NonNull CameraPosition currentCameraPosition, long animationDuration, + @Nullable MapboxMap.CancelableCallback callback) { + updateTiltAnimator((float) targetTilt, (float) currentCameraPosition.tilt, callback); + playTiltAnimator(animationDuration); + } + + private LatLng getPreviousLayerLatLng() { + LatLng previousLatLng; + MapboxAnimator latLngAnimator = animatorArray.get(ANIMATOR_LAYER_LATLNG); + if (latLngAnimator != null) { + previousLatLng = (LatLng) latLngAnimator.getAnimatedValue(); + } else { + previousLatLng = new LatLng(previousLocation); + } + return previousLatLng; + } + + private float getPreviousLayerGpsBearing() { + LayerGpsBearingAnimator animator = (LayerGpsBearingAnimator) animatorArray.get(ANIMATOR_LAYER_GPS_BEARING); + float previousBearing; + if (animator != null) { + previousBearing = (float) animator.getAnimatedValue(); + } else { + previousBearing = previousLocation.getBearing(); + } + return previousBearing; + } + + private float getPreviousLayerCompassBearing() { + LayerCompassBearingAnimator animator = + (LayerCompassBearingAnimator) animatorArray.get(ANIMATOR_LAYER_COMPASS_BEARING); + + float previousBearing; + if (animator != null) { + previousBearing = (float) animator.getAnimatedValue(); + } else { + previousBearing = previousCompassBearing; + } + return previousBearing; + } + + private float getPreviousAccuracyRadius() { + LayerAccuracyAnimator animator = (LayerAccuracyAnimator) animatorArray.get(ANIMATOR_LAYER_ACCURACY); + float previousRadius; + if (animator != null) { + previousRadius = (float) animator.getAnimatedValue(); + } else { + previousRadius = previousAccuracyRadius; + } + return previousRadius; + } + + private void updateLayerAnimators(LatLng previousLatLng, LatLng targetLatLng, + float previousBearing, float targetBearing) { + createNewAnimator(ANIMATOR_LAYER_LATLNG, new LayerLatLngAnimator(previousLatLng, targetLatLng, layerListeners)); + + float normalizedLayerBearing = Utils.shortestRotation(targetBearing, previousBearing); + createNewAnimator(ANIMATOR_LAYER_GPS_BEARING, + new LayerGpsBearingAnimator(previousBearing, normalizedLayerBearing, layerListeners)); + } + + private void updateCameraAnimators(LatLng previousCameraLatLng, float previousCameraBearing, + LatLng targetLatLng, float targetBearing) { + createNewAnimator(ANIMATOR_CAMERA_LATLNG, + new CameraLatLngAnimator(previousCameraLatLng, targetLatLng, cameraListeners)); + + float normalizedCameraBearing = Utils.shortestRotation(targetBearing, previousCameraBearing); + createNewAnimator(ANIMATOR_CAMERA_GPS_BEARING, + new CameraGpsBearingAnimator(previousCameraBearing, normalizedCameraBearing, cameraListeners)); + } + + private void updateCompassAnimators(float targetCompassBearing, float previousLayerBearing, + float previousCameraBearing) { + float normalizedLayerBearing = Utils.shortestRotation(targetCompassBearing, previousLayerBearing); + createNewAnimator(ANIMATOR_LAYER_COMPASS_BEARING, + new LayerCompassBearingAnimator(previousLayerBearing, normalizedLayerBearing, layerListeners)); + + float normalizedCameraBearing = Utils.shortestRotation(targetCompassBearing, previousCameraBearing); + createNewAnimator(ANIMATOR_CAMERA_COMPASS_BEARING, + new CameraCompassBearingAnimator(previousCameraBearing, normalizedCameraBearing, cameraListeners)); + } + + private void updateAccuracyAnimators(float targetAccuracyRadius, float previousAccuracyRadius) { + createNewAnimator(ANIMATOR_LAYER_ACCURACY, + new LayerAccuracyAnimator(previousAccuracyRadius, targetAccuracyRadius, layerListeners)); + } + + private void updateZoomAnimator(float targetZoomLevel, float previousZoomLevel, + @Nullable MapboxMap.CancelableCallback cancelableCallback) { + createNewAnimator(ANIMATOR_ZOOM, + new ZoomAnimator(previousZoomLevel, targetZoomLevel, cameraListeners, cancelableCallback)); + } + + private void updateTiltAnimator(float targetTilt, float previousTiltLevel, + @Nullable MapboxMap.CancelableCallback cancelableCallback) { + createNewAnimator(ANIMATOR_TILT, + new TiltAnimator(previousTiltLevel, targetTilt, cameraListeners, cancelableCallback)); + } + + private long getAnimationDuration() { + long previousUpdateTimeStamp = locationUpdateTimestamp; + locationUpdateTimestamp = SystemClock.elapsedRealtime(); + + long animationDuration; + if (previousUpdateTimeStamp == 0) { + animationDuration = 0; + } else { + animationDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.1f) + /*make animation slightly longer*/; + } + + animationDuration = Math.min(animationDuration, MAX_ANIMATION_DURATION_MS); + + return animationDuration; + } + + private float checkGpsNorth(boolean isGpsNorth, float targetCameraBearing) { + if (isGpsNorth) { + targetCameraBearing = 0; + } + return targetCameraBearing; + } + + private void playLocationAnimators(long duration) { + List<Animator> locationAnimators = new ArrayList<>(); + locationAnimators.add(animatorArray.get(ANIMATOR_LAYER_LATLNG)); + locationAnimators.add(animatorArray.get(ANIMATOR_LAYER_GPS_BEARING)); + locationAnimators.add(animatorArray.get(ANIMATOR_CAMERA_LATLNG)); + locationAnimators.add(animatorArray.get(ANIMATOR_CAMERA_GPS_BEARING)); + AnimatorSet locationAnimatorSet = new AnimatorSet(); + locationAnimatorSet.playTogether(locationAnimators); + locationAnimatorSet.setInterpolator(new LinearInterpolator()); + locationAnimatorSet.setDuration(duration); + locationAnimatorSet.start(); + } + + private void playCompassAnimators(long duration) { + List<Animator> compassAnimators = new ArrayList<>(); + compassAnimators.add(animatorArray.get(ANIMATOR_LAYER_COMPASS_BEARING)); + compassAnimators.add(animatorArray.get(ANIMATOR_CAMERA_COMPASS_BEARING)); + AnimatorSet compassAnimatorSet = new AnimatorSet(); + compassAnimatorSet.playTogether(compassAnimators); + compassAnimatorSet.setDuration(duration); + compassAnimatorSet.start(); + } + + private void playAccuracyAnimator(long duration) { + MapboxAnimator animator = animatorArray.get(ANIMATOR_LAYER_ACCURACY); + animator.setDuration(duration); + animator.start(); + } + + private void playZoomAnimator(long duration) { + MapboxAnimator animator = animatorArray.get(ANIMATOR_ZOOM); + animator.setDuration(duration); + animator.start(); + } + + private void playTiltAnimator(long duration) { + MapboxAnimator animator = animatorArray.get(ANIMATOR_TILT); + animator.setDuration(duration); + animator.start(); + } + + private void playCameraLocationAnimators(long duration) { + List<Animator> locationAnimators = new ArrayList<>(); + locationAnimators.add(animatorArray.get(ANIMATOR_CAMERA_LATLNG)); + locationAnimators.add(animatorArray.get(ANIMATOR_CAMERA_GPS_BEARING)); + AnimatorSet locationAnimatorSet = new AnimatorSet(); + locationAnimatorSet.playTogether(locationAnimators); + locationAnimatorSet.setInterpolator(new LinearInterpolator()); + locationAnimatorSet.setDuration(duration); + locationAnimatorSet.start(); + } + + void resetAllCameraAnimations(CameraPosition currentCameraPosition, boolean isGpsNorth) { + resetCameraCompassAnimation(currentCameraPosition); + resetCameraLocationAnimations(currentCameraPosition, isGpsNorth); + playCameraLocationAnimators(TRANSITION_ANIMATION_DURATION_MS); + } + + private void resetCameraLocationAnimations(CameraPosition currentCameraPosition, boolean isGpsNorth) { + resetCameraLatLngAnimation(currentCameraPosition); + resetCameraGpsBearingAnimation(currentCameraPosition, isGpsNorth); + } + + private void resetCameraLatLngAnimation(CameraPosition currentCameraPosition) { + CameraLatLngAnimator animator = (CameraLatLngAnimator) animatorArray.get(ANIMATOR_CAMERA_LATLNG); + if (animator == null) { + return; + } + + LatLng currentTarget = animator.getTarget(); + LatLng previousCameraTarget = currentCameraPosition.target; + createNewAnimator(ANIMATOR_CAMERA_LATLNG, + new CameraLatLngAnimator(previousCameraTarget, currentTarget, cameraListeners)); + } + + private void resetCameraGpsBearingAnimation(CameraPosition currentCameraPosition, boolean isGpsNorth) { + CameraGpsBearingAnimator animator = (CameraGpsBearingAnimator) animatorArray.get(ANIMATOR_CAMERA_GPS_BEARING); + if (animator == null) { + return; + } + + float currentTargetBearing = animator.getTarget(); + currentTargetBearing = checkGpsNorth(isGpsNorth, currentTargetBearing); + float previousCameraBearing = (float) currentCameraPosition.bearing; + float normalizedCameraBearing = Utils.shortestRotation(currentTargetBearing, previousCameraBearing); + createNewAnimator(ANIMATOR_CAMERA_GPS_BEARING, + new CameraGpsBearingAnimator(previousCameraBearing, normalizedCameraBearing, cameraListeners)); + } + + private void resetCameraCompassAnimation(CameraPosition currentCameraPosition) { + CameraCompassBearingAnimator animator = + (CameraCompassBearingAnimator) animatorArray.get(ANIMATOR_CAMERA_COMPASS_BEARING); + if (animator == null) { + return; + } + + float currentTargetBearing = animator.getTarget(); + float previousCameraBearing = (float) currentCameraPosition.bearing; + float normalizedCameraBearing = Utils.shortestRotation(currentTargetBearing, previousCameraBearing); + createNewAnimator(ANIMATOR_CAMERA_COMPASS_BEARING, + new CameraCompassBearingAnimator(previousCameraBearing, normalizedCameraBearing, cameraListeners)); + } + + private void createNewAnimator(@MapboxAnimator.Type int animatorType, MapboxAnimator animator) { + cancelAnimator(animatorType); + animatorArray.put(animatorType, animator); + } + + void cancelZoomAnimation() { + cancelAnimator(ANIMATOR_ZOOM); + } + + void cancelTiltAnimation() { + cancelAnimator(ANIMATOR_TILT); + } + + void cancelAllAnimations() { + for (int i = 0; i < animatorArray.size(); i++) { + @MapboxAnimator.Type int animatorType = animatorArray.keyAt(i); + cancelAnimator(animatorType); + } + } + + private void cancelAnimator(@MapboxAnimator.Type int animatorType) { + MapboxAnimator animator = animatorArray.get(animatorType); + if (animator != null) { + animator.cancel(); + animator.removeAllUpdateListeners(); + animator.removeAllListeners(); + animatorArray.put(animatorType, null); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java new file mode 100644 index 000000000..501bb95f8 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java @@ -0,0 +1,266 @@ +package com.mapbox.mapboxsdk.location; + +import android.content.Context; +import android.graphics.PointF; +import android.support.annotation.NonNull; +import android.view.MotionEvent; + +import com.mapbox.android.gestures.AndroidGesturesManager; +import com.mapbox.android.gestures.MoveGestureDetector; +import com.mapbox.android.gestures.RotateGestureDetector; +import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.location.modes.CameraMode; +import com.mapbox.mapboxsdk.maps.MapboxMap; + +final class LocationCameraController implements MapboxAnimator.OnCameraAnimationsValuesChangeListener { + + @CameraMode.Mode + private int cameraMode; + + private final MapboxMap mapboxMap; + private final OnCameraTrackingChangedListener internalCameraTrackingChangedListener; + private LocationComponentOptions options; + private boolean adjustFocalPoint; + + private final MoveGestureDetector moveGestureDetector; + private final OnCameraMoveInvalidateListener onCameraMoveInvalidateListener; + + private final AndroidGesturesManager initialGesturesManager; + private final AndroidGesturesManager internalGesturesManager; + + LocationCameraController( + Context context, + MapboxMap mapboxMap, + OnCameraTrackingChangedListener internalCameraTrackingChangedListener, + LocationComponentOptions options, + OnCameraMoveInvalidateListener onCameraMoveInvalidateListener) { + this.mapboxMap = mapboxMap; + + initialGesturesManager = mapboxMap.getGesturesManager(); + internalGesturesManager = new LocationGesturesManager(context); + moveGestureDetector = internalGesturesManager.getMoveGestureDetector(); + mapboxMap.addOnRotateListener(onRotateListener); + mapboxMap.addOnFlingListener(onFlingListener); + mapboxMap.addOnMoveListener(onMoveListener); + + this.internalCameraTrackingChangedListener = internalCameraTrackingChangedListener; + this.onCameraMoveInvalidateListener = onCameraMoveInvalidateListener; + initializeOptions(options); + } + + // Package private for testing purposes + LocationCameraController(MapboxMap mapboxMap, + MoveGestureDetector moveGestureDetector, + OnCameraTrackingChangedListener internalCameraTrackingChangedListener, + OnCameraMoveInvalidateListener onCameraMoveInvalidateListener, + AndroidGesturesManager initialGesturesManager, + AndroidGesturesManager internalGesturesManager) { + this.mapboxMap = mapboxMap; + this.moveGestureDetector = moveGestureDetector; + this.internalCameraTrackingChangedListener = internalCameraTrackingChangedListener; + this.onCameraMoveInvalidateListener = onCameraMoveInvalidateListener; + this.internalGesturesManager = internalGesturesManager; + this.initialGesturesManager = initialGesturesManager; + } + + void initializeOptions(LocationComponentOptions options) { + this.options = options; + if (options.trackingGesturesManagement()) { + mapboxMap.setGesturesManager(internalGesturesManager, true, true); + adjustGesturesThresholds(); + } else { + mapboxMap.setGesturesManager(initialGesturesManager, true, true); + } + } + + void setCameraMode(@CameraMode.Mode int cameraMode) { + final boolean wasTracking = isLocationTracking(); + this.cameraMode = cameraMode; + mapboxMap.cancelTransitions(); + adjustGesturesThresholds(); + notifyCameraTrackingChangeListener(wasTracking); + } + + int getCameraMode() { + return cameraMode; + } + + private void setBearing(float bearing) { + mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing)); + onCameraMoveInvalidateListener.onInvalidateCameraMove(); + } + + private void setLatLng(LatLng latLng) { + mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)); + onCameraMoveInvalidateListener.onInvalidateCameraMove(); + } + + private void setZoom(float zoom) { + mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(zoom)); + onCameraMoveInvalidateListener.onInvalidateCameraMove(); + } + + private void setTilt(float tilt) { + mapboxMap.moveCamera(CameraUpdateFactory.tiltTo(tilt)); + onCameraMoveInvalidateListener.onInvalidateCameraMove(); + } + + @Override + public void onNewLatLngValue(LatLng latLng) { + if (cameraMode == CameraMode.TRACKING + || cameraMode == CameraMode.TRACKING_COMPASS + || cameraMode == CameraMode.TRACKING_GPS + || cameraMode == CameraMode.TRACKING_GPS_NORTH) { + setLatLng(latLng); + + if (adjustFocalPoint) { + PointF focalPoint = mapboxMap.getProjection().toScreenLocation(latLng); + mapboxMap.getUiSettings().setFocalPoint(focalPoint); + adjustFocalPoint = false; + } + } + } + + @Override + public void onNewGpsBearingValue(float gpsBearing) { + boolean trackingNorth = cameraMode == CameraMode.TRACKING_GPS_NORTH + && mapboxMap.getCameraPosition().bearing != 0; + + if (cameraMode == CameraMode.TRACKING_GPS + || cameraMode == CameraMode.NONE_GPS + || trackingNorth) { + setBearing(gpsBearing); + } + } + + @Override + public void onNewCompassBearingValue(float compassBearing) { + if (cameraMode == CameraMode.TRACKING_COMPASS + || cameraMode == CameraMode.NONE_COMPASS) { + setBearing(compassBearing); + } + } + + @Override + public void onNewZoomValue(float zoom) { + setZoom(zoom); + } + + @Override + public void onNewTiltValue(float tilt) { + setTilt(tilt); + } + + private void adjustGesturesThresholds() { + if (options.trackingGesturesManagement()) { + if (isLocationTracking()) { + adjustFocalPoint = true; + moveGestureDetector.setMoveThreshold(options.trackingInitialMoveThreshold()); + } else { + moveGestureDetector.setMoveThreshold(0f); + } + } + } + + private boolean isLocationTracking() { + return cameraMode == CameraMode.TRACKING + || cameraMode == CameraMode.TRACKING_COMPASS + || cameraMode == CameraMode.TRACKING_GPS + || cameraMode == CameraMode.TRACKING_GPS_NORTH; + } + + private boolean isBearingTracking() { + return cameraMode == CameraMode.NONE_COMPASS + || cameraMode == CameraMode.TRACKING_COMPASS + || cameraMode == CameraMode.NONE_GPS + || cameraMode == CameraMode.TRACKING_GPS + || cameraMode == CameraMode.TRACKING_GPS_NORTH; + } + + private void notifyCameraTrackingChangeListener(boolean wasTracking) { + internalCameraTrackingChangedListener.onCameraTrackingChanged(cameraMode); + if (wasTracking && !isLocationTracking()) { + mapboxMap.getUiSettings().setFocalPoint(null); + internalCameraTrackingChangedListener.onCameraTrackingDismissed(); + } + } + + private MapboxMap.OnMoveListener onMoveListener = new MapboxMap.OnMoveListener() { + private boolean interrupt; + + @Override + public void onMoveBegin(@NonNull MoveGestureDetector detector) { + if (options.trackingGesturesManagement() + && detector.getPointersCount() > 1 + && detector.getMoveThreshold() != options.trackingMultiFingerMoveThreshold() + && isLocationTracking()) { + detector.setMoveThreshold(options.trackingMultiFingerMoveThreshold()); + interrupt = true; + } else { + setCameraMode(CameraMode.NONE); + } + } + + @Override + public void onMove(@NonNull MoveGestureDetector detector) { + if (interrupt) { + detector.interrupt(); + return; + } + setCameraMode(CameraMode.NONE); + } + + @Override + public void onMoveEnd(@NonNull MoveGestureDetector detector) { + if (options.trackingGesturesManagement() && !interrupt && isLocationTracking()) { + detector.setMoveThreshold(options.trackingInitialMoveThreshold()); + } + interrupt = false; + } + }; + + private MapboxMap.OnRotateListener onRotateListener = new MapboxMap.OnRotateListener() { + @Override + public void onRotateBegin(@NonNull RotateGestureDetector detector) { + if (isBearingTracking()) { + setCameraMode(CameraMode.NONE); + } + } + + @Override + public void onRotate(@NonNull RotateGestureDetector detector) { + // no implementation + } + + @Override + public void onRotateEnd(@NonNull RotateGestureDetector detector) { + // no implementation + } + }; + + private MapboxMap.OnFlingListener onFlingListener = new MapboxMap.OnFlingListener() { + @Override + public void onFling() { + setCameraMode(CameraMode.NONE); + } + }; + + private class LocationGesturesManager extends AndroidGesturesManager { + + LocationGesturesManager(Context context) { + super(context); + } + + @Override + public boolean onTouchEvent(MotionEvent motionEvent) { + if (motionEvent != null) { + int action = motionEvent.getActionMasked(); + if (action == MotionEvent.ACTION_UP) { + adjustGesturesThresholds(); + } + } + return super.onTouchEvent(motionEvent); + } + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java new file mode 100644 index 000000000..01ef314bf --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java @@ -0,0 +1,1000 @@ +package com.mapbox.mapboxsdk.location; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.hardware.SensorManager; +import android.location.Location; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresPermission; +import android.support.annotation.StyleRes; +import android.support.v7.app.AppCompatDelegate; +import android.view.WindowManager; + +import com.mapbox.android.core.location.LocationEngine; +import com.mapbox.android.core.location.LocationEngineListener; +import com.mapbox.android.core.location.LocationEnginePriority; +import com.mapbox.android.core.location.LocationEngineProvider; +import com.mapbox.mapboxsdk.R; +import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.camera.CameraUpdate; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.location.modes.CameraMode; +import com.mapbox.mapboxsdk.location.modes.RenderMode; +import com.mapbox.mapboxsdk.log.Logger; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraIdleListener; +import com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveListener; +import com.mapbox.mapboxsdk.maps.MapboxMap.OnMapClickListener; + +import java.util.concurrent.CopyOnWriteArrayList; + +import static android.Manifest.permission.ACCESS_COARSE_LOCATION; +import static android.Manifest.permission.ACCESS_FINE_LOCATION; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.DEFAULT_TRACKING_TILT_ANIM_DURATION; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.DEFAULT_TRACKING_ZOOM_ANIM_DURATION; + +/** + * The Location Component provides location awareness to your mobile application. Enabling this + * component provides a contextual experience to your users by showing an icon representing the users + * current location. A few different modes are offered to provide the right context to your users at + * the correct time. {@link RenderMode#NORMAL} simply shows the users location on the map + * represented as a dot. {@link RenderMode#COMPASS} mode allows you to display an arrow icon + * (by default) that points in the direction the device is pointing in. + * {@link RenderMode#GPS} can be used in conjunction with our Navigation SDK to + * display a larger icon (customized with {@link LocationComponentOptions#gpsDrawable()}) we call the user puck. + * <p> + * This component also offers the ability to set a map camera behavior for tracking the user + * location. These different {@link CameraMode}s will track, stop tracking the location based on the + * mode set with {@link LocationComponent#setCameraMode(int)}. + * <p> + * <strong> + * To get the component object use {@link MapboxMap#getLocationComponent()} and activate it with + * {@link #activateLocationComponent(Context)} or one of the overloads. + * Then, manage its visibility with {@link #setLocationComponentEnabled(boolean)}. + * </strong> + * <p> + * Using this component requires you to request permission beforehand manually or using + * {@link com.mapbox.android.core.permissions.PermissionsManager}. Either + * {@code ACCESS_COARSE_LOCATION} or {@code ACCESS_FINE_LOCATION} permissions can be requested and + * this plugin work as expected. + * <p> + * This component offers a default, built-in {@link LocationEngine} with some of the activation methods. + * This engine will be obtained by {@link LocationEngineProvider#obtainBestLocationEngineAvailable} which defaults + * to the {@link com.mapbox.android.core.location.AndroidLocationEngine}. If you'd like to utilize Google Play Services + * for more precise location updates, simply add the Google Play Location Services dependency in your build script. + * This will make the default engine the {@link com.mapbox.android.core.location.GoogleLocationEngine} instead. + * <p> + * When activating the component for the first time, the map's max/min zoom levels will be set to + * {@link LocationComponentOptions#MAX_ZOOM_DEFAULT} and {@link LocationComponentOptions#MIN_ZOOM_DEFAULT} respectively. + * You can adjust the zoom range with {@link LocationComponentOptions#maxZoom()} and + * {@link LocationComponentOptions#minZoom()}. + * <p> + * Location Component doesn't support state saving out-of-the-box. + */ +public final class LocationComponent { + private static final String TAG = "Mbgl-LocationComponent"; + + private final MapboxMap mapboxMap; + private LocationComponentOptions options; + private LocationEngine locationEngine; + private CompassEngine compassEngine; + private boolean usingInternalLocationEngine; + + private LocationLayerController locationLayerController; + private LocationCameraController locationCameraController; + + private LocationAnimatorCoordinator locationAnimatorCoordinator; + + /** + * Holds last location which is being returned in the {@link #getLastKnownLocation()} + * when there is no {@link #locationEngine} set or when the last location returned by the engine is null. + */ + private Location lastLocation; + private CameraPosition lastCameraPosition; + + /** + * Indicates whether the component has been initialized. + */ + private boolean isInitialized; + + /** + * Indicates that the component is enabled and should be displaying location if Mapbox components are available and + * the lifecycle is in a started state. + */ + private boolean isEnabled; + + /** + * Indicated that component's lifecycle {@link #onStart()} method has been called. + * This allows Mapbox components enter started state and display data, and adds state safety for methods like + * {@link #setLocationComponentEnabled(boolean)} + */ + private boolean isComponentStarted; + + /** + * Indicates if Mapbox components are ready to be interacted with. This can differ from {@link #isComponentStarted} + * if the Mapbox style is being reloaded. + */ + private boolean isLayerReady; + + private StaleStateManager staleStateManager; + private final CopyOnWriteArrayList<OnLocationStaleListener> onLocationStaleListeners + = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList<OnLocationClickListener> onLocationClickListeners + = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList<OnLocationLongClickListener> onLocationLongClickListeners + = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList<OnCameraTrackingChangedListener> onCameraTrackingChangedListeners + = new CopyOnWriteArrayList<>(); + + /** + * Internal use. + * <p> + * To get the component object use {@link MapboxMap#getLocationComponent()}. + */ + public LocationComponent(@NonNull MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + } + + /** + * This method initializes the component and needs to be called before any other operations are performed. + * Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}. + * <p> + * <strong>Note</strong>: This method will initialize and use an internal {@link LocationEngine} when enabled. + * + * @param context the context + */ + @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}) + public void activateLocationComponent(@NonNull Context context) { + activateLocationComponent(context, LocationComponentOptions.createFromAttributes(context, R.style + .mapbox_LocationComponent)); + } + + /** + * This method initializes the component and needs to be called before any other operations are performed. + * Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}. + * + * @param context the context + * @param useDefaultLocationEngine true if you want to initialize and use the built-in location engine or false if + * there should be no location engine initialized + */ + @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}) + public void activateLocationComponent(@NonNull Context context, boolean useDefaultLocationEngine) { + if (useDefaultLocationEngine) { + activateLocationComponent(context, R.style.mapbox_LocationComponent); + } else { + activateLocationComponent(context, null, R.style.mapbox_LocationComponent); + } + } + + /** + * This method initializes the component and needs to be called before any other operations are performed. + * Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}. + * <p> + * <strong>Note</strong>: This method will initialize and use an internal {@link LocationEngine} when enabled. + * + * @param context the context + * @param styleRes the LocationComponent style res + */ + @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}) + public void activateLocationComponent(@NonNull Context context, @StyleRes int styleRes) { + activateLocationComponent(context, LocationComponentOptions.createFromAttributes(context, styleRes)); + } + + /** + * This method initializes the component and needs to be called before any other operations are performed. + * Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}. + * <p> + * <strong>Note</strong>: This method will initialize and use an internal {@link LocationEngine} when enabled. + * </p> + * + * @param context the context + * @param options the options + */ + @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}) + public void activateLocationComponent(@NonNull Context context, @NonNull LocationComponentOptions options) { + initialize(context, options); + initializeLocationEngine(context); + applyStyle(options); + } + + /** + * This method initializes the component and needs to be called before any other operations are performed. + * Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}. + * + * @param context the context + * @param locationEngine the engine, or null if you'd like to only force location updates + * @param styleRes the LocationComponent style res + */ + public void activateLocationComponent(@NonNull Context context, @Nullable LocationEngine locationEngine, + @StyleRes int styleRes) { + activateLocationComponent(context, locationEngine, + LocationComponentOptions.createFromAttributes(context, styleRes)); + } + + /** + * This method will show the location icon and enable the camera tracking the location. + * + * @param context the context + * @param locationEngine the engine + */ + public void activateLocationComponent(@NonNull Context context, @NonNull LocationEngine locationEngine) { + activateLocationComponent(context, locationEngine, R.style.mapbox_LocationComponent); + } + + /** + * This method initializes the component and needs to be called before any other operations are performed. + * Afterwards, you can manage component's visibility by {@link #setLocationComponentEnabled(boolean)}. + * + * @param locationEngine the engine, or null if you'd like to only force location updates + * @param options the options + */ + public void activateLocationComponent(@NonNull Context context, @Nullable LocationEngine locationEngine, + @NonNull LocationComponentOptions options) { + initialize(context, options); + setLocationEngine(locationEngine); + applyStyle(options); + } + + /** + * Manage component's visibility after activation. + * + * @param isEnabled true if the plugin should be visible and listen for location updates, false otherwise. + */ + public void setLocationComponentEnabled(boolean isEnabled) { + if (isEnabled) { + enableLocationComponent(); + } else { + disableLocationComponent(); + } + } + + /** + * Returns whether the plugin is enabled, meaning that location can be displayed and camera modes can be used. + * + * @return true if the plugin is enabled, false otherwise + */ + public boolean isLocationComponentEnabled() { + return isEnabled; + } + + /** + * Sets the camera mode, which determines how the map camera will track the rendered location. + * <p> + * <ul> + * <li>{@link CameraMode#NONE}: No camera tracking</li> + * <li>{@link CameraMode#NONE_COMPASS}: Camera does not track location, but does track compass bearing</li> + * <li>{@link CameraMode#NONE_GPS}: Camera does not track location, but does track GPS bearing</li> + * <li>{@link CameraMode#TRACKING}: Camera tracks the user location</li> + * <li>{@link CameraMode#TRACKING_COMPASS}: Camera tracks the user location, with bearing provided by a compass</li> + * <li>{@link CameraMode#TRACKING_GPS}: Camera tracks the user location, with normalized bearing</li> + * <li>{@link CameraMode#TRACKING_GPS_NORTH}: Camera tracks the user location, with bearing always set to north</li> + * </ul> + * + * @param cameraMode one of the modes found in {@link CameraMode} + */ + public void setCameraMode(@CameraMode.Mode int cameraMode) { + locationCameraController.setCameraMode(cameraMode); + boolean isGpsNorth = cameraMode == CameraMode.TRACKING_GPS_NORTH; + locationAnimatorCoordinator.resetAllCameraAnimations(mapboxMap.getCameraPosition(), isGpsNorth); + } + + /** + * Provides the current camera mode being used to track the location or compass updates. + * + * @return the current camera mode + */ + @CameraMode.Mode + public int getCameraMode() { + return locationCameraController.getCameraMode(); + } + + /** + * Sets the render mode, which determines how the location updates will be rendered on the map. + * <p> + * <ul> + * <li>{@link RenderMode#NORMAL}: Shows user location, bearing ignored</li> + * <li>{@link RenderMode#COMPASS}: Shows user location with bearing considered from compass</li> + * <li>{@link RenderMode#GPS}: Shows user location with bearing considered from location</li> + * </ul> + * + * @param renderMode one of the modes found in {@link RenderMode} + */ + public void setRenderMode(@RenderMode.Mode int renderMode) { + locationLayerController.setRenderMode(renderMode); + updateLayerOffsets(true); + } + + /** + * Provides the current render mode being used to show + * the location and/or compass updates on the map. + * + * @return the current render mode + */ + @RenderMode.Mode + public int getRenderMode() { + return locationLayerController.getRenderMode(); + } + + /** + * Returns the current location options being used. + * + * @return the current {@link LocationComponentOptions} + */ + public LocationComponentOptions getLocationComponentOptions() { + return options; + } + + /** + * Apply a new component style with a style resource. + * + * @param styleRes a XML style overriding some or all the options + */ + public void applyStyle(@NonNull Context context, @StyleRes int styleRes) { + applyStyle(LocationComponentOptions.createFromAttributes(context, styleRes)); + } + + /** + * Apply a new component style with location component options. + * + * @param options to update the current style + */ + public void applyStyle(LocationComponentOptions options) { + this.options = options; + locationLayerController.applyStyle(options); + locationCameraController.initializeOptions(options); + staleStateManager.setEnabled(options.enableStaleState()); + staleStateManager.setDelayTime(options.staleStateTimeout()); + updateMapWithOptions(options); + } + + /** + * Zooms to the desired zoom level. + * This API can only be used in pair with camera modes other than {@link CameraMode#NONE}. + * If you are not using any of {@link CameraMode} modes, + * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, + * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + * + * @param zoomLevel The desired zoom level. + * @param animationDuration The zoom animation duration. + * @param callback The callback with finish/cancel information + */ + public void zoomWhileTracking(double zoomLevel, long animationDuration, + @Nullable MapboxMap.CancelableCallback callback) { + if (!isLayerReady) { + return; + } else if (getCameraMode() == CameraMode.NONE) { + Logger.e(TAG, String.format("%s%s", + "LocationComponent#zoomWhileTracking method can only be used", + " when a camera mode other than CameraMode#NONE is engaged.")); + return; + } + locationAnimatorCoordinator.feedNewZoomLevel(zoomLevel, mapboxMap.getCameraPosition(), animationDuration, callback); + } + + /** + * Zooms to the desired zoom level. + * This API can only be used in pair with camera modes other than {@link CameraMode#NONE}. + * If you are not using any of {@link CameraMode} modes, + * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, + * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + * + * @param zoomLevel The desired zoom level. + * @param animationDuration The zoom animation duration. + */ + public void zoomWhileTracking(double zoomLevel, long animationDuration) { + zoomWhileTracking(zoomLevel, animationDuration, null); + } + + /** + * Zooms to the desired zoom level. + * This API can only be used in pair with camera modes other than {@link CameraMode#NONE}. + * If you are not using any of {@link CameraMode} modes, + * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, + * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + * + * @param zoomLevel The desired zoom level. + */ + public void zoomWhileTracking(double zoomLevel) { + zoomWhileTracking(zoomLevel, DEFAULT_TRACKING_ZOOM_ANIM_DURATION, null); + } + + /** + * Cancels animation started by {@link #zoomWhileTracking(double, long, MapboxMap.CancelableCallback)}. + */ + public void cancelZoomWhileTrackingAnimation() { + locationAnimatorCoordinator.cancelZoomAnimation(); + } + + /** + * Tilts the camera. + * This API can only be used in pair with camera modes other than {@link CameraMode#NONE}. + * If you are not using any of {@link CameraMode} modes, + * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, + * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + * + * @param tilt The desired camera tilt. + * @param animationDuration The tilt animation duration. + * @param callback The callback with finish/cancel information + */ + public void tiltWhileTracking(double tilt, long animationDuration, + @Nullable MapboxMap.CancelableCallback callback) { + if (!isLayerReady) { + return; + } else if (getCameraMode() == CameraMode.NONE) { + Logger.e(TAG, String.format("%s%s", + "LocationComponent#tiltWhileTracking method can only be used", + " when a camera mode other than CameraMode#NONE is engaged.")); + return; + } + locationAnimatorCoordinator.feedNewTilt(tilt, mapboxMap.getCameraPosition(), animationDuration, callback); + } + + /** + * Tilts the camera. + * This API can only be used in pair with camera modes other than {@link CameraMode#NONE}. + * If you are not using any of {@link CameraMode} modes, + * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, + * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + * + * @param tilt The desired camera tilt. + * @param animationDuration The tilt animation duration. + */ + public void tiltWhileTracking(double tilt, long animationDuration) { + tiltWhileTracking(tilt, animationDuration, null); + } + + /** + * Tilts the camera. + * This API can only be used in pair with camera modes other than {@link CameraMode#NONE}. + * If you are not using any of {@link CameraMode} modes, + * use one of {@link MapboxMap#moveCamera(CameraUpdate)}, + * {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead. + * + * @param tilt The desired camera tilt. + */ + public void tiltWhileTracking(double tilt) { + tiltWhileTracking(tilt, DEFAULT_TRACKING_TILT_ANIM_DURATION, null); + } + + /** + * Cancels animation started by {@link #tiltWhileTracking(double, long, MapboxMap.CancelableCallback)}. + */ + public void cancelTiltWhileTrackingAnimation() { + locationAnimatorCoordinator.cancelTiltAnimation(); + } + + /** + * Use to either force a location update or to manually control when the user location gets + * updated. + * + * @param location where the location icon is placed on the map + */ + public void forceLocationUpdate(@Nullable Location location) { + updateLocation(location, false); + } + + /** + * Set the location engine to update the current user location. + * <p> + * If {@code null} is passed in, all updates will have to occur through the + * {@link LocationComponent#forceLocationUpdate(Location)} method. + * + * @param locationEngine a {@link LocationEngine} this component should use to handle updates + */ + public void setLocationEngine(@Nullable LocationEngine locationEngine) { + if (this.locationEngine != null) { + // If internal location engines being used, extra steps need to be taken to deconstruct the + // instance. + if (usingInternalLocationEngine) { + this.locationEngine.removeLocationUpdates(); + this.locationEngine.deactivate(); + usingInternalLocationEngine = false; + } + this.locationEngine.removeLocationEngineListener(locationEngineListener); + this.locationEngine = null; + } + + if (locationEngine != null) { + this.locationEngine = locationEngine; + if (isEnabled) { + this.locationEngine.addLocationEngineListener(locationEngineListener); + } + } + } + + /** + * Returns the current {@link LocationEngine} being used for updating the user location. + * + * @return the {@link LocationEngine} being used to update the user location + */ + @Nullable + public LocationEngine getLocationEngine() { + return locationEngine; + } + + /** + * Sets the compass engine used to provide compass heading values. + * + * @param compassEngine to be used + */ + public void setCompassEngine(@NonNull CompassEngine compassEngine) { + this.compassEngine.removeCompassListener(compassListener); + this.compassEngine = compassEngine; + compassEngine.addCompassListener(compassListener); + } + + /** + * Returns the compass engine used to provide compass heading values. + * + * @return compass engine currently being used + */ + @NonNull + public CompassEngine getCompassEngine() { + return compassEngine; + } + + /** + * Get the last know location of the location component. + * + * @return the last known location + */ + @Nullable + @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}) + public Location getLastKnownLocation() { + Location location = locationEngine != null ? locationEngine.getLastLocation() : null; + if (location == null) { + location = lastLocation; + } + return location; + } + + /** + * Return the last known {@link CompassEngine} accuracy status of the location component. + * <p> + * The last known accuracy of the compass sensor, one of SensorManager.SENSOR_STATUS_* + * + * @return the last know compass accuracy bearing + */ + public float getLastKnownCompassAccuracyStatus() { + return compassEngine.getLastAccuracySensorStatus(); + } + + /** + * Add a compass listener to get heading updates every second. Once the first listener gets added, + * the sensor gets initiated and starts returning values. + * + * @param compassListener a {@link CompassListener} for listening into compass heading and + * accuracy changes + */ + public void addCompassListener(@NonNull CompassListener compassListener) { + compassEngine.addCompassListener(compassListener); + } + + /** + * Remove a compass listener. + * + * @param compassListener the {@link CompassListener} which you'd like to remove from the listener + * list. + */ + public void removeCompassListener(@NonNull CompassListener compassListener) { + compassEngine.removeCompassListener(compassListener); + } + + /** + * Adds a listener that gets invoked when the user clicks the displayed location. + * + * @param listener The location click listener that is invoked when the + * location is clicked + */ + public void addOnLocationClickListener(@NonNull OnLocationClickListener listener) { + onLocationClickListeners.add(listener); + } + + /** + * Removes the passed listener from the current list of location click listeners. + * + * @param listener to be removed + */ + public void removeOnLocationClickListener(@NonNull OnLocationClickListener listener) { + onLocationClickListeners.remove(listener); + } + + /** + * Adds a listener that gets invoked when the user long clicks the displayed location. + * + * @param listener The location click listener that is invoked when the + * location is clicked + */ + public void addOnLocationLongClickListener(@NonNull OnLocationLongClickListener listener) { + onLocationLongClickListeners.add(listener); + } + + /** + * Removes the passed listener from the current list of location long click listeners. + * + * @param listener to be removed + */ + public void removeOnLocationLongClickListener(@NonNull OnLocationLongClickListener listener) { + onLocationLongClickListeners.remove(listener); + } + + /** + * Adds a listener that gets invoked when camera tracking state changes. + * + * @param listener Listener that gets invoked when camera tracking state changes. + */ + public void addOnCameraTrackingChangedListener(@NonNull OnCameraTrackingChangedListener listener) { + onCameraTrackingChangedListeners.add(listener); + } + + /** + * Removes a listener that gets invoked when camera tracking state changes. + * + * @param listener Listener that gets invoked when camera tracking state changes. + */ + public void removeOnCameraTrackingChangedListener(@NonNull OnCameraTrackingChangedListener listener) { + onCameraTrackingChangedListeners.remove(listener); + } + + /** + * Adds the passed listener that gets invoked when user updates have stopped long enough for the last update + * to be considered stale. + * <p> + * This timeout is set by {@link LocationComponentOptions#staleStateTimeout()}. + * + * @param listener invoked when last update is considered stale + */ + public void addOnLocationStaleListener(@NonNull OnLocationStaleListener listener) { + onLocationStaleListeners.add(listener); + } + + /** + * Removes the passed listener from the current list of stale listeners. + * + * @param listener to be removed from the list + */ + public void removeOnLocationStaleListener(@NonNull OnLocationStaleListener listener) { + onLocationStaleListeners.remove(listener); + } + + /** + * Internal use. + */ + public void onStart() { + isComponentStarted = true; + onLocationLayerStart(); + } + + /** + * Internal use. + */ + public void onStop() { + onLocationLayerStop(); + isComponentStarted = false; + } + + /** + * Internal use. + */ + public void onDestroy() { + if (locationEngine != null && usingInternalLocationEngine) { + locationEngine.deactivate(); + } + } + + /** + * Internal use. + */ + public void onStartLoadingMap() { + onLocationLayerStop(); + } + + /** + * Internal use. + */ + public void onFinishLoadingStyle() { + if (isInitialized) { + locationLayerController.initializeComponents(options); + locationCameraController.initializeOptions(options); + } + onLocationLayerStart(); + } + + @SuppressLint("MissingPermission") + private void onLocationLayerStart() { + if (!isInitialized || !isComponentStarted) { + return; + } + + if (!isLayerReady) { + isLayerReady = true; + mapboxMap.addOnCameraMoveListener(onCameraMoveListener); + mapboxMap.addOnCameraIdleListener(onCameraIdleListener); + if (options.enableStaleState()) { + staleStateManager.onStart(); + } + compassEngine.onStart(); + } + + if (isEnabled) { + if (locationEngine != null) { + locationEngine.addLocationEngineListener(locationEngineListener); + if (locationEngine.isConnected() && usingInternalLocationEngine) { + locationEngine.requestLocationUpdates(); + } + } + setCameraMode(locationCameraController.getCameraMode()); + setLastLocation(); + setLastCompassHeading(); + } + } + + private void onLocationLayerStop() { + if (!isInitialized || !isLayerReady || !isComponentStarted) { + return; + } + + isLayerReady = false; + locationLayerController.hide(); + staleStateManager.onStop(); + compassEngine.onStop(); + locationAnimatorCoordinator.cancelAllAnimations(); + if (locationEngine != null) { + if (usingInternalLocationEngine) { + locationEngine.removeLocationUpdates(); + } + locationEngine.removeLocationEngineListener(locationEngineListener); + } + mapboxMap.removeOnCameraMoveListener(onCameraMoveListener); + mapboxMap.removeOnCameraIdleListener(onCameraIdleListener); + } + + private void initialize(@NonNull Context context, @NonNull LocationComponentOptions options) { + if (isInitialized) { + return; + } + isInitialized = true; + this.options = options; + + AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); + + mapboxMap.addOnMapClickListener(onMapClickListener); + mapboxMap.addOnMapLongClickListener(onMapLongClickListener); + + LayerSourceProvider sourceProvider = new LayerSourceProvider(); + LayerFeatureProvider featureProvider = new LayerFeatureProvider(); + LayerBitmapProvider bitmapProvider = new LayerBitmapProvider(context); + locationLayerController = new LocationLayerController(mapboxMap, sourceProvider, featureProvider, bitmapProvider, + options); + locationCameraController = new LocationCameraController( + context, mapboxMap, cameraTrackingChangedListener, options, onCameraMoveInvalidateListener); + locationAnimatorCoordinator = new LocationAnimatorCoordinator(); + locationAnimatorCoordinator.addLayerListener(locationLayerController); + locationAnimatorCoordinator.addCameraListener(locationCameraController); + + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + compassEngine = new LocationComponentCompassEngine(windowManager, sensorManager); + compassEngine.addCompassListener(compassListener); + staleStateManager = new StaleStateManager(onLocationStaleListener, options); + + updateMapWithOptions(options); + + setRenderMode(RenderMode.NORMAL); + setCameraMode(CameraMode.NONE); + + onLocationLayerStart(); + } + + private void initializeLocationEngine(@NonNull Context context) { + if (this.locationEngine != null) { + if (usingInternalLocationEngine) { + this.locationEngine.removeLocationUpdates(); + this.locationEngine.deactivate(); + } + this.locationEngine.removeLocationEngineListener(locationEngineListener); + } + + usingInternalLocationEngine = true; + locationEngine = new LocationEngineProvider(context).obtainBestLocationEngineAvailable(); + locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY); + locationEngine.setFastestInterval(1000); + locationEngine.addLocationEngineListener(locationEngineListener); + locationEngine.activate(); + } + + private void enableLocationComponent() { + isEnabled = true; + onLocationLayerStart(); + } + + private void disableLocationComponent() { + isEnabled = false; + onLocationLayerStop(); + } + + private void updateMapWithOptions(final LocationComponentOptions options) { + mapboxMap.setPadding( + options.padding()[0], options.padding()[1], options.padding()[2], options.padding()[3] + ); + + mapboxMap.setMaxZoomPreference(options.maxZoom()); + mapboxMap.setMinZoomPreference(options.minZoom()); + } + + /** + * Updates the user location icon. + * + * @param location the latest user location + */ + private void updateLocation(final Location location, boolean fromLastLocation) { + if (location == null) { + return; + } else if (!isLayerReady) { + lastLocation = location; + return; + } + + showLocationLayerIfHidden(); + + if (!fromLastLocation) { + staleStateManager.updateLatestLocationTime(); + } + CameraPosition currentCameraPosition = mapboxMap.getCameraPosition(); + boolean isGpsNorth = getCameraMode() == CameraMode.TRACKING_GPS_NORTH; + locationAnimatorCoordinator.feedNewLocation(location, currentCameraPosition, isGpsNorth); + updateAccuracyRadius(location, false); + lastLocation = location; + } + + private void showLocationLayerIfHidden() { + boolean isLocationLayerHidden = locationLayerController.isHidden(); + if (isEnabled && isComponentStarted && isLocationLayerHidden) { + locationLayerController.show(); + } + } + + private void updateCompassHeading(float heading) { + locationAnimatorCoordinator.feedNewCompassBearing(heading, mapboxMap.getCameraPosition()); + } + + /** + * If the locationEngine contains a last location value, we use it for the initial location layer + * position. + */ + @SuppressLint("MissingPermission") + private void setLastLocation() { + updateLocation(getLastKnownLocation(), true); + } + + private void setLastCompassHeading() { + updateCompassHeading(compassEngine.getLastHeading()); + } + + @SuppressLint("MissingPermission") + private void updateLayerOffsets(boolean forceUpdate) { + CameraPosition position = mapboxMap.getCameraPosition(); + if (lastCameraPosition == null || forceUpdate) { + lastCameraPosition = position; + locationLayerController.updateForegroundBearing((float) position.bearing); + locationLayerController.updateForegroundOffset(position.tilt); + updateAccuracyRadius(getLastKnownLocation(), true); + return; + } + + if (position.bearing != lastCameraPosition.bearing) { + locationLayerController.updateForegroundBearing((float) position.bearing); + } + if (position.tilt != lastCameraPosition.tilt) { + locationLayerController.updateForegroundOffset(position.tilt); + } + if (position.zoom != lastCameraPosition.zoom) { + updateAccuracyRadius(getLastKnownLocation(), true); + } + lastCameraPosition = position; + } + + private void updateAccuracyRadius(Location location, boolean noAnimation) { + locationAnimatorCoordinator.feedNewAccuracyRadius(Utils.calculateZoomLevelRadius(mapboxMap, location), noAnimation); + } + + private OnCameraMoveListener onCameraMoveListener = new OnCameraMoveListener() { + @Override + public void onCameraMove() { + updateLayerOffsets(false); + } + }; + + private OnCameraIdleListener onCameraIdleListener = new OnCameraIdleListener() { + @Override + public void onCameraIdle() { + updateLayerOffsets(false); + } + }; + + private OnMapClickListener onMapClickListener = new OnMapClickListener() { + @Override + public void onMapClick(@NonNull LatLng point) { + if (!onLocationClickListeners.isEmpty() && locationLayerController.onMapClick(point)) { + for (OnLocationClickListener listener : onLocationClickListeners) { + listener.onLocationComponentClick(); + } + } + } + }; + + private MapboxMap.OnMapLongClickListener onMapLongClickListener = new MapboxMap.OnMapLongClickListener() { + @Override + public void onMapLongClick(@NonNull LatLng point) { + if (!onLocationLongClickListeners.isEmpty() && locationLayerController.onMapClick(point)) { + for (OnLocationLongClickListener listener : onLocationLongClickListeners) { + listener.onLocationComponentLongClick(); + } + } + } + }; + + private OnLocationStaleListener onLocationStaleListener = new OnLocationStaleListener() { + @Override + public void onStaleStateChange(boolean isStale) { + locationLayerController.setLocationsStale(isStale); + + for (OnLocationStaleListener listener : onLocationStaleListeners) { + listener.onStaleStateChange(isStale); + } + } + }; + + private OnCameraMoveInvalidateListener onCameraMoveInvalidateListener = new OnCameraMoveInvalidateListener() { + @Override + public void onInvalidateCameraMove() { + onCameraMoveListener.onCameraMove(); + } + }; + + private CompassListener compassListener = new CompassListener() { + @Override + public void onCompassChanged(float userHeading) { + updateCompassHeading(userHeading); + } + + @Override + public void onCompassAccuracyChange(int compassStatus) { + // Currently don't handle this inside SDK + } + }; + + private LocationEngineListener locationEngineListener = new LocationEngineListener() { + @Override + @SuppressWarnings( {"MissingPermission"}) + public void onConnected() { + if (usingInternalLocationEngine && isLayerReady && isEnabled) { + locationEngine.requestLocationUpdates(); + } + } + + @Override + public void onLocationChanged(Location location) { + updateLocation(location, false); + } + }; + + private OnCameraTrackingChangedListener cameraTrackingChangedListener = new OnCameraTrackingChangedListener() { + @Override + public void onCameraTrackingDismissed() { + for (OnCameraTrackingChangedListener listener : onCameraTrackingChangedListeners) { + listener.onCameraTrackingDismissed(); + } + } + + @Override + public void onCameraTrackingChanged(int currentMode) { + locationAnimatorCoordinator.cancelZoomAnimation(); + locationAnimatorCoordinator.cancelTiltAnimation(); + for (OnCameraTrackingChangedListener listener : onCameraTrackingChangedListeners) { + listener.onCameraTrackingChanged(currentMode); + } + } + }; +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentCompassEngine.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentCompassEngine.java new file mode 100644 index 000000000..b53d909de --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentCompassEngine.java @@ -0,0 +1,267 @@ +package com.mapbox.mapboxsdk.location; + +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.SystemClock; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.Surface; +import android.view.WindowManager; + +import java.util.ArrayList; +import java.util.List; + +import timber.log.Timber; + +/** + * This manager class handles compass events such as starting the tracking of device bearing, or + * when a new compass update occurs. + */ +class LocationComponentCompassEngine implements CompassEngine, SensorEventListener { + + // The rate sensor events will be delivered at. As the Android documentation states, this is only + // a hint to the system and the events might actually be received faster or slower then this + // specified rate. Since the minimum Android API levels about 9, we are able to set this value + // ourselves rather than using one of the provided constants which deliver updates too quickly for + // our use case. The default is set to 100ms + private static final int SENSOR_DELAY_MICROS = 100 * 1000; + // Filtering coefficient 0 < ALPHA < 1 + private static final float ALPHA = 0.45f; + + private final WindowManager windowManager; + private final SensorManager sensorManager; + private final List<CompassListener> compassListeners = new ArrayList<>(); + + // Not all devices have a compassSensor + @Nullable + private Sensor compassSensor; + @Nullable + private Sensor gravitySensor; + @Nullable + private Sensor magneticFieldSensor; + + private float[] truncatedRotationVectorValue = new float[4]; + private float[] rotationMatrix = new float[9]; + private float[] rotationVectorValue; + private float lastHeading; + private int lastAccuracySensorStatus; + + private long compassUpdateNextTimestamp; + private float[] gravityValues = new float[3]; + private float[] magneticValues = new float[3]; + + /** + * Construct a new instance of the this class. A internal compass listeners needed to separate it + * from the cleared list of public listeners. + */ + LocationComponentCompassEngine(WindowManager windowManager, SensorManager sensorManager) { + this.windowManager = windowManager; + this.sensorManager = sensorManager; + compassSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); + if (compassSensor == null) { + if (isGyroscopeAvailable()) { + Timber.d("Rotation vector sensor not supported on device, falling back to orientation."); + compassSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); + } else { + Timber.d("Rotation vector sensor not supported on device, falling back to accelerometer and magnetic field."); + gravitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + magneticFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); + } + } + } + + @Override + public void addCompassListener(@NonNull CompassListener compassListener) { + if (compassListeners.isEmpty()) { + onStart(); + } + compassListeners.add(compassListener); + } + + @Override + public void removeCompassListener(@NonNull CompassListener compassListener) { + compassListeners.remove(compassListener); + if (compassListeners.isEmpty()) { + onStop(); + } + } + + @Override + public int getLastAccuracySensorStatus() { + return lastAccuracySensorStatus; + } + + @Override + public float getLastHeading() { + return lastHeading; + } + + @Override + public void onStart() { + registerSensorListeners(); + } + + @Override + public void onStop() { + unregisterSensorListeners(); + } + + @Override + public void onSensorChanged(SensorEvent event) { + // check when the last time the compass was updated, return if too soon. + long currentTime = SystemClock.elapsedRealtime(); + if (currentTime < compassUpdateNextTimestamp) { + return; + } + if (lastAccuracySensorStatus == SensorManager.SENSOR_STATUS_UNRELIABLE) { + Timber.d("Compass sensor is unreliable, device calibration is needed."); + return; + } + if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { + rotationVectorValue = getRotationVectorFromSensorEvent(event); + updateOrientation(); + + // Update the compassUpdateNextTimestamp + compassUpdateNextTimestamp = currentTime + LocationComponentConstants.COMPASS_UPDATE_RATE_MS; + } else if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) { + notifyCompassChangeListeners((event.values[0] + 360) % 360); + } else if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { + gravityValues = lowPassFilter(getRotationVectorFromSensorEvent(event), gravityValues); + updateOrientation(); + } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { + magneticValues = lowPassFilter(getRotationVectorFromSensorEvent(event), magneticValues); + updateOrientation(); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + if (lastAccuracySensorStatus != accuracy) { + for (CompassListener compassListener : compassListeners) { + compassListener.onCompassAccuracyChange(accuracy); + } + lastAccuracySensorStatus = accuracy; + } + } + + private boolean isGyroscopeAvailable() { + return sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE) != null; + } + + @SuppressWarnings("SuspiciousNameCombination") + private void updateOrientation() { + if (rotationVectorValue != null) { + SensorManager.getRotationMatrixFromVector(rotationMatrix, rotationVectorValue); + } else { + // Get rotation matrix given the gravity and geomagnetic matrices + SensorManager.getRotationMatrix(rotationMatrix, null, gravityValues, magneticValues); + } + + final int worldAxisForDeviceAxisX; + final int worldAxisForDeviceAxisY; + + // Remap the axes as if the device screen was the instrument panel, + // and adjust the rotation matrix for the device orientation. + switch (windowManager.getDefaultDisplay().getRotation()) { + case Surface.ROTATION_90: + worldAxisForDeviceAxisX = SensorManager.AXIS_Z; + worldAxisForDeviceAxisY = SensorManager.AXIS_MINUS_X; + break; + case Surface.ROTATION_180: + worldAxisForDeviceAxisX = SensorManager.AXIS_MINUS_X; + worldAxisForDeviceAxisY = SensorManager.AXIS_MINUS_Z; + break; + case Surface.ROTATION_270: + worldAxisForDeviceAxisX = SensorManager.AXIS_MINUS_Z; + worldAxisForDeviceAxisY = SensorManager.AXIS_X; + break; + case Surface.ROTATION_0: + default: + worldAxisForDeviceAxisX = SensorManager.AXIS_X; + worldAxisForDeviceAxisY = SensorManager.AXIS_Z; + break; + } + + float[] adjustedRotationMatrix = new float[9]; + SensorManager.remapCoordinateSystem(rotationMatrix, worldAxisForDeviceAxisX, + worldAxisForDeviceAxisY, adjustedRotationMatrix); + + // Transform rotation matrix into azimuth/pitch/roll + float[] orientation = new float[3]; + SensorManager.getOrientation(adjustedRotationMatrix, orientation); + + // The x-axis is all we care about here. + notifyCompassChangeListeners((float) Math.toDegrees(orientation[0])); + } + + private void notifyCompassChangeListeners(float heading) { + for (CompassListener compassListener : compassListeners) { + compassListener.onCompassChanged(heading); + } + lastHeading = heading; + } + + private void registerSensorListeners() { + if (isCompassSensorAvailable()) { + // Does nothing if the sensors already registered. + sensorManager.registerListener(this, compassSensor, SENSOR_DELAY_MICROS); + } else { + sensorManager.registerListener(this, gravitySensor, SENSOR_DELAY_MICROS); + sensorManager.registerListener(this, magneticFieldSensor, SENSOR_DELAY_MICROS); + } + } + + private void unregisterSensorListeners() { + if (isCompassSensorAvailable()) { + sensorManager.unregisterListener(this, compassSensor); + } else { + sensorManager.unregisterListener(this, gravitySensor); + sensorManager.unregisterListener(this, magneticFieldSensor); + } + } + + private boolean isCompassSensorAvailable() { + return compassSensor != null; + } + + /** + * Helper function, that filters newValues, considering previous values + * + * @param newValues array of float, that contains new data + * @param smoothedValues array of float, that contains previous state + * @return float filtered array of float + */ + private float[] lowPassFilter(float[] newValues, float[] smoothedValues) { + if (smoothedValues == null) { + return newValues; + } + for (int i = 0; i < newValues.length; i++) { + smoothedValues[i] = smoothedValues[i] + ALPHA * (newValues[i] - smoothedValues[i]); + } + return smoothedValues; + } + + /** + * Pulls out the rotation vector from a SensorEvent, with a maximum length + * vector of four elements to avoid potential compatibility issues. + * + * @param event the sensor event + * @return the events rotation vector, potentially truncated + */ + @NonNull + private float[] getRotationVectorFromSensorEvent(@NonNull SensorEvent event) { + if (event.values.length > 4) { + // On some Samsung devices SensorManager.getRotationMatrixFromVector + // appears to throw an exception if rotation vector has length > 4. + // For the purposes of this class the first 4 values of the + // rotation vector are sufficient (see crbug.com/335298 for details). + // Only affects Android 4.3 + System.arraycopy(event.values, 0, truncatedRotationVectorValue, 0, 4); + return truncatedRotationVectorValue; + } else { + return event.values; + } + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java new file mode 100644 index 000000000..40aae5bb6 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java @@ -0,0 +1,60 @@ +package com.mapbox.mapboxsdk.location; + +/** + * Contains all the constants being used for the Location layer. + */ +final class LocationComponentConstants { + + // Controls the compass update rate in milliseconds + static final int COMPASS_UPDATE_RATE_MS = 500; + + // Sets the transition animation duration when switching camera modes. + static final long TRANSITION_ANIMATION_DURATION_MS = 750; + + // Sets the max allowed time for the location icon animation from one LatLng to another. + static final long MAX_ANIMATION_DURATION_MS = 2000; + + // Sets the duration of change of accuracy radius when a different value is provided. + static final long ACCURACY_RADIUS_ANIMATION_DURATION = 250; + + // Default animation duration for zooming while tracking. + static final long DEFAULT_TRACKING_ZOOM_ANIM_DURATION = 750; + + // Default animation duration for tilting while tracking. + static final long DEFAULT_TRACKING_TILT_ANIM_DURATION = 1250; + + // Sources + static final String LOCATION_SOURCE = "mapbox-location-source"; + static final String PROPERTY_GPS_BEARING = "mapbox-property-gps-bearing"; + static final String PROPERTY_COMPASS_BEARING = "mapbox-property-compass-bearing"; + static final String PROPERTY_LOCATION_STALE = "mapbox-property-location-stale"; + static final String PROPERTY_ACCURACY_RADIUS = "mapbox-property-accuracy-radius"; + static final String PROPERTY_ACCURACY_COLOR = "mapbox-property-accuracy-color"; + static final String PROPERTY_ACCURACY_ALPHA = "mapbox-property-accuracy-alpha"; + static final String PROPERTY_FOREGROUND_ICON_OFFSET = "mapbox-property-foreground-icon-offset"; + static final String PROPERTY_SHADOW_ICON_OFFSET = "mapbox-property-shadow-icon-offset"; + static final String PROPERTY_FOREGROUND_ICON = "mapbox-property-foreground-icon"; + static final String PROPERTY_BACKGROUND_ICON = "mapbox-property-background-icon"; + static final String PROPERTY_FOREGROUND_STALE_ICON = "mapbox-property-foreground-stale-icon"; + static final String PROPERTY_BACKGROUND_STALE_ICON = "mapbox-property-background-stale-icon"; + static final String PROPERTY_BEARING_ICON = "mapbox-property-shadow-icon"; + + // Layers + static final String SHADOW_LAYER = "mapbox-location-shadow"; + static final String FOREGROUND_LAYER = "mapbox-location-layer"; + static final String BACKGROUND_LAYER = "mapbox-location-stroke-layer"; + static final String ACCURACY_LAYER = "mapbox-location-accuracy-layer"; + static final String BEARING_LAYER = "mapbox-location-bearing-layer"; + + // Icons + static final String FOREGROUND_ICON = "mapbox-location-icon"; + static final String BACKGROUND_ICON = "mapbox-location-stroke-icon"; + static final String FOREGROUND_STALE_ICON = "mapbox-location-stale-icon"; + static final String BACKGROUND_STALE_ICON = "mapbox-location-background-stale-icon"; + static final String SHADOW_ICON = "mapbox-location-shadow-icon"; + static final String BEARING_ICON = "mapbox-location-bearing-icon"; + + private LocationComponentConstants() { + // Class should not be initialized + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentOptions.java new file mode 100644 index 000000000..584d214f6 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentOptions.java @@ -0,0 +1,1610 @@ +package com.mapbox.mapboxsdk.location; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.ColorInt; +import android.support.annotation.Dimension; +import android.support.annotation.DrawableRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StyleRes; + +import com.mapbox.android.gestures.AndroidGesturesManager; +import com.mapbox.mapboxsdk.R; +import com.mapbox.mapboxsdk.constants.MapboxConstants; + +import java.util.Arrays; + +/** + * This class exposes options for the Location Component. The options can be set by defining a + * style in your apps style.xml file and passing in directly into the {@link LocationComponent} + * class. Alternatively, if properties need to be changed at runtime depending on a specific state, + * you can build an instance of this class, setting the values you desire, and then passing it into + * either the {@link LocationComponent} activation method (if it isn't initialized yet) or + * {@link LocationComponent#applyStyle(LocationComponentOptions)}. + * <p> + * When the {@link #createFromAttributes(Context, int)} methods called, any attributes not found + * inside the style will revert back to using their default set values. Likewise, when building a + * new {@link LocationComponentOptions} class using the builder, any options neglecting to be set will + * reset to their default values. + * <p> + * If you would like to keep your custom style changes while modifying a single attribute, you can + * get the currently used options object using {@link LocationComponent#getLocationComponentOptions()} + * and it's {@code toBuilder} method to modify a single entry while also maintaining the other + * settings. Once your modifications have been made, you'll need to pass it back into the location + * component using {@link LocationComponent#applyStyle(LocationComponentOptions)}. + */ +public class LocationComponentOptions implements Parcelable { + + /** + * Default accuracy alpha + */ + private static final float ACCURACY_ALPHA_DEFAULT = 0.15f; + + /** + * Default max map zoom + */ + private static final float MAX_ZOOM_DEFAULT = 18; + + /** + * Default min map zoom + */ + private static final float MIN_ZOOM_DEFAULT = 2; + + /** + * Default icon scale factor when the map is zoomed out + */ + private static final float MIN_ZOOM_ICON_SCALE_DEFAULT = 0.6f; + + /** + * Default icon scale factor when the map is zoomed in + */ + private static final float MAX_ZOOM_ICON_SCALE_DEFAULT = 1f; + + /** + * Default map padding + */ + private static final int[] PADDING_DEFAULT = {0, 0, 0, 0}; + + /** + * The default value which is used when the stale state is enabled + */ + private static final long STALE_STATE_DELAY_MS = 30_000L; + + private float accuracyAlpha; + private int accuracyColor; + private int backgroundDrawableStale; + private String backgroundStaleName; + private int foregroundDrawableStale; + private String foregroundStaleName; + private int gpsDrawable; + private String gpsName; + private int foregroundDrawable; + private String foregroundName; + private int backgroundDrawable; + private String backgroundName; + private int bearingDrawable; + private String bearingName; + private Integer bearingTintColor; + private Integer foregroundTintColor; + private Integer backgroundTintColor; + private Integer foregroundStaleTintColor; + private Integer backgroundStaleTintColor; + private float elevation; + private boolean enableStaleState; + private long staleStateTimeout; + private int[] padding; + private double maxZoom; + private double minZoom; + private float maxZoomIconScale; + private float minZoomIconScale; + private boolean trackingGesturesManagement; + private float trackingInitialMoveThreshold; + private float trackingMultiFingerMoveThreshold; + private String layerBelow; + + public LocationComponentOptions( + float accuracyAlpha, + int accuracyColor, + int backgroundDrawableStale, + @Nullable String backgroundStaleName, + int foregroundDrawableStale, + @Nullable String foregroundStaleName, + int gpsDrawable, + @Nullable String gpsName, + int foregroundDrawable, + @Nullable String foregroundName, + int backgroundDrawable, + @Nullable String backgroundName, + int bearingDrawable, + @Nullable String bearingName, + @Nullable Integer bearingTintColor, + @Nullable Integer foregroundTintColor, + @Nullable Integer backgroundTintColor, + @Nullable Integer foregroundStaleTintColor, + @Nullable Integer backgroundStaleTintColor, + float elevation, + boolean enableStaleState, + long staleStateTimeout, + int[] padding, + double maxZoom, + double minZoom, + float maxZoomIconScale, + float minZoomIconScale, + boolean trackingGesturesManagement, + float trackingInitialMoveThreshold, + float trackingMultiFingerMoveThreshold, + String layerBelow) { + this.accuracyAlpha = accuracyAlpha; + this.accuracyColor = accuracyColor; + this.backgroundDrawableStale = backgroundDrawableStale; + this.backgroundStaleName = backgroundStaleName; + this.foregroundDrawableStale = foregroundDrawableStale; + this.foregroundStaleName = foregroundStaleName; + this.gpsDrawable = gpsDrawable; + this.gpsName = gpsName; + this.foregroundDrawable = foregroundDrawable; + this.foregroundName = foregroundName; + this.backgroundDrawable = backgroundDrawable; + this.backgroundName = backgroundName; + this.bearingDrawable = bearingDrawable; + this.bearingName = bearingName; + this.bearingTintColor = bearingTintColor; + this.foregroundTintColor = foregroundTintColor; + this.backgroundTintColor = backgroundTintColor; + this.foregroundStaleTintColor = foregroundStaleTintColor; + this.backgroundStaleTintColor = backgroundStaleTintColor; + this.elevation = elevation; + this.enableStaleState = enableStaleState; + this.staleStateTimeout = staleStateTimeout; + if (padding == null) { + throw new NullPointerException("Null padding"); + } + this.padding = padding; + this.maxZoom = maxZoom; + this.minZoom = minZoom; + this.maxZoomIconScale = maxZoomIconScale; + this.minZoomIconScale = minZoomIconScale; + this.trackingGesturesManagement = trackingGesturesManagement; + this.trackingInitialMoveThreshold = trackingInitialMoveThreshold; + this.trackingMultiFingerMoveThreshold = trackingMultiFingerMoveThreshold; + this.layerBelow = layerBelow; + } + + /** + * Construct a new Location Component Options class using the attributes found within a style + * resource. It's important to note that you only need to define the attributes you plan to + * change and can safely ignore the other attributes which will be set to their default value. + * + * @param context your activity's context used for acquiring resources + * @param styleRes the style id where your custom attributes are defined + * @return a new {@link LocationComponentOptions} object with the settings you defined in your style + * resource + */ + public static LocationComponentOptions createFromAttributes(@NonNull Context context, + @StyleRes int styleRes) { + + TypedArray typedArray = context.obtainStyledAttributes( + styleRes, R.styleable.mapbox_LocationComponent); + + LocationComponentOptions.Builder builder = new LocationComponentOptions.Builder() + .enableStaleState(true) + .staleStateTimeout(STALE_STATE_DELAY_MS) + .maxZoom(MAX_ZOOM_DEFAULT) + .minZoom(MIN_ZOOM_DEFAULT) + .maxZoomIconScale(MAX_ZOOM_ICON_SCALE_DEFAULT) + .minZoomIconScale(MIN_ZOOM_ICON_SCALE_DEFAULT) + .padding(PADDING_DEFAULT); + + builder.foregroundDrawable(typedArray.getResourceId( + R.styleable.mapbox_LocationComponent_mapbox_foregroundDrawable, -1)); + if (typedArray.hasValue(R.styleable.mapbox_LocationComponent_mapbox_foregroundTintColor)) { + builder.foregroundTintColor(typedArray.getColor( + R.styleable.mapbox_LocationComponent_mapbox_foregroundTintColor, -1)); + } + builder.backgroundDrawable(typedArray.getResourceId( + R.styleable.mapbox_LocationComponent_mapbox_backgroundDrawable, -1)); + if (typedArray.hasValue(R.styleable.mapbox_LocationComponent_mapbox_backgroundTintColor)) { + builder.backgroundTintColor(typedArray.getColor( + R.styleable.mapbox_LocationComponent_mapbox_backgroundTintColor, -1)); + } + builder.foregroundDrawableStale(typedArray.getResourceId( + R.styleable.mapbox_LocationComponent_mapbox_foregroundDrawableStale, -1)); + if (typedArray.hasValue(R.styleable.mapbox_LocationComponent_mapbox_foregroundStaleTintColor)) { + builder.foregroundStaleTintColor(typedArray.getColor( + R.styleable.mapbox_LocationComponent_mapbox_foregroundStaleTintColor, -1)); + } + builder.backgroundDrawableStale(typedArray.getResourceId( + R.styleable.mapbox_LocationComponent_mapbox_backgroundDrawableStale, -1)); + if (typedArray.hasValue(R.styleable.mapbox_LocationComponent_mapbox_backgroundStaleTintColor)) { + builder.backgroundStaleTintColor(typedArray.getColor( + R.styleable.mapbox_LocationComponent_mapbox_backgroundStaleTintColor, -1)); + } + builder.bearingDrawable(typedArray.getResourceId( + R.styleable.mapbox_LocationComponent_mapbox_bearingDrawable, -1)); + if (typedArray.hasValue(R.styleable.mapbox_LocationComponent_mapbox_bearingTintColor)) { + builder.bearingTintColor(typedArray.getColor( + R.styleable.mapbox_LocationComponent_mapbox_bearingTintColor, -1)); + } + if (typedArray.hasValue(R.styleable.mapbox_LocationComponent_mapbox_enableStaleState)) { + builder.enableStaleState(typedArray.getBoolean( + R.styleable.mapbox_LocationComponent_mapbox_enableStaleState, true)); + } + if (typedArray.hasValue(R.styleable.mapbox_LocationComponent_mapbox_staleStateTimeout)) { + builder.staleStateTimeout(typedArray.getInteger( + R.styleable.mapbox_LocationComponent_mapbox_staleStateTimeout, (int) STALE_STATE_DELAY_MS)); + } + builder.gpsDrawable(typedArray.getResourceId( + R.styleable.mapbox_LocationComponent_mapbox_gpsDrawable, -1)); + float elevation = typedArray.getDimension( + R.styleable.mapbox_LocationComponent_mapbox_elevation, 0); + builder.accuracyColor(typedArray.getColor( + R.styleable.mapbox_LocationComponent_mapbox_accuracyColor, -1)); + builder.accuracyAlpha(typedArray.getFloat( + R.styleable.mapbox_LocationComponent_mapbox_accuracyAlpha, ACCURACY_ALPHA_DEFAULT)); + builder.elevation(elevation); + + builder.trackingGesturesManagement(typedArray.getBoolean( + R.styleable.mapbox_LocationComponent_mapbox_trackingGesturesManagement, false)); + builder.trackingInitialMoveThreshold(typedArray.getDimension( + R.styleable.mapbox_LocationComponent_mapbox_trackingInitialMoveThreshold, + context.getResources().getDimension(R.dimen.mapbox_locationComponentTrackingInitialMoveThreshold))); + builder.trackingMultiFingerMoveThreshold(typedArray.getDimension( + R.styleable.mapbox_LocationComponent_mapbox_trackingMultiFingerMoveThreshold, + context.getResources().getDimension(R.dimen.mapbox_locationComponentTrackingMultiFingerMoveThreshold))); + + builder.padding(new int[] { + typedArray.getInt(R.styleable.mapbox_LocationComponent_mapbox_iconPaddingLeft, 0), + typedArray.getInt(R.styleable.mapbox_LocationComponent_mapbox_iconPaddingTop, 0), + typedArray.getInt(R.styleable.mapbox_LocationComponent_mapbox_iconPaddingRight, 0), + typedArray.getInt(R.styleable.mapbox_LocationComponent_mapbox_iconPaddingBottom, 0), + }); + + float maxZoom + = typedArray.getFloat(R.styleable.mapbox_LocationComponent_mapbox_maxZoom, MAX_ZOOM_DEFAULT); + if (maxZoom < MapboxConstants.MINIMUM_ZOOM || maxZoom > MapboxConstants.MAXIMUM_ZOOM) { + throw new IllegalArgumentException("Max zoom value must be within " + + MapboxConstants.MINIMUM_ZOOM + " and " + MapboxConstants.MAXIMUM_ZOOM); + } + + float minZoom + = typedArray.getFloat(R.styleable.mapbox_LocationComponent_mapbox_minZoom, MIN_ZOOM_DEFAULT); + if (minZoom < MapboxConstants.MINIMUM_ZOOM || minZoom > MapboxConstants.MAXIMUM_ZOOM) { + throw new IllegalArgumentException("Min zoom value must be within " + + MapboxConstants.MINIMUM_ZOOM + " and " + MapboxConstants.MAXIMUM_ZOOM); + } + + builder.maxZoom(maxZoom); + builder.minZoom(minZoom); + + builder.layerBelow( + typedArray.getString(R.styleable.mapbox_LocationComponent_mapbox_layer_below)); + + float minScale = typedArray.getFloat( + R.styleable.mapbox_LocationComponent_mapbox_minZoomIconScale, MIN_ZOOM_ICON_SCALE_DEFAULT); + float maxScale = typedArray.getFloat( + R.styleable.mapbox_LocationComponent_mapbox_maxZoomIconScale, MAX_ZOOM_ICON_SCALE_DEFAULT); + builder.minZoomIconScale(minScale); + builder.maxZoomIconScale(maxScale); + + typedArray.recycle(); + + return builder.build(); + } + + /** + * Takes the currently constructed {@link LocationComponentOptions} object and provides it's builder + * with all the values set matching the values in this instance. This allows you to modify a + * single attribute and then rebuild the object. + * + * @return the builder which contains the values defined in this current instance as defaults. + */ + public Builder toBuilder() { + return new Builder(this); + } + + /** + * Build a new instance of the {@link LocationComponentOptions} class with all the attributes set + * automatically to their defined defaults in this library. This allows you to adjust a few + * attributes while leaving the rest alone and maintaining their default behavior. + * + * @param context your activities context used to acquire the style resource + * @return the builder which contains the default values defined by the style resource + */ + public static Builder builder(Context context) { + return LocationComponentOptions.createFromAttributes(context, + R.style.mapbox_LocationComponent).toBuilder(); + } + + /** + * Set the opacity of the accuracy view to a value from 0 to 1, where 0 means the accuracy view is + * completely transparent and 1 means the view is completely opaque. + * + * @return the opacity of the accuracy view + * @attr ref R.styleable#LocationComponent_accuracyAlpha + */ + public float accuracyAlpha() { + return accuracyAlpha; + } + + /** + * Solid color to use as the accuracy view color property. + * + * @return the color of the accuracy view + * @attr ref R.styleable#LocationComponent_accuracyColor + */ + @ColorInt + public int accuracyColor() { + return accuracyColor; + } + + /** + * Defines the drawable used for the stale background icon. + * + * @return the drawable resource ID + * @attr ref R.styleable#LocationComponent_backgroundDrawableStale + */ + @DrawableRes + public int backgroundDrawableStale() { + return backgroundDrawableStale; + } + + /** + * String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will use this image in place of the provided or default mapbox_foregroundDrawableStale. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @return String icon or maki-icon name + */ + @Nullable + public String backgroundStaleName() { + return backgroundStaleName; + } + + /** + * Defines the drawable used for the stale foreground icon. + * + * @return the drawable resource ID + * @attr ref R.styleable#LocationComponent_foregroundDrawableStale + */ + @DrawableRes + public int foregroundDrawableStale() { + return foregroundDrawableStale; + } + + /** + * String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will used this image in place of the provided or default mapbox_foregroundDrawableStale. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @return String icon or maki-icon name + */ + @Nullable + public String foregroundStaleName() { + return foregroundStaleName; + } + + /** + * Defines the drawable used for the navigation state icon. + * + * @return the drawable resource ID + * @attr ref R.styleable#LocationComponent_gpsDrawable + */ + @DrawableRes + public int gpsDrawable() { + return gpsDrawable; + } + + /** + * String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will used this image in place of the provided or default mapbox_gpsDrawable. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @return String icon or maki-icon name + */ + @Nullable + public String gpsName() { + return gpsName; + } + + /** + * Supply a Drawable that is to be rendered on top of all of the content in the Location LayerComponent layer stack. + * + * @return the drawable resource used for the foreground layer + * @attr ref R.styleable#LocationComponent_foregroundDrawable + */ + @DrawableRes + public int foregroundDrawable() { + return foregroundDrawable; + } + + /** + * String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will used this image in place of the provided or default mapbox_foregroundDrawable. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @return String icon or maki-icon name + */ + @Nullable + public String foregroundName() { + return foregroundName; + } + + /** + * Defines the drawable used for the background state icon. + * + * @return the drawable resource ID + * @attr ref R.styleable#LocationComponent_backgroundDrawable + */ + @DrawableRes + public int backgroundDrawable() { + return backgroundDrawable; + } + + /** + * String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will used this image in place of the provided or default mapbox_backgroundDrawable. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @return String icon or maki-icon name + */ + @Nullable + public String backgroundName() { + return backgroundName; + } + + /** + * Defines the drawable used for the bearing icon. + * + * @return the drawable resource ID + * @attr ref R.styleable#LocationComponent_bearingDrawable + */ + @DrawableRes + public int bearingDrawable() { + return bearingDrawable; + } + + /** + * String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will used this image in place of the provided or default mapbox_bearingDrawable. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @return String icon or maki-icon name + */ + @Nullable + public String bearingName() { + return bearingName; + } + + /** + * Defines the bearing icon color as an integer. + * + * @return the color integer resource + * @attr ref R.styleable#LocationComponent_bearingTintColor + */ + @ColorInt + @Nullable + public Integer bearingTintColor() { + return bearingTintColor; + } + + /** + * Defines the foreground color as an integer. + * + * @return the color integer resource + * @attr ref R.styleable#LocationComponent_foregroundTintColor + */ + @ColorInt + @Nullable + public Integer foregroundTintColor() { + return foregroundTintColor; + } + + /** + * Defines the background color as an integer. + * + * @return the color integer resource + * @attr ref R.styleable#LocationComponent_backgroundTintColor + */ + @ColorInt + @Nullable + public Integer backgroundTintColor() { + return backgroundTintColor; + } + + /** + * Defines the foreground stale color as an integer. + * + * @return the color integer resource + * @attr ref R.styleable#LocationComponent_foregroundStaleTintColor + */ + @ColorInt + @Nullable + public Integer foregroundStaleTintColor() { + return foregroundStaleTintColor; + } + + /** + * Defines the background stale color as an integer. + * + * @return the color integer resource + * @attr ref R.styleable#LocationComponent_backgroundStaleTintColor + */ + @ColorInt + @Nullable + public Integer backgroundStaleTintColor() { + return backgroundStaleTintColor; + } + + /** + * Sets the base elevation of this view, in pixels. + * + * @return the elevation currently set for the location component icon + * @attr ref R.styleable#LocationComponent_elevation + */ + @Dimension + public float elevation() { + return elevation; + } + + /** + * Enable or disable to stale state mode. This mode indicates to the user that the location being + * displayed on the map hasn't been updated in a specific amount of time. + * + * @return whether the stale state mode is enabled or not + * @attr ref R.styleable#LocationComponent_enableStaleState + */ + public boolean enableStaleState() { + return enableStaleState; + } + + /** + * Set the delay before the location icon becomes stale. The timer begins approximately when a new + * location update comes in and using this defined time, if an update hasn't occured by the end, + * the location is considered stale. + * + * @return the duration in milliseconds which it should take before the location is + * considered stale + * @attr ref R.styleable#LocationComponent_staleStateDelay + */ + public long staleStateTimeout() { + return staleStateTimeout; + } + + /** + * Sets the distance from the edges of the map view’s frame to the edges of the map + * view’s logical viewport. + * </p> + * <p> + * When the value of this property is equal to {0,0,0,0}, viewport + * properties such as `centerCoordinate` assume a viewport that matches the map + * view’s frame. Otherwise, those properties are inset, excluding part of the + * frame from the viewport. For instance, if the only the top edge is inset, the + * map center is effectively shifted downward. + * </p> + * + * @return integer array of padding values + */ + @SuppressWarnings("mutable") + public int[] padding() { + return padding; + } + + /** + * The maximum zoom level the map can be displayed at. + * + * @return the maximum zoom level + */ + public double maxZoom() { + return maxZoom; + } + + /** + * The minimum zoom level the map can be displayed at. + * + * @return the minimum zoom level + */ + public double minZoom() { + return minZoom; + } + + /** + * The scale factor of the location icon when the map is zoomed in. Based on {@link #maxZoom()}. + * Scaling is linear. + * + * @return icon scale factor + */ + public float maxZoomIconScale() { + return maxZoomIconScale; + } + + /** + * The scale factor of the location icon when the map is zoomed out. Based on {@link #minZoom()}. + * Scaling is linear. + * + * @return icon scale factor + */ + public float minZoomIconScale() { + return minZoomIconScale; + } + + /** + * Returns whether gesture threshold should be adjusted when camera is in one of the tracking modes. + * This will adjust the focal point and increase thresholds to enable camera manipulation, + * like zooming in and out, without breaking tracking. + * <p> + * <strong>Note</strong>: If set to true, this can overwrite some of the gesture thresholds + * and the custom {@link com.mapbox.android.gestures.AndroidGesturesManager} that was set with + * {@link com.mapbox.mapboxsdk.maps.MapboxMap#setGesturesManager(AndroidGesturesManager, boolean, boolean)}. + * + * @return true if gestures are adjusted when in one of the camera tracking modes, false otherwise + * @see Builder#trackingInitialMoveThreshold(float) + * @see Builder#trackingMultiFingerMoveThreshold(float) + */ + public boolean trackingGesturesManagement() { + return trackingGesturesManagement; + } + + /** + * Minimum single pointer movement in pixels required to break camera tracking. + * + * @return the minimum movement + */ + public float trackingInitialMoveThreshold() { + return trackingInitialMoveThreshold; + } + + /** + * Minimum multi pointer movement in pixels required to break camera tracking (for example during scale gesture). + * + * @return the minimum movement + */ + public float trackingMultiFingerMoveThreshold() { + return trackingMultiFingerMoveThreshold; + } + + /** + * Gets the id of the layer to add the location component above to. + * + * @return layerBelow the id of the layer to add the location component above to + */ + public String layerBelow() { + return layerBelow; + } + + @Override + public String toString() { + return "LocationComponentOptions{" + + "accuracyAlpha=" + accuracyAlpha + ", " + + "accuracyColor=" + accuracyColor + ", " + + "backgroundDrawableStale=" + backgroundDrawableStale + ", " + + "backgroundStaleName=" + backgroundStaleName + ", " + + "foregroundDrawableStale=" + foregroundDrawableStale + ", " + + "foregroundStaleName=" + foregroundStaleName + ", " + + "gpsDrawable=" + gpsDrawable + ", " + + "gpsName=" + gpsName + ", " + + "foregroundDrawable=" + foregroundDrawable + ", " + + "foregroundName=" + foregroundName + ", " + + "backgroundDrawable=" + backgroundDrawable + ", " + + "backgroundName=" + backgroundName + ", " + + "bearingDrawable=" + bearingDrawable + ", " + + "bearingName=" + bearingName + ", " + + "bearingTintColor=" + bearingTintColor + ", " + + "foregroundTintColor=" + foregroundTintColor + ", " + + "backgroundTintColor=" + backgroundTintColor + ", " + + "foregroundStaleTintColor=" + foregroundStaleTintColor + ", " + + "backgroundStaleTintColor=" + backgroundStaleTintColor + ", " + + "elevation=" + elevation + ", " + + "enableStaleState=" + enableStaleState + ", " + + "staleStateTimeout=" + staleStateTimeout + ", " + + "padding=" + Arrays.toString(padding) + ", " + + "maxZoom=" + maxZoom + ", " + + "minZoom=" + minZoom + ", " + + "maxZoomIconScale=" + maxZoomIconScale + ", " + + "minZoomIconScale=" + minZoomIconScale + ", " + + "trackingGesturesManagement=" + trackingGesturesManagement + ", " + + "trackingInitialMoveThreshold=" + trackingInitialMoveThreshold + ", " + + "trackingMultiFingerMoveThreshold=" + trackingMultiFingerMoveThreshold + ", " + + "layerBelow=" + layerBelow + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof LocationComponentOptions) { + LocationComponentOptions that = (LocationComponentOptions) o; + return (Float.floatToIntBits(this.accuracyAlpha) == Float.floatToIntBits(that.accuracyAlpha())) + && (this.accuracyColor == that.accuracyColor()) + && (this.backgroundDrawableStale == that.backgroundDrawableStale()) + && ((this.backgroundStaleName == null) ? (that.backgroundStaleName() == null) + : this.backgroundStaleName.equals(that.backgroundStaleName())) + && (this.foregroundDrawableStale == that.foregroundDrawableStale()) + && ((this.foregroundStaleName == null) ? (that.foregroundStaleName() == null) + : this.foregroundStaleName.equals(that.foregroundStaleName())) + && (this.gpsDrawable == that.gpsDrawable()) + && ((this.gpsName == null) ? (that.gpsName() == null) : this.gpsName.equals(that.gpsName())) + && (this.foregroundDrawable == that.foregroundDrawable()) + && ((this.foregroundName == null) ? (that.foregroundName() == null) + : this.foregroundName.equals(that.foregroundName())) + && (this.backgroundDrawable == that.backgroundDrawable()) + && ((this.backgroundName == null) ? (that.backgroundName() == null) + : this.backgroundName.equals(that.backgroundName())) + && (this.bearingDrawable == that.bearingDrawable()) + && ((this.bearingName == null) ? (that.bearingName() == null) + : this.bearingName.equals(that.bearingName())) + && ((this.bearingTintColor == null) ? (that.bearingTintColor() == null) + : this.bearingTintColor.equals(that.bearingTintColor())) + && ((this.foregroundTintColor == null) ? (that.foregroundTintColor() == null) + : this.foregroundTintColor.equals(that.foregroundTintColor())) + && ((this.backgroundTintColor == null) ? (that.backgroundTintColor() == null) + : this.backgroundTintColor.equals(that.backgroundTintColor())) + && ((this.foregroundStaleTintColor == null) ? (that.foregroundStaleTintColor() == null) + : this.foregroundStaleTintColor.equals(that.foregroundStaleTintColor())) + && ((this.backgroundStaleTintColor == null) ? (that.backgroundStaleTintColor() == null) + : this.backgroundStaleTintColor.equals(that.backgroundStaleTintColor())) + && (Float.floatToIntBits(this.elevation) == Float.floatToIntBits(that.elevation())) + && (this.enableStaleState == that.enableStaleState()) + && (this.staleStateTimeout == that.staleStateTimeout()) + && (Arrays.equals(this.padding, that.padding()) + && (Double.doubleToLongBits(this.maxZoom) == Double.doubleToLongBits(that.maxZoom())) + && (Double.doubleToLongBits(this.minZoom) == Double.doubleToLongBits(that.minZoom())) + && (Float.floatToIntBits(this.maxZoomIconScale) == Float.floatToIntBits(that.maxZoomIconScale())) + && (Float.floatToIntBits(this.minZoomIconScale) == Float.floatToIntBits(that.minZoomIconScale())) + && (this.trackingGesturesManagement == that.trackingGesturesManagement()) + && (Float.floatToIntBits(this.trackingInitialMoveThreshold) + == Float.floatToIntBits(that.trackingInitialMoveThreshold())) + && (Float.floatToIntBits(this.trackingMultiFingerMoveThreshold) + == Float.floatToIntBits(that.trackingMultiFingerMoveThreshold())) + && layerBelow.equals(that.layerBelow)); + } + return false; + } + + @Override + public int hashCode() { + int h$ = 1; + h$ *= 1000003; + h$ ^= Float.floatToIntBits(accuracyAlpha); + h$ *= 1000003; + h$ ^= accuracyColor; + h$ *= 1000003; + h$ ^= backgroundDrawableStale; + h$ *= 1000003; + h$ ^= (backgroundStaleName == null) ? 0 : backgroundStaleName.hashCode(); + h$ *= 1000003; + h$ ^= foregroundDrawableStale; + h$ *= 1000003; + h$ ^= (foregroundStaleName == null) ? 0 : foregroundStaleName.hashCode(); + h$ *= 1000003; + h$ ^= gpsDrawable; + h$ *= 1000003; + h$ ^= (gpsName == null) ? 0 : gpsName.hashCode(); + h$ *= 1000003; + h$ ^= foregroundDrawable; + h$ *= 1000003; + h$ ^= (foregroundName == null) ? 0 : foregroundName.hashCode(); + h$ *= 1000003; + h$ ^= backgroundDrawable; + h$ *= 1000003; + h$ ^= (backgroundName == null) ? 0 : backgroundName.hashCode(); + h$ *= 1000003; + h$ ^= bearingDrawable; + h$ *= 1000003; + h$ ^= (bearingName == null) ? 0 : bearingName.hashCode(); + h$ *= 1000003; + h$ ^= (bearingTintColor == null) ? 0 : bearingTintColor.hashCode(); + h$ *= 1000003; + h$ ^= (foregroundTintColor == null) ? 0 : foregroundTintColor.hashCode(); + h$ *= 1000003; + h$ ^= (backgroundTintColor == null) ? 0 : backgroundTintColor.hashCode(); + h$ *= 1000003; + h$ ^= (foregroundStaleTintColor == null) ? 0 : foregroundStaleTintColor.hashCode(); + h$ *= 1000003; + h$ ^= (backgroundStaleTintColor == null) ? 0 : backgroundStaleTintColor.hashCode(); + h$ *= 1000003; + h$ ^= Float.floatToIntBits(elevation); + h$ *= 1000003; + h$ ^= enableStaleState ? 1231 : 1237; + h$ *= 1000003; + h$ ^= (int) ((staleStateTimeout >>> 32) ^ staleStateTimeout); + h$ *= 1000003; + h$ ^= Arrays.hashCode(padding); + h$ *= 1000003; + h$ ^= (int) ((Double.doubleToLongBits(maxZoom) >>> 32) ^ Double.doubleToLongBits(maxZoom)); + h$ *= 1000003; + h$ ^= (int) ((Double.doubleToLongBits(minZoom) >>> 32) ^ Double.doubleToLongBits(minZoom)); + h$ *= 1000003; + h$ ^= Float.floatToIntBits(maxZoomIconScale); + h$ *= 1000003; + h$ ^= Float.floatToIntBits(minZoomIconScale); + h$ *= 1000003; + h$ ^= trackingGesturesManagement ? 1231 : 1237; + h$ *= 1000003; + h$ ^= Float.floatToIntBits(trackingInitialMoveThreshold); + h$ *= 1000003; + h$ ^= Float.floatToIntBits(trackingMultiFingerMoveThreshold); + return h$; + } + + public static final Parcelable.Creator<LocationComponentOptions> CREATOR = + new Parcelable.Creator<LocationComponentOptions>() { + @Override + public LocationComponentOptions createFromParcel(Parcel in) { + return new LocationComponentOptions( + in.readFloat(), + in.readInt(), + in.readInt(), + in.readInt() == 0 ? in.readString() : null, + in.readInt(), + in.readInt() == 0 ? in.readString() : null, + in.readInt(), + in.readInt() == 0 ? in.readString() : null, + in.readInt(), + in.readInt() == 0 ? in.readString() : null, + in.readInt(), + in.readInt() == 0 ? in.readString() : null, + in.readInt(), + in.readInt() == 0 ? in.readString() : null, + in.readInt() == 0 ? in.readInt() : null, + in.readInt() == 0 ? in.readInt() : null, + in.readInt() == 0 ? in.readInt() : null, + in.readInt() == 0 ? in.readInt() : null, + in.readInt() == 0 ? in.readInt() : null, + in.readFloat(), + in.readInt() == 1, + in.readLong(), + in.createIntArray(), + in.readDouble(), + in.readDouble(), + in.readFloat(), + in.readFloat(), + in.readInt() == 1, + in.readFloat(), + in.readFloat(), + in.readString() + ); + } + + @Override + public LocationComponentOptions[] newArray(int size) { + return new LocationComponentOptions[size]; + } + }; + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeFloat(accuracyAlpha()); + dest.writeInt(accuracyColor()); + dest.writeInt(backgroundDrawableStale()); + if (backgroundStaleName() == null) { + dest.writeInt(1); + } else { + dest.writeInt(0); + dest.writeString(backgroundStaleName()); + } + dest.writeInt(foregroundDrawableStale()); + if (foregroundStaleName() == null) { + dest.writeInt(1); + } else { + dest.writeInt(0); + dest.writeString(foregroundStaleName()); + } + dest.writeInt(gpsDrawable()); + if (gpsName() == null) { + dest.writeInt(1); + } else { + dest.writeInt(0); + dest.writeString(gpsName()); + } + dest.writeInt(foregroundDrawable()); + if (foregroundName() == null) { + dest.writeInt(1); + } else { + dest.writeInt(0); + dest.writeString(foregroundName()); + } + dest.writeInt(backgroundDrawable()); + if (backgroundName() == null) { + dest.writeInt(1); + } else { + dest.writeInt(0); + dest.writeString(backgroundName()); + } + dest.writeInt(bearingDrawable()); + if (bearingName() == null) { + dest.writeInt(1); + } else { + dest.writeInt(0); + dest.writeString(bearingName()); + } + if (bearingTintColor() == null) { + dest.writeInt(1); + } else { + dest.writeInt(0); + dest.writeInt(bearingTintColor()); + } + if (foregroundTintColor() == null) { + dest.writeInt(1); + } else { + dest.writeInt(0); + dest.writeInt(foregroundTintColor()); + } + if (backgroundTintColor() == null) { + dest.writeInt(1); + } else { + dest.writeInt(0); + dest.writeInt(backgroundTintColor()); + } + if (foregroundStaleTintColor() == null) { + dest.writeInt(1); + } else { + dest.writeInt(0); + dest.writeInt(foregroundStaleTintColor()); + } + if (backgroundStaleTintColor() == null) { + dest.writeInt(1); + } else { + dest.writeInt(0); + dest.writeInt(backgroundStaleTintColor()); + } + dest.writeFloat(elevation()); + dest.writeInt(enableStaleState() ? 1 : 0); + dest.writeLong(staleStateTimeout()); + dest.writeIntArray(padding()); + dest.writeDouble(maxZoom()); + dest.writeDouble(minZoom()); + dest.writeFloat(maxZoomIconScale()); + dest.writeFloat(minZoomIconScale()); + dest.writeInt(trackingGesturesManagement() ? 1 : 0); + dest.writeFloat(trackingInitialMoveThreshold()); + dest.writeFloat(trackingMultiFingerMoveThreshold()); + dest.writeString(layerBelow()); + } + + @Override + public int describeContents() { + return 0; + } + + /** + * Builder class for constructing a new instance of {@link LocationComponentOptions}. + */ + public static class Builder { + + /** + * Build a new instance of this {@link LocationComponentOptions} class. + * + * @return a new instance of {@link LocationComponentOptions} + */ + public LocationComponentOptions build() { + LocationComponentOptions locationComponentOptions = autoBuild(); + if (locationComponentOptions.accuracyAlpha() < 0 || locationComponentOptions.accuracyAlpha() > 1) { + throw new IllegalArgumentException( + "Accuracy alpha value must be between 0.0 and 1.0."); + } + + if (locationComponentOptions.elevation() < 0f) { + throw new IllegalArgumentException("Invalid shadow size " + + locationComponentOptions.elevation() + ". Must be >= 0"); + } + + return locationComponentOptions; + } + + private Float accuracyAlpha; + private Integer accuracyColor; + private Integer backgroundDrawableStale; + private String backgroundStaleName; + private Integer foregroundDrawableStale; + private String foregroundStaleName; + private Integer gpsDrawable; + private String gpsName; + private Integer foregroundDrawable; + private String foregroundName; + private Integer backgroundDrawable; + private String backgroundName; + private Integer bearingDrawable; + private String bearingName; + private Integer bearingTintColor; + private Integer foregroundTintColor; + private Integer backgroundTintColor; + private Integer foregroundStaleTintColor; + private Integer backgroundStaleTintColor; + private Float elevation; + private Boolean enableStaleState; + private Long staleStateTimeout; + private int[] padding; + private Double maxZoom; + private Double minZoom; + private Float maxZoomIconScale; + private Float minZoomIconScale; + private Boolean trackingGesturesManagement; + private Float trackingInitialMoveThreshold; + private Float trackingMultiFingerMoveThreshold; + private String layerBelow; + + Builder() { + } + + private Builder(LocationComponentOptions source) { + this.accuracyAlpha = source.accuracyAlpha(); + this.accuracyColor = source.accuracyColor(); + this.backgroundDrawableStale = source.backgroundDrawableStale(); + this.backgroundStaleName = source.backgroundStaleName(); + this.foregroundDrawableStale = source.foregroundDrawableStale(); + this.foregroundStaleName = source.foregroundStaleName(); + this.gpsDrawable = source.gpsDrawable(); + this.gpsName = source.gpsName(); + this.foregroundDrawable = source.foregroundDrawable(); + this.foregroundName = source.foregroundName(); + this.backgroundDrawable = source.backgroundDrawable(); + this.backgroundName = source.backgroundName(); + this.bearingDrawable = source.bearingDrawable(); + this.bearingName = source.bearingName(); + this.bearingTintColor = source.bearingTintColor(); + this.foregroundTintColor = source.foregroundTintColor(); + this.backgroundTintColor = source.backgroundTintColor(); + this.foregroundStaleTintColor = source.foregroundStaleTintColor(); + this.backgroundStaleTintColor = source.backgroundStaleTintColor(); + this.elevation = source.elevation(); + this.enableStaleState = source.enableStaleState(); + this.staleStateTimeout = source.staleStateTimeout(); + this.padding = source.padding(); + this.maxZoom = source.maxZoom(); + this.minZoom = source.minZoom(); + this.maxZoomIconScale = source.maxZoomIconScale(); + this.minZoomIconScale = source.minZoomIconScale(); + this.trackingGesturesManagement = source.trackingGesturesManagement(); + this.trackingInitialMoveThreshold = source.trackingInitialMoveThreshold(); + this.trackingMultiFingerMoveThreshold = source.trackingMultiFingerMoveThreshold(); + this.layerBelow = source.layerBelow(); + } + + /** + * Set the opacity of the accuracy view to a value from 0 to 1, where 0 means the accuracy view + * is completely transparent and 1 means the view is completely opaque. + * + * @param accuracyAlpha the opacity of the accuracy view + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_accuracyAlpha + */ + public LocationComponentOptions.Builder accuracyAlpha(float accuracyAlpha) { + this.accuracyAlpha = accuracyAlpha; + return this; + } + + /** + * Solid color to use as the accuracy view color property. + * + * @param accuracyColor the color of the accuracy view + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_accuracyColor + */ + public LocationComponentOptions.Builder accuracyColor(int accuracyColor) { + this.accuracyColor = accuracyColor; + return this; + } + + /** + * Defines the drawable used for the stale background icon. + * + * @param backgroundDrawableStale the drawable resource ID + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_backgroundDrawableStale + */ + public LocationComponentOptions.Builder backgroundDrawableStale(int backgroundDrawableStale) { + this.backgroundDrawableStale = backgroundDrawableStale; + return this; + } + + /** + * Given a String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will used this image in place of the provided or default mapbox_backgroundDrawableStale. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @param backgroundStaleName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationComponentOptions.Builder backgroundStaleName(@Nullable String backgroundStaleName) { + this.backgroundStaleName = backgroundStaleName; + return this; + } + + /** + * Defines the drawable used for the stale foreground icon. + * + * @param foregroundDrawableStale the drawable resource ID + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_foregroundDrawableStale + */ + public LocationComponentOptions.Builder foregroundDrawableStale(int foregroundDrawableStale) { + this.foregroundDrawableStale = foregroundDrawableStale; + return this; + } + + /** + * Given a String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will used this image in place of the provided or default mapbox_foregroundDrawableStale. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @param foregroundStaleName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationComponentOptions.Builder foregroundStaleName(@Nullable String foregroundStaleName) { + this.foregroundStaleName = foregroundStaleName; + return this; + } + + /** + * Defines the drawable used for the navigation state icon. + * + * @param gpsDrawable the drawable resource ID + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_gpsDrawable + */ + public LocationComponentOptions.Builder gpsDrawable(int gpsDrawable) { + this.gpsDrawable = gpsDrawable; + return this; + } + + /** + * Given a String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will used this image in place of the provided or default mapbox_gpsDrawable. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @param gpsName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationComponentOptions.Builder gpsName(@Nullable String gpsName) { + this.gpsName = gpsName; + return this; + } + + /** + * Supply a Drawable that is to be rendered on top of all of the content in the Location Component layer stack. + * + * @param foregroundDrawable the drawable resource used for the foreground layer + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_foregroundDrawable + */ + public LocationComponentOptions.Builder foregroundDrawable(int foregroundDrawable) { + this.foregroundDrawable = foregroundDrawable; + return this; + } + + /** + * Given a String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will used this image in place of the provided or default mapbox_foregroundDrawable. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @param foregroundName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationComponentOptions.Builder foregroundName(@Nullable String foregroundName) { + this.foregroundName = foregroundName; + return this; + } + + /** + * Defines the drawable used for the background state icon. + * + * @param backgroundDrawable the drawable resource ID + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_backgroundDrawable + */ + public LocationComponentOptions.Builder backgroundDrawable(int backgroundDrawable) { + this.backgroundDrawable = backgroundDrawable; + return this; + } + + /** + * Given a String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will used this image in place of the provided or default mapbox_backgroundDrawable. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @param backgroundName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationComponentOptions.Builder backgroundName(@Nullable String backgroundName) { + this.backgroundName = backgroundName; + return this; + } + + /** + * Defines the drawable used for the bearing icon. + * + * @param bearingDrawable the drawable resource ID + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_bearingDrawable + */ + public LocationComponentOptions.Builder bearingDrawable(int bearingDrawable) { + this.bearingDrawable = bearingDrawable; + return this; + } + + /** + * Given a String image name, identical to one used in + * the first parameter of {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}, the + * component, will used this image in place of the provided or default mapbox_bearingDrawable. + * <p> + * A maki-icon name (example: "circle-15") may also be provided. These are images that can be loaded + * with certain styles. Note, this will fail if the provided icon name is not provided by the loaded map style. + * </p> + * + * @param bearingName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationComponentOptions.Builder bearingName(@Nullable String bearingName) { + this.bearingName = bearingName; + return this; + } + + /** + * Defines the bearing icon color as an integer. + * + * @param bearingTintColor the color integer resource + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_bearingTintColor + */ + public LocationComponentOptions.Builder bearingTintColor(@Nullable Integer bearingTintColor) { + this.bearingTintColor = bearingTintColor; + return this; + } + + /** + * Defines the foreground color as an integer. + * + * @param foregroundTintColor the color integer resource + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_foregroundTintColor + */ + public LocationComponentOptions.Builder foregroundTintColor(@Nullable Integer foregroundTintColor) { + this.foregroundTintColor = foregroundTintColor; + return this; + } + + /** + * Defines the background color as an integer. + * + * @param backgroundTintColor the color integer resource + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_backgroundTintColor + */ + public LocationComponentOptions.Builder backgroundTintColor(@Nullable Integer backgroundTintColor) { + this.backgroundTintColor = backgroundTintColor; + return this; + } + + /** + * Defines the foreground stale color as an integer. + * + * @param foregroundStaleTintColor the color integer resource + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_foregroundStaleTintColor + */ + public LocationComponentOptions.Builder foregroundStaleTintColor(@Nullable Integer foregroundStaleTintColor) { + this.foregroundStaleTintColor = foregroundStaleTintColor; + return this; + } + + /** + * Defines the background stale color as an integer. + * + * @param backgroundStaleTintColor the color integer resource + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_backgroundStaleTintColor + */ + public LocationComponentOptions.Builder backgroundStaleTintColor(@Nullable Integer backgroundStaleTintColor) { + this.backgroundStaleTintColor = backgroundStaleTintColor; + return this; + } + + /** + * Sets the base elevation of this view, in pixels. + * + * @param elevation the elevation currently set for the location icon + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_elevation + */ + public LocationComponentOptions.Builder elevation(float elevation) { + this.elevation = elevation; + return this; + } + + /** + * Enable or disable to stale state mode. This mode indicates to the user that the location + * being displayed on the map hasn't been updated in a specific amount of time. + * + * @param enabled whether the stale state mode is enabled or not + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_enableStaleState + */ + public LocationComponentOptions.Builder enableStaleState(boolean enabled) { + this.enableStaleState = enabled; + return this; + } + + /** + * Set the timeout before the location icon becomes stale. The timer begins approximately when a + * new location update comes in and using this defined time, if an update hasn't occurred by the + * end, the location is considered stale. + * + * @param timeout the duration in milliseconds which it should take before the location is + * considered stale + * @return this builder for chaining options together + * @attr ref R.styleable#LocationComponent_staleStateTimeout + */ + public LocationComponentOptions.Builder staleStateTimeout(long timeout) { + this.staleStateTimeout = timeout; + return this; + } + + /** + * Sets the distance from the edges of the map view’s frame to the edges of the map + * view’s logical viewport. + * </p> + * <p> + * When the value of this property is equal to {0,0,0,0}, viewport + * properties such as `centerCoordinate` assume a viewport that matches the map + * view’s frame. Otherwise, those properties are inset, excluding part of the + * frame from the viewport. For instance, if the only the top edge is inset, the + * map center is effectively shifted downward. + * </p> + * + * @param padding The margins for the map in pixels (left, top, right, bottom). + */ + public LocationComponentOptions.Builder padding(int[] padding) { + if (padding == null) { + throw new NullPointerException("Null padding"); + } + this.padding = padding; + return this; + } + + /** + * Sets the maximum zoom level the map can be displayed at. + * <p> + * The default maximum zoomn level is 22. The upper bound for this value is 25.5. + * + * @param maxZoom The new maximum zoom level. + */ + public LocationComponentOptions.Builder maxZoom(double maxZoom) { + this.maxZoom = maxZoom; + return this; + } + + /** + * Sets the minimum zoom level the map can be displayed at. + * + * @param minZoom The new minimum zoom level. + */ + public LocationComponentOptions.Builder minZoom(double minZoom) { + this.minZoom = minZoom; + return this; + } + + /** + * Sets the scale factor of the location icon when the map is zoomed in. Based on {@link #maxZoom()}. + * Scaling is linear and the new pixel size of the image will be the original pixel size multiplied by the argument. + * <p> + * Set both this and {@link #minZoomIconScale(float)} to 1f to disable location icon scaling. + * </p> + * + * @param maxZoomIconScale icon scale factor + */ + public LocationComponentOptions.Builder maxZoomIconScale(float maxZoomIconScale) { + this.maxZoomIconScale = maxZoomIconScale; + return this; + } + + /** + * Sets the scale factor of the location icon when the map is zoomed out. Based on {@link #maxZoom()}. + * Scaling is linear and the new pixel size of the image will be the original pixel size multiplied by the argument. + * <p> + * Set both this and {@link #maxZoomIconScale(float)} to 1f to disable location icon scaling. + * </p> + * + * @param minZoomIconScale icon scale factor + */ + public LocationComponentOptions.Builder minZoomIconScale(float minZoomIconScale) { + this.minZoomIconScale = minZoomIconScale; + return this; + } + + /** + * Set whether gesture threshold should be adjusted when camera is in one of the tracking modes. + * This will adjust the focal point and increase thresholds to enable camera manipulation, + * like zooming in and out, without breaking tracking. + * <p> + * <strong>Note</strong>: This can overwrite some of the gesture thresholds + * and the custom {@link com.mapbox.android.gestures.AndroidGesturesManager} that was set with + * {@link com.mapbox.mapboxsdk.maps.MapboxMap#setGesturesManager(AndroidGesturesManager, boolean, boolean)}. + * + * @param trackingGesturesManagement true if gestures should be adjusted when in one of the camera tracking modes, + * false otherwise + * @see Builder#trackingInitialMoveThreshold(float) + * @see Builder#trackingMultiFingerMoveThreshold(float) + */ + public LocationComponentOptions.Builder trackingGesturesManagement(boolean trackingGesturesManagement) { + this.trackingGesturesManagement = trackingGesturesManagement; + return this; + } + + /** + * Sets minimum single pointer movement (map pan) in pixels required to break camera tracking. + * + * @param moveThreshold the minimum movement + */ + public LocationComponentOptions.Builder trackingInitialMoveThreshold(float moveThreshold) { + this.trackingInitialMoveThreshold = moveThreshold; + return this; + } + + /** + * Sets minimum multi pointer movement (map pan) in pixels required to break camera tracking + * (for example during scale gesture). + * + * @param moveThreshold the minimum movement + */ + public LocationComponentOptions.Builder trackingMultiFingerMoveThreshold(float moveThreshold) { + this.trackingMultiFingerMoveThreshold = moveThreshold; + return this; + } + + /** + * Sets the layer id to set the location component below to. + * + * @param layerBelow the id to set the location component below to. + */ + public LocationComponentOptions.Builder layerBelow(String layerBelow) { + this.layerBelow = layerBelow; + return this; + } + + LocationComponentOptions autoBuild() { + String missing = ""; + if (this.accuracyAlpha == null) { + missing += " accuracyAlpha"; + } + if (this.accuracyColor == null) { + missing += " accuracyColor"; + } + if (this.backgroundDrawableStale == null) { + missing += " backgroundDrawableStale"; + } + if (this.foregroundDrawableStale == null) { + missing += " foregroundDrawableStale"; + } + if (this.gpsDrawable == null) { + missing += " gpsDrawable"; + } + if (this.foregroundDrawable == null) { + missing += " foregroundDrawable"; + } + if (this.backgroundDrawable == null) { + missing += " backgroundDrawable"; + } + if (this.bearingDrawable == null) { + missing += " bearingDrawable"; + } + if (this.elevation == null) { + missing += " elevation"; + } + if (this.enableStaleState == null) { + missing += " enableStaleState"; + } + if (this.staleStateTimeout == null) { + missing += " staleStateTimeout"; + } + if (this.padding == null) { + missing += " padding"; + } + if (this.maxZoom == null) { + missing += " maxZoom"; + } + if (this.minZoom == null) { + missing += " minZoom"; + } + if (this.maxZoomIconScale == null) { + missing += " maxZoomIconScale"; + } + if (this.minZoomIconScale == null) { + missing += " minZoomIconScale"; + } + if (this.trackingGesturesManagement == null) { + missing += " trackingGesturesManagement"; + } + if (this.trackingInitialMoveThreshold == null) { + missing += " trackingInitialMoveThreshold"; + } + if (this.trackingMultiFingerMoveThreshold == null) { + missing += " trackingMultiFingerMoveThreshold"; + } + if (!missing.isEmpty()) { + throw new IllegalStateException("Missing required properties:" + missing); + } + return new LocationComponentOptions( + this.accuracyAlpha, + this.accuracyColor, + this.backgroundDrawableStale, + this.backgroundStaleName, + this.foregroundDrawableStale, + this.foregroundStaleName, + this.gpsDrawable, + this.gpsName, + this.foregroundDrawable, + this.foregroundName, + this.backgroundDrawable, + this.backgroundName, + this.bearingDrawable, + this.bearingName, + this.bearingTintColor, + this.foregroundTintColor, + this.backgroundTintColor, + this.foregroundStaleTintColor, + this.backgroundStaleTintColor, + this.elevation, + this.enableStaleState, + this.staleStateTimeout, + this.padding, + this.maxZoom, + this.minZoom, + this.maxZoomIconScale, + this.minZoomIconScale, + trackingGesturesManagement, + this.trackingInitialMoveThreshold, + this.trackingMultiFingerMoveThreshold, + this.layerBelow); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java new file mode 100644 index 000000000..da3144eea --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java @@ -0,0 +1,398 @@ +package com.mapbox.mapboxsdk.location; + +import android.graphics.Bitmap; +import android.graphics.PointF; +import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.mapbox.geojson.Feature; +import com.mapbox.geojson.Point; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.location.modes.RenderMode; +import com.mapbox.mapboxsdk.style.layers.Layer; +import com.mapbox.mapboxsdk.style.layers.SymbolLayer; +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; + +import java.util.ArrayList; +import java.util.List; + +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.ACCURACY_LAYER; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BACKGROUND_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BACKGROUND_LAYER; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BACKGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BEARING_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BEARING_LAYER; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.FOREGROUND_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.FOREGROUND_LAYER; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.FOREGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.LOCATION_SOURCE; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_ACCURACY_ALPHA; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_ACCURACY_COLOR; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_ACCURACY_RADIUS; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_BACKGROUND_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_BACKGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_BEARING_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_FOREGROUND_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_FOREGROUND_ICON_OFFSET; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_FOREGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_GPS_BEARING; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_LOCATION_STALE; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_SHADOW_ICON_OFFSET; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.SHADOW_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.SHADOW_LAYER; +import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate; +import static com.mapbox.mapboxsdk.style.expressions.Expression.linear; +import static com.mapbox.mapboxsdk.style.expressions.Expression.stop; +import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom; +import static com.mapbox.mapboxsdk.style.layers.Property.NONE; +import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.colorToRgbaString; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility; + +final class LocationLayerController implements MapboxAnimator.OnLayerAnimationsValuesChangeListener { + + @RenderMode.Mode + private int renderMode; + + private final MapboxMap mapboxMap; + private final LayerSourceProvider layerSourceProvider; + private final LayerBitmapProvider bitmapProvider; + private LocationComponentOptions options; + + private final List<String> layerMap = new ArrayList<>(); + private Feature locationFeature; + private GeoJsonSource locationSource; + + private boolean isHidden = true; + + LocationLayerController(MapboxMap mapboxMap, LayerSourceProvider layerSourceProvider, + LayerFeatureProvider featureProvider, LayerBitmapProvider bitmapProvider, + LocationComponentOptions options) { + this.mapboxMap = mapboxMap; + this.layerSourceProvider = layerSourceProvider; + this.bitmapProvider = bitmapProvider; + this.locationFeature = featureProvider.generateLocationFeature(locationFeature, options); + initializeComponents(options); + setRenderMode(RenderMode.NORMAL); + } + + void initializeComponents(LocationComponentOptions options) { + addLocationSource(); + addLayers(options.layerBelow()); + applyStyle(options); + + if (isHidden) { + hide(); + } else { + show(); + } + } + + void applyStyle(@NonNull LocationComponentOptions options) { + this.options = options; + + float elevation = options.elevation(); + // Only add icon elevation if the values greater than 0. + if (elevation > 0) { + styleShadow(options); + } + styleForeground(options); + styleBackground(options); + styleBearing(options); + styleAccuracy(options.accuracyAlpha(), options.accuracyColor()); + styleScaling(options); + determineIconsSource(options); + } + + void setRenderMode(@RenderMode.Mode int renderMode) { + this.renderMode = renderMode; + + if (!isHidden) { + boolean isStale = locationFeature.getBooleanProperty(PROPERTY_LOCATION_STALE); + switch (renderMode) { + case RenderMode.NORMAL: + styleForeground(options); + setLayerVisibility(SHADOW_LAYER, true); + setLayerVisibility(FOREGROUND_LAYER, true); + setLayerVisibility(BACKGROUND_LAYER, true); + setLayerVisibility(ACCURACY_LAYER, !isStale); + setLayerVisibility(BEARING_LAYER, false); + break; + case RenderMode.COMPASS: + styleForeground(options); + setLayerVisibility(SHADOW_LAYER, true); + setLayerVisibility(FOREGROUND_LAYER, true); + setLayerVisibility(BACKGROUND_LAYER, true); + setLayerVisibility(ACCURACY_LAYER, !isStale); + setLayerVisibility(BEARING_LAYER, true); + break; + case RenderMode.GPS: + styleForeground(options); + setLayerVisibility(SHADOW_LAYER, false); + setLayerVisibility(FOREGROUND_LAYER, true); + setLayerVisibility(BACKGROUND_LAYER, true); + setLayerVisibility(ACCURACY_LAYER, false); + setLayerVisibility(BEARING_LAYER, false); + break; + default: + break; + } + + determineIconsSource(options); + } + } + + int getRenderMode() { + return renderMode; + } + + // + // Layer action + // + + void show() { + isHidden = false; + setRenderMode(renderMode); + } + + void hide() { + isHidden = true; + for (String layerId : layerMap) { + setLayerVisibility(layerId, false); + } + } + + void updateForegroundOffset(double tilt) { + JsonArray foregroundJsonArray = new JsonArray(); + foregroundJsonArray.add(0f); + foregroundJsonArray.add((float) (-0.05 * tilt)); + locationFeature.addProperty(PROPERTY_FOREGROUND_ICON_OFFSET, foregroundJsonArray); + + JsonArray backgroundJsonArray = new JsonArray(); + backgroundJsonArray.add(0f); + backgroundJsonArray.add((float) (0.05 * tilt)); + locationFeature.addProperty(PROPERTY_SHADOW_ICON_OFFSET, backgroundJsonArray); + + refreshSource(); + } + + void updateForegroundBearing(float bearing) { + if (renderMode != RenderMode.GPS) { + setBearingProperty(PROPERTY_GPS_BEARING, bearing); + } + } + + boolean isHidden() { + return isHidden; + } + + private void setLayerVisibility(String layerId, boolean visible) { + Layer layer = mapboxMap.getLayer(layerId); + if (layer != null) { + String targetVisibility = visible ? VISIBLE : NONE; + if (!layer.getVisibility().value.equals(targetVisibility)) { + layer.setProperties(visibility(visible ? VISIBLE : NONE)); + } + } + } + + private void addLayers(String idBelowLayer) { + addSymbolLayer(BEARING_LAYER, idBelowLayer); + addSymbolLayer(FOREGROUND_LAYER, BEARING_LAYER); + addSymbolLayer(BACKGROUND_LAYER, FOREGROUND_LAYER); + addSymbolLayer(SHADOW_LAYER, BACKGROUND_LAYER); + addAccuracyLayer(); + } + + private void addSymbolLayer(String layerId, String beforeLayerId) { + Layer layer = layerSourceProvider.generateLayer(layerId); + addLayerToMap(layer, beforeLayerId); + } + + private void addAccuracyLayer() { + Layer accuracyLayer = layerSourceProvider.generateAccuracyLayer(); + addLayerToMap(accuracyLayer, BACKGROUND_LAYER); + } + + private void addLayerToMap(Layer layer, @NonNull String idBelowLayer) { + mapboxMap.addLayerBelow(layer, idBelowLayer); + layerMap.add(layer.getId()); + } + + private void setBearingProperty(String propertyId, float bearing) { + locationFeature.addNumberProperty(propertyId, bearing); + refreshSource(); + } + + private void updateAccuracyRadius(float accuracy) { + if (renderMode == RenderMode.COMPASS || renderMode == RenderMode.NORMAL) { + locationFeature.addNumberProperty(PROPERTY_ACCURACY_RADIUS, accuracy); + refreshSource(); + } + } + + // + // Source actions + // + + private void addLocationSource() { + locationSource = layerSourceProvider.generateSource(locationFeature); + mapboxMap.addSource(locationSource); + } + + private void refreshSource() { + GeoJsonSource source = mapboxMap.getSourceAs(LOCATION_SOURCE); + if (source != null) { + locationSource.setGeoJson(locationFeature); + } + } + + private void setLocationPoint(Point locationPoint) { + JsonObject properties = locationFeature.properties(); + if (properties != null) { + locationFeature = Feature.fromGeometry(locationPoint, properties); + refreshSource(); + } + } + + // + // Styling + // + + private void styleBackground(LocationComponentOptions options) { + Bitmap backgroundBitmap = bitmapProvider.generateBitmap( + options.backgroundDrawable(), options.backgroundTintColor() + ); + Bitmap backgroundStaleBitmap = bitmapProvider.generateBitmap( + options.backgroundDrawableStale(), options.backgroundStaleTintColor() + ); + mapboxMap.addImage(BACKGROUND_ICON, backgroundBitmap); + mapboxMap.addImage(BACKGROUND_STALE_ICON, backgroundStaleBitmap); + } + + private void styleShadow(LocationComponentOptions options) { + mapboxMap.addImage(SHADOW_ICON, bitmapProvider.generateShadowBitmap(options)); + } + + private void styleBearing(LocationComponentOptions options) { + Bitmap bearingBitmap = bitmapProvider.generateBitmap(options.bearingDrawable(), options.bearingTintColor()); + mapboxMap.addImage(BEARING_ICON, bearingBitmap); + } + + private void styleAccuracy(float accuracyAlpha, @ColorInt int accuracyColor) { + locationFeature.addNumberProperty(PROPERTY_ACCURACY_ALPHA, accuracyAlpha); + locationFeature.addStringProperty(PROPERTY_ACCURACY_COLOR, colorToRgbaString(accuracyColor)); + refreshSource(); + } + + private void styleForeground(LocationComponentOptions options) { + Bitmap foregroundBitmap = bitmapProvider.generateBitmap( + options.foregroundDrawable(), options.foregroundTintColor() + ); + Bitmap foregroundBitmapStale = bitmapProvider.generateBitmap( + options.foregroundDrawableStale(), options.foregroundStaleTintColor() + ); + if (renderMode == RenderMode.GPS) { + foregroundBitmap = bitmapProvider.generateBitmap( + options.gpsDrawable(), options.foregroundTintColor() + ); + foregroundBitmapStale = bitmapProvider.generateBitmap( + options.gpsDrawable(), options.foregroundStaleTintColor() + ); + } + mapboxMap.addImage(FOREGROUND_ICON, foregroundBitmap); + mapboxMap.addImage(FOREGROUND_STALE_ICON, foregroundBitmapStale); + } + + private void styleScaling(LocationComponentOptions options) { + for (String layerId : layerMap) { + Layer layer = mapboxMap.getLayer(layerId); + if (layer != null && layer instanceof SymbolLayer) { + layer.setProperties( + iconSize( + interpolate(linear(), zoom(), + stop(options.minZoom(), options.minZoomIconScale()), + stop(options.maxZoom(), options.maxZoomIconScale()) + ) + ) + ); + } + } + } + + private void determineIconsSource(LocationComponentOptions options) { + String foregroundIconString = buildIconString( + renderMode == RenderMode.GPS ? options.gpsName() : options.foregroundName(), FOREGROUND_ICON); + String foregroundStaleIconString = buildIconString(options.foregroundStaleName(), FOREGROUND_STALE_ICON); + String backgroundIconString = buildIconString(options.backgroundName(), BACKGROUND_ICON); + String backgroundStaleIconString = buildIconString(options.backgroundStaleName(), BACKGROUND_STALE_ICON); + String bearingIconString = buildIconString(options.bearingName(), BEARING_ICON); + + locationFeature.addStringProperty(PROPERTY_FOREGROUND_ICON, foregroundIconString); + locationFeature.addStringProperty(PROPERTY_BACKGROUND_ICON, backgroundIconString); + locationFeature.addStringProperty(PROPERTY_FOREGROUND_STALE_ICON, foregroundStaleIconString); + locationFeature.addStringProperty(PROPERTY_BACKGROUND_STALE_ICON, backgroundStaleIconString); + locationFeature.addStringProperty(PROPERTY_BEARING_ICON, bearingIconString); + refreshSource(); + } + + private String buildIconString(@Nullable String bitmapName, @NonNull String drawableName) { + if (bitmapName != null) { + return bitmapName; + } + return drawableName; + } + + void setLocationsStale(boolean isStale) { + locationFeature.addBooleanProperty(PROPERTY_LOCATION_STALE, isStale); + refreshSource(); + if (renderMode != RenderMode.GPS) { + setLayerVisibility(ACCURACY_LAYER, !isStale); + } + } + + // + // Map click event + // + + boolean onMapClick(LatLng point) { + PointF screenLoc = mapboxMap.getProjection().toScreenLocation(point); + List<Feature> features = mapboxMap.queryRenderedFeatures(screenLoc, + BACKGROUND_LAYER, + FOREGROUND_LAYER, + BEARING_LAYER + ); + return !features.isEmpty(); + } + + @Override + public void onNewLatLngValue(LatLng latLng) { + Point point = Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude()); + setLocationPoint(point); + } + + @Override + public void onNewGpsBearingValue(float gpsBearing) { + if (renderMode == RenderMode.GPS) { + setBearingProperty(PROPERTY_GPS_BEARING, gpsBearing); + } + } + + @Override + public void onNewCompassBearingValue(float compassBearing) { + if (renderMode == RenderMode.COMPASS) { + setBearingProperty(PROPERTY_COMPASS_BEARING, compassBearing); + } + } + + @Override + public void onNewAccuracyRadiusValue(float accuracyRadiusValue) { + updateAccuracyRadius(accuracyRadiusValue); + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxAnimator.java new file mode 100644 index 000000000..a72bf08a8 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxAnimator.java @@ -0,0 +1,92 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.TypeEvaluator; +import android.animation.ValueAnimator; +import android.support.annotation.IntDef; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; + +/** + * Abstract class for all of the location component animators. + * + * @param <K> Data type that will be animated. + * @param <L> Listener of animation updates. + */ +abstract class MapboxAnimator<K, L> extends ValueAnimator implements ValueAnimator.AnimatorUpdateListener { + @Retention(RetentionPolicy.SOURCE) + @IntDef( { + ANIMATOR_LAYER_LATLNG, + ANIMATOR_CAMERA_LATLNG, + ANIMATOR_LAYER_GPS_BEARING, + ANIMATOR_LAYER_COMPASS_BEARING, + ANIMATOR_CAMERA_GPS_BEARING, + ANIMATOR_CAMERA_COMPASS_BEARING, + ANIMATOR_LAYER_ACCURACY, + ANIMATOR_ZOOM, + ANIMATOR_TILT + }) + @interface Type { + } + + static final int ANIMATOR_LAYER_LATLNG = 0; + static final int ANIMATOR_CAMERA_LATLNG = 1; + static final int ANIMATOR_LAYER_GPS_BEARING = 2; + static final int ANIMATOR_LAYER_COMPASS_BEARING = 3; + static final int ANIMATOR_CAMERA_GPS_BEARING = 4; + static final int ANIMATOR_CAMERA_COMPASS_BEARING = 5; + static final int ANIMATOR_LAYER_ACCURACY = 6; + static final int ANIMATOR_ZOOM = 7; + static final int ANIMATOR_TILT = 8; + + private final int animatorType = provideAnimatorType(); + final List<L> updateListeners; + private final K target; + + MapboxAnimator(K previous, K target, List<L> updateListeners) { + setObjectValues(previous, target); + setEvaluator(provideEvaluator()); + this.updateListeners = updateListeners; + this.target = target; + addUpdateListener(this); + } + + K getTarget() { + return target; + } + + @Type + int getAnimatorType() { + return animatorType; + } + + @Type + abstract int provideAnimatorType(); + + abstract TypeEvaluator provideEvaluator(); + + interface OnLayerAnimationsValuesChangeListener { + void onNewLatLngValue(LatLng latLng); + + void onNewGpsBearingValue(float gpsBearing); + + void onNewCompassBearingValue(float compassBearing); + + void onNewAccuracyRadiusValue(float accuracyRadiusValue); + } + + interface OnCameraAnimationsValuesChangeListener { + void onNewLatLngValue(LatLng latLng); + + void onNewGpsBearingValue(float gpsBearing); + + void onNewCompassBearingValue(float compassBearing); + + void onNewZoomValue(float zoom); + + void onNewTiltValue(float tilt); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxCameraAnimatorAdapter.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxCameraAnimatorAdapter.java new file mode 100644 index 000000000..89d27a38f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxCameraAnimatorAdapter.java @@ -0,0 +1,38 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.support.annotation.Nullable; + +import com.mapbox.mapboxsdk.maps.MapboxMap; + +import java.util.List; + +abstract class MapboxCameraAnimatorAdapter extends + MapboxFloatAnimator<MapboxAnimator.OnCameraAnimationsValuesChangeListener> { + private final MapboxMap.CancelableCallback cancelableCallback; + + MapboxCameraAnimatorAdapter(Float previous, Float target, + List<OnCameraAnimationsValuesChangeListener> updateListeners, + @Nullable MapboxMap.CancelableCallback cancelableCallback) { + super(previous, target, updateListeners); + this.cancelableCallback = cancelableCallback; + addListener(new MapboxAnimatorListener()); + } + + private final class MapboxAnimatorListener extends AnimatorListenerAdapter { + @Override + public void onAnimationCancel(Animator animation) { + if (cancelableCallback != null) { + cancelableCallback.onCancel(); + } + } + + @Override + public void onAnimationEnd(Animator animation) { + if (cancelableCallback != null) { + cancelableCallback.onFinish(); + } + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxFloatAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxFloatAnimator.java new file mode 100644 index 000000000..4a6d8c3b7 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxFloatAnimator.java @@ -0,0 +1,17 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.FloatEvaluator; +import android.animation.TypeEvaluator; + +import java.util.List; + +abstract class MapboxFloatAnimator<L> extends MapboxAnimator<Float, L> { + MapboxFloatAnimator(Float previous, Float target, List<L> updateListeners) { + super(previous, target, updateListeners); + } + + @Override + TypeEvaluator provideEvaluator() { + return new FloatEvaluator(); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxLatLngAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxLatLngAnimator.java new file mode 100644 index 000000000..b2f1b61a2 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxLatLngAnimator.java @@ -0,0 +1,19 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.TypeEvaluator; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.util.List; + +abstract class MapboxLatLngAnimator<L> extends MapboxAnimator<LatLng, L> { + + MapboxLatLngAnimator(LatLng previous, LatLng target, List<L> updateListeners) { + super(previous, target, updateListeners); + } + + @Override + TypeEvaluator provideEvaluator() { + return new LatLngEvaluator(); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnCameraMoveInvalidateListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnCameraMoveInvalidateListener.java new file mode 100644 index 000000000..6594e543f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnCameraMoveInvalidateListener.java @@ -0,0 +1,7 @@ +package com.mapbox.mapboxsdk.location; + +interface OnCameraMoveInvalidateListener { + + void onInvalidateCameraMove(); + +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnCameraTrackingChangedListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnCameraTrackingChangedListener.java new file mode 100644 index 000000000..1ea80d26a --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnCameraTrackingChangedListener.java @@ -0,0 +1,21 @@ +package com.mapbox.mapboxsdk.location; + +import com.mapbox.mapboxsdk.location.modes.CameraMode; + +/** + * Listener that gets invoked when camera tracking state changes. + */ +public interface OnCameraTrackingChangedListener { + /** + * Invoked whenever camera tracking is broken. + * This callback gets invoked just after {@link #onCameraTrackingChanged(int)}, if needed. + */ + void onCameraTrackingDismissed(); + + /** + * Invoked on every {@link CameraMode} change. + * + * @param currentMode current active {@link CameraMode}. + */ + void onCameraTrackingChanged(@CameraMode.Mode int currentMode); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationClickListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationClickListener.java new file mode 100644 index 000000000..fdd2aeb81 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationClickListener.java @@ -0,0 +1,14 @@ +package com.mapbox.mapboxsdk.location; + +/** + * The Location Component exposes an API for listening to when the user clicks on the location + * layer icon visible on the map. When this event occurs, the {@link #onLocationComponentClick()} method + * gets invoked. + */ +public interface OnLocationClickListener { + + /** + * Called whenever user clicks on the location layer drawn on the map. + */ + void onLocationComponentClick(); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationLongClickListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationLongClickListener.java new file mode 100644 index 000000000..0c34614f3 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationLongClickListener.java @@ -0,0 +1,14 @@ +package com.mapbox.mapboxsdk.location; + +/** + * The Location Component exposes an API for listening to when the user long clicks on the location + * layer icon visible on the map. when this event occurs, the {@link #onLocationComponentLongClick()} method + * gets invoked. + */ +public interface OnLocationLongClickListener { + + /** + * Called whenever user long clicks on the location layer drawn on the map. + */ + void onLocationComponentLongClick(); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationStaleListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationStaleListener.java new file mode 100644 index 000000000..6bbe7f34b --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationStaleListener.java @@ -0,0 +1,17 @@ +package com.mapbox.mapboxsdk.location; + +/** + * Listener that can be added as a callback when the last location update + * is considered stale. + * <p> + * The time from the last location update that determines if a location update + * is stale or not is provided by {@link LocationComponentOptions#staleStateTimeout()}. + */ +public interface OnLocationStaleListener { + + /** + * Called when the stale state changes. + * @param isStale true if location is stale, false otherwise + */ + void onStaleStateChange(boolean isStale); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/StaleStateManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/StaleStateManager.java new file mode 100644 index 000000000..c8f6ed58b --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/StaleStateManager.java @@ -0,0 +1,80 @@ +package com.mapbox.mapboxsdk.location; + +import android.os.Handler; + +/** + * Class controls the location stale state when the {@link android.location.Location} hasn't + * been updated in 'x' amount of time. {@link LocationComponentOptions#staleStateTimeout()} can be used to + * control the amount of time before the location's considered stale. + * {@link LocationComponentOptions#enableStaleState()} is available for disabling this behaviour. + */ +class StaleStateManager { + + private boolean isEnabled; + private final OnLocationStaleListener innerOnLocationStaleListeners; + private final Handler handler; + private boolean isStale = true; + private long delayTime; + + StaleStateManager(OnLocationStaleListener innerListener, LocationComponentOptions options) { + innerOnLocationStaleListeners = innerListener; + handler = new Handler(); + isEnabled = options.enableStaleState(); + delayTime = options.staleStateTimeout(); + } + + private Runnable staleStateRunnable = new Runnable() { + @Override + public void run() { + setState(true); + } + }; + + void setEnabled(boolean enabled) { + if (enabled) { + setState(isStale); + } else if (isEnabled) { + onStop(); + innerOnLocationStaleListeners.onStaleStateChange(false); + } + isEnabled = enabled; + } + + boolean isStale() { + return isStale; + } + + void updateLatestLocationTime() { + setState(false); + postTheCallback(); + } + + void setDelayTime(long delayTime) { + this.delayTime = delayTime; + postTheCallback(); + } + + void onStart() { + if (!isStale) { + postTheCallback(); + } + } + + void onStop() { + handler.removeCallbacksAndMessages(null); + } + + private void postTheCallback() { + handler.removeCallbacksAndMessages(null); + handler.postDelayed(staleStateRunnable, delayTime); + } + + private void setState(boolean stale) { + if (stale != isStale) { + isStale = stale; + if (isEnabled) { + innerOnLocationStaleListeners.onStaleStateChange(stale); + } + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/TiltAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/TiltAnimator.java new file mode 100644 index 000000000..8ff0f97a7 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/TiltAnimator.java @@ -0,0 +1,27 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.ValueAnimator; +import android.support.annotation.Nullable; + +import com.mapbox.mapboxsdk.maps.MapboxMap; + +import java.util.List; + +class TiltAnimator extends MapboxCameraAnimatorAdapter { + TiltAnimator(Float previous, Float target, List<OnCameraAnimationsValuesChangeListener> updateListeners, + @Nullable MapboxMap.CancelableCallback cancelableCallback) { + super(previous, target, updateListeners, cancelableCallback); + } + + @Override + int provideAnimatorType() { + return ANIMATOR_TILT; + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + for (OnCameraAnimationsValuesChangeListener listener : updateListeners) { + listener.onNewTiltValue((Float) animation.getAnimatedValue()); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java new file mode 100644 index 000000000..ff0a9ce19 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java @@ -0,0 +1,102 @@ +package com.mapbox.mapboxsdk.location; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.PorterDuff; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.location.Location; +import android.os.Build; +import android.support.annotation.ColorInt; +import android.support.annotation.DrawableRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; + +import com.mapbox.mapboxsdk.maps.MapboxMap; + +public final class Utils { + + private Utils() { + // Class should not be initialized + } + + /** + * Util for finding the shortest path from the current rotated degree to the new degree. + * + * @param heading the new position of the rotation + * @param previousHeading the current position of the rotation + * @return the shortest degree of rotation possible + */ + public static float shortestRotation(float heading, float previousHeading) { + double diff = previousHeading - heading; + if (diff > 180.0f) { + heading += 360.0f; + } else if (diff < -180.0f) { + heading -= 360.f; + } + return heading; + } + + static Bitmap getBitmapFromDrawable(Drawable drawable) { + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } else { + // width and height are equal for all assets since they are ovals. + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } + } + + static Bitmap generateShadow(Drawable drawable, float elevation) { + int width = drawable.getIntrinsicWidth(); + int height = drawable.getIntrinsicHeight(); + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + bitmap = Bitmap.createScaledBitmap(bitmap, + toEven(width + elevation), toEven(height + elevation), false); + return bitmap; + } + + static Drawable getDrawable(@NonNull Context context, @DrawableRes int drawableRes, + @ColorInt Integer tintColor) { + Drawable drawable = ContextCompat.getDrawable(context, drawableRes); + if (tintColor == null) { + return drawable; + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + drawable.setTint(tintColor); + } else { + drawable.mutate().setColorFilter(tintColor, PorterDuff.Mode.SRC_IN); + } + return drawable; + } + + static float calculateZoomLevelRadius(@NonNull MapboxMap mapboxMap, @Nullable Location location) { + if (location == null) { + return 0; + } + double metersPerPixel = mapboxMap.getProjection().getMetersPerPixelAtLatitude( + location.getLatitude()); + return (float) (location.getAccuracy() * (1 / metersPerPixel)); + } + + /** + * Casts the value to an even integer. + */ + private static int toEven(float value) { + int i = (int) (value + .5f); + if (i % 2 == 1) { + return i - 1; + } + return i; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/ZoomAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/ZoomAnimator.java new file mode 100644 index 000000000..323b51fa8 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/ZoomAnimator.java @@ -0,0 +1,28 @@ +package com.mapbox.mapboxsdk.location; + +import android.animation.ValueAnimator; +import android.support.annotation.Nullable; + +import com.mapbox.mapboxsdk.maps.MapboxMap; + +import java.util.List; + +class ZoomAnimator extends MapboxCameraAnimatorAdapter { + + ZoomAnimator(Float previous, Float target, List<OnCameraAnimationsValuesChangeListener> updateListeners, + @Nullable MapboxMap.CancelableCallback cancelableCallback) { + super(previous, target, updateListeners, cancelableCallback); + } + + @Override + int provideAnimatorType() { + return ANIMATOR_ZOOM; + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + for (OnCameraAnimationsValuesChangeListener listener : updateListeners) { + listener.onNewZoomValue((Float) animation.getAnimatedValue()); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/modes/CameraMode.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/modes/CameraMode.java new file mode 100644 index 000000000..51806a33c --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/modes/CameraMode.java @@ -0,0 +1,66 @@ +package com.mapbox.mapboxsdk.location.modes; + +import android.location.Location; +import android.support.annotation.IntDef; + +import com.mapbox.mapboxsdk.location.LocationComponent; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Contains the variety of camera modes which determine how the camera will track + * the user location. + */ +public final class CameraMode { + + private CameraMode() { + // Class should not be initialized + } + + /** + * Determine the camera tracking behavior in the {@link LocationComponent}. + */ + @IntDef( {NONE, NONE_COMPASS, NONE_GPS, TRACKING, TRACKING_COMPASS, TRACKING_GPS, TRACKING_GPS_NORTH}) + @Retention(RetentionPolicy.SOURCE) + public @interface Mode { + } + + /** + * No camera tracking. + */ + public static final int NONE = 0x00000008; + + /** + * Camera does not track location, but does track compass bearing. + */ + public static final int NONE_COMPASS = 0x00000010; + + /** + * Camera does not track location, but does track GPS {@link Location} bearing. + */ + public static final int NONE_GPS = 0x00000016; + + /** + * Camera tracks the user location. + */ + public static final int TRACKING = 0x00000018; + + /** + * Camera tracks the user location, with bearing + * provided by a compass. + */ + public static final int TRACKING_COMPASS = 0x00000020; + + /** + * Camera tracks the user location, with bearing + * provided by a normalized {@link Location#getBearing()}. + */ + public static final int TRACKING_GPS = 0x00000022; + + /** + * Camera tracks the user location, with bearing + * always set to north (0). + */ + public static final int TRACKING_GPS_NORTH = 0x00000024; +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/modes/RenderMode.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/modes/RenderMode.java new file mode 100644 index 000000000..3d20313df --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/modes/RenderMode.java @@ -0,0 +1,45 @@ +package com.mapbox.mapboxsdk.location.modes; + +import android.support.annotation.IntDef; + +import com.mapbox.mapboxsdk.location.CompassEngine; +import com.mapbox.mapboxsdk.location.LocationComponent; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Contains the variety of ways the user location can be rendered on the map. + */ +public final class RenderMode { + + private RenderMode() { + // Class should not be initialized + } + + /** + * One of these constants should be used with {@link LocationComponent#setRenderMode(int)}. + * Mode can be switched at anytime by calling the {@code setLocationLayerMode} method passing + * in the new mode you'd like the location layer to be in. + */ + @IntDef( {COMPASS, GPS, NORMAL}) + @Retention(RetentionPolicy.SOURCE) + public @interface Mode { + } + + /** + * Basic tracking is enabled, bearing ignored. + */ + public static final int NORMAL = 0x00000012; + + /** + * Tracking the user location with bearing considered + * from a {@link CompassEngine}. + */ + public static final int COMPASS = 0x00000004; + + /** + * Tracking the user location with bearing considered from {@link android.location.Location}. + */ + public static final int GPS = 0x00000008; +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/package-info.java new file mode 100644 index 000000000..c871a16eb --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the Mapbox Location layer plugin. + */ +package com.mapbox.mapboxsdk.location;
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index 6fcc2c199..73495f78e 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -44,6 +44,7 @@ import com.mapbox.mapboxsdk.net.ConnectivityReceiver; import com.mapbox.mapboxsdk.offline.OfflineGeometryRegionDefinition; import com.mapbox.mapboxsdk.offline.OfflineRegionDefinition; import com.mapbox.mapboxsdk.offline.OfflineTilePyramidRegionDefinition; +import com.mapbox.mapboxsdk.location.LocationComponent; import com.mapbox.mapboxsdk.storage.FileSource; import com.mapbox.mapboxsdk.utils.BitmapUtils; @@ -178,9 +179,9 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback { Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(), cameraChangeDispatcher); + // MapboxMap mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, proj, registerTouchListener, annotationManager, cameraChangeDispatcher); - mapCallback.attachMapboxMap(mapboxMap); // user input @@ -194,8 +195,13 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback { mapGestureDetector, cameraChangeDispatcher, getWidth(), getHeight()); mapZoomButtonController.bind(uiSettings, zoomListener); + // compass compassView.injectCompassAnimationListener(createCompassAnimationListener(cameraChangeDispatcher)); compassView.setOnClickListener(createCompassClickListener(cameraChangeDispatcher)); + + // LocationComponent + mapboxMap.injectLocationComponent(new LocationComponent(mapboxMap)); + // inject widgets with MapboxMap attrView.setOnClickListener(new AttributionClickListener(context, mapboxMap)); @@ -420,6 +426,10 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback { onMapChangedListeners.clear(); mapCallback.clearOnMapReadyCallbacks(); + if (mapboxMap != null) { + mapboxMap.onDestroy(); + } + if (nativeMapView != null && hasSurface) { // null when destroying an activity programmatically mapbox-navigation-android/issues/503 nativeMapView.destroy(); @@ -1214,11 +1224,17 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback { @Override public void onMapChanged(@MapChange int change) { - if (change == DID_FINISH_LOADING_STYLE && initialLoad) { - initialLoad = false; - mapboxMap.onPreMapReady(); - onMapReady(); - mapboxMap.onPostMapReady(); + if (change == WILL_START_LOADING_MAP && !initialLoad) { + mapboxMap.onStartLoadingMap(); + } else if (change == DID_FINISH_LOADING_STYLE) { + if (initialLoad) { + initialLoad = false; + mapboxMap.onPreMapReady(); + onMapReady(); + mapboxMap.onPostMapReady(); + } else { + mapboxMap.onFinishLoadingStyle(); + } } else if (change == DID_FINISH_RENDERING_FRAME || change == DID_FINISH_RENDERING_FRAME_FULLY_RENDERED) { mapboxMap.onUpdateFullyRendered(); } else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java index 08369bb56..c1392be73 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java @@ -42,6 +42,7 @@ import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; +import com.mapbox.mapboxsdk.location.LocationComponent; import com.mapbox.mapboxsdk.log.Logger; import com.mapbox.mapboxsdk.style.expressions.Expression; import com.mapbox.mapboxsdk.style.layers.Layer; @@ -75,6 +76,7 @@ public final class MapboxMap { private final OnGesturesManagerInteractionListener onGesturesManagerInteractionListener; + private LocationComponent locationComponent; private MapboxMap.OnFpsChangedListener onFpsChangedListener; MapboxMap(NativeMapView map, Transform transform, UiSettings ui, Projection projection, @@ -110,12 +112,14 @@ public final class MapboxMap { // if user hasn't loaded a Style yet nativeMapView.setStyleUrl(Style.MAPBOX_STREETS); } + locationComponent.onStart(); } /** * Called when the hosting Activity/Fragment onStop() method is called. */ void onStop() { + locationComponent.onStop(); } /** @@ -155,6 +159,13 @@ public final class MapboxMap { } /** + * Called when the hosting Activity/Fragment onDestroy()/onDestroyView() method is called. + */ + void onDestroy() { + locationComponent.onDestroy(); + } + + /** * Called before the OnMapReadyCallback is invoked. */ void onPreMapReady() { @@ -175,6 +186,20 @@ public final class MapboxMap { } /** + * Called when the map will start loading style. + */ + void onStartLoadingMap() { + locationComponent.onStartLoadingMap(); + } + + /** + * Called the map finished loading style. + */ + void onFinishLoadingStyle() { + locationComponent.onFinishLoadingStyle(); + } + + /** * Called when the region is changing or has changed. */ void onUpdateRegionChange() { @@ -2284,6 +2309,29 @@ public final class MapboxMap { } // + // LocationComponent + // + + void injectLocationComponent(LocationComponent locationComponent) { + this.locationComponent = locationComponent; + } + + /** + * Returns the {@link LocationComponent} that can be used to display user's location on the map. + * <p> + * Use {@link LocationComponent#activateLocationComponent(Context)} or any overload to activate the component, + * then, enable it with {@link LocationComponent#setLocationComponentEnabled(boolean)}. + * <p> + * You can customize the location icon and more with {@link com.mapbox.mapboxsdk.location.LocationComponentOptions}. + * + * @return the Location Component + */ + @NonNull + public LocationComponent getLocationComponent() { + return locationComponent; + } + + // // Interfaces // diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java index 2322d8211..bdeeeb092 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java @@ -2849,6 +2849,66 @@ public class Expression { } /** + * Returns true if the input string is expected to render legibly. + * Returns false if the input string contains sections that cannot be rendered without potential loss of meaning + * (e.g. Indic scripts that require complex text shaping, + * or right-to-left scripts if the the mapbox-gl-rtl-text plugin is not in use in Mapbox GL JS). + * <p> + * Example usage: + * </p> + * <pre> + * {@code + * mapboxMap.addLayer(new SymbolLayer("layer-id", "source-id") + * .withProperties( + * textField( + * switchCase( + * isSupportedScript(get("name_property")), get("name_property"), + * literal("not-compatible") + * ) + * ) + * )); + * } + * </pre> + * + * @param expression the expression to evaluate + * @return expression + * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-is-supported-script">Style specification</a> + */ + public static Expression isSupportedScript(Expression expression) { + return new Expression("is-supported-script", expression); + } + + /** + * Returns true if the input string is expected to render legibly. + * Returns false if the input string contains sections that cannot be rendered without potential loss of meaning + * (e.g. Indic scripts that require complex text shaping, + * or right-to-left scripts if the the mapbox-gl-rtl-text plugin is not in use in Mapbox GL JS). + * <p> + * Example usage: + * </p> + * <pre> + * {@code + * mapboxMap.addLayer(new SymbolLayer("layer-id", "source-id") + * .withProperties( + * textField( + * switchCase( + * isSupportedScript("ಗೌರವಾರ್ಥವಾಗಿ"), literal("ಗೌರವಾರ್ಥವಾಗಿ"), + * literal("not-compatible") + * ) + * ) + * ); + * } + * </pre> + * + * @param string the string to evaluate + * @return expression + * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-is-supported-script">Style specification</a> + */ + public static Expression isSupportedScript(String string) { + return new Expression("is-supported-script", literal(string)); + } + + /** * Returns the input string converted to uppercase. * <p> * Follows the Unicode Default Case Conversion algorithm diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java index ba3619567..1c87b9004 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java @@ -108,6 +108,27 @@ public final class Property { @Retention(RetentionPolicy.SOURCE) public @interface SYMBOL_PLACEMENT {} + // SYMBOL_Z_ORDER: Controls the order in which overlapping symbols in the same layer are rendered + + /** + * Symbols will be sorted by their y-position relative to the viewport. + */ + public static final String SYMBOL_Z_ORDER_VIEWPORT_Y = "viewport-y"; + /** + * Symbols will be rendered in the same order as the source data with no sorting applied. + */ + public static final String SYMBOL_Z_ORDER_SOURCE = "source"; + + /** + * Controls the order in which overlapping symbols in the same layer are rendered + */ + @StringDef({ + SYMBOL_Z_ORDER_VIEWPORT_Y, + SYMBOL_Z_ORDER_SOURCE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SYMBOL_Z_ORDER {} + // ICON_ROTATION_ALIGNMENT: In combination with `symbol-placement`, determines the rotation behavior of icons. /** diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java index c619d0141..670548f12 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java @@ -1765,6 +1765,26 @@ public class PropertyFactory { } /** + * Controls the order in which overlapping symbols in the same layer are rendered + * + * @param value a String value + * @return property wrapper around String + */ + public static PropertyValue<String> symbolZOrder(@Property.SYMBOL_Z_ORDER String value) { + return new LayoutPropertyValue<>("symbol-z-order", value); + } + + /** + * Controls the order in which overlapping symbols in the same layer are rendered + * + * @param value a String value + * @return property wrapper around String + */ + public static PropertyValue<Expression> symbolZOrder(Expression value) { + return new LayoutPropertyValue<>("symbol-z-order", value); + } + + /** * If true, the icon will be visible even if it collides with other previously drawn symbols. * * @param value a Boolean value diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java index 3c4924bb6..1d45f34bd 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java @@ -171,6 +171,17 @@ public class SymbolLayer extends Layer { } /** + * Get the SymbolZOrder property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getSymbolZOrder() { + checkThread(); + return (PropertyValue<String>) new PropertyValue("symbol-z-order", nativeGetSymbolZOrder()); + } + + /** * Get the IconAllowOverlap property * * @return property wrapper value around Boolean @@ -1005,6 +1016,9 @@ public class SymbolLayer extends Layer { private native Object nativeGetSymbolAvoidEdges(); @Keep + private native Object nativeGetSymbolZOrder(); + + @Keep private native Object nativeGetIconAllowOverlap(); @Keep diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/StringUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/StringUtils.java new file mode 100644 index 000000000..8a0be63de --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/StringUtils.java @@ -0,0 +1,27 @@ +package com.mapbox.mapboxsdk.utils; + +import android.support.annotation.Keep; +import android.support.annotation.NonNull; + +import java.text.Normalizer; + +/** + * String utility class used by core from jni. + */ +@Keep +class StringUtils { + + /** + * Normalises String input and strip diacritics from it. + * + * @return normalised String with stripped diacritics. + */ + @Keep + @NonNull + static String unaccent(@NonNull String value) { + return Normalizer.normalize(value, Normalizer.Form.NFD) + .replaceAll("(\\p{InCombiningDiacriticalMarks}" + + "|\\p{InCombiningDiacriticalMarksForSymbols}" + + "|\\p{InCombiningDiacriticalMarksSupplement})+", ""); + } +} 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 1c3653479..b6f6abeba 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml @@ -107,4 +107,45 @@ <!-- Exposed colors --> <public name="mapbox_blue" type="color" /> + + <public name="mapbox_LocationComponent" type="style"/> + + <public name="mapbox_foregroundDrawable" format="reference" type="attr"/> + <public name="mapbox_foregroundTintColor" format="color" type="attr"/> + <public name="mapbox_backgroundDrawable" format="reference" type="attr"/> + <public name="mapbox_backgroundTintColor" format="color" type="attr"/> + <public name="mapbox_bearingDrawable" format="reference" type="attr"/> + <public name="mapbox_bearingTintColor" format="color" type="attr"/> + <public name="mapbox_navigationDrawable" format="reference" type="attr"/> + + <public name="mapbox_foregroundDrawableStale" format="reference" type="attr"/> + <public name="mapbox_foregroundStaleTintColor" format="color" type="attr"/> + <public name="mapbox_backgroundDrawableStale" format="reference" type="attr"/> + <public name="mapbox_backgroundStaleTintColor" format="color" type="attr"/> + + <public name="mapbox_accuracyAlpha" format="float" type="attr"/> + <public name="mapbox_accuracyColor" format="color" type="attr"/> + + <public name="mapbox_elevation" format="dimension" type="attr"/> + + <public name="mapbox_enableStaleState" format="boolean" type="attr"/> + <public name="mapbox_staleStateTimeout" format="integer" min="0" type="attr"/> + + <!-- Location icon padding --> + <public name="mapbox_iconPaddingLeft" format="integer" type="attr"/> + <public name="mapbox_iconPaddingTop" format="integer" type="attr"/> + <public name="mapbox_iconPaddingRight" format="integer" type="attr"/> + <public name="mapbox_iconPaddingBottom" format="integer" type="attr"/> + + <!-- Map zoom levels --> + <public name="mapbox_maxZoom" format="float" type="attr"/> + <public name="mapbox_minZoom" format="float" type="attr"/> + + <!-- Icon scale based on map zoom levels --> + <public name="mapbox_maxZoomIconScale" format="float" type="attr"/> + <public name="mapbox_minZoomIconScale" format="float" type="attr"/> + + <!-- Camera tracking settings --> + <public name="mapbox_trackingInitialMoveThreshold" format="float" type="attr"/> + <public name="mapbox_trackingMultiFingerMoveThreshold" format="float" type="attr"/> </resources> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_bearing_icon.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_bearing_icon.xml new file mode 100644 index 000000000..51bb1161a --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_bearing_icon.xml @@ -0,0 +1,10 @@ +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:width="44dp" + android:height="44dp" + android:viewportHeight="36.0" + android:viewportWidth="36.0"> + <path + android:fillColor="@color/mapbox_location_layer_blue" + android:pathData="M18,0L23,7L13,7L18,0ZM22.8,7C21.33,6.36 19.71,6 18,6C16.29,6 14.67,6.36 13.2,7L22.8,7Z"/> +</vector> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon.xml new file mode 100644 index 000000000..42f7d35aa --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon.xml @@ -0,0 +1,10 @@ +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:width="14dp" + android:height="14dp" + android:viewportHeight="14.0" + android:viewportWidth="14.0"> + <path + android:fillColor="@color/mapbox_location_layer_blue" + android:pathData="M7,7m-7,0a7,7 0,1 1,14 0a7,7 0,1 1,-14 0"/> +</vector> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon_shadow.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon_shadow.xml new file mode 100644 index 000000000..05e30364d --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon_shadow.xml @@ -0,0 +1,19 @@ +<layer-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:opacity="opaque"> + <item + android:gravity="center"> + <shape + android:shape="oval"> + <size + android:width="22dp" + android:height="22dp"/> + <gradient + android:centerColor="#40000000" + android:endColor="#00000000" + android:gradientRadius="11dp" + android:startColor="#40000000" + android:type="radial"/> + </shape> + </item> +</layer-list>
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon_stale.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon_stale.xml new file mode 100644 index 000000000..ecfb85b2e --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon_stale.xml @@ -0,0 +1,10 @@ +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:width="14dp" + android:height="14dp" + android:viewportHeight="14.0" + android:viewportWidth="14.0"> + <path + android:fillColor="@color/mapbox_location_layer_gray" + android:pathData="M7,7m-7,0a7,7 0,1 1,14 0a7,7 0,1 1,-14 0"/> +</vector> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_puck_icon.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_puck_icon.xml new file mode 100644 index 000000000..4f1326841 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_puck_icon.xml @@ -0,0 +1,17 @@ +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:width="75dp" + android:height="75dp" + android:viewportHeight="75.0" + android:viewportWidth="75.0"> + <path + android:fillAlpha="0.16" + android:fillColor="#263D57" + android:pathData="M37.5,37.5m-37.5,0a37.5,37.5 0,1 1,75 0a37.5,37.5 0,1 1,-75 0"/> + <path + android:fillColor="#FFFFFF" + android:pathData="M37.5,37.5m-28.5,0a28.5,28.5 0,1 1,57 0a28.5,28.5 0,1 1,-57 0"/> + <path + android:fillColor="@color/mapbox_location_layer_blue" + android:pathData="M39.2,28.46C39.01,27.99 38.54,27.68 38.02,27.69C37.5,27.7 37.02,28.01 36.81,28.49L27.05,45.83C26.83,46.32 26.92,46.89 27.28,47.26C27.65,47.64 28.21,47.75 28.71,47.54L37.07,44.03C37.39,43.89 37.75,43.89 38.06,44.02L46.27,47.34C46.75,47.54 47.33,47.42 47.71,47.03C48.09,46.64 48.21,46.07 48,45.59L39.2,28.46Z"/> +</vector> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_stroke_icon.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_stroke_icon.xml new file mode 100644 index 000000000..b4213a7e8 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_stroke_icon.xml @@ -0,0 +1,10 @@ +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:width="22dp" + android:height="22dp" + android:viewportHeight="14.0" + android:viewportWidth="14.0"> + <path + android:fillColor="#ffffff" + android:pathData="M7,7m-7,0a7,7 0,1 1,14 0a7,7 0,1 1,-14 0"/> +</vector> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml index 053da80ad..b279252c4 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml @@ -128,4 +128,51 @@ <enum name="bottom" value="3"/> </attr> </declare-styleable> + + <declare-styleable name="mapbox_LocationComponent"> + <attr name="mapbox_foregroundDrawable" format="reference"/> + <attr name="mapbox_foregroundTintColor" format="color"/> + <attr name="mapbox_backgroundDrawable" format="reference"/> + <attr name="mapbox_backgroundTintColor" format="color"/> + <attr name="mapbox_bearingDrawable" format="reference"/> + <attr name="mapbox_bearingTintColor" format="color"/> + <attr name="mapbox_gpsDrawable" format="reference"/> + + <attr name="mapbox_foregroundDrawableStale" format="reference"/> + <attr name="mapbox_foregroundStaleTintColor" format="color"/> + <attr name="mapbox_backgroundDrawableStale" format="reference"/> + <attr name="mapbox_backgroundStaleTintColor" format="color"/> + + <attr name="mapbox_accuracyAlpha" format="float"/> + <attr name="mapbox_accuracyColor" format="color"/> + + <attr name="mapbox_elevation" format="dimension"/> + + <!-- Stale state --> + <attr name="mapbox_enableStaleState" format="boolean"/> + <attr name="mapbox_staleStateTimeout" format="integer" min="0"/> + + <!-- Location icon padding --> + <attr name="mapbox_iconPaddingLeft" format="integer"/> + <attr name="mapbox_iconPaddingTop" format="integer"/> + <attr name="mapbox_iconPaddingRight" format="integer"/> + <attr name="mapbox_iconPaddingBottom" format="integer"/> + + <!-- Map layer configuration --> + <attr name="mapbox_layer_below" format="string"/> + + <!-- Map zoom levels --> + <attr name="mapbox_maxZoom" format="float"/> + <attr name="mapbox_minZoom" format="float"/> + + <!-- Icon scale based on map zoom levels --> + <attr name="mapbox_maxZoomIconScale" format="float"/> + <attr name="mapbox_minZoomIconScale" format="float"/> + + <!-- Camera tracking settings --> + <attr name="mapbox_trackingGesturesManagement" format="boolean"/> + <attr name="mapbox_trackingInitialMoveThreshold" format="dimension"/> + <attr name="mapbox_trackingMultiFingerMoveThreshold" format="dimension"/> + + </declare-styleable> </resources> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml index 19007f503..565d1c99c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml @@ -3,4 +3,7 @@ <color name="mapbox_gray_dark">#5F5F5F</color> <color name="mapbox_gray">#7D7F80</color> <color name="mapbox_blue">#1E8CAB</color> + + <color name="mapbox_location_layer_blue">#4A90E2</color> + <color name="mapbox_location_layer_gray">#A1B0C0</color> </resources> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml index 00fc05cf6..d2428d8d8 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml @@ -15,4 +15,7 @@ <!--Minimum angular velocity required to start rotation animation--> <dimen name="mapbox_minimum_angular_velocity">0.025dp</dimen> + + <dimen name="mapbox_locationComponentTrackingInitialMoveThreshold">25dp</dimen> + <dimen name="mapbox_locationComponentTrackingMultiFingerMoveThreshold">400dp</dimen> </resources> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml new file mode 100644 index 000000000..122b76ba3 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <style name="mapbox_LocationComponent"> + <item name="mapbox_foregroundDrawable">@drawable/mapbox_user_icon</item> + <item name="mapbox_backgroundDrawable">@drawable/mapbox_user_stroke_icon</item> + <item name="mapbox_bearingDrawable">@drawable/mapbox_user_bearing_icon</item> + <item name="mapbox_gpsDrawable">@drawable/mapbox_user_puck_icon</item> + + <item name="mapbox_foregroundDrawableStale">@drawable/mapbox_user_icon_stale</item> + <item name="mapbox_backgroundDrawableStale">@drawable/mapbox_user_stroke_icon</item> + + <item name="mapbox_accuracyAlpha">0.15</item> + <item name="mapbox_accuracyColor">@color/mapbox_location_layer_blue</item> + + <item name="mapbox_elevation">12dp</item> + + <item name="mapbox_enableStaleState">true</item> + <item name="mapbox_staleStateTimeout">30000</item> + + <!-- Location icon padding --> + <item name="mapbox_iconPaddingLeft">0</item> + <item name="mapbox_iconPaddingTop">0</item> + <item name="mapbox_iconPaddingRight">0</item> + <item name="mapbox_iconPaddingBottom">0</item> + + <!-- Map zoom levels --> + <item name="mapbox_maxZoom">18</item> + <item name="mapbox_minZoom">2</item> + + <!-- Location icon scale based on map zoom levels --> + <item name="mapbox_maxZoomIconScale">1</item> + <item name="mapbox_minZoomIconScale">0.6</item> + + <!-- Camera tracking settings --> + <item name="mapbox_trackingGesturesManagement">false</item> + <item name="mapbox_trackingInitialMoveThreshold">@dimen/mapbox_locationComponentTrackingInitialMoveThreshold</item> + <item name="mapbox_trackingMultiFingerMoveThreshold">@dimen/mapbox_locationComponentTrackingMultiFingerMoveThreshold</item> + + </style> +</resources>
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/CompassEngineTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/CompassEngineTest.java new file mode 100644 index 000000000..bc6437926 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/CompassEngineTest.java @@ -0,0 +1,64 @@ +package com.mapbox.mapboxsdk.location; + +import android.hardware.Sensor; +import android.hardware.SensorManager; +import android.view.WindowManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import static junit.framework.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class CompassEngineTest { + + private LocationComponentCompassEngine compassEngine; + + @Mock + private WindowManager windowManager; + + @Mock + private SensorManager sensorManager; + + @Before + public void setUp() throws Exception { + compassEngine = new LocationComponentCompassEngine(windowManager, sensorManager); + } + + @Test + public void lastKnownCompassBearingAccuracyDefault() { + assertEquals("Last accuracy should match", compassEngine.getLastAccuracySensorStatus(), 0); + } + + @Test + public void lastKnownCompassAccuracyStatusValue() { + Sensor sensor = mock(Sensor.class); + compassEngine.onAccuracyChanged(sensor, 2); + assertEquals("Last accuracy should match", compassEngine.getLastAccuracySensorStatus(), 2); + } + + @Test + public void whenGyroscopeIsNull_fallbackToGravity() { + SensorManager sensorManager = mock(SensorManager.class); + when(sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)).thenReturn(null); + new LocationComponentCompassEngine(windowManager, sensorManager); + + verify(sensorManager, times(1)).getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + } + + @Test + public void whenGyroscopeIsNull_fallbackToMagneticField() { + SensorManager sensorManager = mock(SensorManager.class); + when(sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)).thenReturn(null); + new LocationComponentCompassEngine(windowManager, sensorManager); + + verify(sensorManager, times(1)).getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinatorTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinatorTest.kt new file mode 100644 index 000000000..2c9464261 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinatorTest.kt @@ -0,0 +1,284 @@ +package com.mapbox.mapboxsdk.location + +import android.location.Location +import com.mapbox.mapboxsdk.camera.CameraPosition +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.location.LocationComponentConstants.DEFAULT_TRACKING_TILT_ANIM_DURATION +import com.mapbox.mapboxsdk.location.LocationComponentConstants.DEFAULT_TRACKING_ZOOM_ANIM_DURATION +import com.mapbox.mapboxsdk.location.MapboxAnimator.* +import junit.framework.Assert.assertEquals +import junit.framework.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class LocationAnimatorCoordinatorTest { + + private lateinit var locationAnimatorCoordinator: LocationAnimatorCoordinator + private val cameraPosition: CameraPosition = CameraPosition.DEFAULT + + @Before + fun setUp() { + locationAnimatorCoordinator = LocationAnimatorCoordinator() + } + + @Test + fun feedNewLocation_animatorsAreCreated() { + locationAnimatorCoordinator.feedNewLocation(Location(""), cameraPosition, false) + + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_CAMERA_LATLNG] != null) + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_CAMERA_GPS_BEARING] != null) + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_LATLNG] != null) + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_GPS_BEARING] != null) + } + + @Test + fun feedNewLocation_animatorValue() { + val location = Location("") + location.latitude = 51.0 + location.longitude = 17.0 + location.bearing = 35f + locationAnimatorCoordinator.feedNewLocation(location, cameraPosition, false) + + val cameraLatLngTarget = locationAnimatorCoordinator.animatorArray[ANIMATOR_CAMERA_LATLNG]?.target as LatLng + assertEquals(cameraLatLngTarget.latitude, cameraLatLngTarget.latitude) + + val layerLatLngTarget = locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_LATLNG]?.target as LatLng + assertEquals(layerLatLngTarget.latitude, layerLatLngTarget.latitude) + + val cameraBearingTarget = locationAnimatorCoordinator.animatorArray[ANIMATOR_CAMERA_GPS_BEARING]?.target as Float + assertEquals(location.bearing, cameraBearingTarget) + + val layerBearingTarget = locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_GPS_BEARING]?.target as Float + assertEquals(location.bearing, layerBearingTarget) + } + + @Test + fun feedNewLocation_isNorth_animatorsAreCreated() { + val location = Location("") + location.latitude = 51.0 + location.longitude = 17.0 + location.bearing = 35f + locationAnimatorCoordinator.feedNewLocation(location, cameraPosition, false) + + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_CAMERA_LATLNG] != null) + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_CAMERA_GPS_BEARING] != null) + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_LATLNG] != null) + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_GPS_BEARING] != null) + } + + @Test + fun feedNewLocation_isNorth_animatorValue() { + val location = Location("") + location.latitude = 51.0 + location.longitude = 17.0 + location.bearing = 35f + locationAnimatorCoordinator.feedNewLocation(location, cameraPosition, true) + + val cameraLatLngTarget = locationAnimatorCoordinator.animatorArray[ANIMATOR_CAMERA_LATLNG]?.target as LatLng + assertEquals(cameraLatLngTarget.latitude, cameraLatLngTarget.latitude) + + val layerLatLngTarget = locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_LATLNG]?.target as LatLng + assertEquals(layerLatLngTarget.latitude, layerLatLngTarget.latitude) + + val cameraBearingTarget = locationAnimatorCoordinator.animatorArray[ANIMATOR_CAMERA_GPS_BEARING]?.target as Float + assertEquals(0f, cameraBearingTarget) + + val layerBearingTarget = locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_GPS_BEARING]?.target as Float + assertEquals(location.bearing, layerBearingTarget) + } + + @Test + fun feedNewCompassBearing_animatorsAreCreated() { + locationAnimatorCoordinator.feedNewCompassBearing(77f, cameraPosition) + + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_CAMERA_COMPASS_BEARING] != null) + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_COMPASS_BEARING] != null) + } + + @Test + fun feedNewCompassBearing_animatorValue() { + val bearing = 77f + locationAnimatorCoordinator.feedNewCompassBearing(bearing, cameraPosition) + + val cameraBearingTarget = locationAnimatorCoordinator.animatorArray[ANIMATOR_CAMERA_COMPASS_BEARING]?.target as Float + assertEquals(bearing, cameraBearingTarget) + + val layerBearingTarget = locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_COMPASS_BEARING]?.target as Float + assertEquals(bearing, layerBearingTarget) + } + + @Test + fun feedNewAccuracyRadius_animatorsCreated() { + locationAnimatorCoordinator.feedNewAccuracyRadius(150f, false) + + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_ACCURACY] != null) + } + + @Test + fun feedNewAccuracyRadius_animatorValue() { + val accuracy = 150f + locationAnimatorCoordinator.feedNewAccuracyRadius(accuracy, false) + + val layerAccuracy = locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_ACCURACY]?.target as Float + assertEquals(layerAccuracy, accuracy) + + val animationDuration = locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_ACCURACY]?.duration as Long + assertEquals(LocationComponentConstants.ACCURACY_RADIUS_ANIMATION_DURATION, animationDuration) + } + + @Test + fun feedNewAccuracyRadius_noAnimation_animatorsCreated() { + locationAnimatorCoordinator.feedNewAccuracyRadius(150f, true) + + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_ACCURACY] != null) + } + + @Test + fun feedNewAccuracyRadius_noAnimation_animatorValue() { + val accuracy = 150f + locationAnimatorCoordinator.feedNewAccuracyRadius(accuracy, true) + + val layerAccuracy = locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_ACCURACY]?.target as Float + assertEquals(layerAccuracy, accuracy) + + val animationDuration = locationAnimatorCoordinator.animatorArray[ANIMATOR_LAYER_ACCURACY]?.duration as Long + assertEquals(0L, animationDuration) + } + + @Test + fun feedNewZoomLevel_animatorsCreated() { + locationAnimatorCoordinator.feedNewZoomLevel( + 15.0, + cameraPosition, + DEFAULT_TRACKING_ZOOM_ANIM_DURATION, + null + ) + + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_ZOOM] != null) + } + + @Test + fun feedNewZoomLevel_animatorValue() { + val zoom = 15.0f + locationAnimatorCoordinator.feedNewZoomLevel( + zoom.toDouble(), + cameraPosition, + DEFAULT_TRACKING_ZOOM_ANIM_DURATION, + null + ) + + val animationDuration = locationAnimatorCoordinator.animatorArray[ANIMATOR_ZOOM]?.duration as Long + assertEquals(DEFAULT_TRACKING_ZOOM_ANIM_DURATION, animationDuration) + + val target = locationAnimatorCoordinator.animatorArray[ANIMATOR_ZOOM]?.target as Float + assertEquals(zoom, target) + } + + @Test + fun feedNewTiltLevel_animatorsCreated() { + locationAnimatorCoordinator.feedNewTilt( + 30.0, + cameraPosition, + DEFAULT_TRACKING_TILT_ANIM_DURATION, + null + ) + + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_TILT] != null) + } + + @Test + fun feedNewTiltLevel_animatorValue() { + val tilt = 30.0f + locationAnimatorCoordinator.feedNewTilt( + tilt.toDouble(), + cameraPosition, + DEFAULT_TRACKING_TILT_ANIM_DURATION, + null + ) + + val animationDuration = locationAnimatorCoordinator.animatorArray[ANIMATOR_TILT]?.duration as Long + assertEquals(DEFAULT_TRACKING_TILT_ANIM_DURATION, animationDuration) + + val target = locationAnimatorCoordinator.animatorArray[ANIMATOR_TILT]?.target as Float + assertEquals(tilt, target) + } + + @Test + fun cancelAllAnimators() { + locationAnimatorCoordinator.feedNewLocation(Location(""), cameraPosition, true) + locationAnimatorCoordinator.cancelAllAnimations() + + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_CAMERA_LATLNG] == null) + } + + @Test + fun cancelZoomAnimators() { + locationAnimatorCoordinator.feedNewZoomLevel( + 15.0, + cameraPosition, + DEFAULT_TRACKING_ZOOM_ANIM_DURATION, + null + ) + locationAnimatorCoordinator.cancelZoomAnimation() + + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_ZOOM] == null) + } + + @Test + fun cancelTiltAnimation() { + locationAnimatorCoordinator.feedNewTilt( + 30.0, + cameraPosition, + DEFAULT_TRACKING_TILT_ANIM_DURATION, + null + ) + + locationAnimatorCoordinator.cancelTiltAnimation() + + assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_TILT] == null) + } + + @Test + fun resetAllCameraAnimations_empty() { + locationAnimatorCoordinator.resetAllCameraAnimations(cameraPosition, false) + assertTrue(locationAnimatorCoordinator.animatorArray.size() == 0) + } + + @Test + fun addLayerListener() { + val layerListener = Mockito.mock(OnLayerAnimationsValuesChangeListener::class.java) + locationAnimatorCoordinator.addLayerListener(layerListener) + + assertTrue(locationAnimatorCoordinator.layerListeners.contains(layerListener)) + } + + @Test + fun removeLayerListener() { + val layerListener = Mockito.mock(OnLayerAnimationsValuesChangeListener::class.java) + locationAnimatorCoordinator.addLayerListener(layerListener) + locationAnimatorCoordinator.removeLayerListener(layerListener) + + assertTrue(locationAnimatorCoordinator.layerListeners.isEmpty()) + } + + @Test + fun addCameraListener() { + val cameraListener = Mockito.mock(OnCameraAnimationsValuesChangeListener::class.java) + locationAnimatorCoordinator.addCameraListener(cameraListener) + + assertTrue(locationAnimatorCoordinator.cameraListeners.contains(cameraListener)) + } + + @Test + fun removeCameraListener() { + val cameraListener = Mockito.mock(OnCameraAnimationsValuesChangeListener::class.java) + locationAnimatorCoordinator.addCameraListener(cameraListener) + locationAnimatorCoordinator.removeCameraListener(cameraListener) + + assertTrue(locationAnimatorCoordinator.cameraListeners.isEmpty()) + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java new file mode 100644 index 000000000..616e86bd7 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java @@ -0,0 +1,400 @@ +package com.mapbox.mapboxsdk.location; + +import android.graphics.PointF; + +import com.mapbox.android.gestures.AndroidGesturesManager; +import com.mapbox.android.gestures.MoveGestureDetector; +import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.camera.CameraUpdate; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.location.modes.CameraMode; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.Projection; +import com.mapbox.mapboxsdk.maps.UiSettings; + +import org.junit.Test; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class LocationCameraControllerTest { + + @Test + public void setCameraMode_mapTransitionsAreCancelled() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + + camera.setCameraMode(CameraMode.TRACKING_GPS); + + verify(mapboxMap).cancelTransitions(); + } + + @Test + public void setCameraMode_gestureThresholdIsAdjusted() { + MoveGestureDetector moveGestureDetector = mock(MoveGestureDetector.class); + LocationCameraController camera = buildCamera(moveGestureDetector); + LocationComponentOptions options = mock(LocationComponentOptions.class); + float moveThreshold = 5f; + when(options.trackingInitialMoveThreshold()).thenReturn(moveThreshold); + when(options.trackingGesturesManagement()).thenReturn(true); + camera.initializeOptions(options); + + camera.setCameraMode(CameraMode.TRACKING_GPS); + + verify(moveGestureDetector).setMoveThreshold(moveThreshold); + } + + @Test + public void setCameraMode_gestureThresholdNotAdjustedWhenDisabled() { + MoveGestureDetector moveGestureDetector = mock(MoveGestureDetector.class); + LocationCameraController camera = buildCamera(moveGestureDetector); + LocationComponentOptions options = mock(LocationComponentOptions.class); + float moveThreshold = 5f; + when(options.trackingInitialMoveThreshold()).thenReturn(moveThreshold); + when(options.trackingGesturesManagement()).thenReturn(false); + camera.initializeOptions(options); + + camera.setCameraMode(CameraMode.TRACKING_GPS); + + verify(moveGestureDetector, times(0)).setMoveThreshold(moveThreshold); + verify(moveGestureDetector, times(0)).setMoveThreshold(0f); + } + + @Test + public void setCameraMode_gestureThresholdIsResetWhenNotTracking() { + MoveGestureDetector moveGestureDetector = mock(MoveGestureDetector.class); + LocationCameraController camera = buildCamera(moveGestureDetector); + LocationComponentOptions options = mock(LocationComponentOptions.class); + when(options.trackingGesturesManagement()).thenReturn(true); + camera.initializeOptions(options); + + camera.setCameraMode(CameraMode.NONE); + + verify(moveGestureDetector, times(2)).setMoveThreshold(0f); // one for initialization + } + + @Test + public void setCameraMode_notTrackingAdjustsFocalPoint() { + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class)); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + + camera.setCameraMode(CameraMode.TRACKING_GPS); + camera.setCameraMode(CameraMode.NONE); + + verify(mapboxMap.getUiSettings()).setFocalPoint(null); + } + + @Test + public void setCameraMode_trackingChangeListenerCameraDismissedIsCalled() { + OnCameraTrackingChangedListener internalTrackingChangedListener = mock(OnCameraTrackingChangedListener.class); + LocationCameraController camera = buildCamera(internalTrackingChangedListener); + camera.initializeOptions(mock(LocationComponentOptions.class)); + + camera.setCameraMode(CameraMode.TRACKING_GPS); + camera.setCameraMode(CameraMode.NONE); + + verify(internalTrackingChangedListener).onCameraTrackingDismissed(); + } + + @Test + public void setCameraMode_internalCameraTrackingChangeListenerIsCalled() { + OnCameraTrackingChangedListener internalTrackingChangedListener = mock(OnCameraTrackingChangedListener.class); + LocationCameraController camera = buildCamera(internalTrackingChangedListener); + camera.initializeOptions(mock(LocationComponentOptions.class)); + int cameraMode = CameraMode.NONE; + + camera.setCameraMode(cameraMode); + + verify(internalTrackingChangedListener).onCameraTrackingChanged(cameraMode); + } + + @Test + public void onNewLatLngValue_cameraModeTrackingUpdatesLatLng() { + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class)); + when(mapboxMap.getProjection()).thenReturn(mock(Projection.class)); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.TRACKING); + LatLng latLng = mock(LatLng.class); + + camera.onNewLatLngValue(latLng); + + verify(mapboxMap).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewLatLngValue_cameraModeTrackingGpsNorthUpdatesLatLng() { + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class)); + when(mapboxMap.getProjection()).thenReturn(mock(Projection.class)); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.TRACKING_GPS_NORTH); + LatLng latLng = mock(LatLng.class); + + camera.onNewLatLngValue(latLng); + + verify(mapboxMap).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewLatLngValue_cameraModeTrackingGpsUpdatesLatLng() { + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class)); + when(mapboxMap.getProjection()).thenReturn(mock(Projection.class)); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.TRACKING_GPS); + LatLng latLng = mock(LatLng.class); + + camera.onNewLatLngValue(latLng); + + verify(mapboxMap).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewLatLngValue_cameraModeTrackingCompassUpdatesLatLng() { + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class)); + when(mapboxMap.getProjection()).thenReturn(mock(Projection.class)); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.TRACKING_COMPASS); + LatLng latLng = mock(LatLng.class); + + camera.onNewLatLngValue(latLng); + + verify(mapboxMap).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewLatLngValue_cameraModeNoneIgnored() { + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class)); + when(mapboxMap.getProjection()).thenReturn(mock(Projection.class)); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.NONE); + LatLng latLng = mock(LatLng.class); + + camera.onNewLatLngValue(latLng); + + verify(mapboxMap, times(0)).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewLatLngValue_focalPointIsAdjusted() { + MapboxMap mapboxMap = mock(MapboxMap.class); + UiSettings uiSettings = mock(UiSettings.class); + when(mapboxMap.getUiSettings()).thenReturn(uiSettings); + Projection projection = mock(Projection.class); + PointF pointF = mock(PointF.class); + when(projection.toScreenLocation(any(LatLng.class))).thenReturn(pointF); + when(mapboxMap.getProjection()).thenReturn(projection); + LocationCameraController camera = buildCamera(mapboxMap); + LocationComponentOptions options = mock(LocationComponentOptions.class); + when(options.trackingGesturesManagement()).thenReturn(true); + camera.initializeOptions(options); + camera.setCameraMode(CameraMode.TRACKING); + LatLng latLng = mock(LatLng.class); + + camera.onNewLatLngValue(latLng); + + verify(uiSettings).setFocalPoint(pointF); + } + + @Test + public void onNewGpsBearingValue_cameraModeTrackingGpsUpdatesBearing() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.TRACKING_GPS); + float gpsBearing = 5f; + + camera.onNewGpsBearingValue(gpsBearing); + + verify(mapboxMap).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewGpsBearingValue_cameraModeNoneGpsUpdatesBearing() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.NONE_GPS); + float gpsBearing = 5f; + + camera.onNewGpsBearingValue(gpsBearing); + + verify(mapboxMap).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewGpsBearingValue_cameraModeTrackingNorthUpdatesBearing() { + MapboxMap mapboxMap = mock(MapboxMap.class); + CameraPosition cameraPosition = new CameraPosition.Builder().bearing(7d).build(); + when(mapboxMap.getCameraPosition()).thenReturn(cameraPosition); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.TRACKING_GPS_NORTH); + float gpsBearing = 5f; + + camera.onNewGpsBearingValue(gpsBearing); + + verify(mapboxMap).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewGpsBearingValue_cameraModeTrackingNorthBearingZeroIgnored() { + MapboxMap mapboxMap = mock(MapboxMap.class); + CameraPosition cameraPosition = new CameraPosition.Builder().bearing(0d).build(); + when(mapboxMap.getCameraPosition()).thenReturn(cameraPosition); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.TRACKING_GPS_NORTH); + float gpsBearing = 5f; + + camera.onNewGpsBearingValue(gpsBearing); + + verify(mapboxMap, times(0)).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewGpsBearingValue_cameraModeNoneIgnored() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.NONE); + float gpsBearing = 5f; + + camera.onNewGpsBearingValue(gpsBearing); + + verify(mapboxMap, times(0)).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewCompassBearingValue_cameraModeTrackingCompassUpdatesBearing() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.TRACKING_COMPASS); + float compassBearing = 5f; + + camera.onNewCompassBearingValue(compassBearing); + + verify(mapboxMap).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewCompassBearingValue_cameraModeNoneCompassUpdatesBearing() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.NONE_COMPASS); + float compassBearing = 5f; + + camera.onNewCompassBearingValue(compassBearing); + + verify(mapboxMap).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewCompassBearingValue_cameraModeNoneIgnored() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.NONE); + float compassBearing = 5f; + + camera.onNewCompassBearingValue(compassBearing); + + verify(mapboxMap, times(0)).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void onNewZoomValue_cameraIsUpdated() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationCameraController camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationComponentOptions.class)); + camera.setCameraMode(CameraMode.TRACKING); + float zoom = 5f; + + camera.onNewZoomValue(zoom); + + verify(mapboxMap).moveCamera(any(CameraUpdate.class)); + } + + @Test + public void gesturesManagement_enabled() { + MapboxMap mapboxMap = mock(MapboxMap.class); + AndroidGesturesManager initialGesturesManager = mock(AndroidGesturesManager.class); + AndroidGesturesManager internalGesturesManager = mock(AndroidGesturesManager.class); + LocationCameraController camera = buildCamera(mapboxMap, initialGesturesManager, internalGesturesManager); + LocationComponentOptions options = mock(LocationComponentOptions.class); + when(options.trackingGesturesManagement()).thenReturn(true); + camera.initializeOptions(options); + + verify(mapboxMap).setGesturesManager(internalGesturesManager, true, true); + } + + @Test + public void gesturesManagement_disabled() { + MapboxMap mapboxMap = mock(MapboxMap.class); + AndroidGesturesManager initialGesturesManager = mock(AndroidGesturesManager.class); + AndroidGesturesManager internalGesturesManager = mock(AndroidGesturesManager.class); + LocationCameraController camera = buildCamera(mapboxMap, initialGesturesManager, internalGesturesManager); + LocationComponentOptions options = mock(LocationComponentOptions.class); + when(options.trackingGesturesManagement()).thenReturn(false); + camera.initializeOptions(options); + + verify(mapboxMap).setGesturesManager(initialGesturesManager, true, true); + } + + private LocationCameraController buildCamera(OnCameraTrackingChangedListener onCameraTrackingChangedListener) { + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class)); + MoveGestureDetector moveGestureDetector = mock(MoveGestureDetector.class); + OnCameraMoveInvalidateListener onCameraMoveInvalidateListener = mock(OnCameraMoveInvalidateListener.class); + AndroidGesturesManager initialGesturesManager = mock(AndroidGesturesManager.class); + AndroidGesturesManager internalGesturesManager = mock(AndroidGesturesManager.class); + return new LocationCameraController(mapboxMap, moveGestureDetector, + onCameraTrackingChangedListener, onCameraMoveInvalidateListener, initialGesturesManager, internalGesturesManager); + } + + private LocationCameraController buildCamera(MoveGestureDetector moveGestureDetector) { + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class)); + OnCameraTrackingChangedListener onCameraTrackingChangedListener = mock(OnCameraTrackingChangedListener.class); + OnCameraMoveInvalidateListener onCameraMoveInvalidateListener = mock(OnCameraMoveInvalidateListener.class); + AndroidGesturesManager initialGesturesManager = mock(AndroidGesturesManager.class); + AndroidGesturesManager internalGesturesManager = mock(AndroidGesturesManager.class); + return new LocationCameraController(mapboxMap, moveGestureDetector, + onCameraTrackingChangedListener, onCameraMoveInvalidateListener, initialGesturesManager, internalGesturesManager); + } + + private LocationCameraController buildCamera(MapboxMap mapboxMap) { + MoveGestureDetector moveGestureDetector = mock(MoveGestureDetector.class); + OnCameraTrackingChangedListener onCameraTrackingChangedListener = mock(OnCameraTrackingChangedListener.class); + OnCameraMoveInvalidateListener onCameraMoveInvalidateListener = mock(OnCameraMoveInvalidateListener.class); + AndroidGesturesManager initialGesturesManager = mock(AndroidGesturesManager.class); + AndroidGesturesManager internalGesturesManager = mock(AndroidGesturesManager.class); + return new LocationCameraController(mapboxMap, moveGestureDetector, + onCameraTrackingChangedListener, onCameraMoveInvalidateListener, initialGesturesManager, internalGesturesManager); + } + + private LocationCameraController buildCamera(MapboxMap mapboxMap, AndroidGesturesManager initialGesturesManager, + AndroidGesturesManager internalGesturesManager) { + MoveGestureDetector moveGestureDetector = mock(MoveGestureDetector.class); + OnCameraTrackingChangedListener onCameraTrackingChangedListener = mock(OnCameraTrackingChangedListener.class); + OnCameraMoveInvalidateListener onCameraMoveInvalidateListener = mock(OnCameraMoveInvalidateListener.class); + return new LocationCameraController(mapboxMap, moveGestureDetector, + onCameraTrackingChangedListener, onCameraMoveInvalidateListener, initialGesturesManager, internalGesturesManager); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentOptionsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentOptionsTest.java new file mode 100644 index 000000000..4c25fa840 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentOptionsTest.java @@ -0,0 +1,68 @@ +package com.mapbox.mapboxsdk.location; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; + +import com.mapbox.mapboxsdk.R; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class LocationComponentOptionsTest { + + @Mock + private Context context; + @Mock + private TypedArray array; + @Mock + private Resources resources; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void setUp() throws Exception { + when(context.obtainStyledAttributes(R.style.mapbox_LocationComponent, R.styleable.mapbox_LocationComponent)) + .thenReturn(array); + when(array.getResourceId(R.styleable.mapbox_LocationComponent_mapbox_foregroundDrawable, -1)) + .thenReturn(R.drawable.mapbox_user_icon); + when(context.getResources()).thenReturn(resources); + } + + @Test + public void sanity() throws Exception { + LocationComponentOptions locationComponentOptions = LocationComponentOptions.builder(context) + .accuracyAlpha(0.5f) + .build(); + assertNotNull(locationComponentOptions); + } + + @Test + public void passingOutOfRangeAccuracyAlpha_throwsException() throws Exception { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Accuracy alpha value must be between 0.0 and " + + "1.0."); + LocationComponentOptions.builder(context) + .accuracyAlpha(2f) + .build(); + } + + @Test + public void negativeElevation_causesExceptionToBeThrown() throws Exception { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Invalid shadow size -500.0. Must be >= 0"); + LocationComponentOptions.builder(context) + .elevation(-500) + .build(); + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java new file mode 100644 index 000000000..cb6dcd8fe --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java @@ -0,0 +1,466 @@ +package com.mapbox.mapboxsdk.location; + +import android.graphics.Bitmap; + +import com.google.gson.JsonElement; +import com.mapbox.geojson.Feature; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.location.modes.RenderMode; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.style.layers.Layer; +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; + +import org.junit.Test; + +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BACKGROUND_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BACKGROUND_LAYER; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BACKGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BEARING_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.BEARING_LAYER; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.FOREGROUND_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.FOREGROUND_LAYER; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.FOREGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.LOCATION_SOURCE; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_ACCURACY_RADIUS; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_FOREGROUND_ICON_OFFSET; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_GPS_BEARING; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.PROPERTY_SHADOW_ICON_OFFSET; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.SHADOW_ICON; +import static com.mapbox.mapboxsdk.location.LocationComponentConstants.SHADOW_LAYER; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class LocationLayerControllerTest { + + @Test + public void onInitialization_locationSourceIsAdded() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + GeoJsonSource locationSource = mock(GeoJsonSource.class); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addSource(locationSource); + } + + @Test + public void onInitialization_shadowLayerIsAdded() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + Layer shadowLayer = mock(Layer.class); + when(sourceProvider.generateLayer(SHADOW_LAYER)).thenReturn(shadowLayer); + GeoJsonSource locationSource = mock(GeoJsonSource.class); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addLayerBelow(shadowLayer, BACKGROUND_LAYER); + } + + @Test + public void onInitialization_backgroundLayerIsAdded() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + Layer backgroundLayer = mock(Layer.class); + when(sourceProvider.generateLayer(BACKGROUND_LAYER)).thenReturn(backgroundLayer); + GeoJsonSource locationSource = mock(GeoJsonSource.class); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addLayerBelow(backgroundLayer, FOREGROUND_LAYER); + } + + @Test + public void onInitialization_foregroundLayerIsAdded() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + Layer foregroundLayer = mock(Layer.class); + when(sourceProvider.generateLayer(FOREGROUND_LAYER)).thenReturn(foregroundLayer); + GeoJsonSource locationSource = mock(GeoJsonSource.class); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addLayerBelow(foregroundLayer, BEARING_LAYER); + } + + @Test + public void onInitialization_bearingLayerIsAdded() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + Layer bearingLayer = mock(Layer.class); + when(sourceProvider.generateLayer(BEARING_LAYER)).thenReturn(bearingLayer); + GeoJsonSource locationSource = mock(GeoJsonSource.class); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + String layerBelow = "layer-below"; + when(options.layerBelow()).thenReturn(layerBelow); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addLayerBelow(bearingLayer, layerBelow); + } + + @Test + public void onInitialization_accuracyLayerIsAdded() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + Layer accuracyLayer = mock(Layer.class); + when(sourceProvider.generateAccuracyLayer()).thenReturn(accuracyLayer); + GeoJsonSource locationSource = mock(GeoJsonSource.class); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addLayerBelow(accuracyLayer, BACKGROUND_LAYER); + } + + @Test + public void applyStyle_styleShadowWithValidElevation() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(mock(GeoJsonSource.class)); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + Bitmap bitmap = mock(Bitmap.class); + when(bitmapProvider.generateShadowBitmap(any(LocationComponentOptions.class))).thenReturn(bitmap); + LocationComponentOptions options = mock(LocationComponentOptions.class); + when(options.elevation()).thenReturn(2f); + + // Style is applied on initialization + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addImage(SHADOW_ICON, bitmap); + } + + @Test + public void applyStyle_ignoreStyleShadowWithInvalidElevation() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(mock(GeoJsonSource.class)); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + Bitmap bitmap = mock(Bitmap.class); + when(bitmapProvider.generateShadowBitmap(any(LocationComponentOptions.class))).thenReturn(bitmap); + LocationComponentOptions options = mock(LocationComponentOptions.class); + when(options.elevation()).thenReturn(0f); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap, times(0)).addImage(SHADOW_ICON, bitmap); + } + + @Test + public void applyStyle_styleForegroundFromOptions() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(mock(GeoJsonSource.class)); + LocationComponentOptions options = mock(LocationComponentOptions.class); + int drawableResId = 123; + int tintColor = 456; + when(options.foregroundDrawable()).thenReturn(drawableResId); + when(options.foregroundTintColor()).thenReturn(tintColor); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + Bitmap bitmap = mock(Bitmap.class); + when(bitmapProvider.generateBitmap(drawableResId, tintColor)).thenReturn(bitmap); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addImage(FOREGROUND_ICON, bitmap); + } + + @Test + public void applyStyle_styleForegroundStaleFromOptions() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(mock(GeoJsonSource.class)); + LocationComponentOptions options = mock(LocationComponentOptions.class); + int drawableResId = 123; + int tintColor = 456; + when(options.foregroundDrawableStale()).thenReturn(drawableResId); + when(options.foregroundStaleTintColor()).thenReturn(tintColor); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + Bitmap bitmap = mock(Bitmap.class); + when(bitmapProvider.generateBitmap(drawableResId, tintColor)).thenReturn(bitmap); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addImage(FOREGROUND_STALE_ICON, bitmap); + } + + @Test + public void applyStyle_styleBackgroundFromOptions() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(mock(GeoJsonSource.class)); + LocationComponentOptions options = mock(LocationComponentOptions.class); + int drawableResId = 123; + int tintColor = 456; + when(options.backgroundDrawable()).thenReturn(drawableResId); + when(options.backgroundTintColor()).thenReturn(tintColor); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + Bitmap bitmap = mock(Bitmap.class); + when(bitmapProvider.generateBitmap(drawableResId, tintColor)).thenReturn(bitmap); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addImage(BACKGROUND_ICON, bitmap); + } + + @Test + public void applyStyle_styleBackgroundStaleFromOptions() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(mock(GeoJsonSource.class)); + LocationComponentOptions options = mock(LocationComponentOptions.class); + int drawableResId = 123; + int tintColor = 456; + when(options.backgroundDrawableStale()).thenReturn(drawableResId); + when(options.backgroundStaleTintColor()).thenReturn(tintColor); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + Bitmap bitmap = mock(Bitmap.class); + when(bitmapProvider.generateBitmap(drawableResId, tintColor)).thenReturn(bitmap); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addImage(BACKGROUND_STALE_ICON, bitmap); + } + + @Test + public void applyStyle_styleBearingFromOptions() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(mock(GeoJsonSource.class)); + LocationComponentOptions options = mock(LocationComponentOptions.class); + int drawableResId = 123; + int tintColor = 456; + when(options.bearingDrawable()).thenReturn(drawableResId); + when(options.bearingTintColor()).thenReturn(tintColor); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + Bitmap bitmap = mock(Bitmap.class); + when(bitmapProvider.generateBitmap(drawableResId, tintColor)).thenReturn(bitmap); + + new LocationLayerController(mapboxMap, sourceProvider, buildFeatureProvider(options), bitmapProvider, options); + + verify(mapboxMap).addImage(BEARING_ICON, bitmap); + } + + @Test + public void updateForegroundOffset_foregroundIconPropertyIsUpdated() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + GeoJsonSource locationSource = mock(GeoJsonSource.class); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayerController layer = new LocationLayerController( + mapboxMap, sourceProvider, buildFeatureProvider(locationFeature, options), bitmapProvider, options + ); + + layer.updateForegroundOffset(2d); + + verify(locationFeature).addProperty(eq(PROPERTY_FOREGROUND_ICON_OFFSET), any(JsonElement.class)); + } + + @Test + public void updateForegroundOffset_shadowPropertyIsUpdated() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LayerSourceProvider sourceProvider = buildLayerProvider(); + GeoJsonSource locationSource = mock(GeoJsonSource.class); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayerController layer = new LocationLayerController( + mapboxMap, sourceProvider, buildFeatureProvider(locationFeature, options), bitmapProvider, options + ); + + layer.updateForegroundOffset(2d); + + verify(locationFeature).addProperty(eq(PROPERTY_SHADOW_ICON_OFFSET), any(JsonElement.class)); + } + + @Test + public void onNewLatLngValue_locationFeatureIsUpdated() { + GeoJsonSource locationSource = mock(GeoJsonSource.class); + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getSourceAs(LOCATION_SOURCE)).thenReturn(locationSource); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayerController layer = new LocationLayerController( + mapboxMap, sourceProvider, buildFeatureProvider(locationFeature, options), bitmapProvider, options + ); + + layer.onNewLatLngValue(new LatLng()); + + // wanted twice (once for initialization) + verify(locationSource, times(2)).setGeoJson(locationFeature); + } + + @Test + public void onNewGpsBearingValue_locationFeatureIsUpdated() { + GeoJsonSource locationSource = mock(GeoJsonSource.class); + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getSourceAs(LOCATION_SOURCE)).thenReturn(locationSource); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayerController layer = new LocationLayerController( + mapboxMap, sourceProvider, buildFeatureProvider(locationFeature, options), bitmapProvider, options + ); + layer.setRenderMode(RenderMode.GPS); + float gpsBearing = 2f; + + layer.onNewGpsBearingValue(gpsBearing); + + verify(locationFeature).addNumberProperty(PROPERTY_GPS_BEARING, gpsBearing); + } + + @Test + public void onNewGpsBearingValue_updateIgnoredWithInvalidRenderMode() { + GeoJsonSource locationSource = mock(GeoJsonSource.class); + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getSourceAs(LOCATION_SOURCE)).thenReturn(locationSource); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayerController layer = new LocationLayerController( + mapboxMap, sourceProvider, buildFeatureProvider(locationFeature, options), bitmapProvider, options + ); + layer.setRenderMode(RenderMode.COMPASS); + float gpsBearing = 2f; + + layer.onNewGpsBearingValue(gpsBearing); + + verify(locationFeature, times(0)).addNumberProperty(PROPERTY_GPS_BEARING, gpsBearing); + } + + @Test + public void onNewCompassBearingValue_locationFeatureIsUpdated() { + GeoJsonSource locationSource = mock(GeoJsonSource.class); + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getSourceAs(LOCATION_SOURCE)).thenReturn(locationSource); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayerController layer = new LocationLayerController( + mapboxMap, sourceProvider, buildFeatureProvider(locationFeature, options), bitmapProvider, options + ); + layer.setRenderMode(RenderMode.COMPASS); + float compassBearing = 2f; + + layer.onNewCompassBearingValue(compassBearing); + + verify(locationFeature).addNumberProperty(PROPERTY_COMPASS_BEARING, compassBearing); + } + + @Test + public void onNewCompassBearingValue_updateIgnoredWithInvalidRenderMode() { + GeoJsonSource locationSource = mock(GeoJsonSource.class); + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getSourceAs(LOCATION_SOURCE)).thenReturn(locationSource); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayerController layer = new LocationLayerController( + mapboxMap, sourceProvider, buildFeatureProvider(locationFeature, options), bitmapProvider, options + ); + layer.setRenderMode(RenderMode.GPS); + float compassBearing = 2f; + + layer.onNewCompassBearingValue(compassBearing); + + verify(locationFeature, times(0)).addNumberProperty(PROPERTY_COMPASS_BEARING, compassBearing); + } + + @Test + public void onNewAccuracyRadiusValue_locationFeatureIsUpdated() { + GeoJsonSource locationSource = mock(GeoJsonSource.class); + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getSourceAs(LOCATION_SOURCE)).thenReturn(locationSource); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayerController layer = new LocationLayerController( + mapboxMap, sourceProvider, buildFeatureProvider(locationFeature, options), bitmapProvider, options + ); + float accuracyRadiusValue = 2f; + + layer.onNewAccuracyRadiusValue(accuracyRadiusValue); + + verify(locationFeature).addNumberProperty(PROPERTY_ACCURACY_RADIUS, accuracyRadiusValue); + } + + @Test + public void onNewAccuracyRadiusValue_updateIgnoredWithInvalidRenderMode() { + GeoJsonSource locationSource = mock(GeoJsonSource.class); + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getSourceAs(LOCATION_SOURCE)).thenReturn(locationSource); + LayerSourceProvider sourceProvider = buildLayerProvider(); + when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource); + LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class); + LocationComponentOptions options = mock(LocationComponentOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayerController layer = new LocationLayerController( + mapboxMap, sourceProvider, buildFeatureProvider(locationFeature, options), bitmapProvider, options + ); + layer.setRenderMode(RenderMode.GPS); + float accuracyRadiusValue = 2f; + + layer.onNewAccuracyRadiusValue(accuracyRadiusValue); + + verify(locationFeature, times(0)).addNumberProperty(PROPERTY_ACCURACY_RADIUS, accuracyRadiusValue); + } + + private LayerFeatureProvider buildFeatureProvider(LocationComponentOptions options) { + LayerFeatureProvider provider = mock(LayerFeatureProvider.class); + when(provider.generateLocationFeature(null, options)).thenReturn(mock(Feature.class)); + return provider; + } + + private LayerFeatureProvider buildFeatureProvider(Feature feature, LocationComponentOptions options) { + LayerFeatureProvider provider = mock(LayerFeatureProvider.class); + when(provider.generateLocationFeature(null, options)).thenReturn(feature); + return provider; + } + + private LayerSourceProvider buildLayerProvider() { + LayerSourceProvider layerSourceProvider = mock(LayerSourceProvider.class); + when(layerSourceProvider.generateLayer(SHADOW_LAYER)).thenReturn(mock(Layer.class)); + when(layerSourceProvider.generateLayer(BACKGROUND_LAYER)).thenReturn(mock(Layer.class)); + when(layerSourceProvider.generateLayer(FOREGROUND_LAYER)).thenReturn(mock(Layer.class)); + when(layerSourceProvider.generateLayer(BEARING_LAYER)).thenReturn(mock(Layer.class)); + when(layerSourceProvider.generateAccuracyLayer()).thenReturn(mock(Layer.class)); + return layerSourceProvider; + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/UtilsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/UtilsTest.java new file mode 100644 index 000000000..bf5ee40f4 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/UtilsTest.java @@ -0,0 +1,28 @@ +package com.mapbox.mapboxsdk.location; + +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + +public final class UtilsTest { + + @Test + public void shortestRotation_doesReturnValueDistanceQuickestToZero() throws Exception { + float value = Utils.shortestRotation(0, 181); + assertEquals(360f, value); + value = Utils.shortestRotation(0, 179); + assertEquals(0f, value); + value = Utils.shortestRotation(0, 180); + assertEquals(0f, value); + } + + @Test + public void shortestRotation_doesReturnValueDistanceQuickestToFifty() throws Exception { + float value = Utils.shortestRotation(50, 231); + assertEquals(410f, value); + value = Utils.shortestRotation(50, 229); + assertEquals(50f, value); + value = Utils.shortestRotation(50, 180); + assertEquals(50f, value); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java index 054d9da8a..61105d89b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java @@ -43,6 +43,7 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.has; import static com.mapbox.mapboxsdk.style.expressions.Expression.heatmapDensity; import static com.mapbox.mapboxsdk.style.expressions.Expression.id; import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate; +import static com.mapbox.mapboxsdk.style.expressions.Expression.isSupportedScript; import static com.mapbox.mapboxsdk.style.expressions.Expression.length; import static com.mapbox.mapboxsdk.style.expressions.Expression.let; import static com.mapbox.mapboxsdk.style.expressions.Expression.linear; @@ -1388,4 +1389,18 @@ public class ExpressionTest { String actual = Expression.toString(get("name_en")).toString(); assertEquals("Reverse string conversion should match", expected, actual); } + + @Test + public void testIsSupportedScriptLiteral() { + Object[] expected = new Object[] {"is-supported-script", "ಗೌರವಾರ್ಥವಾಗಿ"}; + Object[] actual = isSupportedScript("ಗೌರವಾರ್ಥವಾಗಿ").toArray(); + assertTrue("expression should match", Arrays.deepEquals(expected, actual)); + } + + @Test + public void testIsSupportedScriptExpressions() { + Object[] expected = new Object[] {"is-supported-script", new Object[] {"get", "property_name"}}; + Object[] actual = isSupportedScript(get("property_name")).toArray(); + assertTrue("expression should match", Arrays.deepEquals(expected, actual)); + } }
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle index cf0a8ed66..dee713ffc 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle +++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle @@ -11,6 +11,9 @@ android { versionCode 13 versionName "6.0.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary true + } } compileOptions { @@ -63,6 +66,7 @@ dependencies { implementation dependenciesList.supportAppcompatV7 implementation dependenciesList.supportRecyclerView implementation dependenciesList.supportDesign + implementation dependenciesList.supportConstraintLayout // implementation dependenciesList.lost implementation dependenciesList.gmsLocation diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt new file mode 100644 index 000000000..aa3e2eea6 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt @@ -0,0 +1,1182 @@ +package com.mapbox.mapboxsdk.location + +import android.Manifest +import android.R +import android.content.Context +import android.graphics.Color +import android.graphics.RectF +import android.location.Location +import android.support.test.espresso.Espresso.onView +import android.support.test.espresso.IdlingRegistry +import android.support.test.espresso.UiController +import android.support.test.espresso.assertion.ViewAssertions.matches +import android.support.test.espresso.matcher.ViewMatchers.* +import android.support.test.rule.GrantPermissionRule +import android.support.test.runner.AndroidJUnit4 +import android.support.v4.content.ContextCompat +import com.mapbox.geojson.Point +import com.mapbox.mapboxsdk.camera.CameraUpdateFactory +import com.mapbox.mapboxsdk.constants.Style +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.location.LocationComponentConstants.* +import com.mapbox.mapboxsdk.location.modes.CameraMode +import com.mapbox.mapboxsdk.location.modes.RenderMode +import com.mapbox.mapboxsdk.location.utils.* +import com.mapbox.mapboxsdk.location.utils.MapboxTestingUtils.Companion.MAPBOX_HEAVY_STYLE +import com.mapbox.mapboxsdk.location.utils.MapboxTestingUtils.Companion.MAP_CONNECTION_DELAY +import com.mapbox.mapboxsdk.location.utils.MapboxTestingUtils.Companion.MAP_RENDER_DELAY +import com.mapbox.mapboxsdk.location.utils.MapboxTestingUtils.Companion.pushSourceUpdates +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest +import com.mapbox.mapboxsdk.testapp.activity.SingleActivity +import com.mapbox.mapboxsdk.utils.ColorUtils +import org.hamcrest.CoreMatchers.* +import org.junit.* +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class LocationComponentTest : BaseActivityTest() { + + @Rule + @JvmField + val permissionRule: GrantPermissionRule = GrantPermissionRule.grant(Manifest.permission.ACCESS_FINE_LOCATION) + + override fun getActivityClass(): Class<*> { + return SingleActivity::class.java + } + + private lateinit var styleChangeIdlingResource: StyleChangeIdlingResource + private val location: Location by lazy { + val initLocation = Location("") + initLocation.latitude = 15.0 + initLocation.longitude = 17.0 + initLocation.bearing = 10f + initLocation.accuracy = 150f + initLocation + } + + @Before + override fun beforeTest() { + super.beforeTest() + styleChangeIdlingResource = StyleChangeIdlingResource() + IdlingRegistry.getInstance().register(styleChangeIdlingResource) + } + + @Test + fun locationComponent_initializesLocationEngineCorrectlyWhenOnesNotProvided() { + validateTestSetup() + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context) + component.isLocationComponentEnabled = true + + val locationEngine = component.locationEngine + assertThat(locationEngine, notNullValue()) + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + assertThat(locationEngine?.isConnected, `is`(true)) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun locationComponent_initializesLocationEngineCorrectlyWhenOnesNotProvidedButHasOptions() { + validateTestSetup() + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent( + context, + LocationComponentOptions.builder(context) + .staleStateTimeout(200) + .enableStaleState(false) + .accuracyAlpha(.5f) + .accuracyColor(Color.BLUE) + .build()) + component.isLocationComponentEnabled = true + + val locationEngine = component.locationEngine + val componentOptions = component.locationComponentOptions + + assertThat(locationEngine, notNullValue()) + assertThat(componentOptions, notNullValue()) + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + assertThat(locationEngine?.isConnected, `is`(true)) + assertThat(componentOptions?.accuracyAlpha(), `is`(.5f)) + assertThat(componentOptions?.accuracyColor(), `is`(Color.BLUE)) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun locationComponent_doesntInitializeEngineWhenNullProvided() { + validateTestSetup() + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent( + context, + null, + LocationComponentOptions.builder(context) + .staleStateTimeout(200) + .enableStaleState(false) + .accuracyAlpha(.5f) + .accuracyColor(Color.BLUE) + .build()) + component.isLocationComponentEnabled = true + + val locationEngine = component.locationEngine + val componentOptions = component.locationComponentOptions + + assertThat(locationEngine, nullValue()) + assertThat(componentOptions, notNullValue()) + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + assertThat(componentOptions?.accuracyAlpha(), `is`(.5f)) + assertThat(componentOptions?.accuracyColor(), `is`(Color.BLUE)) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun settingMapStyleImmediatelyBeforeLoadingComponent_doesStillLoadLayersProperly() { + validateTestSetup() + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + mapboxMap.setStyle(Style.LIGHT) + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + assertThat(component.renderMode, `is`(equalTo(RenderMode.NORMAL))) + assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false)) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun locationComponent_doesntShowUntilFirstLocationFix() { + validateTestSetup() + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + + // Source should be present but empty + val mapView = (rule.activity as SingleActivity).mapView + assertThat(mapboxMap.queryRenderedFeatures( + RectF(0f, 0f, mapView.width.toFloat(), mapView.height.toFloat()), FOREGROUND_LAYER) + .isEmpty(), `is`(true)) + + // Force the first location update + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + // Check if the puck is visible + assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(false)) + } + } + executeComponentTest(componentAction) + } + + // + // Location Layer Options + // + + @Test + fun locationComponentOptions_disablingStaleStateDoesWorkCorrectly() { + validateTestSetup() + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, + null, + LocationComponentOptions.builder(context) + .staleStateTimeout(200) + .enableStaleState(false) + .build()) + component.isLocationComponentEnabled = true + + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + uiController.loopMainThreadForAtLeast(500) + + mapboxMap.querySourceFeatures(LOCATION_SOURCE).also { + it.forEach { + assertThat(it.getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(false)) + } + } + } + } + + executeComponentTest(componentAction) + } + + @Test + fun locationComponentOptions_loadsForegroundBitmapFromNameOption() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, + null, + LocationComponentOptions.builder(context) + .foregroundName("custom-foreground-bitmap") + .backgroundName("custom-background-bitmap") + .foregroundStaleName("custom-foreground-stale-bitmap") + .backgroundStaleName("custom-background-stale-bitmap") + .bearingName("custom-bearing-bitmap") + .build()) + component.isLocationComponentEnabled = true + + val foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.ic_media_play) + foregroundDrawable?.let { + mapboxMap.addImageFromDrawable("custom-foreground-bitmap", it) + mapboxMap.addImageFromDrawable("custom-background-bitmap", it) + mapboxMap.addImageFromDrawable("custom-foreground-stale-bitmap", it) + mapboxMap.addImageFromDrawable("custom-background-stale-bitmap", it) + mapboxMap.addImageFromDrawable("custom-bearing-bitmap", it) + } + + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(false)) + + val feature = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0] + assertThat(feature.getStringProperty(PROPERTY_FOREGROUND_ICON), `is`(equalTo("custom-foreground-bitmap"))) + assertThat(feature.getStringProperty(PROPERTY_BACKGROUND_ICON), `is`(equalTo("custom-background-bitmap"))) + assertThat(feature.getStringProperty(PROPERTY_FOREGROUND_STALE_ICON), `is`(equalTo("custom-foreground-stale-bitmap"))) + assertThat(feature.getStringProperty(PROPERTY_BACKGROUND_STALE_ICON), `is`(equalTo("custom-background-stale-bitmap"))) + assertThat(feature.getStringProperty(PROPERTY_BEARING_ICON), `is`(equalTo("custom-bearing-bitmap"))) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun locationComponentOptions_loadsGpsNameWithGpsRenderMode() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, + null, + LocationComponentOptions.builder(context) + .foregroundName("custom-foreground-bitmap") + .gpsName("custom-gps-bitmap") + .build()) + component.isLocationComponentEnabled = true + + component.renderMode = RenderMode.GPS + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + val foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.ic_media_play) + foregroundDrawable?.let { + mapboxMap.addImageFromDrawable("custom-foreground-bitmap", it) + mapboxMap.addImageFromDrawable("custom-gps-bitmap", it) + } + + val foregroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) + assertThat(foregroundId, `is`(equalTo("custom-gps-bitmap"))) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun locationComponentOptions_customIconNameRevertsToDefault() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, + null, + LocationComponentOptions.builder(context) + .foregroundName("custom-foreground-bitmap") + .gpsName("custom-gps-bitmap") + .build()) + component.isLocationComponentEnabled = true + + component.renderMode = RenderMode.GPS + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + val foregroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) + assertThat(foregroundId, `is`(equalTo("custom-gps-bitmap"))) + + component.applyStyle(LocationComponentOptions.builder(context).build()) + + val renderCheck = { + mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) == FOREGROUND_ICON + } + waitForRenderResult(uiController, renderCheck, true) + assertThat(renderCheck.invoke(), `is`(true)) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun locationComponentOptions_customGpsIconNameChangeBackWithMode() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + component.activateLocationComponent(context, + null, + LocationComponentOptions.builder(context) + .gpsName("custom-gps-bitmap") + .build()) + component.isLocationComponentEnabled = true + + component.renderMode = RenderMode.GPS + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + val foregroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) + assertThat(foregroundId, `is`(equalTo("custom-gps-bitmap"))) + + component.renderMode = RenderMode.NORMAL + + val renderCheck = { + mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) == FOREGROUND_ICON + } + waitForRenderResult(uiController, renderCheck, true) + assertThat(renderCheck.invoke(), `is`(true)) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun stillStaleAfterResuming() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, + null, + LocationComponentOptions.builder(context) + .staleStateTimeout(200) + .build()) + component.isLocationComponentEnabled = true + + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + uiController.loopMainThreadForAtLeast(250) // engaging stale state + + val renderCheck = { + mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE) + } + waitForRenderResult(uiController, renderCheck, true) + assertThat(renderCheck.invoke(), `is`(true)) + + component.onStop() + component.onStart() + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(false)) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun stillNotStaleAfterResuming() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(false)) + + component.onStop() + component.onStart() + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(false)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun locationComponentOptions_accuracyRingWithColor() { + val color = Color.parseColor("#4A90E2") + val rgbaColor = ColorUtils.colorToRgbaString(color) + + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, + null, + LocationComponentOptions.builder(context) + .accuracyColor(color) + .build()) + component.isLocationComponentEnabled = true + + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + // Check that the source property changes correctly + mapboxMap.querySourceFeatures(LOCATION_SOURCE).also { + it.forEach { + assertThat(it.getStringProperty(PROPERTY_ACCURACY_COLOR), `is`(equalTo(rgbaColor))) + } + } + } + } + + executeComponentTest(componentAction) + } + + @Test + fun forceLocationUpdate_doesMoveLocationLayerIconToCorrectPosition() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + val point: Point = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].geometry() as Point + + assertThat(component.locationEngine, nullValue()) + assertEquals(point.latitude(), location.latitude, 0.1) + assertEquals(point.longitude(), location.longitude, 0.1) + } + } + executeComponentTest(componentAction) + } + + @Test + fun disablingComponentHidesPuck() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + val point: Point = mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER)[0].geometry() as Point + assertEquals(point.latitude(), location.latitude, 0.1) + assertEquals(point.longitude(), location.longitude, 0.1) + + component.isLocationComponentEnabled = false + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER, true) + assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(true)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun disablingComponentAndChangingStyleAllowsToEnableAgain() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + component.isLocationComponentEnabled = false + mapboxMap.setStyle(Style.LIGHT) + + component.isLocationComponentEnabled = true + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun lifecycle_isDisabledOnStart() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + assertThat(component.isLocationComponentEnabled, `is`(false)) + component.onStop() + component.onStart() + assertThat(component.isLocationComponentEnabled, `is`(false)) + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + assertThat(component.isLocationComponentEnabled, `is`(true)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun lifecycle_keepsEnabledWhenStoppedAndStarted() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + assertThat(component.isLocationComponentEnabled, `is`(true)) + component.onStop() + component.onStart() + assertThat(component.isLocationComponentEnabled, `is`(true)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun lifecycle_keepsDisabledWhenStoppedAndStarted() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.isLocationComponentEnabled = false + assertThat(component.isLocationComponentEnabled, `is`(false)) + component.onStop() + component.onStart() + assertThat(component.isLocationComponentEnabled, `is`(false)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun lifecycle_ableToChangeStyleAfterResuming() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + + component.onStop() + component.onStart() + + mapboxMap.setStyle(Style.DARK) + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + } + } + executeComponentTest(componentAction) + } + + @Test + fun lifecycle_interruptedDuringStyleChange() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + mapboxMap.setStyle(Style.DARK) + component.onStop() + component.onStart() + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + } + } + executeComponentTest(componentAction) + } + + @Test + fun lifecycle_forceLocationUpdateAfterStopped() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.onStop() + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE).isEmpty(), `is`(true)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun lifecycle_acceptAndReuseLocationUpdatesBeforeLayerStarted() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.onStop() + component.forceLocationUpdate(location) + component.onStart() + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + val point: Point = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].geometry() as Point + assertEquals(point.latitude(), location.latitude, 0.1) + assertEquals(point.longitude(), location.longitude, 0.1) + } + } + executeComponentTest(componentAction) + } + + @Test + fun lifecycle_lifecycleChangeRightAfterStyleReload() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.forceLocationUpdate(location) + mapboxMap.setStyle(Style.LIGHT) + component.onStop() + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + component.onStart() + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + val point: Point = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].geometry() as Point + assertEquals(point.latitude(), location.latitude, 0.1) + assertEquals(point.longitude(), location.longitude, 0.1) + + assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun mapChange_settingComponentStyle() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + styleChangeIdlingResource.waitForStyle((rule.activity as SingleActivity).mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + val options = LocationComponentOptions.builder(context) + .accuracyColor(Color.RED) + .build() + + pushSourceUpdates(styleChangeIdlingResource) { + component.applyStyle(options) + } + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + } + } + executeComponentTest(componentAction) + + // Waiting for style to finish loading while pushing updates + onView(withId(R.id.content)).check(matches(isDisplayed())) + } + + @Test + fun mapChange_forcingLocation() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + styleChangeIdlingResource.waitForStyle((rule.activity as SingleActivity).mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + + pushSourceUpdates(styleChangeIdlingResource) { + component.forceLocationUpdate(location) + } + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + } + } + executeComponentTest(componentAction) + + // Waiting for style to finish loading while pushing updates + onView(withId(R.id.content)).check(matches(isDisplayed())) + } + + @Test + fun mapChange_settingMapStyleBeforeComponentCreation() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + styleChangeIdlingResource.waitForStyle((rule.activity as SingleActivity).mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + + val options = LocationComponentOptions.builder(context) + .accuracyColor(Color.RED) + .build() + + pushSourceUpdates(styleChangeIdlingResource) { + component.forceLocationUpdate(location) + component.applyStyle(options) + } + } + } + executeComponentTest(componentAction) + + // Waiting for style to finish loading while pushing updates + onView(withId(R.id.content)).check(matches(isDisplayed())) + } + + @Test + fun animators_layerBearingCorrect() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.renderMode = RenderMode.GPS + location.bearing = 77f + component.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS + MAP_RENDER_DELAY) + assertEquals(77.0, mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getNumberProperty(PROPERTY_GPS_BEARING) as Double, 0.1) + + location.bearing = 92f + component.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS + MAP_RENDER_DELAY) // Waiting for the animation to finish + assertEquals(92.0, mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getNumberProperty(PROPERTY_GPS_BEARING) as Double, 0.1) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun animators_cameraLatLngBearingCorrect() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.TRACKING_GPS + location.bearing = 77f + component.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS + MAP_RENDER_DELAY) + assertEquals(77.0, mapboxMap.cameraPosition.bearing, 0.1) + assertEquals(location.latitude, mapboxMap.cameraPosition.target.latitude, 0.1) + assertEquals(location.longitude, mapboxMap.cameraPosition.target.longitude, 0.1) + + location.bearing = 92f + location.latitude = 30.0 + location.longitude = 35.0 + component.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS + MAP_RENDER_DELAY) // Waiting for the animation to finish + assertEquals(92.0, mapboxMap.cameraPosition.bearing, 0.1) + assertEquals(location.latitude, mapboxMap.cameraPosition.target.latitude, 0.1) + assertEquals(location.longitude, mapboxMap.cameraPosition.target.longitude, 0.1) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun animators_cameraBearingCorrect() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.NONE_GPS + val latitude = mapboxMap.cameraPosition.target.latitude + val longitude = mapboxMap.cameraPosition.target.longitude + + location.bearing = 77f + component.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS + MAP_RENDER_DELAY) + assertEquals(77.0, mapboxMap.cameraPosition.bearing, 0.1) + assertEquals(latitude, mapboxMap.cameraPosition.target.latitude, 0.1) + assertEquals(longitude, mapboxMap.cameraPosition.target.longitude, 0.1) + + location.bearing = 92f + location.latitude = 30.0 + location.longitude = 35.0 + component.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS + MAP_RENDER_DELAY) + assertEquals(92.0, mapboxMap.cameraPosition.bearing, 0.1) + assertEquals(latitude, mapboxMap.cameraPosition.target.latitude, 0.1) + assertEquals(longitude, mapboxMap.cameraPosition.target.longitude, 0.1) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun animators_cameraNoneCorrect() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.NONE + val latitude = mapboxMap.cameraPosition.target.latitude + val longitude = mapboxMap.cameraPosition.target.longitude + val bearing = mapboxMap.cameraPosition.bearing + + location.bearing = 77f + component.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS + MAP_RENDER_DELAY) + assertEquals(bearing, mapboxMap.cameraPosition.bearing, 0.1) + assertEquals(latitude, mapboxMap.cameraPosition.target.latitude, 0.1) + assertEquals(longitude, mapboxMap.cameraPosition.target.longitude, 0.1) + + location.bearing = 92f + location.latitude = 30.0 + location.longitude = 35.0 + component.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS + MAP_RENDER_DELAY) // Waiting for the animation to finish + assertEquals(bearing, mapboxMap.cameraPosition.bearing, 0.1) + assertEquals(latitude, mapboxMap.cameraPosition.target.latitude, 0.1) + assertEquals(longitude, mapboxMap.cameraPosition.target.longitude, 0.1) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun animators_focalPointAdjustment() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.TRACKING + component.cameraMode = CameraMode.NONE + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + assertThat(mapboxMap.uiSettings.focalPoint, nullValue()) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun animators_dontZoomWhileNotTracking() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.NONE + val zoom = mapboxMap.cameraPosition.zoom + component.zoomWhileTracking(10.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION) + + assertEquals(zoom, mapboxMap.cameraPosition.zoom, 0.1) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun animators_zoomWhileTracking() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.TRACKING + component.zoomWhileTracking(10.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION) + + assertEquals(10.0, mapboxMap.cameraPosition.zoom, 0.1) + } + } + + executeComponentTest(componentAction) + } + + @Test + @Ignore + fun animators_zoomWhileTrackingCanceledOnModeChange() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.TRACKING + component.zoomWhileTracking(15.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION / 2) + component.cameraMode = CameraMode.NONE + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION / 2) + + assertEquals(15.0 / 2.0, mapboxMap.cameraPosition.zoom, 3.0) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun animators_dontZoomWhileStopped() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + + component.cameraMode = CameraMode.TRACKING + val zoom = mapboxMap.cameraPosition.zoom + + component.onStop() + component.zoomWhileTracking(10.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION) + + assertEquals(zoom, mapboxMap.cameraPosition.zoom, 0.1) + } + } + + executeComponentTest(componentAction) + } + + @Test + @Ignore + fun animators_cancelZoomWhileTracking() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.TRACKING + component.zoomWhileTracking(15.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION / 2) + component.cancelZoomWhileTrackingAnimation() + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION / 2) + + assertEquals(15.0 / 2.0, mapboxMap.cameraPosition.zoom, 3.0) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun animators_dontTiltWhileNotTracking() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.NONE + val tilt = mapboxMap.cameraPosition.tilt + component.tiltWhileTracking(30.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION) + + assertEquals(tilt, mapboxMap.cameraPosition.tilt, 0.1) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun animators_tiltWhileTracking() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.TRACKING + component.tiltWhileTracking(30.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION) + + assertEquals(30.0, mapboxMap.cameraPosition.tilt, 0.1) + } + } + + executeComponentTest(componentAction) + } + + @Test + @Ignore + fun animators_tiltWhileTrackingCanceledOnModeChange() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.TRACKING + component.tiltWhileTracking(30.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION / 2) + component.cameraMode = CameraMode.NONE + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION / 2) + + assertEquals(30.0 / 2.0, mapboxMap.cameraPosition.tilt, 3.0) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun animators_dontTiltWhileStopped() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.TRACKING + val tilt = mapboxMap.cameraPosition.tilt + + component.onStop() + component.tiltWhileTracking(30.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION) + + assertEquals(tilt, mapboxMap.cameraPosition.tilt, 0.1) + } + } + + executeComponentTest(componentAction) + } + + @Test + @Ignore + fun animators_cancelTiltWhileTracking() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.TRACKING + component.tiltWhileTracking(30.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION / 2) + component.cancelTiltWhileTrackingAnimation() + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION / 2) + + assertEquals(30.0 / 2.0, mapboxMap.cameraPosition.tilt, 3.0) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun cameraPositionAdjustedToTrackingModeWhenComponentEnabled() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.cameraMode = CameraMode.TRACKING_GPS + component.forceLocationUpdate(location) + component.isLocationComponentEnabled = false + mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(LatLng(51.0, 17.0))) + mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(90.0)) + component.isLocationComponentEnabled = true + uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS + MAP_RENDER_DELAY) + + assertEquals(location.bearing.toDouble(), mapboxMap.cameraPosition.bearing, 0.1) + assertEquals(location.latitude, mapboxMap.cameraPosition.target.latitude, 0.1) + assertEquals(location.longitude, mapboxMap.cameraPosition.target.longitude, 0.1) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun compassEngine_onComponentInitializedDefaultIsProvided() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + assertTrue(component.compassEngine is LocationComponentCompassEngine) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun compassEngine_changesWhenNewProvided() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + val engine: CompassEngine = object : CompassEngine { + override fun addCompassListener(compassListener: CompassListener) { + } + + override fun removeCompassListener(compassListener: CompassListener) { + } + + override fun getLastHeading(): Float { + return 0f + } + + override fun getLastAccuracySensorStatus(): Int { + return 0 + } + + override fun onStart() { + } + + override fun onStop() { + } + } + + component.compassEngine = engine + assertThat(component.compassEngine, notNullValue()) + assertThat(component.compassEngine, `is`(equalTo(engine))) + } + } + + executeComponentTest(componentAction) + } + + @Test + fun defaultLocationEngine_deactivatedWhenDestroyed() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context) + component.isLocationComponentEnabled = true + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + assertThat(component.locationEngine?.isConnected, `is`(true)) + + component.onStop() + component.onDestroy() + assertThat(component.locationEngine?.isConnected, `is`(false)) + } + } + + executeComponentTest(componentAction) + } + + @After + override fun afterTest() { + super.afterTest() + IdlingRegistry.getInstance().unregister(styleChangeIdlingResource) + } + + private fun executeComponentTest(listener: LocationComponentAction.OnPerformLocationComponentAction) { + onView(withId(R.id.content)).perform(LocationComponentAction(mapboxMap, listener)) + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt new file mode 100644 index 000000000..41a349b99 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt @@ -0,0 +1,404 @@ +package com.mapbox.mapboxsdk.location + +import android.Manifest +import android.R +import android.content.Context +import android.location.Location +import android.support.test.espresso.Espresso.onView +import android.support.test.espresso.IdlingRegistry +import android.support.test.espresso.UiController +import android.support.test.espresso.assertion.ViewAssertions.matches +import android.support.test.espresso.matcher.ViewMatchers.isDisplayed +import android.support.test.espresso.matcher.ViewMatchers.withId +import android.support.test.rule.GrantPermissionRule +import android.support.test.rule.GrantPermissionRule.grant +import android.support.test.runner.AndroidJUnit4 +import com.mapbox.mapboxsdk.camera.CameraUpdateFactory +import com.mapbox.mapboxsdk.constants.Style +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.location.LocationComponentConstants.* +import com.mapbox.mapboxsdk.location.modes.RenderMode +import com.mapbox.mapboxsdk.location.utils.* +import com.mapbox.mapboxsdk.location.utils.MapboxTestingUtils.Companion.MAPBOX_HEAVY_STYLE +import com.mapbox.mapboxsdk.location.utils.MapboxTestingUtils.Companion.MAP_CONNECTION_DELAY +import com.mapbox.mapboxsdk.location.utils.MapboxTestingUtils.Companion.MAP_RENDER_DELAY +import com.mapbox.mapboxsdk.location.utils.MapboxTestingUtils.Companion.pushSourceUpdates +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource +import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest +import com.mapbox.mapboxsdk.testapp.activity.SingleActivity +import org.hamcrest.CoreMatchers.`is` +import org.hamcrest.CoreMatchers.notNullValue +import org.hamcrest.Matchers.equalTo +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertThat +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class LocationLayerControllerTest : BaseActivityTest() { + + @Rule + @JvmField + val permissionRule: GrantPermissionRule = grant(Manifest.permission.ACCESS_FINE_LOCATION) + + override fun getActivityClass(): Class<*> { + return SingleActivity::class.java + } + + private lateinit var styleChangeIdlingResource: StyleChangeIdlingResource + private val location: Location by lazy { + val initLocation = Location("") + initLocation.latitude = 15.0 + initLocation.longitude = 17.0 + initLocation.bearing = 10f + initLocation.accuracy = 150f + initLocation + } + + @Before + override fun beforeTest() { + super.beforeTest() + styleChangeIdlingResource = StyleChangeIdlingResource() + IdlingRegistry.getInstance().register(styleChangeIdlingResource) + } + + // + // Location Source + // + + @Test + fun renderModeNormal_sourceDoesGetAdded() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.renderMode = RenderMode.NORMAL + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + assertThat(mapboxMap.getSource(LOCATION_SOURCE), notNullValue()) + } + } + executeComponentTest(componentAction) + } + + // + // Location Layers + // + + @Test + fun renderModeNormal_trackingNormalLayersDoGetAdded() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.renderMode = RenderMode.NORMAL + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun renderModeCompass_bearingLayersDoGetAdded() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.renderMode = RenderMode.COMPASS + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(true)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun renderModeGps_navigationLayersDoGetAdded() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.renderMode = RenderMode.GPS + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(false)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(false)) + assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun dontShowPuckWhenRenderModeSetAndComponentDisabled() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + component.isLocationComponentEnabled = false + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER, shouldDisappear = true) + component.renderMode = RenderMode.GPS + + // waiting for layer to appear or timing out + val renderCheck = { + mapboxMap.isLayerVisible(FOREGROUND_LAYER) + } + waitForRenderResult(uiController, renderCheck, true) + + assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(false)) + assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(false)) + assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(false)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(false)) + assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun whenLocationComponentDisabled_doesSetAllLayersToVisibilityNone() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.renderMode = RenderMode.NORMAL + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + component.isLocationComponentEnabled = false + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER, shouldDisappear = true) + + // Check that all layers visibilities are set to none + assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(false)) + assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(false)) + assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(false)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(false)) + assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun onMapChange_locationComponentLayersDoGetRedrawn() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.renderMode = RenderMode.NORMAL + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + mapboxMap.setStyleUrl(Style.LIGHT) + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + assertThat(component.renderMode, `is`(equalTo(RenderMode.NORMAL))) + + // Check that the Source has been re-added to the new map style + val source: GeoJsonSource? = mapboxMap.getSourceAs(LOCATION_SOURCE) + assertThat(source, notNullValue()) + + // Check that all layers visibilities are set to visible + assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(SHADOW_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true)) + assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun whenStyleChanged_continuesUsingStaleIcons() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.applyStyle(LocationComponentOptions.builder(context).staleStateTimeout(100).build()) + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + uiController.loopMainThreadForAtLeast(150) + + val renderCheck = { + mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE) + } + waitForRenderResult(uiController, renderCheck, true) + + assertThat(renderCheck.invoke(), `is`(true)) + + mapboxMap.setStyleUrl(Style.LIGHT) + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun whenStyleChanged_staleStateChanges() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.applyStyle(LocationComponentOptions.builder(context).staleStateTimeout(1).build()) + styleChangeIdlingResource.waitForStyle((rule.activity as SingleActivity).mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + pushSourceUpdates(styleChangeIdlingResource) { + component.forceLocationUpdate(location) + } + } + } + executeComponentTest(componentAction) + + // Waiting for style to finish loading while pushing updates + onView(withId(R.id.content)).check(matches(isDisplayed())) + } + + @Test + fun whenStyleChanged_layerVisibilityUpdates() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + styleChangeIdlingResource.waitForStyle((rule.activity as SingleActivity).mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + var show = true + component.activateLocationComponent(context, false) + pushSourceUpdates(styleChangeIdlingResource) { + component.isLocationComponentEnabled = show + show = !show + } + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + } + } + executeComponentTest(componentAction) + + // Waiting for style to finish loading while pushing updates + onView(withId(R.id.content)).check(matches(isDisplayed())) + } + + @Test + fun accuracy_visibleWithNewLocation() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(location), 16.0)) + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + uiController.loopMainThreadForAtLeast(ACCURACY_RADIUS_ANIMATION_DURATION) + + assertEquals(Utils.calculateZoomLevelRadius(mapboxMap, location) /*meters projected to radius on zoom 16*/, + mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0] + .getNumberProperty(PROPERTY_ACCURACY_RADIUS).toFloat(), 0.1f) + } + } + executeComponentTest(componentAction) + } + + @Test + fun accuracy_visibleWhenCameraEased() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + val target = LatLng(location) + val zoom = 16.0 + mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(target, zoom), 300) + uiController.loopMainThreadForAtLeast(300) + + val cameraCheck = { + Math.abs(zoom - mapboxMap.cameraPosition.zoom) < 0.1 + && Math.abs(target.latitude - mapboxMap.cameraPosition.target.latitude) < 0.1 + && Math.abs(target.longitude - mapboxMap.cameraPosition.target.longitude) < 0.1 + } + waitForRenderResult(uiController, cameraCheck, true) + + val expectedRadius = Utils.calculateZoomLevelRadius(mapboxMap, location) /*meters projected to radius on zoom 16*/ + val renderCheck = { + Math.abs(expectedRadius - mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getNumberProperty(PROPERTY_ACCURACY_RADIUS).toFloat()) < 0.1 + } + waitForRenderResult(uiController, renderCheck, true) + + assertThat(renderCheck.invoke(), `is`(true)) + } + } + executeComponentTest(componentAction) + } + + @Test + fun accuracy_visibleWhenCameraMoved() { + val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction { + override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + component.activateLocationComponent(context, false) + component.isLocationComponentEnabled = true + component.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + + val target = LatLng(location) + val zoom = 16.0 + mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(target, zoom)) + + val cameraCheck = { + Math.abs(zoom - mapboxMap.cameraPosition.zoom) < 0.1 + && Math.abs(target.latitude - mapboxMap.cameraPosition.target.latitude) < 0.1 + && Math.abs(target.longitude - mapboxMap.cameraPosition.target.longitude) < 0.1 + } + waitForRenderResult(uiController, cameraCheck, true) + + val expectedRadius = Utils.calculateZoomLevelRadius(mapboxMap, location) /*meters projected to radius on zoom 16*/ + val renderCheck = { + Math.abs(expectedRadius - mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getNumberProperty(PROPERTY_ACCURACY_RADIUS).toFloat()) < 0.1 + } + waitForRenderResult(uiController, renderCheck, true) + + assertThat(renderCheck.invoke(), `is`(true)) + } + } + executeComponentTest(componentAction) + } + + @After + override fun afterTest() { + super.afterTest() + IdlingRegistry.getInstance().unregister(styleChangeIdlingResource) + } + + private fun executeComponentTest(listener: LocationComponentAction.OnPerformLocationComponentAction) { + onView(withId(R.id.content)).perform(LocationComponentAction(mapboxMap, listener)) + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/LocationComponentAction.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/LocationComponentAction.kt new file mode 100644 index 000000000..75fae82cf --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/LocationComponentAction.kt @@ -0,0 +1,34 @@ +package com.mapbox.mapboxsdk.location.utils + +import android.content.Context +import android.support.test.espresso.UiController +import android.support.test.espresso.ViewAction +import android.support.test.espresso.matcher.ViewMatchers.isDisplayed +import android.view.View +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.location.LocationComponent +import org.hamcrest.Matcher + +class LocationComponentAction(private val mapboxMap: MapboxMap, + private val onPerformLocationComponentAction: OnPerformLocationComponentAction) : ViewAction { + + override fun getConstraints(): Matcher<View> { + return isDisplayed() + } + + override fun getDescription(): String { + return javaClass.simpleName + } + + override fun perform(uiController: UiController, view: View) { + onPerformLocationComponentAction.onLocationComponentAction( + mapboxMap.locationComponent, + mapboxMap, + uiController, + view.context) + } + + interface OnPerformLocationComponentAction { + fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, uiController: UiController, context: Context) + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/MapboxTestingUtils.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/MapboxTestingUtils.kt new file mode 100644 index 000000000..7d362a6f7 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/MapboxTestingUtils.kt @@ -0,0 +1,113 @@ +package com.mapbox.mapboxsdk.location.utils + +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable +import android.location.Location +import android.os.Handler +import android.os.Looper +import android.support.test.espresso.UiController +import com.mapbox.geojson.Feature +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.style.layers.Property +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource + +fun MapboxMap.querySourceFeatures(sourceId: String): List<Feature> { + return this.getSourceAs<GeoJsonSource>(sourceId)?.querySourceFeatures(null) ?: emptyList() +} + +fun MapboxMap.queryRenderedFeatures(location: Location, layerId: String): List<Feature> { + val latLng = LatLng(location.latitude, location.longitude) + val point = this.projection.toScreenLocation(latLng) + return this.queryRenderedFeatures(point, layerId) +} + +fun MapboxMap.isLayerVisible(layerId: String): Boolean { + return this.getLayer(layerId)?.visibility?.value?.equals(Property.VISIBLE)!! +} + +fun MapboxMap.waitForSource(uiController: UiController, sourceId: String) { + var counter = 0 + val delay = MapboxTestingUtils.MAP_RENDER_DELAY + while (this.querySourceFeatures(sourceId).isEmpty() && delay * counter < MapboxTestingUtils.RENDER_TIMEOUT) { + uiController.loopMainThreadForAtLeast(delay) + counter++ + } +} + +fun MapboxMap.waitForLayer(uiController: UiController, location: Location, layerId: String, shouldDisappear: Boolean = false) { + var counter = 0 + val delay = MapboxTestingUtils.MAP_RENDER_DELAY + while ( + if (shouldDisappear) this.queryRenderedFeatures(location, layerId).isNotEmpty() else this.queryRenderedFeatures(location, layerId).isEmpty() + && delay * counter < MapboxTestingUtils.RENDER_TIMEOUT) { + uiController.loopMainThreadForAtLeast(delay) + counter++ + } +} + +inline fun waitForRenderResult(uiController: UiController, checkFunction: () -> Boolean, expectedResult: Boolean) { + var counter = 0 + val delay = MapboxTestingUtils.MAP_RENDER_DELAY + while (checkFunction.invoke() != expectedResult && delay * counter < MapboxTestingUtils.RENDER_TIMEOUT) { + uiController.loopMainThreadForAtLeast(delay) + counter++ + } +} + +class MapboxTestingUtils { + companion object { + + const val MAP_RENDER_DELAY = 250L + const val MAP_CONNECTION_DELAY = 1000L + const val RENDER_TIMEOUT = 2_500L + + /** + * Used to increase style load time for stress testing. + */ + const val MAPBOX_HEAVY_STYLE = "asset://heavy_style.json" + + private const val DATA_PUSH_INTERVAL = 1L + + /** + * Pushes data updates every [DATA_PUSH_INTERVAL] milliseconds until the style has been loaded, + * checked with [StyleChangeIdlingResource]. + */ + fun pushSourceUpdates(styleChangeIdlingResource: StyleChangeIdlingResource, update: () -> Unit) { + val mainHandler = Handler(Looper.getMainLooper()) + val runnable = object : Runnable { + override fun run() { + update.invoke() + if (!styleChangeIdlingResource.isIdleNow) { + mainHandler.postDelayed(this, DATA_PUSH_INTERVAL) + } + } + } + + if (!styleChangeIdlingResource.isIdleNow) { + if (Looper.myLooper() == Looper.getMainLooper()) { + runnable.run() + } else { + mainHandler.post(runnable) + } + } + } + } +} + +fun MapboxMap.addImageFromDrawable(string: String, drawable: Drawable) { + val bitmapFromDrawable = getBitmapFromDrawable(drawable) + this.addImage(string, bitmapFromDrawable) +} + +private fun getBitmapFromDrawable(drawable: Drawable): Bitmap { + if (drawable is BitmapDrawable) return drawable.bitmap + val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, + drawable.intrinsicHeight, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + drawable.setBounds(0, 0, canvas.width, canvas.height) + drawable.draw(canvas) + return bitmap +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/OnMapFragmentReadyIdlingResource.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/OnMapFragmentReadyIdlingResource.kt new file mode 100644 index 000000000..4d02a4d2b --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/OnMapFragmentReadyIdlingResource.kt @@ -0,0 +1,39 @@ +package com.mapbox.mapboxsdk.location.utils + +import android.os.Handler +import android.os.Looper +import android.support.test.espresso.IdlingResource + +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.maps.OnMapReadyCallback +import com.mapbox.mapboxsdk.maps.SupportMapFragment + +class OnMapFragmentReadyIdlingResource(fragment: SupportMapFragment?) : IdlingResource, OnMapReadyCallback { + + lateinit var mapboxMap: MapboxMap + + private var resourceCallback: IdlingResource.ResourceCallback? = null + + init { + Handler(Looper.getMainLooper()).post { + fragment?.getMapAsync(this) + } + } + + override fun getName(): String { + return javaClass.simpleName + } + + override fun isIdleNow(): Boolean { + return this::mapboxMap.isInitialized + } + + override fun registerIdleTransitionCallback(resourceCallback: IdlingResource.ResourceCallback) { + this.resourceCallback = resourceCallback + } + + override fun onMapReady(mapboxMap: MapboxMap) { + this.mapboxMap = mapboxMap + resourceCallback?.onTransitionToIdle() + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/OnMapReadyIdlingResource.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/OnMapReadyIdlingResource.java new file mode 100644 index 000000000..9adb30ee3 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/OnMapReadyIdlingResource.java @@ -0,0 +1,63 @@ +package com.mapbox.mapboxsdk.location.utils; + +import android.app.Activity; +import android.os.Handler; +import android.os.Looper; +import android.support.test.espresso.IdlingResource; + +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; + +import java.lang.reflect.Field; + +public class OnMapReadyIdlingResource implements IdlingResource, OnMapReadyCallback { + + private MapboxMap mapboxMap; + private MapView mapView; + private IdlingResource.ResourceCallback resourceCallback; + + public OnMapReadyIdlingResource(Activity activity) { + new Handler(Looper.getMainLooper()).post(() -> { + try { + Field field = activity.getClass().getDeclaredField("mapView"); + field.setAccessible(true); + mapView = ((MapView) field.get(activity)); + mapView.getMapAsync(this); + } catch (Exception err) { + throw new RuntimeException(err); + } + }); + } + + @Override + public String getName() { + return getClass().getSimpleName(); + } + + @Override + public boolean isIdleNow() { + return mapboxMap != null; + } + + @Override + public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { + this.resourceCallback = resourceCallback; + } + + public MapView getMapView() { + return mapView; + } + + public MapboxMap getMapboxMap() { + return mapboxMap; + } + + @Override + public void onMapReady(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + if (resourceCallback != null) { + resourceCallback.onTransitionToIdle(); + } + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/StyleChangeIdlingResource.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/StyleChangeIdlingResource.kt new file mode 100644 index 000000000..0f37498a2 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/StyleChangeIdlingResource.kt @@ -0,0 +1,46 @@ +package com.mapbox.mapboxsdk.location.utils + +import android.support.test.espresso.IdlingResource +import com.mapbox.mapboxsdk.maps.MapView +import com.mapbox.mapboxsdk.maps.MapboxMap + +/** + * Resource, that's idling until the provided style is loaded. + * Remember to add any espresso action (like view assertion) after the [waitForStyle] call + * for the test to keep running. + */ +class StyleChangeIdlingResource : IdlingResource { + + private var callback: IdlingResource.ResourceCallback? = null + private var isIdle = true + + override fun getName(): String { + return javaClass.simpleName + } + + override fun isIdleNow(): Boolean { + return isIdle + } + + override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) { + this.callback = callback + } + + private fun setIdle() { + isIdle = true + callback?.onTransitionToIdle() + } + + fun waitForStyle(mapView: MapView, mapboxMap: MapboxMap, styleUrl: String) { + isIdle = false + mapView.addOnMapChangedListener(object : MapView.OnMapChangedListener { + override fun onMapChanged(change: Int) { + if (change == MapView.DID_FINISH_LOADING_STYLE) { + mapView.removeOnMapChangedListener(this) + setIdle() + } + } + }) + mapboxMap.setStyleUrl(styleUrl) + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/MapboxMapAction.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/MapboxMapAction.java index 5e8f3ed36..926212afc 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/MapboxMapAction.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/MapboxMapAction.java @@ -1,5 +1,6 @@ package com.mapbox.mapboxsdk.testapp.action; +import android.support.annotation.NonNull; import android.support.test.espresso.UiController; import android.support.test.espresso.ViewAction; import android.view.View; @@ -42,7 +43,7 @@ public class MapboxMapAction implements ViewAction { } public interface OnInvokeActionListener { - void onInvokeAction(UiController uiController, MapboxMap mapboxMap); + void onInvokeAction(@NonNull UiController uiController, @NonNull MapboxMap mapboxMap); } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java index 5480aa7a1..3682440ae 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java @@ -4,19 +4,24 @@ import android.app.Activity; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.support.test.espresso.Espresso; +import android.support.test.espresso.IdlingRegistry; import android.support.test.espresso.IdlingResourceTimeoutException; import android.support.test.espresso.ViewInteraction; import android.support.test.rule.ActivityTestRule; + import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.testapp.R; import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction; import com.mapbox.mapboxsdk.testapp.action.WaitAction; import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource; + import junit.framework.Assert; + import org.junit.After; import org.junit.Before; import org.junit.Rule; +import org.junit.rules.TestName; + import timber.log.Timber; import static android.support.test.espresso.Espresso.onView; @@ -28,15 +33,19 @@ public abstract class BaseActivityTest { @Rule public ActivityTestRule<Activity> rule = new ActivityTestRule<>(getActivityClass()); + + @Rule + public TestName testNameRule = new TestName(); + protected MapboxMap mapboxMap; protected OnMapReadyIdlingResource idlingResource; @Before public void beforeTest() { try { - Timber.e("@Before test: register idle resource"); + Timber.e(String.format("%s - %s", testNameRule.getMethodName(), "@Before test: register idle resource")); idlingResource = new OnMapReadyIdlingResource(rule.getActivity()); - Espresso.registerIdlingResources(idlingResource); + IdlingRegistry.getInstance().register(idlingResource); checkViewIsDisplayed(R.id.mapView); mapboxMap = idlingResource.getMapboxMap(); } catch (IdlingResourceTimeoutException idlingResourceTimeoutException) { @@ -91,8 +100,8 @@ public abstract class BaseActivityTest { @After public void afterTest() { - Timber.e("@After test: unregister idle resource"); - Espresso.unregisterIdlingResources(idlingResource); + Timber.e(String.format("%s - %s", testNameRule.getMethodName(), "@After test: unregister idle resource")); + IdlingRegistry.getInstance().unregister(idlingResource); } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/string/UppperLowerCaseTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/string/UppperLowerCaseTest.java new file mode 100644 index 000000000..f5b4586a8 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/string/UppperLowerCaseTest.java @@ -0,0 +1,50 @@ +package com.mapbox.mapboxsdk.testapp.string; + +import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest; +import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + +/** + * Test verifying if String#toUpperCase and String#toLowerCase produces desired results + * <p> + * See core test in https://github.com/mapbox/mapbox-gl-native/blob/master/test/util/text_conversions.test.cpp + * </p> + */ +public class UppperLowerCaseTest extends BaseActivityTest { + + @Override + protected Class getActivityClass() { + return EspressoTestActivity.class; + } + + @Test + public void testToUpperCase() { + assertEquals("STREET", "strEEt".toUpperCase()); // EN + assertEquals("ROAD", "rOAd".toUpperCase()); // EN + + assertEquals("STRASSE", "straße".toUpperCase()); // DE + assertEquals("MASSE", "maße".toUpperCase()); // DE + assertEquals("WEISSKOPFSEEADLER", "weißkopfseeadler".toUpperCase()); // DE + + assertEquals("BÊNÇÃO", "bênção".toUpperCase()); // PT + assertEquals("AZƏRBAYCAN", "Azərbaycan".toUpperCase()); // AZ + assertEquals("ὈΔΥΣΣΕΎΣ", "Ὀδυσσεύς".toUpperCase()); // GR + } + + @Test + public void testToLowerCase() { + assertEquals("street", "strEEt".toLowerCase()); // EN + assertEquals("road", "rOAd".toLowerCase()); // EN + + assertEquals("straße", "Straße".toLowerCase()); // DE + assertEquals("strasse", "STRASSE".toLowerCase()); // DE + assertEquals("masse", "MASSE".toLowerCase()); // DE + assertEquals("weisskopfseeadler", "weiSSkopfseeadler".toLowerCase()); // DE + + assertEquals("bênção", "BÊNÇÃO".toLowerCase()); // PT + assertEquals("azərbaycan", "AZƏRBAYCAN".toLowerCase()); // + } + +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java index 8cf452a6c..98c9c27fc 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java @@ -160,6 +160,20 @@ public class SymbolLayerTest extends BaseActivityTest { } @Test + public void testSymbolZOrderAsConstant() { + validateTestSetup(); + setupLayer(); + Timber.i("symbol-z-order"); + invoke(mapboxMap, (uiController, mapboxMap) -> { + assertNotNull(layer); + + // Set and Get + layer.setProperties(symbolZOrder(SYMBOL_Z_ORDER_VIEWPORT_Y)); + assertEquals((String) layer.getSymbolZOrder().getValue(), (String) SYMBOL_Z_ORDER_VIEWPORT_Y); + }); + } + + @Test public void testIconAllowOverlapAsConstant() { validateTestSetup(); setupLayer(); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/debug/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..489ec3f40 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/AndroidManifest.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.mapbox.mapboxsdk.testapp"> + + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> + <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> + <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + + <application> + <activity android:name=".activity.SingleFragmentActivity"/> + <activity android:name=".activity.SingleActivity"/> + + </application> +</manifest>
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/debug/assets/heavy_style.json b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/assets/heavy_style.json new file mode 100644 index 000000000..238ed7d9f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/assets/heavy_style.json @@ -0,0 +1,81857 @@ +{ + "version": 8, + "name": "Streets-copy", + "metadata": { + "mapbox:autocomposite": true, + "mapbox:type": "default", + "mapbox:origin": "streets-v10", + "mapbox:groups": { + "1444934828655.3389": { + "name": "Aeroways", + "collapsed": true + }, + "1444933322393.2852": { + "name": "POI labels (scalerank 1)", + "collapsed": true + }, + "1444855786460.0557": { + "name": "Roads", + "collapsed": true + }, + "1444933575858.6992": { + "name": "Highway shields", + "collapsed": true + }, + "1444934295202.7542": { + "name": "Admin boundaries", + "collapsed": true + }, + "1444856151690.9143": { + "name": "State labels", + "collapsed": true + }, + "1444933721429.3076": { + "name": "Road labels", + "collapsed": true + }, + "1444933358918.2366": { + "name": "POI labels (scalerank 2)", + "collapsed": true + }, + "1444933808272.805": { + "name": "Water labels", + "collapsed": true + }, + "1444933372896.5967": { + "name": "POI labels (scalerank 3)", + "collapsed": true + }, + "1444855799204.86": { + "name": "Bridges", + "collapsed": true + }, + "1444856087950.3635": { + "name": "Marine labels", + "collapsed": true + }, + "1456969573402.7817": { + "name": "Hillshading", + "collapsed": true + }, + "1444862510685.128": { + "name": "City labels", + "collapsed": true + }, + "1444855769305.6016": { + "name": "Tunnels", + "collapsed": true + }, + "1456970288113.8113": { + "name": "Landcover", + "collapsed": true + }, + "1444856144497.7825": { + "name": "Country labels", + "collapsed": true + }, + "1444933456003.5437": { + "name": "POI labels (scalerank 4)", + "collapsed": true + } + }, + "mapbox:sdk-support": { + "js": "0.45.0", + "android": "6.0.0", + "ios": "4.0.0" + } + }, + "center": [ + -122.4241, + 37.78 + ], + "zoom": 9, + "bearing": 0, + "pitch": 0, + "sources": { + "composite": { + "url": "mapbox://mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v7", + "type": "vector" + } + }, + "sprite": "mapbox://sprites/lukaspaczos/cjj5gy5q00ips2rnqgjcneimy", + "glyphs": "mapbox://fonts/lukaspaczos/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "layout": {}, + "paint": { + "background-color": { + "base": 1, + "stops": [ + [ + 11, + "hsl(35, 32%, 91%)" + ], + [ + 13, + "hsl(35, 12%, 89%)" + ] + ] + } + } + }, + { + "id": "landcover_snow", + "type": "fill", + "metadata": { + "mapbox:group": "1456970288113.8113" + }, + "source": "composite", + "source-layer": "landcover", + "filter": [ + "==", + "class", + "snow" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-opacity": 0.2, + "fill-antialias": false + } + }, + { + "id": "landcover_wood", + "type": "fill", + "metadata": { + "mapbox:group": "1456970288113.8113" + }, + "source": "composite", + "source-layer": "landcover", + "maxzoom": 14, + "filter": [ + "==", + "class", + "wood" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(75, 62%, 81%)", + "fill-opacity": { + "base": 1.5, + "stops": [ + [ + 2, + 0.3 + ], + [ + 7, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "landcover_scrub", + "type": "fill", + "metadata": { + "mapbox:group": "1456970288113.8113" + }, + "source": "composite", + "source-layer": "landcover", + "maxzoom": 14, + "filter": [ + "==", + "class", + "scrub" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(75, 62%, 81%)", + "fill-opacity": { + "base": 1.5, + "stops": [ + [ + 2, + 0.3 + ], + [ + 7, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "landcover_grass", + "type": "fill", + "metadata": { + "mapbox:group": "1456970288113.8113" + }, + "source": "composite", + "source-layer": "landcover", + "maxzoom": 14, + "filter": [ + "==", + "class", + "grass" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(75, 62%, 81%)", + "fill-opacity": { + "base": 1.5, + "stops": [ + [ + 2, + 0.3 + ], + [ + 7, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "landcover_crop", + "type": "fill", + "metadata": { + "mapbox:group": "1456970288113.8113" + }, + "source": "composite", + "source-layer": "landcover", + "maxzoom": 14, + "filter": [ + "==", + "class", + "crop" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(75, 62%, 81%)", + "fill-opacity": { + "base": 1.5, + "stops": [ + [ + 2, + 0.3 + ], + [ + 7, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "national_park", + "type": "fill", + "source": "composite", + "source-layer": "landuse_overlay", + "filter": [ + "==", + "class", + "national_park" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(100, 58%, 76%)", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 5, + 0 + ], + [ + 6, + 0.5 + ] + ] + } + } + }, + { + "id": "hospital", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "hospital" + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 15.5, + "hsl(340, 37%, 87%)" + ], + [ + 16, + "hsl(340, 63%, 89%)" + ] + ] + } + } + }, + { + "id": "school", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "school" + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 15.5, + "hsl(50, 47%, 81%)" + ], + [ + 16, + "hsl(50, 63%, 84%)" + ] + ] + } + } + }, + { + "id": "park", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "park" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(100, 58%, 76%)", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 5, + 0 + ], + [ + 6, + 1 + ] + ] + } + } + }, + { + "id": "pitch", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "pitch" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(100, 57%, 72%)" + } + }, + { + "id": "pitch-line", + "type": "line", + "source": "composite", + "source-layer": "landuse", + "minzoom": 15, + "filter": [ + "==", + "class", + "pitch" + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-color": "hsl(75, 57%, 84%)" + } + }, + { + "id": "cemetery", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "cemetery" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(75, 37%, 81%)" + } + }, + { + "id": "industrial", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "industrial" + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 15.5, + "hsl(230, 15%, 86%)" + ], + [ + 16, + "hsl(230, 29%, 89%)" + ] + ] + } + } + }, + { + "id": "sand", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "sand" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(60, 46%, 87%)" + } + }, + { + "id": "hillshade_highlight_bright", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 94 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.12 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "hillshade_highlight_med", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 90 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.12 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "hillshade_shadow_faint", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 89 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(56, 59%, 22%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.05 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "hillshade_shadow_med", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 78 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(56, 59%, 22%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.05 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "hillshade_shadow_dark", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 67 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(56, 59%, 22%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.06 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "hillshade_shadow_extreme", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 56 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(56, 59%, 22%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.06 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "waterway-river-canal", + "type": "line", + "source": "composite", + "source-layer": "waterway", + "minzoom": 8, + "filter": [ + "in", + "class", + "canal", + "river" + ], + "layout": { + "line-cap": { + "base": 1, + "stops": [ + [ + 0, + "butt" + ], + [ + 11, + "round" + ] + ] + }, + "line-join": "round" + }, + "paint": { + "line-color": "hsl(205, 87%, 76%)", + "line-width": { + "base": 1.3, + "stops": [ + [ + 8.5, + 0.1 + ], + [ + 20, + 8 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 8, + 0 + ], + [ + 8.5, + 1 + ] + ] + } + } + }, + { + "id": "waterway-small", + "type": "line", + "source": "composite", + "source-layer": "waterway", + "minzoom": 13, + "filter": [ + "!in", + "class", + "canal", + "river" + ], + "layout": { + "line-join": "round", + "line-cap": "round" + }, + "paint": { + "line-color": "hsl(205, 87%, 76%)", + "line-width": { + "base": 1.35, + "stops": [ + [ + 13.5, + 0.1 + ], + [ + 20, + 3 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13, + 0 + ], + [ + 13.5, + 1 + ] + ] + } + } + }, + { + "id": "water-shadow", + "type": "fill", + "source": "composite", + "source-layer": "water", + "layout": {}, + "paint": { + "fill-color": "hsl(215, 84%, 69%)", + "fill-translate": { + "base": 1.2, + "stops": [ + [ + 7, + [ + 0, + 0 + ] + ], + [ + 16, + [ + -1, + -1 + ] + ] + ] + }, + "fill-translate-anchor": "viewport", + "fill-opacity": 1 + } + }, + { + "id": "water", + "type": "fill", + "source": "composite", + "source-layer": "water", + "layout": {}, + "paint": { + "fill-color": "hsl(196, 80%, 70%)" + } + }, + { + "id": "barrier_line-land-polygon", + "type": "fill", + "source": "composite", + "source-layer": "barrier_line", + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "==", + "class", + "land" + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(35, 12%, 89%)" + } + }, + { + "id": "barrier_line-land-line", + "type": "line", + "source": "composite", + "source-layer": "barrier_line", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "class", + "land" + ] + ], + "layout": { + "line-cap": "round" + }, + "paint": { + "line-width": { + "base": 1.99, + "stops": [ + [ + 14, + 0.75 + ], + [ + 20, + 40 + ] + ] + }, + "line-color": "hsl(35, 12%, 89%)" + } + }, + { + "id": "aeroway-polygon", + "type": "fill", + "metadata": { + "mapbox:group": "1444934828655.3389" + }, + "source": "composite", + "source-layer": "aeroway", + "minzoom": 11, + "filter": [ + "all", + [ + "!=", + "type", + "apron" + ], + [ + "==", + "$type", + "Polygon" + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(230, 23%, 82%)" + ], + [ + 16, + "hsl(230, 37%, 84%)" + ] + ] + }, + "fill-opacity": { + "base": 1, + "stops": [ + [ + 11, + 0 + ], + [ + 11.5, + 1 + ] + ] + } + } + }, + { + "id": "aeroway-runway", + "type": "line", + "metadata": { + "mapbox:group": "1444934828655.3389" + }, + "source": "composite", + "source-layer": "aeroway", + "minzoom": 9, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "type", + "runway" + ] + ], + "layout": {}, + "paint": { + "line-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(230, 23%, 82%)" + ], + [ + 16, + "hsl(230, 37%, 84%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 9, + 1 + ], + [ + 18, + 80 + ] + ] + } + } + }, + { + "id": "aeroway-taxiway", + "type": "line", + "metadata": { + "mapbox:group": "1444934828655.3389" + }, + "source": "composite", + "source-layer": "aeroway", + "minzoom": 9, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "type", + "taxiway" + ] + ], + "layout": {}, + "paint": { + "line-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(230, 23%, 82%)" + ], + [ + 16, + "hsl(230, 37%, 84%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 0.5 + ], + [ + 18, + 20 + ] + ] + } + } + }, + { + "id": "building-line", + "type": "line", + "source": "composite", + "source-layer": "building", + "minzoom": 15, + "filter": [ + "all", + [ + "!=", + "type", + "building:part" + ], + [ + "==", + "underground", + "false" + ] + ], + "layout": {}, + "paint": { + "line-color": "hsl(35, 6%, 79%)", + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 0.75 + ], + [ + 20, + 3 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15.5, + 0 + ], + [ + 16, + 1 + ] + ] + } + } + }, + { + "id": "building", + "type": "fill", + "source": "composite", + "source-layer": "building", + "minzoom": 15, + "filter": [ + "all", + [ + "!=", + "type", + "building:part" + ], + [ + "==", + "underground", + "false" + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(35, 11%, 88%)" + ], + [ + 16, + "hsl(35, 8%, 85%)" + ] + ] + }, + "fill-opacity": { + "base": 1, + "stops": [ + [ + 15.5, + 0 + ], + [ + 16, + 1 + ] + ] + }, + "fill-outline-color": "hsl(35, 6%, 79%)" + } + }, + { + "id": "tunnel-street-low", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "tunnel-street_limited-low", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "tunnel-service-link-track-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 19%, 75%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ] + } + }, + { + "id": "tunnel-street_limited-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 19%, 75%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-street-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 19%, 75%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-secondary-tertiary-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ], + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(230, 19%, 75%)" + } + }, + { + "id": "tunnel-primary-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ], + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(230, 19%, 75%)" + } + }, + { + "id": "tunnel-trunk_link-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ] + } + }, + { + "id": "tunnel-motorway_link-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ] + } + }, + { + "id": "tunnel-trunk-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "==", + "type", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": 1, + "line-dasharray": [ + 3, + 3 + ] + } + }, + { + "id": "tunnel-motorway-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": 1, + "line-dasharray": [ + 3, + 3 + ] + } + }, + { + "id": "tunnel-construction", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "tunnel-path", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-color": "hsl(35, 26%, 95%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-steps", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(35, 26%, 95%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-trunk_link", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 77%, 78%)", + "line-opacity": 1, + "line-dasharray": [ + 1, + 0 + ] + } + }, + { + "id": "tunnel-motorway_link", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 78%)", + "line-opacity": 1, + "line-dasharray": [ + 1, + 0 + ] + } + }, + { + "id": "tunnel-pedestrian", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "tunnel-service-link-track", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": [ + 1, + 0 + ] + } + }, + { + "id": "tunnel-street_limited", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-street", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-secondary-tertiary", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": [ + 1, + 0 + ], + "line-blur": 0 + } + }, + { + "id": "tunnel-primary", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": [ + 1, + 0 + ], + "line-blur": 0 + } + }, + { + "id": "tunnel-oneway-arrows-blue-minor", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "tunnel-oneway-arrows-blue-major", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "tunnel-trunk", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 77%, 78%)" + } + }, + { + "id": "tunnel-motorway", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": 1, + "line-color": "hsl(26, 100%, 78%)", + "line-blur": 0 + } + }, + { + "id": "tunnel-oneway-arrows-white", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "ferry", + "type": "line", + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "type", + "ferry" + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(205, 73%, 63%)" + ], + [ + 17, + "hsl(230, 73%, 63%)" + ] + ] + }, + "line-opacity": 1, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 12, + [ + 1, + 0 + ] + ], + [ + 13, + [ + 12, + 4 + ] + ] + ] + } + } + }, + { + "id": "ferry_auto", + "type": "line", + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "type", + "ferry_auto" + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(205, 73%, 63%)" + ], + [ + 17, + "hsl(230, 73%, 63%)" + ] + ] + }, + "line-opacity": 1, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-path-bg", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-path-bg copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill copy", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern copy", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon copy", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-path-bg copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill copy 1", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern copy 1", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon copy 1", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-path-bg copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill copy 2", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern copy 2", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon copy 2", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-path-bg copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill copy 3", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern copy 3", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon copy 3", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-path-bg copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill copy 4", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern copy 4", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon copy 4", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "bridge-path-bg", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-path-bg copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2 copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2 copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2 copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2 copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-path-bg copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2 copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2 copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2 copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2 copy 1", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-path-bg copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2 copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2 copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2 copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2 copy 2", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-path-bg copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2 copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2 copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2 copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2 copy 3", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-path-bg copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2 copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2 copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2 copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2 copy 4", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "aerialway", + "type": "line", + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "class", + "aerialway" + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": "hsl(230, 10%, 74%)", + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "admin-3-4-boundaries-bg", + "type": "line", + "metadata": { + "mapbox:group": "1444934295202.7542" + }, + "source": "composite", + "source-layer": "admin", + "filter": [ + "all", + [ + "==", + "maritime", + 0 + ], + [ + ">=", + "admin_level", + 3 + ] + ], + "layout": { + "line-join": "bevel" + }, + "paint": { + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(35, 12%, 89%)" + ], + [ + 16, + "hsl(230, 49%, 90%)" + ] + ] + }, + "line-width": { + "base": 1, + "stops": [ + [ + 7, + 3.75 + ], + [ + 12, + 5.5 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 7, + 0 + ], + [ + 8, + 0.75 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-translate": [ + 0, + 0 + ], + "line-blur": { + "base": 1, + "stops": [ + [ + 3, + 0 + ], + [ + 8, + 3 + ] + ] + } + } + }, + { + "id": "admin-2-boundaries-bg", + "type": "line", + "metadata": { + "mapbox:group": "1444934295202.7542" + }, + "source": "composite", + "source-layer": "admin", + "minzoom": 1, + "filter": [ + "all", + [ + "==", + "admin_level", + 2 + ], + [ + "==", + "maritime", + 0 + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1, + "stops": [ + [ + 3, + 3.5 + ], + [ + 10, + 8 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(35, 12%, 89%)" + ], + [ + 8, + "hsl(230, 49%, 90%)" + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 3, + 0 + ], + [ + 4, + 0.5 + ] + ] + }, + "line-translate": [ + 0, + 0 + ], + "line-blur": { + "base": 1, + "stops": [ + [ + 3, + 0 + ], + [ + 10, + 2 + ] + ] + } + } + }, + { + "id": "admin-3-4-boundaries", + "type": "line", + "metadata": { + "mapbox:group": "1444934295202.7542" + }, + "source": "composite", + "source-layer": "admin", + "filter": [ + "all", + [ + "==", + "maritime", + 0 + ], + [ + ">=", + "admin_level", + 3 + ] + ], + "layout": { + "line-join": "round", + "line-cap": "round" + }, + "paint": { + "line-dasharray": { + "base": 1, + "stops": [ + [ + 6, + [ + 2, + 0 + ] + ], + [ + 7, + [ + 2, + 2, + 6, + 2 + ] + ] + ] + }, + "line-width": { + "base": 1, + "stops": [ + [ + 7, + 0.75 + ], + [ + 12, + 1.5 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 2, + 0 + ], + [ + 3, + 1 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 3, + "hsl(230, 14%, 77%)" + ], + [ + 7, + "hsl(230, 8%, 62%)" + ] + ] + } + } + }, + { + "id": "admin-2-boundaries", + "type": "line", + "metadata": { + "mapbox:group": "1444934295202.7542" + }, + "source": "composite", + "source-layer": "admin", + "minzoom": 1, + "filter": [ + "all", + [ + "==", + "admin_level", + 2 + ], + [ + "==", + "disputed", + 0 + ], + [ + "==", + "maritime", + 0 + ] + ], + "layout": { + "line-join": "round", + "line-cap": "round" + }, + "paint": { + "line-color": "hsl(230, 8%, 51%)", + "line-width": { + "base": 1, + "stops": [ + [ + 3, + 0.5 + ], + [ + 10, + 2 + ] + ] + } + } + }, + { + "id": "admin-2-boundaries-dispute", + "type": "line", + "metadata": { + "mapbox:group": "1444934295202.7542" + }, + "source": "composite", + "source-layer": "admin", + "minzoom": 1, + "filter": [ + "all", + [ + "==", + "admin_level", + 2 + ], + [ + "==", + "disputed", + 1 + ], + [ + "==", + "maritime", + 0 + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-dasharray": [ + 1.5, + 1.5 + ], + "line-color": "hsl(230, 8%, 51%)", + "line-width": { + "base": 1, + "stops": [ + [ + 3, + 0.5 + ], + [ + 10, + 2 + ] + ] + } + } + }, + { + "id": "housenum-label", + "type": "symbol", + "source": "composite", + "source-layer": "housenum_label", + "minzoom": 17, + "layout": { + "text-field": "{house_num}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-padding": 4, + "text-max-width": 7, + "text-size": 9.5 + }, + "paint": { + "text-color": "hsl(35, 2%, 69%)", + "text-halo-color": "hsl(35, 8%, 85%)", + "text-halo-width": 0.5, + "text-halo-blur": 0 + } + }, + { + "id": "housenum-label copy", + "type": "symbol", + "source": "composite", + "source-layer": "housenum_label", + "minzoom": 17, + "layout": { + "text-field": "{house_num}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-padding": 4, + "text-max-width": 7, + "text-size": 9.5 + }, + "paint": { + "text-color": "hsl(35, 2%, 69%)", + "text-halo-color": "hsl(35, 8%, 85%)", + "text-halo-width": 0.5, + "text-halo-blur": 0 + } + }, + { + "id": "housenum-label copy 1", + "type": "symbol", + "source": "composite", + "source-layer": "housenum_label", + "minzoom": 17, + "layout": { + "text-field": "{house_num}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-padding": 4, + "text-max-width": 7, + "text-size": 9.5 + }, + "paint": { + "text-color": "hsl(35, 2%, 69%)", + "text-halo-color": "hsl(35, 8%, 85%)", + "text-halo-width": 0.5, + "text-halo-blur": 0 + } + }, + { + "id": "waterway-label", + "type": "symbol", + "source": "composite", + "source-layer": "waterway_label", + "minzoom": 12, + "filter": [ + "in", + "class", + "canal", + "river" + ], + "layout": { + "text-field": "{name_en}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-pitch-alignment": "viewport", + "text-max-angle": 30, + "text-size": { + "base": 1, + "stops": [ + [ + 13, + 12 + ], + [ + 18, + 16 + ] + ] + } + }, + "paint": { + "text-halo-width": 0.5, + "text-halo-color": "hsl(196, 80%, 70%)", + "text-color": "hsl(230, 48%, 44%)", + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-scalerank4-l15", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933456003.5437" + }, + "source": "composite", + "source-layer": "poi_label", + "minzoom": 17, + "filter": [ + "all", + [ + "!in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ], + [ + "==", + "scalerank", + 4 + ], + [ + ">=", + "localrank", + 15 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{maki}-11", + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-scalerank4-l1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933456003.5437" + }, + "source": "composite", + "source-layer": "poi_label", + "minzoom": 15, + "filter": [ + "all", + [ + "!in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ], + [ + "<=", + "localrank", + 14 + ], + [ + "==", + "scalerank", + 4 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{maki}-11", + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 1, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-parks_scalerank4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933456003.5437" + }, + "source": "composite", + "source-layer": "poi_label", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "scalerank", + 4 + ], + [ + "in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{maki}-11", + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 1, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(100, 100%, 20%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-scalerank3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933372896.5967" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "!in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ], + [ + "==", + "scalerank", + 3 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{maki}-11", + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 1, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-parks-scalerank3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933372896.5967" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "==", + "scalerank", + 3 + ], + [ + "in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{maki}-11", + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(100, 100%, 20%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "road-label-small", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933721429.3076" + }, + "source": "composite", + "source-layer": "road_label", + "minzoom": 15, + "filter": [ + "all", + [ + "!in", + "class", + "golf", + "link", + "motorway", + "pedestrian", + "primary", + "secondary", + "street", + "street_limited", + "tertiary", + "trunk" + ], + [ + "==", + "$type", + "LineString" + ] + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 15, + 10 + ], + [ + 20, + 13 + ] + ] + }, + "text-max-angle": 30, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-padding": 1, + "text-rotation-alignment": "map", + "text-pitch-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.01 + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1.25, + "text-halo-blur": 1 + } + }, + { + "id": "road-label-medium", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933721429.3076" + }, + "source": "composite", + "source-layer": "road_label", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "in", + "class", + "link", + "pedestrian", + "street", + "street_limited" + ] + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 11, + 10 + ], + [ + 20, + 14 + ] + ] + }, + "text-max-angle": 30, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-padding": 1, + "text-rotation-alignment": "map", + "text-pitch-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.01 + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "road-label-large", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933721429.3076" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "in", + "class", + "motorway", + "primary", + "secondary", + "tertiary", + "trunk" + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 9, + 10 + ], + [ + 20, + 16 + ] + ] + }, + "text-max-angle": 30, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-padding": 1, + "text-rotation-alignment": "map", + "text-pitch-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.01 + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsla(0, 0%, 100%, 0.75)", + "text-halo-width": 1, + "text-halo-blur": 1 + } + }, + { + "id": "road-shields-black", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "!in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ], + [ + "<=", + "reflen", + 6 + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 7%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "road-shields-white", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "<=", + "reflen", + 6 + ], + [ + "in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "motorway-junction", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "motorway_junction", + "minzoom": 14, + "filter": [ + "all", + [ + "<=", + "reflen", + 9 + ], + [ + ">", + "reflen", + 0 + ] + ], + "layout": { + "text-field": "{ref}", + "text-size": 9, + "icon-image": "motorway-exit-{reflen}", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ] + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "text-translate": [ + 0, + 0 + ] + } + }, + { + "id": "road-shields-black copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "!in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ], + [ + "<=", + "reflen", + 6 + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 7%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "road-shields-white copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "<=", + "reflen", + 6 + ], + [ + "in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "motorway-junction copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "motorway_junction", + "minzoom": 14, + "filter": [ + "all", + [ + "<=", + "reflen", + 9 + ], + [ + ">", + "reflen", + 0 + ] + ], + "layout": { + "text-field": "{ref}", + "text-size": 9, + "icon-image": "motorway-exit-{reflen}", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ] + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "text-translate": [ + 0, + 0 + ] + } + }, + { + "id": "road-shields-black copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "!in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ], + [ + "<=", + "reflen", + 6 + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 7%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "road-shields-white copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "<=", + "reflen", + 6 + ], + [ + "in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "motorway-junction copy 1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "motorway_junction", + "minzoom": 14, + "filter": [ + "all", + [ + "<=", + "reflen", + 9 + ], + [ + ">", + "reflen", + 0 + ] + ], + "layout": { + "text-field": "{ref}", + "text-size": 9, + "icon-image": "motorway-exit-{reflen}", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ] + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "text-translate": [ + 0, + 0 + ] + } + }, + { + "id": "poi-scalerank2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933358918.2366" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "!in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ], + [ + "==", + "scalerank", + 2 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 14, + 11 + ], + [ + 20, + 14 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 14, + "{maki}-11" + ], + [ + 15, + "{maki}-15" + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-parks-scalerank2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933358918.2366" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "==", + "scalerank", + 2 + ], + [ + "in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 14, + 11 + ], + [ + 20, + 14 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 14, + "{maki}-11" + ], + [ + 15, + "{maki}-15" + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(100, 100%, 20%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "rail-label", + "type": "symbol", + "source": "composite", + "source-layer": "rail_station_label", + "minzoom": 12, + "filter": [ + "!=", + "maki", + "entrance" + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{network}", + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-offset": [ + 0, + 0.85 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": { + "base": 1, + "stops": [ + [ + 0, + "" + ], + [ + 13, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.01, + "icon-padding": 0, + "text-max-width": 7 + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "icon-halo-width": 4, + "icon-halo-color": "#fff", + "text-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "text-halo-blur": 0.5 + } + }, + { + "id": "water-label-sm", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933808272.805" + }, + "source": "composite", + "source-layer": "water_label", + "minzoom": 15, + "filter": [ + "<=", + "area", + 10000 + ], + "layout": { + "text-field": "{name_en}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-max-width": 7, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 13 + ], + [ + 20, + 16 + ] + ] + } + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)" + } + }, + { + "id": "water-label", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933808272.805" + }, + "source": "composite", + "source-layer": "water_label", + "minzoom": 5, + "filter": [ + ">", + "area", + 10000 + ], + "layout": { + "text-field": "{name_en}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-max-width": 7, + "text-size": { + "base": 1, + "stops": [ + [ + 13, + 13 + ], + [ + 18, + 18 + ] + ] + } + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)" + } + }, + { + "id": "place-residential", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "maxzoom": 18, + "filter": [ + "all", + [ + "all", + [ + "<=", + "localrank", + 10 + ], + [ + "==", + "type", + "residential" + ] + ], + [ + "in", + "$type", + "LineString", + "Point", + "Polygon" + ] + ], + "layout": { + "text-line-height": 1.2, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11 + ], + [ + 18, + 14 + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0 + ], + "text-rotation-alignment": "viewport", + "text-field": "{name_en}", + "text-max-width": 7 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-parks-scalerank1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933322393.2852" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "<=", + "scalerank", + 1 + ], + [ + "in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11 + ], + [ + 18, + 14 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 13, + "{maki}-11" + ], + [ + 14, + "{maki}-15" + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(100, 100%, 20%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-scalerank1", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933322393.2852" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "!in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ], + [ + "<=", + "scalerank", + 1 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11 + ], + [ + 18, + 14 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 13, + "{maki}-11" + ], + [ + 14, + "{maki}-15" + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "airport-label", + "type": "symbol", + "source": "composite", + "source-layer": "airport_label", + "minzoom": 9, + "filter": [ + "<=", + "scalerank", + 2 + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 12 + ], + [ + 18, + 18 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 12, + "{maki}-11" + ], + [ + 13, + "{maki}-15" + ] + ] + }, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.75 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": { + "stops": [ + [ + 11, + "{ref}" + ], + [ + 12, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.01, + "text-max-width": 9 + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "airport-label copy", + "type": "symbol", + "source": "composite", + "source-layer": "airport_label", + "minzoom": 9, + "filter": [ + "<=", + "scalerank", + 2 + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 12 + ], + [ + 18, + 18 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 12, + "{maki}-11" + ], + [ + 13, + "{maki}-15" + ] + ] + }, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.75 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": { + "stops": [ + [ + 11, + "{ref}" + ], + [ + 12, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.01, + "text-max-width": 9 + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "airport-label copy 1", + "type": "symbol", + "source": "composite", + "source-layer": "airport_label", + "minzoom": 9, + "filter": [ + "<=", + "scalerank", + 2 + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 12 + ], + [ + 18, + 18 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 12, + "{maki}-11" + ], + [ + 13, + "{maki}-15" + ] + ] + }, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.75 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": { + "stops": [ + [ + 11, + "{ref}" + ], + [ + 12, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.01, + "text-max-width": 9 + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "place-islet-archipelago-aboriginal", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "maxzoom": 16, + "filter": [ + "in", + "type", + "aboriginal_lands", + "archipelago", + "islet" + ], + "layout": { + "text-line-height": 1.2, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11 + ], + [ + 18, + 16 + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0 + ], + "text-rotation-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(230, 29%, 35%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "place-neighbourhood", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 10, + "maxzoom": 16, + "filter": [ + "==", + "type", + "neighbourhood" + ], + "layout": { + "text-field": "{name_en}", + "text-transform": "uppercase", + "text-letter-spacing": 0.1, + "text-max-width": 7, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-padding": 3, + "text-size": { + "base": 1, + "stops": [ + [ + 12, + 11 + ], + [ + 16, + 16 + ] + ] + } + }, + "paint": { + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "text-color": "hsl(230, 29%, 35%)", + "text-halo-blur": 0.5 + } + }, + { + "id": "place-suburb", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 10, + "maxzoom": 16, + "filter": [ + "==", + "type", + "suburb" + ], + "layout": { + "text-field": "{name_en}", + "text-transform": "uppercase", + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-letter-spacing": 0.15, + "text-max-width": 7, + "text-padding": 3, + "text-size": { + "base": 1, + "stops": [ + [ + 11, + 11 + ], + [ + 15, + 18 + ] + ] + } + }, + "paint": { + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "text-color": "hsl(230, 29%, 35%)", + "text-halo-blur": 0.5 + } + }, + { + "id": "place-suburb copy", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 10, + "maxzoom": 16, + "filter": [ + "==", + "type", + "suburb" + ], + "layout": { + "text-field": "{name_en}", + "text-transform": "uppercase", + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-letter-spacing": 0.15, + "text-max-width": 7, + "text-padding": 3, + "text-size": { + "base": 1, + "stops": [ + [ + 11, + 11 + ], + [ + 15, + 18 + ] + ] + } + }, + "paint": { + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "text-color": "hsl(230, 29%, 35%)", + "text-halo-blur": 0.5 + } + }, + { + "id": "place-hamlet", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 10, + "maxzoom": 16, + "filter": [ + "==", + "type", + "hamlet" + ], + "layout": { + "text-field": "{name_en}", + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1, + "stops": [ + [ + 12, + 11.5 + ], + [ + 15, + 16 + ] + ] + } + }, + "paint": { + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1.25, + "text-color": "hsl(0, 0%, 0%)" + } + }, + { + "id": "place-village", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 8, + "maxzoom": 15, + "filter": [ + "==", + "type", + "village" + ], + "layout": { + "text-field": "{name_en}", + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-max-width": 7, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11.5 + ], + [ + 16, + 18 + ] + ] + } + }, + "paint": { + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1.25, + "text-color": "hsl(0, 0%, 0%)" + } + }, + { + "id": "place-town", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 6, + "maxzoom": 15, + "filter": [ + "==", + "type", + "town" + ], + "layout": { + "icon-image": "dot-9", + "text-font": { + "base": 1, + "stops": [ + [ + 11, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 12, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7, + [ + 0, + -0.15 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "bottom" + ], + [ + 8, + "center" + ] + ] + }, + "text-field": "{name_en}", + "text-max-width": 7, + "text-size": { + "base": 1, + "stops": [ + [ + 7, + 11.5 + ], + [ + 15, + 20 + ] + ] + } + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1.25, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + } + } + }, + { + "id": "place-island", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "maxzoom": 16, + "filter": [ + "==", + "type", + "island" + ], + "layout": { + "text-line-height": 1.2, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11 + ], + [ + 18, + 16 + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0 + ], + "text-rotation-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 7 + }, + "paint": { + "text-color": "hsl(230, 29%, 35%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "place-city-sm", + "type": "symbol", + "metadata": { + "mapbox:group": "1444862510685.128" + }, + "source": "composite", + "source-layer": "place_label", + "maxzoom": 14, + "filter": [ + "all", + [ + "!in", + "scalerank", + 0, + 1, + 2, + 3, + 4, + 5 + ], + [ + "==", + "type", + "city" + ] + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 6, + 12 + ], + [ + 14, + 22 + ] + ] + }, + "icon-image": "dot-9", + "text-font": { + "base": 1, + "stops": [ + [ + 7, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 8, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7.99, + [ + 0, + -0.2 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "bottom" + ], + [ + 8, + "center" + ] + ] + }, + "text-field": "{name_en}", + "text-max-width": 7 + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1.25, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + } + } + }, + { + "id": "place-city-md-s", + "type": "symbol", + "metadata": { + "mapbox:group": "1444862510685.128" + }, + "source": "composite", + "source-layer": "place_label", + "maxzoom": 14, + "filter": [ + "all", + [ + "==", + "type", + "city" + ], + [ + "in", + "ldir", + "E", + "S", + "SE", + "SW" + ], + [ + "in", + "scalerank", + 3, + 4, + 5 + ] + ], + "layout": { + "text-field": "{name_en}", + "icon-image": "dot-10", + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "top" + ], + [ + 8, + "center" + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7.99, + [ + 0, + 0.1 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-font": { + "base": 1, + "stops": [ + [ + 7, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 8, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-size": { + "base": 0.9, + "stops": [ + [ + 5, + 12 + ], + [ + 12, + 22 + ] + ] + } + }, + "paint": { + "text-halo-width": 1, + "text-halo-color": "hsl(0, 0%, 100%)", + "text-color": "hsl(0, 0%, 0%)", + "text-halo-blur": 1, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + } + } + }, + { + "id": "place-city-md-n", + "type": "symbol", + "metadata": { + "mapbox:group": "1444862510685.128" + }, + "source": "composite", + "source-layer": "place_label", + "maxzoom": 14, + "filter": [ + "all", + [ + "==", + "type", + "city" + ], + [ + "in", + "ldir", + "N", + "NE", + "NW", + "W" + ], + [ + "in", + "scalerank", + 3, + 4, + 5 + ] + ], + "layout": { + "icon-image": "dot-10", + "text-font": { + "base": 1, + "stops": [ + [ + 7, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 8, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7.99, + [ + 0, + -0.25 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "bottom" + ], + [ + 8, + "center" + ] + ] + }, + "text-field": "{name_en}", + "text-max-width": 7, + "text-size": { + "base": 0.9, + "stops": [ + [ + 5, + 12 + ], + [ + 12, + 22 + ] + ] + } + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + }, + "text-halo-blur": 1 + } + }, + { + "id": "place-city-lg-s", + "type": "symbol", + "metadata": { + "mapbox:group": "1444862510685.128" + }, + "source": "composite", + "source-layer": "place_label", + "minzoom": 1, + "maxzoom": 14, + "filter": [ + "all", + [ + "<=", + "scalerank", + 2 + ], + [ + "==", + "type", + "city" + ], + [ + "in", + "ldir", + "E", + "S", + "SE", + "SW" + ] + ], + "layout": { + "icon-image": "dot-11", + "text-font": { + "base": 1, + "stops": [ + [ + 7, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 8, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7.99, + [ + 0, + 0.15 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "top" + ], + [ + 8, + "center" + ] + ] + }, + "text-field": "{name_en}", + "text-max-width": 7, + "text-size": { + "base": 0.9, + "stops": [ + [ + 4, + 12 + ], + [ + 10, + 22 + ] + ] + } + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + }, + "text-halo-blur": 1 + } + }, + { + "id": "place-city-lg-n", + "type": "symbol", + "metadata": { + "mapbox:group": "1444862510685.128" + }, + "source": "composite", + "source-layer": "place_label", + "minzoom": 1, + "maxzoom": 14, + "filter": [ + "all", + [ + "<=", + "scalerank", + 2 + ], + [ + "==", + "type", + "city" + ], + [ + "in", + "ldir", + "N", + "NE", + "NW", + "W" + ] + ], + "layout": { + "icon-image": "dot-11", + "text-font": { + "base": 1, + "stops": [ + [ + 7, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 8, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7.99, + [ + 0, + -0.25 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "bottom" + ], + [ + 8, + "center" + ] + ] + }, + "text-field": "{name_en}", + "text-max-width": 7, + "text-size": { + "base": 0.9, + "stops": [ + [ + 4, + 12 + ], + [ + 10, + 22 + ] + ] + } + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-opacity": 1, + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + }, + "text-halo-blur": 1 + } + }, + { + "id": "marine-label-sm-ln", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 3, + "maxzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + ">=", + "labelrank", + 4 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 3, + 12 + ], + [ + 6, + 16 + ] + ] + }, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 4, + 100 + ], + [ + 6, + 400 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-pitch-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.1, + "text-max-width": 5 + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "marine-label-sm-pt", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 3, + "maxzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + ">=", + "labelrank", + 4 + ] + ], + "layout": { + "text-field": "{name_en}", + "text-max-width": 5, + "text-letter-spacing": 0.1, + "text-line-height": 1.5, + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1, + "stops": [ + [ + 3, + 12 + ], + [ + 6, + 16 + ] + ] + } + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "marine-label-md-ln", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 2, + "maxzoom": 8, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "in", + "labelrank", + 2, + 3 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1.1, + "stops": [ + [ + 2, + 12 + ], + [ + 5, + 20 + ] + ] + }, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-pitch-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.15, + "text-max-width": 5 + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "marine-label-md-pt", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 2, + "maxzoom": 8, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "labelrank", + 2, + 3 + ] + ], + "layout": { + "text-field": "{name_en}", + "text-max-width": 5, + "text-letter-spacing": 0.15, + "text-line-height": 1.5, + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1.1, + "stops": [ + [ + 2, + 14 + ], + [ + 5, + 20 + ] + ] + } + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "marine-label-lg-ln", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 1, + "maxzoom": 4, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "labelrank", + 1 + ] + ], + "layout": { + "text-field": "{name_en}", + "text-max-width": 4, + "text-letter-spacing": 0.25, + "text-line-height": 1.1, + "symbol-placement": "line", + "text-pitch-alignment": "viewport", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1, + "stops": [ + [ + 1, + 14 + ], + [ + 4, + 30 + ] + ] + } + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "marine-label-lg-pt", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 1, + "maxzoom": 4, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "labelrank", + 1 + ] + ], + "layout": { + "text-field": "{name_en}", + "text-max-width": 4, + "text-letter-spacing": 0.25, + "text-line-height": 1.5, + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1, + "stops": [ + [ + 1, + 14 + ], + [ + 4, + 30 + ] + ] + } + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "state-label-sm", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856151690.9143" + }, + "source": "composite", + "source-layer": "state_label", + "minzoom": 3, + "maxzoom": 9, + "filter": [ + "<", + "area", + 20000 + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 6, + 10 + ], + [ + 9, + 14 + ] + ] + }, + "text-transform": "uppercase", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "text-field": { + "base": 1, + "stops": [ + [ + 0, + "{abbr}" + ], + [ + 6, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.15, + "text-max-width": 5 + }, + "paint": { + "text-opacity": 1, + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "state-label-md", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856151690.9143" + }, + "source": "composite", + "source-layer": "state_label", + "minzoom": 3, + "maxzoom": 8, + "filter": [ + "all", + [ + "<", + "area", + 80000 + ], + [ + ">=", + "area", + 20000 + ] + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 5, + 10 + ], + [ + 8, + 16 + ] + ] + }, + "text-transform": "uppercase", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "text-field": { + "base": 1, + "stops": [ + [ + 0, + "{abbr}" + ], + [ + 5, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.15, + "text-max-width": 6 + }, + "paint": { + "text-opacity": 1, + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "state-label-lg", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856151690.9143" + }, + "source": "composite", + "source-layer": "state_label", + "minzoom": 3, + "maxzoom": 7, + "filter": [ + ">=", + "area", + 80000 + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 4, + 10 + ], + [ + 7, + 18 + ] + ] + }, + "text-transform": "uppercase", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "text-padding": 1, + "text-field": { + "base": 1, + "stops": [ + [ + 0, + "{abbr}" + ], + [ + 4, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.15, + "text-max-width": 6 + }, + "paint": { + "text-opacity": 1, + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "background copy", + "type": "background", + "layout": {}, + "paint": { + "background-color": { + "base": 1, + "stops": [ + [ + 11, + "hsl(35, 32%, 91%)" + ], + [ + 13, + "hsl(35, 12%, 89%)" + ] + ] + } + } + }, + { + "id": "landcover_snow copy", + "type": "fill", + "metadata": { + "mapbox:group": "1456970288113.8113" + }, + "source": "composite", + "source-layer": "landcover", + "filter": [ + "==", + "class", + "snow" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-opacity": 0.2, + "fill-antialias": false + } + }, + { + "id": "landcover_wood copy", + "type": "fill", + "metadata": { + "mapbox:group": "1456970288113.8113" + }, + "source": "composite", + "source-layer": "landcover", + "maxzoom": 14, + "filter": [ + "==", + "class", + "wood" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(75, 62%, 81%)", + "fill-opacity": { + "base": 1.5, + "stops": [ + [ + 2, + 0.3 + ], + [ + 7, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "landcover_scrub copy", + "type": "fill", + "metadata": { + "mapbox:group": "1456970288113.8113" + }, + "source": "composite", + "source-layer": "landcover", + "maxzoom": 14, + "filter": [ + "==", + "class", + "scrub" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(75, 62%, 81%)", + "fill-opacity": { + "base": 1.5, + "stops": [ + [ + 2, + 0.3 + ], + [ + 7, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "landcover_grass copy", + "type": "fill", + "metadata": { + "mapbox:group": "1456970288113.8113" + }, + "source": "composite", + "source-layer": "landcover", + "maxzoom": 14, + "filter": [ + "==", + "class", + "grass" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(75, 62%, 81%)", + "fill-opacity": { + "base": 1.5, + "stops": [ + [ + 2, + 0.3 + ], + [ + 7, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "landcover_crop copy", + "type": "fill", + "metadata": { + "mapbox:group": "1456970288113.8113" + }, + "source": "composite", + "source-layer": "landcover", + "maxzoom": 14, + "filter": [ + "==", + "class", + "crop" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(75, 62%, 81%)", + "fill-opacity": { + "base": 1.5, + "stops": [ + [ + 2, + 0.3 + ], + [ + 7, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "national_park copy", + "type": "fill", + "source": "composite", + "source-layer": "landuse_overlay", + "filter": [ + "==", + "class", + "national_park" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(100, 58%, 76%)", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 5, + 0 + ], + [ + 6, + 0.5 + ] + ] + } + } + }, + { + "id": "hospital copy", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "hospital" + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 15.5, + "hsl(340, 37%, 87%)" + ], + [ + 16, + "hsl(340, 63%, 89%)" + ] + ] + } + } + }, + { + "id": "school copy", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "school" + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 15.5, + "hsl(50, 47%, 81%)" + ], + [ + 16, + "hsl(50, 63%, 84%)" + ] + ] + } + } + }, + { + "id": "park copy", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "park" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(100, 58%, 76%)", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 5, + 0 + ], + [ + 6, + 1 + ] + ] + } + } + }, + { + "id": "pitch copy", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "pitch" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(100, 57%, 72%)" + } + }, + { + "id": "pitch-line copy", + "type": "line", + "source": "composite", + "source-layer": "landuse", + "minzoom": 15, + "filter": [ + "==", + "class", + "pitch" + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-color": "hsl(75, 57%, 84%)" + } + }, + { + "id": "cemetery copy", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "cemetery" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(75, 37%, 81%)" + } + }, + { + "id": "industrial copy", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "industrial" + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 15.5, + "hsl(230, 15%, 86%)" + ], + [ + 16, + "hsl(230, 29%, 89%)" + ] + ] + } + } + }, + { + "id": "sand copy", + "type": "fill", + "source": "composite", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "sand" + ], + "layout": {}, + "paint": { + "fill-color": "hsl(60, 46%, 87%)" + } + }, + { + "id": "hillshade_highlight_bright copy", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 94 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.12 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "hillshade_highlight_med copy", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 90 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.12 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "hillshade_shadow_faint copy", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 89 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(56, 59%, 22%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.05 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "hillshade_shadow_med copy", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 78 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(56, 59%, 22%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.05 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "hillshade_shadow_dark copy", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 67 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(56, 59%, 22%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.06 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "hillshade_shadow_extreme copy", + "type": "fill", + "metadata": { + "mapbox:group": "1456969573402.7817" + }, + "source": "composite", + "source-layer": "hillshade", + "maxzoom": 16, + "filter": [ + "==", + "level", + 56 + ], + "layout": {}, + "paint": { + "fill-color": "hsl(56, 59%, 22%)", + "fill-opacity": { + "stops": [ + [ + 14, + 0.06 + ], + [ + 16, + 0 + ] + ] + }, + "fill-antialias": false + } + }, + { + "id": "waterway-river-canal copy", + "type": "line", + "source": "composite", + "source-layer": "waterway", + "minzoom": 8, + "filter": [ + "in", + "class", + "canal", + "river" + ], + "layout": { + "line-cap": { + "base": 1, + "stops": [ + [ + 0, + "butt" + ], + [ + 11, + "round" + ] + ] + }, + "line-join": "round" + }, + "paint": { + "line-color": "hsl(205, 87%, 76%)", + "line-width": { + "base": 1.3, + "stops": [ + [ + 8.5, + 0.1 + ], + [ + 20, + 8 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 8, + 0 + ], + [ + 8.5, + 1 + ] + ] + } + } + }, + { + "id": "waterway-small copy", + "type": "line", + "source": "composite", + "source-layer": "waterway", + "minzoom": 13, + "filter": [ + "!in", + "class", + "canal", + "river" + ], + "layout": { + "line-join": "round", + "line-cap": "round" + }, + "paint": { + "line-color": "hsl(205, 87%, 76%)", + "line-width": { + "base": 1.35, + "stops": [ + [ + 13.5, + 0.1 + ], + [ + 20, + 3 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13, + 0 + ], + [ + 13.5, + 1 + ] + ] + } + } + }, + { + "id": "water-shadow copy", + "type": "fill", + "source": "composite", + "source-layer": "water", + "layout": {}, + "paint": { + "fill-color": "hsl(215, 84%, 69%)", + "fill-translate": { + "base": 1.2, + "stops": [ + [ + 7, + [ + 0, + 0 + ] + ], + [ + 16, + [ + -1, + -1 + ] + ] + ] + }, + "fill-translate-anchor": "viewport", + "fill-opacity": 1 + } + }, + { + "id": "water copy", + "type": "fill", + "source": "composite", + "source-layer": "water", + "layout": {}, + "paint": { + "fill-color": "hsl(196, 80%, 70%)" + } + }, + { + "id": "barrier_line-land-polygon copy", + "type": "fill", + "source": "composite", + "source-layer": "barrier_line", + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "==", + "class", + "land" + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(35, 12%, 89%)" + } + }, + { + "id": "barrier_line-land-line copy", + "type": "line", + "source": "composite", + "source-layer": "barrier_line", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "class", + "land" + ] + ], + "layout": { + "line-cap": "round" + }, + "paint": { + "line-width": { + "base": 1.99, + "stops": [ + [ + 14, + 0.75 + ], + [ + 20, + 40 + ] + ] + }, + "line-color": "hsl(35, 12%, 89%)" + } + }, + { + "id": "aeroway-polygon copy", + "type": "fill", + "metadata": { + "mapbox:group": "1444934828655.3389" + }, + "source": "composite", + "source-layer": "aeroway", + "minzoom": 11, + "filter": [ + "all", + [ + "!=", + "type", + "apron" + ], + [ + "==", + "$type", + "Polygon" + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(230, 23%, 82%)" + ], + [ + 16, + "hsl(230, 37%, 84%)" + ] + ] + }, + "fill-opacity": { + "base": 1, + "stops": [ + [ + 11, + 0 + ], + [ + 11.5, + 1 + ] + ] + } + } + }, + { + "id": "aeroway-runway copy", + "type": "line", + "metadata": { + "mapbox:group": "1444934828655.3389" + }, + "source": "composite", + "source-layer": "aeroway", + "minzoom": 9, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "type", + "runway" + ] + ], + "layout": {}, + "paint": { + "line-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(230, 23%, 82%)" + ], + [ + 16, + "hsl(230, 37%, 84%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 9, + 1 + ], + [ + 18, + 80 + ] + ] + } + } + }, + { + "id": "aeroway-taxiway copy", + "type": "line", + "metadata": { + "mapbox:group": "1444934828655.3389" + }, + "source": "composite", + "source-layer": "aeroway", + "minzoom": 9, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "type", + "taxiway" + ] + ], + "layout": {}, + "paint": { + "line-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(230, 23%, 82%)" + ], + [ + 16, + "hsl(230, 37%, 84%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 0.5 + ], + [ + 18, + 20 + ] + ] + } + } + }, + { + "id": "building-line copy", + "type": "line", + "source": "composite", + "source-layer": "building", + "minzoom": 15, + "filter": [ + "all", + [ + "!=", + "type", + "building:part" + ], + [ + "==", + "underground", + "false" + ] + ], + "layout": {}, + "paint": { + "line-color": "hsl(35, 6%, 79%)", + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 0.75 + ], + [ + 20, + 3 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15.5, + 0 + ], + [ + 16, + 1 + ] + ] + } + } + }, + { + "id": "building copy", + "type": "fill", + "source": "composite", + "source-layer": "building", + "minzoom": 15, + "filter": [ + "all", + [ + "!=", + "type", + "building:part" + ], + [ + "==", + "underground", + "false" + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(35, 11%, 88%)" + ], + [ + 16, + "hsl(35, 8%, 85%)" + ] + ] + }, + "fill-opacity": { + "base": 1, + "stops": [ + [ + 15.5, + 0 + ], + [ + 16, + 1 + ] + ] + }, + "fill-outline-color": "hsl(35, 6%, 79%)" + } + }, + { + "id": "tunnel-street-low copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "tunnel-street_limited-low copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "tunnel-service-link-track-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 19%, 75%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ] + } + }, + { + "id": "tunnel-street_limited-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 19%, 75%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-street-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 19%, 75%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-secondary-tertiary-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ], + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(230, 19%, 75%)" + } + }, + { + "id": "tunnel-primary-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ], + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(230, 19%, 75%)" + } + }, + { + "id": "tunnel-trunk_link-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ] + } + }, + { + "id": "tunnel-motorway_link-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-dasharray": [ + 3, + 3 + ] + } + }, + { + "id": "tunnel-trunk-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "==", + "type", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": 1, + "line-dasharray": [ + 3, + 3 + ] + } + }, + { + "id": "tunnel-motorway-case copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": 1, + "line-dasharray": [ + 3, + 3 + ] + } + }, + { + "id": "tunnel-construction copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "tunnel-path copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-color": "hsl(35, 26%, 95%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-steps copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(35, 26%, 95%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-trunk_link copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 77%, 78%)", + "line-opacity": 1, + "line-dasharray": [ + 1, + 0 + ] + } + }, + { + "id": "tunnel-motorway_link copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 78%)", + "line-opacity": 1, + "line-dasharray": [ + 1, + 0 + ] + } + }, + { + "id": "tunnel-pedestrian copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "tunnel-service-link-track copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": [ + 1, + 0 + ] + } + }, + { + "id": "tunnel-street_limited copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-street copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "tunnel-secondary-tertiary copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": [ + 1, + 0 + ], + "line-blur": 0 + } + }, + { + "id": "tunnel-primary copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": [ + 1, + 0 + ], + "line-blur": 0 + } + }, + { + "id": "tunnel-oneway-arrows-blue-minor copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "tunnel-oneway-arrows-blue-major copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "tunnel-trunk copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 77%, 78%)" + } + }, + { + "id": "tunnel-motorway copy", + "type": "line", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": 1, + "line-color": "hsl(26, 100%, 78%)", + "line-blur": 0 + } + }, + { + "id": "tunnel-oneway-arrows-white copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855769305.6016" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "tunnel" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "ferry copy", + "type": "line", + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "type", + "ferry" + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(205, 73%, 63%)" + ], + [ + 17, + "hsl(230, 73%, 63%)" + ] + ] + }, + "line-opacity": 1, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 12, + [ + 1, + 0 + ] + ], + [ + 13, + [ + 12, + 4 + ] + ] + ] + } + } + }, + { + "id": "ferry_auto copy", + "type": "line", + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "type", + "ferry_auto" + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "base": 1, + "stops": [ + [ + 15, + "hsl(205, 73%, 63%)" + ], + [ + 17, + "hsl(230, 73%, 63%)" + ] + ] + }, + "line-opacity": 1, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-path-bg copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline copy 10", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill copy 10", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern copy 10", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon copy 10", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor copy 10", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major copy 10", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings copy 10", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white copy 10", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features copy 10", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-path-bg copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline copy 9", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill copy 9", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern copy 9", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon copy 9", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor copy 9", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major copy 9", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings copy 9", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white copy 9", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features copy 9", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-path-bg copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline copy 8", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill copy 8", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern copy 8", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon copy 8", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor copy 8", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major copy 8", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings copy 8", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white copy 8", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features copy 8", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-path-bg copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline copy 7", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill copy 7", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern copy 7", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon copy 7", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor copy 7", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major copy 7", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings copy 7", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white copy 7", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features copy 7", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-path-bg copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline copy 6", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill copy 6", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern copy 6", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon copy 6", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor copy 6", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major copy 6", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings copy 6", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white copy 6", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features copy 6", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-path-bg copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-steps-bg copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "road-sidewalk-bg copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 0.75 + ] + ] + } + } + }, + { + "id": "turning-features-outline copy 5", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle-outline", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.122 + ], + [ + 18, + 0.969 + ], + [ + 20, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "road-pedestrian-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-low copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-street_limited-low copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11, + 0 + ], + [ + 11.25, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "road-service-link-track-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "road-street_limited-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-primary-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 9.99, + 0 + ], + [ + 10, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway_link-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 6, + 0 + ], + [ + 6.1, + 1 + ] + ] + } + } + }, + { + "id": "road-motorway-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "road-construction copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "road-sidewalks copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "type", + "crossing", + "sidewalk" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-path copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "crossing", + "sidewalk", + "steps" + ], + [ + "==", + "class", + "path" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-steps copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "road-trunk_link copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)", + "line-opacity": 1 + } + }, + { + "id": "road-motorway_link copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)", + "line-opacity": 1 + } + }, + { + "id": "road-pedestrian copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "road-pedestrian-polygon-fill copy 5", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": { + "base": 1, + "stops": [ + [ + 16, + "hsl(230, 16%, 94%)" + ], + [ + 16.25, + "hsl(230, 50%, 98%)" + ] + ] + }, + "fill-outline-color": "hsl(230, 26%, 88%)", + "fill-opacity": 1 + } + }, + { + "id": "road-pedestrian-polygon-pattern copy 5", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "==", + "structure", + "none" + ], + [ + "in", + "class", + "path", + "pedestrian" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "hsl(35, 10%, 83%)", + "fill-pattern": "pedestrian-polygon", + "fill-opacity": { + "base": 1, + "stops": [ + [ + 16, + 0 + ], + [ + 16.25, + 1 + ] + ] + } + } + }, + { + "id": "road-polygon copy 5", + "type": "fill", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 12, + "filter": [ + "all", + [ + "==", + "$type", + "Polygon" + ], + [ + "all", + [ + "!in", + "class", + "motorway", + "path", + "pedestrian", + "trunk" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ] + ] + ], + "layout": {}, + "paint": { + "fill-color": "hsl(0, 0%, 100%)", + "fill-outline-color": "#d6d9e6" + } + }, + { + "id": "road-service-link-track copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "road-street_limited copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-street copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "none" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "road-secondary-tertiary copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 8, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "road-primary copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 5, + "hsl(35, 32%, 91%)" + ], + [ + 7, + "hsl(0, 0%, 100%)" + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "road-oneway-arrows-blue-minor copy 5", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-blue-major copy 5", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "icon-rotation-alignment": "map", + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "road-trunk copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "trunk" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(0, 0%, 100%)" + ], + [ + 6.1, + "hsl(46, 80%, 60%)" + ], + [ + 9, + "hsl(46, 85%, 67%)" + ] + ] + } + } + }, + { + "id": "road-motorway copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "==", + "class", + "motorway" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(26, 87%, 62%)" + ], + [ + 9, + "hsl(26, 100%, 68%)" + ] + ] + } + } + }, + { + "id": "road-rail copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "road-rail-tracks copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "level-crossings copy 5", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "class", + "level_crossing" + ] + ], + "layout": { + "icon-size": 1, + "icon-image": "level-crossing", + "icon-allow-overlap": true + }, + "paint": {} + }, + { + "id": "road-oneway-arrows-white copy 5", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "structure", + "bridge", + "tunnel" + ], + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "icon-padding": 2, + "symbol-spacing": 200 + }, + "paint": {} + }, + { + "id": "turning-features copy 5", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855786460.0557" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "class", + "turning_circle", + "turning_loop" + ] + ], + "layout": { + "icon-image": "turning-circle", + "icon-size": { + "base": 1.5, + "stops": [ + [ + 14, + 0.095 + ], + [ + 18, + 1 + ] + ] + }, + "icon-allow-overlap": true, + "icon-ignore-placement": true, + "icon-padding": 0, + "icon-rotation-alignment": "map" + }, + "paint": {} + }, + { + "id": "bridge-path-bg copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor copy 10", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major copy 10", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2 copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2 copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2 copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2 copy 10", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white copy 10", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-path-bg copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor copy 9", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major copy 9", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2 copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2 copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2 copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2 copy 9", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white copy 9", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-path-bg copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor copy 8", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major copy 8", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2 copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2 copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2 copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2 copy 8", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white copy 8", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-path-bg copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor copy 7", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major copy 7", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2 copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2 copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2 copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2 copy 7", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white copy 7", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-path-bg copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor copy 6", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major copy 6", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2 copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2 copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2 copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2 copy 6", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white copy 6", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-path-bg copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 18, + 7 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-color": "hsl(230, 17%, 82%)", + "line-blur": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 15, + 0 + ], + [ + 15.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps-bg copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 2 + ], + [ + 17, + 4.6 + ], + [ + 18, + 7 + ] + ] + }, + "line-color": "hsl(230, 17%, 82%)", + "line-dasharray": [ + 1, + 0 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 0.75 + ] + ] + } + } + }, + { + "id": "bridge-pedestrian-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 2 + ], + [ + 18, + 14.5 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": 0, + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street-low copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-low copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "stops": [ + [ + 11.5, + 0 + ], + [ + 12, + 1 + ], + [ + 14, + 1 + ], + [ + 14.01, + 0 + ] + ] + } + } + }, + { + "id": "bridge-service-link-track-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + } + } + }, + { + "id": "bridge-street_limited-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-street-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 13, + 0 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.2, + "stops": [ + [ + 10, + 0.75 + ], + [ + 18, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-primary-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "primary" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-translate": [ + 0, + 0 + ] + } + }, + { + "id": "bridge-trunk_link-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-construction copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "construction" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(230, 24%, 87%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 0.4, + 0.8 + ] + ], + [ + 15, + [ + 0.3, + 0.6 + ] + ], + [ + 16, + [ + 0.2, + 0.3 + ] + ], + [ + 17, + [ + 0.2, + 0.25 + ] + ], + [ + 18, + [ + 0.15, + 0.15 + ] + ] + ] + } + } + }, + { + "id": "bridge-path copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "steps" + ], + [ + "==", + "class", + "path" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 18, + 4 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 1, + 0.5 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-steps copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "steps" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 15, + 1 + ], + [ + 16, + 1.6 + ], + [ + 18, + 6 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.75, + 1 + ] + ], + [ + 16, + [ + 1, + 0.75 + ] + ], + [ + 17, + [ + 0.3, + 0.3 + ] + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 14, + 0 + ], + [ + 14.25, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-pedestrian copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "pedestrian" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1, + "line-dasharray": { + "base": 1, + "stops": [ + [ + 14, + [ + 1, + 0 + ] + ], + [ + 15, + [ + 1.5, + 0.4 + ] + ], + [ + 16, + [ + 1, + 0.2 + ] + ] + ] + } + } + }, + { + "id": "bridge-service-link-track copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 14, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!=", + "type", + "trunk_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "service", + "track" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 18, + 12 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)" + } + }, + { + "id": "bridge-street_limited copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street_limited" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(35, 14%, 93%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-street copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "street" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12.5, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + } + } + }, + { + "id": "bridge-secondary-tertiary copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "type", + "secondary", + "tertiary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 8.5, + 0.5 + ], + [ + 10, + 0.75 + ], + [ + 18, + 26 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": { + "base": 1.2, + "stops": [ + [ + 5, + 0 + ], + [ + 5.5, + 1 + ] + ] + } + } + }, + { + "id": "bridge-primary copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "primary" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-opacity": 1 + } + }, + { + "id": "bridge-oneway-arrows-blue-minor copy 5", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "path", + "pedestrian", + "service", + "track" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 17, + "oneway-small" + ], + [ + 18, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-oneway-arrows-blue-major copy 5", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "primary", + "secondary", + "street", + "street_limited", + "tertiary" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-small" + ], + [ + 17, + "oneway-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-rotation-alignment": "map", + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "bridge-trunk copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "layer", + 2, + 3, + 4, + 5 + ], + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-rail copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-rail-tracks copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "major_rail", + "minor_rail" + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": { + "stops": [ + [ + 13, + "hsl(50, 17%, 82%)" + ], + [ + 16, + "hsl(230, 10%, 74%)" + ] + ] + }, + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 4 + ], + [ + 20, + 8 + ] + ] + }, + "line-dasharray": [ + 0.1, + 15 + ], + "line-opacity": { + "base": 1, + "stops": [ + [ + 13.75, + 0 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 10.99, + 0 + ], + [ + 11, + 1 + ] + ] + } + } + }, + { + "id": "bridge-motorway_link-2-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.75 + ], + [ + 20, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-opacity": 1 + } + }, + { + "id": "bridge-trunk-2-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-motorway-2-case copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 10, + 1 + ], + [ + 16, + 2 + ] + ] + }, + "line-color": "hsl(0, 0%, 100%)", + "line-gap-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + } + } + }, + { + "id": "bridge-trunk_link-2 copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "structure", + "bridge" + ], + [ + "==", + "type", + "trunk_link" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway_link-2 copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway_link" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 12, + 0.5 + ], + [ + 14, + 2 + ], + [ + 18, + 18 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-trunk-2 copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(46, 85%, 67%)" + } + }, + { + "id": "bridge-motorway-2 copy 5", + "type": "line", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "==", + "class", + "motorway" + ], + [ + "==", + "structure", + "bridge" + ], + [ + ">=", + "layer", + 2 + ] + ] + ], + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "paint": { + "line-width": { + "base": 1.5, + "stops": [ + [ + 5, + 0.75 + ], + [ + 18, + 32 + ] + ] + }, + "line-color": "hsl(26, 100%, 68%)" + } + }, + { + "id": "bridge-oneway-arrows-white copy 5", + "type": "symbol", + "metadata": { + "mapbox:group": "1444855799204.86" + }, + "source": "composite", + "source-layer": "road", + "minzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "!in", + "type", + "primary_link", + "secondary_link", + "tertiary_link" + ], + [ + "==", + "oneway", + "true" + ], + [ + "==", + "structure", + "bridge" + ], + [ + "in", + "class", + "link", + "motorway", + "motorway_link", + "trunk" + ] + ] + ], + "layout": { + "symbol-placement": "line", + "icon-image": { + "base": 1, + "stops": [ + [ + 16, + "oneway-white-small" + ], + [ + 17, + "oneway-white-large" + ] + ] + }, + "symbol-spacing": 200, + "icon-padding": 2 + }, + "paint": {} + }, + { + "id": "aerialway copy", + "type": "line", + "source": "composite", + "source-layer": "road", + "minzoom": 13, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "class", + "aerialway" + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-color": "hsl(230, 10%, 74%)", + "line-width": { + "base": 1.5, + "stops": [ + [ + 14, + 0.5 + ], + [ + 20, + 1 + ] + ] + } + } + }, + { + "id": "admin-3-4-boundaries-bg copy", + "type": "line", + "metadata": { + "mapbox:group": "1444934295202.7542" + }, + "source": "composite", + "source-layer": "admin", + "filter": [ + "all", + [ + "==", + "maritime", + 0 + ], + [ + ">=", + "admin_level", + 3 + ] + ], + "layout": { + "line-join": "bevel" + }, + "paint": { + "line-color": { + "base": 1, + "stops": [ + [ + 8, + "hsl(35, 12%, 89%)" + ], + [ + 16, + "hsl(230, 49%, 90%)" + ] + ] + }, + "line-width": { + "base": 1, + "stops": [ + [ + 7, + 3.75 + ], + [ + 12, + 5.5 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 7, + 0 + ], + [ + 8, + 0.75 + ] + ] + }, + "line-dasharray": [ + 1, + 0 + ], + "line-translate": [ + 0, + 0 + ], + "line-blur": { + "base": 1, + "stops": [ + [ + 3, + 0 + ], + [ + 8, + 3 + ] + ] + } + } + }, + { + "id": "admin-2-boundaries-bg copy", + "type": "line", + "metadata": { + "mapbox:group": "1444934295202.7542" + }, + "source": "composite", + "source-layer": "admin", + "minzoom": 1, + "filter": [ + "all", + [ + "==", + "admin_level", + 2 + ], + [ + "==", + "maritime", + 0 + ] + ], + "layout": { + "line-join": "miter" + }, + "paint": { + "line-width": { + "base": 1, + "stops": [ + [ + 3, + 3.5 + ], + [ + 10, + 8 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 6, + "hsl(35, 12%, 89%)" + ], + [ + 8, + "hsl(230, 49%, 90%)" + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 3, + 0 + ], + [ + 4, + 0.5 + ] + ] + }, + "line-translate": [ + 0, + 0 + ], + "line-blur": { + "base": 1, + "stops": [ + [ + 3, + 0 + ], + [ + 10, + 2 + ] + ] + } + } + }, + { + "id": "admin-3-4-boundaries copy", + "type": "line", + "metadata": { + "mapbox:group": "1444934295202.7542" + }, + "source": "composite", + "source-layer": "admin", + "filter": [ + "all", + [ + "==", + "maritime", + 0 + ], + [ + ">=", + "admin_level", + 3 + ] + ], + "layout": { + "line-join": "round", + "line-cap": "round" + }, + "paint": { + "line-dasharray": { + "base": 1, + "stops": [ + [ + 6, + [ + 2, + 0 + ] + ], + [ + 7, + [ + 2, + 2, + 6, + 2 + ] + ] + ] + }, + "line-width": { + "base": 1, + "stops": [ + [ + 7, + 0.75 + ], + [ + 12, + 1.5 + ] + ] + }, + "line-opacity": { + "base": 1, + "stops": [ + [ + 2, + 0 + ], + [ + 3, + 1 + ] + ] + }, + "line-color": { + "base": 1, + "stops": [ + [ + 3, + "hsl(230, 14%, 77%)" + ], + [ + 7, + "hsl(230, 8%, 62%)" + ] + ] + } + } + }, + { + "id": "admin-2-boundaries copy", + "type": "line", + "metadata": { + "mapbox:group": "1444934295202.7542" + }, + "source": "composite", + "source-layer": "admin", + "minzoom": 1, + "filter": [ + "all", + [ + "==", + "admin_level", + 2 + ], + [ + "==", + "disputed", + 0 + ], + [ + "==", + "maritime", + 0 + ] + ], + "layout": { + "line-join": "round", + "line-cap": "round" + }, + "paint": { + "line-color": "hsl(230, 8%, 51%)", + "line-width": { + "base": 1, + "stops": [ + [ + 3, + 0.5 + ], + [ + 10, + 2 + ] + ] + } + } + }, + { + "id": "admin-2-boundaries-dispute copy", + "type": "line", + "metadata": { + "mapbox:group": "1444934295202.7542" + }, + "source": "composite", + "source-layer": "admin", + "minzoom": 1, + "filter": [ + "all", + [ + "==", + "admin_level", + 2 + ], + [ + "==", + "disputed", + 1 + ], + [ + "==", + "maritime", + 0 + ] + ], + "layout": { + "line-join": "round" + }, + "paint": { + "line-dasharray": [ + 1.5, + 1.5 + ], + "line-color": "hsl(230, 8%, 51%)", + "line-width": { + "base": 1, + "stops": [ + [ + 3, + 0.5 + ], + [ + 10, + 2 + ] + ] + } + } + }, + { + "id": "housenum-label copy 4", + "type": "symbol", + "source": "composite", + "source-layer": "housenum_label", + "minzoom": 17, + "layout": { + "text-field": "{house_num}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-padding": 4, + "text-max-width": 7, + "text-size": 9.5 + }, + "paint": { + "text-color": "hsl(35, 2%, 69%)", + "text-halo-color": "hsl(35, 8%, 85%)", + "text-halo-width": 0.5, + "text-halo-blur": 0 + } + }, + { + "id": "housenum-label copy 3", + "type": "symbol", + "source": "composite", + "source-layer": "housenum_label", + "minzoom": 17, + "layout": { + "text-field": "{house_num}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-padding": 4, + "text-max-width": 7, + "text-size": 9.5 + }, + "paint": { + "text-color": "hsl(35, 2%, 69%)", + "text-halo-color": "hsl(35, 8%, 85%)", + "text-halo-width": 0.5, + "text-halo-blur": 0 + } + }, + { + "id": "housenum-label copy 2", + "type": "symbol", + "source": "composite", + "source-layer": "housenum_label", + "minzoom": 17, + "layout": { + "text-field": "{house_num}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-padding": 4, + "text-max-width": 7, + "text-size": 9.5 + }, + "paint": { + "text-color": "hsl(35, 2%, 69%)", + "text-halo-color": "hsl(35, 8%, 85%)", + "text-halo-width": 0.5, + "text-halo-blur": 0 + } + }, + { + "id": "waterway-label copy", + "type": "symbol", + "source": "composite", + "source-layer": "waterway_label", + "minzoom": 12, + "filter": [ + "in", + "class", + "canal", + "river" + ], + "layout": { + "text-field": "{name_en}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-pitch-alignment": "viewport", + "text-max-angle": 30, + "text-size": { + "base": 1, + "stops": [ + [ + 13, + 12 + ], + [ + 18, + 16 + ] + ] + } + }, + "paint": { + "text-halo-width": 0.5, + "text-halo-color": "hsl(196, 80%, 70%)", + "text-color": "hsl(230, 48%, 44%)", + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-scalerank4-l15 copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933456003.5437" + }, + "source": "composite", + "source-layer": "poi_label", + "minzoom": 17, + "filter": [ + "all", + [ + "!in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ], + [ + "==", + "scalerank", + 4 + ], + [ + ">=", + "localrank", + 15 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{maki}-11", + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-scalerank4-l1 copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933456003.5437" + }, + "source": "composite", + "source-layer": "poi_label", + "minzoom": 15, + "filter": [ + "all", + [ + "!in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ], + [ + "<=", + "localrank", + 14 + ], + [ + "==", + "scalerank", + 4 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{maki}-11", + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 1, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-parks_scalerank4 copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933456003.5437" + }, + "source": "composite", + "source-layer": "poi_label", + "minzoom": 15, + "filter": [ + "all", + [ + "==", + "scalerank", + 4 + ], + [ + "in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{maki}-11", + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 1, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(100, 100%, 20%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-scalerank3 copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933372896.5967" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "!in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ], + [ + "==", + "scalerank", + 3 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{maki}-11", + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 1, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-parks-scalerank3 copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933372896.5967" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "==", + "scalerank", + 3 + ], + [ + "in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{maki}-11", + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(100, 100%, 20%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "road-label-small copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933721429.3076" + }, + "source": "composite", + "source-layer": "road_label", + "minzoom": 15, + "filter": [ + "all", + [ + "!in", + "class", + "golf", + "link", + "motorway", + "pedestrian", + "primary", + "secondary", + "street", + "street_limited", + "tertiary", + "trunk" + ], + [ + "==", + "$type", + "LineString" + ] + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 15, + 10 + ], + [ + 20, + 13 + ] + ] + }, + "text-max-angle": 30, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-padding": 1, + "text-rotation-alignment": "map", + "text-pitch-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.01 + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1.25, + "text-halo-blur": 1 + } + }, + { + "id": "road-label-medium copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933721429.3076" + }, + "source": "composite", + "source-layer": "road_label", + "minzoom": 11, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "in", + "class", + "link", + "pedestrian", + "street", + "street_limited" + ] + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 11, + 10 + ], + [ + 20, + 14 + ] + ] + }, + "text-max-angle": 30, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-padding": 1, + "text-rotation-alignment": "map", + "text-pitch-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.01 + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "road-label-large copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933721429.3076" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "in", + "class", + "motorway", + "primary", + "secondary", + "tertiary", + "trunk" + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 9, + 10 + ], + [ + 20, + 16 + ] + ] + }, + "text-max-angle": 30, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-padding": 1, + "text-rotation-alignment": "map", + "text-pitch-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.01 + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsla(0, 0%, 100%, 0.75)", + "text-halo-width": 1, + "text-halo-blur": 1 + } + }, + { + "id": "road-shields-black copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "!in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ], + [ + "<=", + "reflen", + 6 + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 7%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "road-shields-white copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "<=", + "reflen", + 6 + ], + [ + "in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "motorway-junction copy 4", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "motorway_junction", + "minzoom": 14, + "filter": [ + "all", + [ + "<=", + "reflen", + 9 + ], + [ + ">", + "reflen", + 0 + ] + ], + "layout": { + "text-field": "{ref}", + "text-size": 9, + "icon-image": "motorway-exit-{reflen}", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ] + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "text-translate": [ + 0, + 0 + ] + } + }, + { + "id": "road-shields-black copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "!in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ], + [ + "<=", + "reflen", + 6 + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 7%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "road-shields-white copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "<=", + "reflen", + 6 + ], + [ + "in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "motorway-junction copy 3", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "motorway_junction", + "minzoom": 14, + "filter": [ + "all", + [ + "<=", + "reflen", + 9 + ], + [ + ">", + "reflen", + 0 + ] + ], + "layout": { + "text-field": "{ref}", + "text-size": 9, + "icon-image": "motorway-exit-{reflen}", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ] + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "text-translate": [ + 0, + 0 + ] + } + }, + { + "id": "road-shields-black copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "!in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ], + [ + "<=", + "reflen", + 6 + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 7%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "road-shields-white copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "road_label", + "filter": [ + "all", + [ + "<=", + "reflen", + 6 + ], + [ + "in", + "shield", + "at-expressway", + "at-motorway", + "at-state-b", + "bg-motorway", + "bg-national", + "ch-main", + "ch-motorway", + "cz-motorway", + "cz-road", + "de-motorway", + "e-road", + "fi-main", + "gr-motorway", + "gr-national", + "hr-motorway", + "hr-state", + "hu-main", + "hu-motorway", + "nz-state", + "pl-expressway", + "pl-motorway", + "pl-national", + "ro-county", + "ro-motorway", + "ro-national", + "rs-motorway", + "rs-state-1b", + "se-main", + "si-expressway", + "si-motorway", + "sk-highway", + "sk-road", + "us-interstate", + "us-interstate-business", + "us-interstate-duplex", + "us-interstate-truck", + "za-metropolitan", + "za-national", + "za-provincial", + "za-regional" + ] + ], + "layout": { + "text-size": 9, + "icon-image": "{shield}-{reflen}", + "icon-rotation-alignment": "viewport", + "text-max-angle": 38, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 11, + 150 + ], + [ + 14, + 200 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "symbol-placement": { + "base": 1, + "stops": [ + [ + 10, + "point" + ], + [ + 11, + "line" + ] + ] + }, + "text-padding": 2, + "text-rotation-alignment": "viewport", + "text-field": "{ref}", + "text-letter-spacing": 0.05, + "icon-padding": 2 + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "icon-halo-color": "rgba(0, 0, 0, 1)", + "icon-halo-width": 1, + "text-opacity": 1, + "icon-color": "white", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0 + } + }, + { + "id": "motorway-junction copy 2", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933575858.6992" + }, + "source": "composite", + "source-layer": "motorway_junction", + "minzoom": 14, + "filter": [ + "all", + [ + "<=", + "reflen", + 9 + ], + [ + ">", + "reflen", + 0 + ] + ], + "layout": { + "text-field": "{ref}", + "text-size": 9, + "icon-image": "motorway-exit-{reflen}", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ] + }, + "paint": { + "text-color": "hsl(0, 0%, 100%)", + "text-translate": [ + 0, + 0 + ] + } + }, + { + "id": "poi-scalerank2 copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933358918.2366" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "!in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ], + [ + "==", + "scalerank", + 2 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 14, + 11 + ], + [ + 20, + 14 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 14, + "{maki}-11" + ], + [ + 15, + "{maki}-15" + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-parks-scalerank2 copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933358918.2366" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "==", + "scalerank", + 2 + ], + [ + "in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 14, + 11 + ], + [ + 20, + 14 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 14, + "{maki}-11" + ], + [ + 15, + "{maki}-15" + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(100, 100%, 20%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "rail-label copy", + "type": "symbol", + "source": "composite", + "source-layer": "rail_station_label", + "minzoom": 12, + "filter": [ + "!=", + "maki", + "entrance" + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 11 + ], + [ + 20, + 13 + ] + ] + }, + "icon-image": "{network}", + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-offset": [ + 0, + 0.85 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": { + "base": 1, + "stops": [ + [ + 0, + "" + ], + [ + 13, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.01, + "icon-padding": 0, + "text-max-width": 7 + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "icon-halo-width": 4, + "icon-halo-color": "#fff", + "text-opacity": { + "base": 1, + "stops": [ + [ + 13.99, + 0 + ], + [ + 14, + 1 + ] + ] + }, + "text-halo-blur": 0.5 + } + }, + { + "id": "water-label-sm copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933808272.805" + }, + "source": "composite", + "source-layer": "water_label", + "minzoom": 15, + "filter": [ + "<=", + "area", + 10000 + ], + "layout": { + "text-field": "{name_en}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-max-width": 7, + "text-size": { + "base": 1, + "stops": [ + [ + 16, + 13 + ], + [ + 20, + 16 + ] + ] + } + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)" + } + }, + { + "id": "water-label copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933808272.805" + }, + "source": "composite", + "source-layer": "water_label", + "minzoom": 5, + "filter": [ + ">", + "area", + 10000 + ], + "layout": { + "text-field": "{name_en}", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-max-width": 7, + "text-size": { + "base": 1, + "stops": [ + [ + 13, + 13 + ], + [ + 18, + 18 + ] + ] + } + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)" + } + }, + { + "id": "place-residential copy", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "maxzoom": 18, + "filter": [ + "all", + [ + "all", + [ + "<=", + "localrank", + 10 + ], + [ + "==", + "type", + "residential" + ] + ], + [ + "in", + "$type", + "LineString", + "Point", + "Polygon" + ] + ], + "layout": { + "text-line-height": 1.2, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11 + ], + [ + 18, + 14 + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0 + ], + "text-rotation-alignment": "viewport", + "text-field": "{name_en}", + "text-max-width": 7 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-parks-scalerank1 copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933322393.2852" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "<=", + "scalerank", + 1 + ], + [ + "in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11 + ], + [ + 18, + 14 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 13, + "{maki}-11" + ], + [ + 14, + "{maki}-15" + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(100, 100%, 20%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "poi-scalerank1 copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444933322393.2852" + }, + "source": "composite", + "source-layer": "poi_label", + "filter": [ + "all", + [ + "!in", + "maki", + "campsite", + "cemetery", + "dog-park", + "garden", + "golf", + "park", + "picnic-site", + "playground", + "zoo" + ], + [ + "<=", + "scalerank", + 1 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11 + ], + [ + 18, + 14 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 13, + "{maki}-11" + ], + [ + 14, + "{maki}-15" + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.65 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(26, 25%, 32%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "airport-label copy 4", + "type": "symbol", + "source": "composite", + "source-layer": "airport_label", + "minzoom": 9, + "filter": [ + "<=", + "scalerank", + 2 + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 12 + ], + [ + 18, + 18 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 12, + "{maki}-11" + ], + [ + 13, + "{maki}-15" + ] + ] + }, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.75 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": { + "stops": [ + [ + 11, + "{ref}" + ], + [ + 12, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.01, + "text-max-width": 9 + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "airport-label copy 3", + "type": "symbol", + "source": "composite", + "source-layer": "airport_label", + "minzoom": 9, + "filter": [ + "<=", + "scalerank", + 2 + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 12 + ], + [ + 18, + 18 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 12, + "{maki}-11" + ], + [ + 13, + "{maki}-15" + ] + ] + }, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.75 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": { + "stops": [ + [ + 11, + "{ref}" + ], + [ + 12, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.01, + "text-max-width": 9 + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "airport-label copy 2", + "type": "symbol", + "source": "composite", + "source-layer": "airport_label", + "minzoom": 9, + "filter": [ + "<=", + "scalerank", + 2 + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 12 + ], + [ + 18, + 18 + ] + ] + }, + "icon-image": { + "stops": [ + [ + 12, + "{maki}-11" + ], + [ + 13, + "{maki}-15" + ] + ] + }, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0.75 + ], + "text-rotation-alignment": "viewport", + "text-anchor": "top", + "text-field": { + "stops": [ + [ + 11, + "{ref}" + ], + [ + 12, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.01, + "text-max-width": 9 + }, + "paint": { + "text-color": "hsl(230, 48%, 44%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 0.5, + "text-halo-blur": 0.5 + } + }, + { + "id": "place-islet-archipelago-aboriginal copy", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "maxzoom": 16, + "filter": [ + "in", + "type", + "aboriginal_lands", + "archipelago", + "islet" + ], + "layout": { + "text-line-height": 1.2, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11 + ], + [ + 18, + 16 + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0 + ], + "text-rotation-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 8 + }, + "paint": { + "text-color": "hsl(230, 29%, 35%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "place-neighbourhood copy", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 10, + "maxzoom": 16, + "filter": [ + "==", + "type", + "neighbourhood" + ], + "layout": { + "text-field": "{name_en}", + "text-transform": "uppercase", + "text-letter-spacing": 0.1, + "text-max-width": 7, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-padding": 3, + "text-size": { + "base": 1, + "stops": [ + [ + 12, + 11 + ], + [ + 16, + 16 + ] + ] + } + }, + "paint": { + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "text-color": "hsl(230, 29%, 35%)", + "text-halo-blur": 0.5 + } + }, + { + "id": "place-suburb copy 2", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 10, + "maxzoom": 16, + "filter": [ + "==", + "type", + "suburb" + ], + "layout": { + "text-field": "{name_en}", + "text-transform": "uppercase", + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-letter-spacing": 0.15, + "text-max-width": 7, + "text-padding": 3, + "text-size": { + "base": 1, + "stops": [ + [ + 11, + 11 + ], + [ + 15, + 18 + ] + ] + } + }, + "paint": { + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "text-color": "hsl(230, 29%, 35%)", + "text-halo-blur": 0.5 + } + }, + { + "id": "place-suburb copy 1", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 10, + "maxzoom": 16, + "filter": [ + "==", + "type", + "suburb" + ], + "layout": { + "text-field": "{name_en}", + "text-transform": "uppercase", + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-letter-spacing": 0.15, + "text-max-width": 7, + "text-padding": 3, + "text-size": { + "base": 1, + "stops": [ + [ + 11, + 11 + ], + [ + 15, + 18 + ] + ] + } + }, + "paint": { + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "text-color": "hsl(230, 29%, 35%)", + "text-halo-blur": 0.5 + } + }, + { + "id": "place-hamlet copy", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 10, + "maxzoom": 16, + "filter": [ + "==", + "type", + "hamlet" + ], + "layout": { + "text-field": "{name_en}", + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1, + "stops": [ + [ + 12, + 11.5 + ], + [ + 15, + 16 + ] + ] + } + }, + "paint": { + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1.25, + "text-color": "hsl(0, 0%, 0%)" + } + }, + { + "id": "place-village copy", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 8, + "maxzoom": 15, + "filter": [ + "==", + "type", + "village" + ], + "layout": { + "text-field": "{name_en}", + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-max-width": 7, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11.5 + ], + [ + 16, + 18 + ] + ] + } + }, + "paint": { + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1.25, + "text-color": "hsl(0, 0%, 0%)" + } + }, + { + "id": "place-town copy", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "minzoom": 6, + "maxzoom": 15, + "filter": [ + "==", + "type", + "town" + ], + "layout": { + "icon-image": "dot-9", + "text-font": { + "base": 1, + "stops": [ + [ + 11, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 12, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7, + [ + 0, + -0.15 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "bottom" + ], + [ + 8, + "center" + ] + ] + }, + "text-field": "{name_en}", + "text-max-width": 7, + "text-size": { + "base": 1, + "stops": [ + [ + 7, + 11.5 + ], + [ + 15, + 20 + ] + ] + } + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1.25, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + } + } + }, + { + "id": "place-island copy", + "type": "symbol", + "source": "composite", + "source-layer": "place_label", + "maxzoom": 16, + "filter": [ + "==", + "type", + "island" + ], + "layout": { + "text-line-height": 1.2, + "text-size": { + "base": 1, + "stops": [ + [ + 10, + 11 + ], + [ + 18, + 16 + ] + ] + }, + "text-max-angle": 38, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ], + "text-padding": 2, + "text-offset": [ + 0, + 0 + ], + "text-rotation-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.01, + "text-max-width": 7 + }, + "paint": { + "text-color": "hsl(230, 29%, 35%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "place-city-sm copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444862510685.128" + }, + "source": "composite", + "source-layer": "place_label", + "maxzoom": 14, + "filter": [ + "all", + [ + "!in", + "scalerank", + 0, + 1, + 2, + 3, + 4, + 5 + ], + [ + "==", + "type", + "city" + ] + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 6, + 12 + ], + [ + 14, + 22 + ] + ] + }, + "icon-image": "dot-9", + "text-font": { + "base": 1, + "stops": [ + [ + 7, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 8, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7.99, + [ + 0, + -0.2 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "bottom" + ], + [ + 8, + "center" + ] + ] + }, + "text-field": "{name_en}", + "text-max-width": 7 + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1.25, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + } + } + }, + { + "id": "place-city-md-s copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444862510685.128" + }, + "source": "composite", + "source-layer": "place_label", + "maxzoom": 14, + "filter": [ + "all", + [ + "==", + "type", + "city" + ], + [ + "in", + "ldir", + "E", + "S", + "SE", + "SW" + ], + [ + "in", + "scalerank", + 3, + 4, + 5 + ] + ], + "layout": { + "text-field": "{name_en}", + "icon-image": "dot-10", + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "top" + ], + [ + 8, + "center" + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7.99, + [ + 0, + 0.1 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-font": { + "base": 1, + "stops": [ + [ + 7, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 8, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-size": { + "base": 0.9, + "stops": [ + [ + 5, + 12 + ], + [ + 12, + 22 + ] + ] + } + }, + "paint": { + "text-halo-width": 1, + "text-halo-color": "hsl(0, 0%, 100%)", + "text-color": "hsl(0, 0%, 0%)", + "text-halo-blur": 1, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + } + } + }, + { + "id": "place-city-md-n copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444862510685.128" + }, + "source": "composite", + "source-layer": "place_label", + "maxzoom": 14, + "filter": [ + "all", + [ + "==", + "type", + "city" + ], + [ + "in", + "ldir", + "N", + "NE", + "NW", + "W" + ], + [ + "in", + "scalerank", + 3, + 4, + 5 + ] + ], + "layout": { + "icon-image": "dot-10", + "text-font": { + "base": 1, + "stops": [ + [ + 7, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 8, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7.99, + [ + 0, + -0.25 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "bottom" + ], + [ + 8, + "center" + ] + ] + }, + "text-field": "{name_en}", + "text-max-width": 7, + "text-size": { + "base": 0.9, + "stops": [ + [ + 5, + 12 + ], + [ + 12, + 22 + ] + ] + } + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + }, + "text-halo-blur": 1 + } + }, + { + "id": "place-city-lg-s copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444862510685.128" + }, + "source": "composite", + "source-layer": "place_label", + "minzoom": 1, + "maxzoom": 14, + "filter": [ + "all", + [ + "<=", + "scalerank", + 2 + ], + [ + "==", + "type", + "city" + ], + [ + "in", + "ldir", + "E", + "S", + "SE", + "SW" + ] + ], + "layout": { + "icon-image": "dot-11", + "text-font": { + "base": 1, + "stops": [ + [ + 7, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 8, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7.99, + [ + 0, + 0.15 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "top" + ], + [ + 8, + "center" + ] + ] + }, + "text-field": "{name_en}", + "text-max-width": 7, + "text-size": { + "base": 0.9, + "stops": [ + [ + 4, + 12 + ], + [ + 10, + 22 + ] + ] + } + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + }, + "text-halo-blur": 1 + } + }, + { + "id": "place-city-lg-n copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444862510685.128" + }, + "source": "composite", + "source-layer": "place_label", + "minzoom": 1, + "maxzoom": 14, + "filter": [ + "all", + [ + "<=", + "scalerank", + 2 + ], + [ + "==", + "type", + "city" + ], + [ + "in", + "ldir", + "N", + "NE", + "NW", + "W" + ] + ], + "layout": { + "icon-image": "dot-11", + "text-font": { + "base": 1, + "stops": [ + [ + 7, + [ + "DIN Offc Pro Regular", + "Arial Unicode MS Regular" + ] + ], + [ + 8, + [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ] + ] + ] + }, + "text-offset": { + "base": 1, + "stops": [ + [ + 7.99, + [ + 0, + -0.25 + ] + ], + [ + 8, + [ + 0, + 0 + ] + ] + ] + }, + "text-anchor": { + "base": 1, + "stops": [ + [ + 7, + "bottom" + ], + [ + 8, + "center" + ] + ] + }, + "text-field": "{name_en}", + "text-max-width": 7, + "text-size": { + "base": 0.9, + "stops": [ + [ + 4, + 12 + ], + [ + 10, + 22 + ] + ] + } + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-opacity": 1, + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1, + "icon-opacity": { + "base": 1, + "stops": [ + [ + 7.99, + 1 + ], + [ + 8, + 0 + ] + ] + }, + "text-halo-blur": 1 + } + }, + { + "id": "marine-label-sm-ln copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 3, + "maxzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + ">=", + "labelrank", + 4 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1, + "stops": [ + [ + 3, + 12 + ], + [ + 6, + 16 + ] + ] + }, + "symbol-spacing": { + "base": 1, + "stops": [ + [ + 4, + 100 + ], + [ + 6, + 400 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-pitch-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.1, + "text-max-width": 5 + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "marine-label-sm-pt copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 3, + "maxzoom": 10, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + ">=", + "labelrank", + 4 + ] + ], + "layout": { + "text-field": "{name_en}", + "text-max-width": 5, + "text-letter-spacing": 0.1, + "text-line-height": 1.5, + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1, + "stops": [ + [ + 3, + 12 + ], + [ + 6, + 16 + ] + ] + } + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "marine-label-md-ln copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 2, + "maxzoom": 8, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "in", + "labelrank", + 2, + 3 + ] + ], + "layout": { + "text-line-height": 1.1, + "text-size": { + "base": 1.1, + "stops": [ + [ + 2, + 12 + ], + [ + 5, + 20 + ] + ] + }, + "symbol-spacing": 250, + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "symbol-placement": "line", + "text-pitch-alignment": "viewport", + "text-field": "{name_en}", + "text-letter-spacing": 0.15, + "text-max-width": 5 + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "marine-label-md-pt copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 2, + "maxzoom": 8, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "labelrank", + 2, + 3 + ] + ], + "layout": { + "text-field": "{name_en}", + "text-max-width": 5, + "text-letter-spacing": 0.15, + "text-line-height": 1.5, + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1.1, + "stops": [ + [ + 2, + 14 + ], + [ + 5, + 20 + ] + ] + } + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "marine-label-lg-ln copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 1, + "maxzoom": 4, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "==", + "labelrank", + 1 + ] + ], + "layout": { + "text-field": "{name_en}", + "text-max-width": 4, + "text-letter-spacing": 0.25, + "text-line-height": 1.1, + "symbol-placement": "line", + "text-pitch-alignment": "viewport", + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1, + "stops": [ + [ + 1, + 14 + ], + [ + 4, + 30 + ] + ] + } + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "marine-label-lg-pt copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856087950.3635" + }, + "source": "composite", + "source-layer": "marine_label", + "minzoom": 1, + "maxzoom": 4, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "labelrank", + 1 + ] + ], + "layout": { + "text-field": "{name_en}", + "text-max-width": 4, + "text-letter-spacing": 0.25, + "text-line-height": 1.5, + "text-font": [ + "DIN Offc Pro Italic", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1, + "stops": [ + [ + 1, + 14 + ], + [ + 4, + 30 + ] + ] + } + }, + "paint": { + "text-color": "hsl(205, 83%, 88%)" + } + }, + { + "id": "state-label-sm copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856151690.9143" + }, + "source": "composite", + "source-layer": "state_label", + "minzoom": 3, + "maxzoom": 9, + "filter": [ + "<", + "area", + 20000 + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 6, + 10 + ], + [ + 9, + 14 + ] + ] + }, + "text-transform": "uppercase", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "text-field": { + "base": 1, + "stops": [ + [ + 0, + "{abbr}" + ], + [ + 6, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.15, + "text-max-width": 5 + }, + "paint": { + "text-opacity": 1, + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "state-label-md copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856151690.9143" + }, + "source": "composite", + "source-layer": "state_label", + "minzoom": 3, + "maxzoom": 8, + "filter": [ + "all", + [ + "<", + "area", + 80000 + ], + [ + ">=", + "area", + 20000 + ] + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 5, + 10 + ], + [ + 8, + 16 + ] + ] + }, + "text-transform": "uppercase", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "text-field": { + "base": 1, + "stops": [ + [ + 0, + "{abbr}" + ], + [ + 5, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.15, + "text-max-width": 6 + }, + "paint": { + "text-opacity": 1, + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "state-label-lg copy", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856151690.9143" + }, + "source": "composite", + "source-layer": "state_label", + "minzoom": 3, + "maxzoom": 7, + "filter": [ + ">=", + "area", + 80000 + ], + "layout": { + "text-size": { + "base": 1, + "stops": [ + [ + 4, + 10 + ], + [ + 7, + 18 + ] + ] + }, + "text-transform": "uppercase", + "text-font": [ + "DIN Offc Pro Bold", + "Arial Unicode MS Bold" + ], + "text-padding": 1, + "text-field": { + "base": 1, + "stops": [ + [ + 0, + "{abbr}" + ], + [ + 4, + "{name_en}" + ] + ] + }, + "text-letter-spacing": 0.15, + "text-max-width": 6 + }, + "paint": { + "text-opacity": 1, + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": "hsl(0, 0%, 100%)", + "text-halo-width": 1 + } + }, + { + "id": "country-label-sm", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856144497.7825" + }, + "source": "composite", + "source-layer": "country_label", + "minzoom": 1, + "maxzoom": 10, + "filter": [ + ">=", + "scalerank", + 5 + ], + "layout": { + "text-field": "{name_en}", + "text-max-width": 6, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 0.9, + "stops": [ + [ + 5, + 14 + ], + [ + 9, + 22 + ] + ] + } + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": { + "base": 1, + "stops": [ + [ + 2, + "rgba(255,255,255,0.75)" + ], + [ + 3, + "hsl(0, 0%, 100%)" + ] + ] + }, + "text-halo-width": 1.25 + } + }, + { + "id": "country-label-md", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856144497.7825" + }, + "source": "composite", + "source-layer": "country_label", + "minzoom": 1, + "maxzoom": 8, + "filter": [ + "in", + "scalerank", + 3, + 4 + ], + "layout": { + "text-field": { + "base": 1, + "stops": [ + [ + 0, + "{code}" + ], + [ + 2, + "{name_en}" + ] + ] + }, + "text-max-width": 6, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1, + "stops": [ + [ + 3, + 10 + ], + [ + 8, + 24 + ] + ] + } + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": { + "base": 1, + "stops": [ + [ + 2, + "rgba(255,255,255,0.75)" + ], + [ + 3, + "hsl(0, 0%, 100%)" + ] + ] + }, + "text-halo-width": 1.25 + } + }, + { + "id": "country-label-lg", + "type": "symbol", + "metadata": { + "mapbox:group": "1444856144497.7825" + }, + "source": "composite", + "source-layer": "country_label", + "minzoom": 1, + "maxzoom": 7, + "filter": [ + "in", + "scalerank", + 1, + 2 + ], + "layout": { + "text-field": "{name_en}", + "text-max-width": { + "base": 1, + "stops": [ + [ + 0, + 5 + ], + [ + 3, + 6 + ] + ] + }, + "text-font": [ + "DIN Offc Pro Medium", + "Arial Unicode MS Regular" + ], + "text-size": { + "base": 1, + "stops": [ + [ + 1, + 10 + ], + [ + 6, + 24 + ] + ] + } + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)", + "text-halo-color": { + "base": 1, + "stops": [ + [ + 2, + "rgba(255,255,255,0.75)" + ], + [ + 3, + "hsl(0, 0%, 100%)" + ] + ] + }, + "text-halo-width": 1.25 + } + } + ], + "created": "2018-07-03T09:06:20.716Z", + "id": "cjj5gy5q00ips2rnqgjcneimy", + "modified": "2018-07-03T09:31:38.205Z", + "owner": "lukaspaczos", + "visibility": "public", + "draft": false +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleActivity.java new file mode 100644 index 000000000..5daea88ba --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleActivity.java @@ -0,0 +1,66 @@ +package com.mapbox.mapboxsdk.testapp.activity; + +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; + +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.testapp.R; + +public class SingleActivity extends AppCompatActivity { + private MapView mapView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_single); + + mapView = (MapView) findViewById(R.id.mapView); + mapView.onCreate(savedInstanceState); + } + + public MapView getMapView() { + return mapView; + } + + @Override + protected void onStart() { + super.onStart(); + mapView.onStart(); + } + + @Override + protected void onResume() { + super.onResume(); + mapView.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + mapView.onPause(); + } + + @Override + protected void onStop() { + super.onStop(); + mapView.onStop(); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapView.onLowMemory(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleFragmentActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleFragmentActivity.java new file mode 100644 index 000000000..823b80af1 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleFragmentActivity.java @@ -0,0 +1,36 @@ +package com.mapbox.mapboxsdk.testapp.activity; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.app.AppCompatActivity; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.mapbox.mapboxsdk.testapp.R; + +/** + * Used for testing fragments inside a fake activity. + */ +public class SingleFragmentActivity extends AppCompatActivity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + FrameLayout content = new FrameLayout(this); + content.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + content.setId(R.id.container); + setContentView(content); + } + + public void setFragment(Fragment fragment) { + getSupportFragmentManager().beginTransaction() + .add(R.id.container, fragment, "TEST") + .commit(); + } + + public void replaceFragment(Fragment fragment) { + getSupportFragmentManager().beginTransaction() + .replace(R.id.container, fragment).commit(); + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/debug/res/layout/activity_single.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/res/layout/activity_single.xml new file mode 100644 index 000000000..f7e3d1f8e --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/res/layout/activity_single.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <com.mapbox.mapboxsdk.maps.MapView + android:id="@+id/mapView" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:mapbox_cameraZoomMin="2.0" /> + +</RelativeLayout>
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml index e23b1d64f..a0594d8b8 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml @@ -266,6 +266,9 @@ <meta-data android:name="@string/category" android:value="@string/category_basic" /> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".activity.FeatureOverviewActivity" /> </activity> <activity android:name=".activity.offline.OfflineActivity" @@ -706,6 +709,9 @@ <meta-data android:name="@string/category" android:value="@string/category_maplayout" /> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".activity.FeatureOverviewActivity" /> </activity> <!-- TextureView --> @@ -716,6 +722,9 @@ <meta-data android:name="@string/category" android:value="@string/category_textureview" /> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".activity.FeatureOverviewActivity" /> </activity> <activity android:name=".activity.textureview.TextureViewResizeActivity" @@ -724,6 +733,9 @@ <meta-data android:name="@string/category" android:value="@string/category_textureview" /> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".activity.FeatureOverviewActivity" /> </activity> <activity android:name=".activity.textureview.TextureViewTransparentBackgroundActivity" @@ -743,6 +755,9 @@ <meta-data android:name="@string/category" android:value="@string/category_textureview" /> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".activity.FeatureOverviewActivity" /> </activity> <activity android:name=".activity.maplayout.LocalGlyphActivity" @@ -800,6 +815,50 @@ android:name="android.support.PARENT_ACTIVITY" android:value="com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity" /> </activity> + <activity + android:name=".activity.location.LocationMapChangeActivity" + android:description="@string/description_location_map_change" + android:label="@string/activity_location_map_change"> + <meta-data + android:name="@string/category" + android:value="@string/category_location" /> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".activity.FeatureOverviewActivity" /> + </activity> + <activity + android:name=".activity.location.LocationModesActivity" + android:description="@string/description_location_modes" + android:label="@string/activity_location_modes"> + <meta-data + android:name="@string/category" + android:value="@string/category_location" /> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".activity.FeatureOverviewActivity" /> + </activity> + <activity + android:name=".activity.location.LocationFragmentActivity" + android:description="@string/description_location_fragment" + android:label="@string/activity_location_fragment"> + <meta-data + android:name="@string/category" + android:value="@string/category_location" /> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".activity.FeatureOverviewActivity" /> + </activity> + <activity + android:name=".activity.location.ManualLocationUpdatesActivity" + android:description="@string/description_location_manual" + android:label="@string/activity_location_manual"> + <meta-data + android:name="@string/category" + android:value="@string/category_location" /> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".activity.FeatureOverviewActivity" /> + </activity> <!-- For Instrumentation tests --> <activity diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java index fbf439448..28a89f4b4 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java @@ -68,7 +68,7 @@ public class PolylineActivity extends AppCompatActivity { mapboxMap.setOnPolylineClickListener(polyline -> Toast.makeText( PolylineActivity.this, - "You clicked on polygon with id = " + polyline.getId(), + "You clicked on polyline with id = " + polyline.getId(), Toast.LENGTH_SHORT ).show()); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java index 29c0ae0fc..67fe05eaa 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java @@ -43,13 +43,15 @@ public class PressForMarkerActivity extends AppCompatActivity { mapboxMap = map; resetMap(); - mapboxMap.setOnMapLongClickListener(point -> addMarker(point)); + mapboxMap.addOnMapLongClickListener(point -> addMarker(point)); - mapboxMap.setOnMapClickListener(point -> addMarker(point)); + mapboxMap.addOnMapClickListener(point -> addMarker(point)); if (savedInstanceState != null) { markerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST); - mapboxMap.addMarkers(markerList); + if (markerList != null) { + mapboxMap.addMarkers(markerList); + } } }); } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java index e069a7fd0..4ee835498 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java @@ -61,12 +61,18 @@ public class LatLngBoundsActivity extends AppCompatActivity implements View.OnCl } private void initMap() { + disableGestures(); addMarkers(); initFab(); initBottomSheet(); moveToBounds(bottomSheet.getMeasuredHeight(), BOUNDS_PADDING_DIVIDER_SMALL, ANIMATION_DURATION_SHORT); } + private void disableGestures() { + mapboxMap.getUiSettings().setTiltGesturesEnabled(false); + mapboxMap.getUiSettings().setRotateGesturesEnabled(false); + } + private void addMarkers() { for (LatLng location : LOCATIONS) { mapboxMap.addMarker(new MarkerOptions().position(location)); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QuerySourceFeaturesActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QuerySourceFeaturesActivity.java index 79069a26f..3a52a22f6 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QuerySourceFeaturesActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QuerySourceFeaturesActivity.java @@ -1,6 +1,8 @@ package com.mapbox.mapboxsdk.testapp.activity.feature; import android.os.Bundle; +import android.support.design.widget.FloatingActionButton; +import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.widget.Toast; @@ -9,7 +11,7 @@ import com.mapbox.geojson.Feature; import com.mapbox.geojson.FeatureCollection; import com.mapbox.geojson.Point; import com.mapbox.mapboxsdk.maps.MapView; -import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.style.expressions.Expression; import com.mapbox.mapboxsdk.style.layers.CircleLayer; import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; import com.mapbox.mapboxsdk.testapp.R; @@ -27,7 +29,6 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.neq; public class QuerySourceFeaturesActivity extends AppCompatActivity { public MapView mapView; - private MapboxMap mapboxMap; @Override protected void onCreate(Bundle savedInstanceState) { @@ -38,31 +39,45 @@ public class QuerySourceFeaturesActivity extends AppCompatActivity { mapView = (MapView) findViewById(R.id.mapView); mapView.onCreate(savedInstanceState); mapView.getMapAsync(mapboxMap -> { - QuerySourceFeaturesActivity.this.mapboxMap = mapboxMap; - JsonObject properties = new JsonObject(); properties.addProperty("key1", "value1"); final GeoJsonSource source = new GeoJsonSource("test-source", FeatureCollection.fromFeatures(new Feature[] { - Feature.fromGeometry(Point.fromLngLat(0, 0), properties) + Feature.fromGeometry(Point.fromLngLat(17.1, 51), properties), + Feature.fromGeometry(Point.fromLngLat(17.2, 51), properties), + Feature.fromGeometry(Point.fromLngLat(17.3, 51), properties), + Feature.fromGeometry(Point.fromLngLat(17.4, 51), properties), })); mapboxMap.addSource(source); - mapboxMap.addLayer(new CircleLayer("test-layer", source.getId()).withFilter(neq(get("key1"), literal("value1")))); + Expression visible = eq(get("key1"), literal("value1")); + Expression invisible = neq(get("key1"), literal("value1")); + + CircleLayer layer = new CircleLayer("test-layer", source.getId()) + .withFilter(visible); + mapboxMap.addLayer(layer); // Add a click listener - mapboxMap.setOnMapClickListener(point -> { + mapboxMap.addOnMapClickListener(point -> { // Query List<Feature> features = source.querySourceFeatures(eq(get("key1"), literal("value1"))); Toast.makeText(QuerySourceFeaturesActivity.this, String.format("Found %s features", features.size()), Toast.LENGTH_SHORT).show(); }); - }); - } - - public MapboxMap getMapboxMap() { - return mapboxMap; + FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); + fab.setColorFilter(ContextCompat.getColor(this, R.color.primary)); + fab.setOnClickListener(view -> { + Expression visibility = layer.getFilter(); + if (visibility != null && visibility.equals(visible)) { + layer.setFilter(invisible); + fab.setImageResource(R.drawable.ic_layers_clear); + } else { + layer.setFilter(visible); + fab.setImageResource(R.drawable.ic_layers); + } + }); + }); } @Override diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt new file mode 100644 index 000000000..035ad67e1 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt @@ -0,0 +1,172 @@ +package com.mapbox.mapboxsdk.testapp.activity.location + +import android.annotation.SuppressLint +import android.app.Fragment +import android.location.Location +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import android.widget.Toast +import com.mapbox.android.core.location.LocationEngineListener +import com.mapbox.android.core.permissions.PermissionsListener +import com.mapbox.android.core.permissions.PermissionsManager +import com.mapbox.mapboxsdk.camera.CameraUpdateFactory +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.maps.MapView +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.location.LocationComponent +import com.mapbox.mapboxsdk.testapp.R +import kotlinx.android.synthetic.main.activity_location_layer_fragment.* + +class LocationFragmentActivity : AppCompatActivity() { + private lateinit var permissionsManager: PermissionsManager + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_location_layer_fragment) + + fab.setOnClickListener { + val fragment = fragmentManager.findFragmentByTag(EmptyFragment.TAG) + if (fragment == null) { + fragmentManager + .beginTransaction() + .replace(R.id.container, EmptyFragment.newInstance(), EmptyFragment.TAG) + .addToBackStack("transaction2") + .commit() + } else { + this.onBackPressed() + } + } + supportActionBar?.setDisplayHomeAsUpEnabled(true) + + if (PermissionsManager.areLocationPermissionsGranted(this)) { + if (savedInstanceState == null) { + fragmentManager + .beginTransaction() + .replace(R.id.container, LocationFragment.newInstance(), LocationFragment.TAG) + .commit() + } + } else { + permissionsManager = PermissionsManager(object : PermissionsListener { + override fun onExplanationNeeded(permissionsToExplain: MutableList<String>?) { + Toast.makeText(this@LocationFragmentActivity, "You need to accept location permissions.", + Toast.LENGTH_SHORT).show() + } + + override fun onPermissionResult(granted: Boolean) { + if (granted) { + if (savedInstanceState == null) { + fragmentManager + .beginTransaction() + .replace(R.id.container, LocationFragment.newInstance(), LocationFragment.TAG) + .commit() + } + } else { + finish() + } + } + }) + permissionsManager.requestLocationPermissions(this) + } + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults) + } + + class LocationFragment : Fragment(), LocationEngineListener { + companion object { + const val TAG = "LFragment" + fun newInstance(): LocationFragment { + return LocationFragment() + } + } + + private lateinit var mapView: MapView + private lateinit var mapboxMap: MapboxMap + private var component: LocationComponent? = null + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + mapView = MapView(inflater.context) + return mapView + } + + @SuppressLint("MissingPermission") + override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { + mapView.onCreate(savedInstanceState) + mapView.getMapAsync { + mapboxMap = it + component = mapboxMap.locationComponent + component?.activateLocationComponent(activity) + component?.isLocationComponentEnabled = true + component?.locationEngine?.addLocationEngineListener(this) + } + } + + override fun onLocationChanged(location: Location?) { + if (location != null) { + mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(location), 12.0)) + component?.locationEngine?.removeLocationEngineListener(this) + } + } + + override fun onConnected() { + // no impl + } + + override fun onStart() { + super.onStart() + mapView.onStart() + } + + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onPause() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } + + override fun onStop() { + super.onStop() + mapView.onStop() + } + + override fun onLowMemory() { + super.onLowMemory() + mapView.onLowMemory() + } + + override fun onDestroyView() { + super.onDestroyView() + mapView.onDestroy() + component?.locationEngine?.removeLocationEngineListener(this) + } + } + + class EmptyFragment : Fragment() { + companion object { + const val TAG = "EmptyFragment" + fun newInstance(): EmptyFragment { + return EmptyFragment() + } + } + + override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View { + val textView = TextView(inflater?.context) + textView.text = "This is an empty Fragment" + return textView + } + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationMapChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationMapChangeActivity.java new file mode 100644 index 000000000..e53604fdd --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationMapChangeActivity.java @@ -0,0 +1,132 @@ +package com.mapbox.mapboxsdk.testapp.activity.location; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.FloatingActionButton; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.Toast; + +import com.mapbox.android.core.permissions.PermissionsListener; +import com.mapbox.android.core.permissions.PermissionsManager; +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; +import com.mapbox.mapboxsdk.location.LocationComponent; +import com.mapbox.mapboxsdk.location.modes.RenderMode; +import com.mapbox.mapboxsdk.testapp.R; + +import java.util.List; + +public class LocationMapChangeActivity extends AppCompatActivity implements OnMapReadyCallback { + + private MapView mapView; + private MapboxMap mapboxMap; + private PermissionsManager permissionsManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_location_layer_map_change); + + mapView = findViewById(R.id.mapView); + FloatingActionButton stylesFab = findViewById(R.id.fabStyles); + + stylesFab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mapboxMap != null) { + mapboxMap.setStyleUrl(Utils.getNextStyle()); + } + } + }); + + mapView.setStyleUrl(Utils.getNextStyle()); + mapView.onCreate(savedInstanceState); + + if (PermissionsManager.areLocationPermissionsGranted(this)) { + mapView.getMapAsync(this); + } else { + permissionsManager = new PermissionsManager(new PermissionsListener() { + @Override + public void onExplanationNeeded(List<String> permissionsToExplain) { + Toast.makeText(LocationMapChangeActivity.this, "You need to accept location permissions.", + Toast.LENGTH_SHORT).show(); + } + + @Override + public void onPermissionResult(boolean granted) { + if (granted) { + mapView.getMapAsync(LocationMapChangeActivity.this); + } else { + finish(); + } + } + }); + permissionsManager.requestLocationPermissions(this); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + + @Override + public void onMapReady(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + activateLocationComponent(); + } + + @SuppressLint("MissingPermission") + private void activateLocationComponent() { + LocationComponent locationComponent = mapboxMap.getLocationComponent(); + locationComponent.activateLocationComponent(this); + locationComponent.setLocationComponentEnabled(true); + locationComponent.setRenderMode(RenderMode.COMPASS); + } + + @Override + protected void onStart() { + super.onStart(); + mapView.onStart(); + } + + @Override + protected void onResume() { + super.onResume(); + mapView.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + mapView.onPause(); + } + + @Override + protected void onStop() { + super.onStop(); + mapView.onStop(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapView.onLowMemory(); + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationModesActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationModesActivity.java new file mode 100644 index 000000000..86feb00de --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationModesActivity.java @@ -0,0 +1,416 @@ +package com.mapbox.mapboxsdk.testapp.activity.location; + +import android.annotation.SuppressLint; +import android.content.res.Configuration; +import android.location.Location; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.ListPopupWindow; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.Toast; + +import com.mapbox.android.core.location.LocationEngine; +import com.mapbox.android.core.location.LocationEngineListener; +import com.mapbox.android.core.location.LocationEnginePriority; +import com.mapbox.android.core.location.LocationEngineProvider; +import com.mapbox.android.core.permissions.PermissionsListener; +import com.mapbox.android.core.permissions.PermissionsManager; +import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; +import com.mapbox.mapboxsdk.constants.Style; +import com.mapbox.mapboxsdk.location.OnLocationClickListener; +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; +import com.mapbox.mapboxsdk.location.LocationComponentOptions; +import com.mapbox.mapboxsdk.location.LocationComponent; +import com.mapbox.mapboxsdk.location.OnCameraTrackingChangedListener; +import com.mapbox.mapboxsdk.location.modes.CameraMode; +import com.mapbox.mapboxsdk.location.modes.RenderMode; +import com.mapbox.mapboxsdk.testapp.R; + +import java.util.ArrayList; +import java.util.List; + +public class LocationModesActivity extends AppCompatActivity implements OnMapReadyCallback, + LocationEngineListener, OnLocationClickListener, OnCameraTrackingChangedListener { + + private MapView mapView; + private Button locationModeBtn; + private Button locationTrackingBtn; + + private PermissionsManager permissionsManager; + + private LocationComponent locationComponent; + private LocationEngine locationEngine; + private MapboxMap mapboxMap; + private boolean customStyle; + + private static final String SAVED_STATE_CAMERA = "saved_state_camera"; + private static final String SAVED_STATE_RENDER = "saved_state_render"; + private static final String SAVED_STATE_LOCATION = "saved_state_location"; + + @CameraMode.Mode + private int cameraMode = CameraMode.TRACKING; + + @RenderMode.Mode + private int renderMode = RenderMode.NORMAL; + + private Location lastLocation; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_location_layer_mode); + + mapView = findViewById(R.id.mapView); + + locationModeBtn = findViewById(R.id.button_location_mode); + locationModeBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (locationComponent == null) { + return; + } + showModeListDialog(); + } + }); + + locationTrackingBtn = findViewById(R.id.button_location_tracking); + locationTrackingBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (locationComponent == null) { + return; + } + showTrackingListDialog(); + } + }); + + + if (savedInstanceState != null) { + cameraMode = savedInstanceState.getInt(SAVED_STATE_CAMERA); + renderMode = savedInstanceState.getInt(SAVED_STATE_RENDER); + lastLocation = savedInstanceState.getParcelable(SAVED_STATE_LOCATION); + } + + mapView.onCreate(savedInstanceState); + + if (PermissionsManager.areLocationPermissionsGranted(this)) { + mapView.getMapAsync(this); + } else { + permissionsManager = new PermissionsManager(new PermissionsListener() { + @Override + public void onExplanationNeeded(List<String> permissionsToExplain) { + Toast.makeText(LocationModesActivity.this, "You need to accept location permissions.", + Toast.LENGTH_SHORT).show(); + } + + @Override + public void onPermissionResult(boolean granted) { + if (granted) { + mapView.getMapAsync(LocationModesActivity.this); + } else { + finish(); + } + } + }); + permissionsManager.requestLocationPermissions(this); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + + @SuppressLint("MissingPermission") + @Override + public void onMapReady(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + + locationEngine = new LocationEngineProvider(this).obtainBestLocationEngineAvailable(); + locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY); + locationEngine.setFastestInterval(1000); + locationEngine.addLocationEngineListener(this); + locationEngine.activate(); + + int[] padding; + if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { + padding = new int[] {0, 750, 0, 0}; + } else { + padding = new int[] {0, 250, 0, 0}; + } + + LocationComponentOptions options = LocationComponentOptions.builder(this) + .padding(padding) + .layerBelow("waterway-label") + .build(); + + locationComponent = mapboxMap.getLocationComponent(); + locationComponent.activateLocationComponent(this, locationEngine, options); + locationComponent.setLocationComponentEnabled(true); + locationComponent.addOnLocationClickListener(this); + locationComponent.addOnCameraTrackingChangedListener(this); + locationComponent.setCameraMode(cameraMode); + setRendererMode(renderMode); + locationComponent.forceLocationUpdate(lastLocation); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_location_mode, menu); + return true; + } + + @SuppressLint("MissingPermission") + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (locationComponent == null) { + return super.onOptionsItemSelected(item); + } + + int id = item.getItemId(); + if (id == R.id.action_style_change) { + toggleStyle(); + return true; + } else if (id == R.id.action_map_style_change) { + toggleMapStyle(); + return true; + } else if (id == R.id.action_component_disable) { + locationComponent.setLocationComponentEnabled(false); + return true; + } else if (id == R.id.action_component_enabled) { + locationComponent.setLocationComponentEnabled(true); + return true; + } else if (id == R.id.action_gestures_management_disabled) { + disableGesturesManagement(); + return true; + } else if (id == R.id.action_gestures_management_enabled) { + enableGesturesManagement(); + return true; + } + + return super.onOptionsItemSelected(item); + } + + private void toggleStyle() { + customStyle = !customStyle; + locationComponent.applyStyle( + this, + customStyle ? R.style.CustomLocationComponent : R.style.mapbox_LocationComponent); + } + + private void toggleMapStyle() { + String styleUrl = mapboxMap.getStyleUrl().contentEquals(Style.DARK) ? Style.LIGHT : Style.DARK; + mapboxMap.setStyle(styleUrl); + } + + private void disableGesturesManagement() { + LocationComponentOptions options = locationComponent + .getLocationComponentOptions() + .toBuilder() + .trackingGesturesManagement(false) + .build(); + locationComponent.applyStyle(options); + } + + private void enableGesturesManagement() { + LocationComponentOptions options = locationComponent + .getLocationComponentOptions() + .toBuilder() + .trackingGesturesManagement(true) + .build(); + locationComponent.applyStyle(options); + } + + @Override + @SuppressWarnings( {"MissingPermission"}) + protected void onStart() { + super.onStart(); + mapView.onStart(); + if (locationEngine != null) { + locationEngine.addLocationEngineListener(this); + if (locationEngine.isConnected()) { + locationEngine.requestLocationUpdates(); + } else { + locationEngine.activate(); + } + } + } + + @Override + protected void onResume() { + super.onResume(); + mapView.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + mapView.onPause(); + } + + @Override + protected void onStop() { + super.onStop(); + mapView.onStop(); + if (locationEngine != null) { + locationEngine.removeLocationEngineListener(this); + locationEngine.removeLocationUpdates(); + } + } + + @SuppressLint("MissingPermission") + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + outState.putInt(SAVED_STATE_CAMERA, cameraMode); + outState.putInt(SAVED_STATE_RENDER, renderMode); + if (locationComponent != null) { + outState.putParcelable(SAVED_STATE_LOCATION, locationComponent.getLastKnownLocation()); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + if (locationEngine != null) { + locationEngine.deactivate(); + } + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapView.onLowMemory(); + } + + @Override + @SuppressWarnings( {"MissingPermission"}) + public void onConnected() { + locationEngine.requestLocationUpdates(); + } + + @Override + public void onLocationChanged(Location location) { + // no impl + } + + @Override + public void onLocationComponentClick() { + Toast.makeText(this, "OnLocationComponentClick", Toast.LENGTH_LONG).show(); + } + + private void showModeListDialog() { + List<String> modes = new ArrayList<>(); + modes.add("Normal"); + modes.add("Compass"); + modes.add("GPS"); + ArrayAdapter<String> profileAdapter = new ArrayAdapter<>(this, + android.R.layout.simple_list_item_1, modes); + ListPopupWindow listPopup = new ListPopupWindow(this); + listPopup.setAdapter(profileAdapter); + listPopup.setAnchorView(locationModeBtn); + listPopup.setOnItemClickListener((parent, itemView, position, id) -> { + String selectedMode = modes.get(position); + locationModeBtn.setText(selectedMode); + if (selectedMode.contentEquals("Normal")) { + setRendererMode(RenderMode.NORMAL); + } else if (selectedMode.contentEquals("Compass")) { + setRendererMode(RenderMode.COMPASS); + } else if (selectedMode.contentEquals("GPS")) { + setRendererMode(RenderMode.GPS); + } + listPopup.dismiss(); + }); + listPopup.show(); + } + + private void setRendererMode(@RenderMode.Mode int mode) { + renderMode = mode; + locationComponent.setRenderMode(mode); + if (mode == RenderMode.NORMAL) { + locationModeBtn.setText("Normal"); + } else if (mode == RenderMode.COMPASS) { + locationModeBtn.setText("Compass"); + } else if (mode == RenderMode.GPS) { + locationModeBtn.setText("Gps"); + } + } + + private void showTrackingListDialog() { + List<String> trackingTypes = new ArrayList<>(); + trackingTypes.add("None"); + trackingTypes.add("Tracking"); + trackingTypes.add("Tracking Compass"); + trackingTypes.add("Tracking GPS"); + trackingTypes.add("Tracking GPS North"); + ArrayAdapter<String> profileAdapter = new ArrayAdapter<>(this, + android.R.layout.simple_list_item_1, trackingTypes); + ListPopupWindow listPopup = new ListPopupWindow(this); + listPopup.setAdapter(profileAdapter); + listPopup.setAnchorView(locationTrackingBtn); + listPopup.setOnItemClickListener((parent, itemView, position, id) -> { + String selectedTrackingType = trackingTypes.get(position); + locationTrackingBtn.setText(selectedTrackingType); + if (selectedTrackingType.contentEquals("None")) { + locationComponent.setCameraMode(CameraMode.NONE); + } else if (selectedTrackingType.contentEquals("Tracking")) { + locationComponent.setCameraMode(CameraMode.TRACKING); + } else if (selectedTrackingType.contentEquals("Tracking Compass")) { + locationComponent.setCameraMode(CameraMode.TRACKING_COMPASS); + } else if (selectedTrackingType.contentEquals("Tracking GPS")) { + locationComponent.setCameraMode(CameraMode.TRACKING_GPS); + } else if (selectedTrackingType.contentEquals("Tracking GPS North")) { + locationComponent.setCameraMode(CameraMode.TRACKING_GPS_NORTH); + } + listPopup.dismiss(); + + if (locationComponent.getCameraMode() != CameraMode.NONE) { + locationComponent.zoomWhileTracking(15, 750, new MapboxMap.CancelableCallback() { + @Override + public void onCancel() { + // No impl + } + + @Override + public void onFinish() { + locationComponent.tiltWhileTracking(45); + } + }); + } else { + mapboxMap.easeCamera(CameraUpdateFactory.tiltTo(0)); + } + }); + listPopup.show(); + } + + @Override + public void onCameraTrackingDismissed() { + locationTrackingBtn.setText("None"); + } + + @Override + public void onCameraTrackingChanged(int currentMode) { + this.cameraMode = currentMode; + if (currentMode == CameraMode.NONE) { + locationTrackingBtn.setText("None"); + } else if (currentMode == CameraMode.TRACKING) { + locationTrackingBtn.setText("Tracking"); + } else if (currentMode == CameraMode.TRACKING_COMPASS) { + locationTrackingBtn.setText("Tracking Compass"); + } else if (currentMode == CameraMode.TRACKING_GPS) { + locationTrackingBtn.setText("Tracking GPS"); + } else if (currentMode == CameraMode.TRACKING_GPS_NORTH) { + locationTrackingBtn.setText("Tracking GPS North"); + } + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/ManualLocationUpdatesActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/ManualLocationUpdatesActivity.java new file mode 100644 index 000000000..265113727 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/ManualLocationUpdatesActivity.java @@ -0,0 +1,191 @@ +package com.mapbox.mapboxsdk.testapp.activity.location; + +import android.location.Location; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.FloatingActionButton; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.Toast; + +import com.mapbox.android.core.location.LocationEngine; +import com.mapbox.android.core.location.LocationEngineListener; +import com.mapbox.android.core.location.LocationEnginePriority; +import com.mapbox.android.core.location.LocationEngineProvider; +import com.mapbox.android.core.permissions.PermissionsListener; +import com.mapbox.android.core.permissions.PermissionsManager; +import com.mapbox.mapboxsdk.geometry.LatLngBounds; +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; +import com.mapbox.mapboxsdk.location.LocationComponent; +import com.mapbox.mapboxsdk.location.modes.RenderMode; +import com.mapbox.mapboxsdk.testapp.R; + +import java.util.List; + +import timber.log.Timber; + +public class ManualLocationUpdatesActivity extends AppCompatActivity implements OnMapReadyCallback, + LocationEngineListener { + + private MapView mapView; + private LocationComponent locationComponent; + private LocationEngine locationEngine; + private PermissionsManager permissionsManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_location_manual_update); + + FloatingActionButton fabManualUpdate = findViewById(R.id.fabManualLocationChange); + fabManualUpdate.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (locationComponent != null && locationComponent.getLocationEngine() == null) { + locationComponent.forceLocationUpdate( + Utils.getRandomLocation(LatLngBounds.from(60, 25, 40, -5))); + } + } + }); + fabManualUpdate.setEnabled(false); + + FloatingActionButton fabToggle = findViewById(R.id.fabToggleManualLocation); + fabToggle.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (locationComponent != null) { + locationComponent.setLocationEngine(locationComponent.getLocationEngine() == null ? locationEngine : + null); + + if (locationComponent.getLocationEngine() == null) { + fabToggle.setImageResource(R.drawable.ic_layers_clear); + fabManualUpdate.setEnabled(true); + fabManualUpdate.setAlpha(1f); + Toast.makeText( + ManualLocationUpdatesActivity.this, + "LocationEngine disable, use manual updates", + Toast.LENGTH_SHORT).show(); + } else { + fabToggle.setImageResource(R.drawable.ic_layers); + fabManualUpdate.setEnabled(false); + fabManualUpdate.setAlpha(0.5f); + Toast.makeText( + ManualLocationUpdatesActivity.this, + "LocationEngine enabled", + Toast.LENGTH_SHORT).show(); + } + } + } + }); + + mapView = findViewById(R.id.mapView); + mapView.onCreate(savedInstanceState); + + if (PermissionsManager.areLocationPermissionsGranted(this)) { + mapView.getMapAsync(this); + } else { + permissionsManager = new PermissionsManager(new PermissionsListener() { + @Override + public void onExplanationNeeded(List<String> permissionsToExplain) { + Toast.makeText(ManualLocationUpdatesActivity.this, "You need to accept location permissions.", + Toast.LENGTH_SHORT).show(); + } + + @Override + public void onPermissionResult(boolean granted) { + if (granted) { + mapView.getMapAsync(ManualLocationUpdatesActivity.this); + } else { + finish(); + } + } + }); + permissionsManager.requestLocationPermissions(this); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + + @Override + public void onMapReady(MapboxMap mapboxMap) { + locationEngine = new LocationEngineProvider(this).obtainBestLocationEngineAvailable(); + locationEngine.addLocationEngineListener(this); + locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY); + locationEngine.activate(); + locationComponent = mapboxMap.getLocationComponent(); + locationComponent.activateLocationComponent(this, locationEngine); + locationComponent.setLocationComponentEnabled(true); + locationComponent.setRenderMode(RenderMode.COMPASS); + } + + @Override + @SuppressWarnings( {"MissingPermission"}) + public void onConnected() { + locationEngine.requestLocationUpdates(); + } + + @Override + public void onLocationChanged(Location location) { + Timber.d("Location change occurred: %s", location.toString()); + } + + @Override + @SuppressWarnings( {"MissingPermission"}) + protected void onStart() { + super.onStart(); + mapView.onStart(); + if (locationEngine != null) { + locationEngine.requestLocationUpdates(); + locationEngine.addLocationEngineListener(this); + } + } + + @Override + protected void onResume() { + super.onResume(); + mapView.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + mapView.onPause(); + } + + @Override + protected void onStop() { + super.onStop(); + mapView.onStop(); + if (locationEngine != null) { + locationEngine.removeLocationEngineListener(this); + locationEngine.removeLocationUpdates(); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + if (locationEngine != null) { + locationEngine.deactivate(); + } + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapView.onLowMemory(); + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/Utils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/Utils.java new file mode 100644 index 000000000..41c308c69 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/Utils.java @@ -0,0 +1,59 @@ +package com.mapbox.mapboxsdk.testapp.activity.location; + +import android.location.Location; + +import com.mapbox.mapboxsdk.constants.Style; +import com.mapbox.mapboxsdk.geometry.LatLngBounds; + +import java.util.Random; + +import timber.log.Timber; + +/** + * Useful utilities used throughout the testapp. + */ +public class Utils { + + private static final String[] STYLES = new String[] { + Style.MAPBOX_STREETS, + Style.OUTDOORS, + Style.LIGHT, + Style.DARK, + Style.SATELLITE_STREETS + }; + + private static int index; + + /** + * Utility to cycle through map styles. Useful to test if runtime styling source and layers transfer over to new + * style. + * + * @return a string ID representing the map style + */ + public static String getNextStyle() { + index++; + if (index == STYLES.length) { + index = 0; + } + return STYLES[index]; + } + + /** + * Utility for getting a random coordinate inside a provided bounds and creates a {@link Location} from it. + * + * @param bounds bounds of the generated location + * @return a {@link Location} object using the random coordinate + */ + public static Location getRandomLocation(LatLngBounds bounds) { + Random random = new Random(); + + double randomLat = bounds.getLatSouth() + (bounds.getLatNorth() - bounds.getLatSouth()) * random.nextDouble(); + double randomLon = bounds.getLonWest() + (bounds.getLonEast() - bounds.getLonWest()) * random.nextDouble(); + + Location location = new Location("random-loc"); + location.setLongitude(randomLon); + location.setLatitude(randomLat); + Timber.d("getRandomLatLng: %s", location.toString()); + return location; + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java index 01c047761..13d0ad424 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java @@ -97,7 +97,7 @@ public class DoubleMapActivity extends AppCompatActivity { uiSettings.setAttributionEnabled(false); uiSettings.setLogoEnabled(false); - mapboxMap.setOnMapClickListener(point -> { + mapboxMap.addOnMapClickListener(point -> { // test if we can open 2 activities after each other Toast.makeText(mapViewMini.getContext(), "Creating a new Activity instance",Toast.LENGTH_SHORT).show(); startActivity(new Intent(mapViewMini.getContext(), DoubleMapActivity.class)); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestActivity.java index e3c525480..7bbaed192 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestActivity.java @@ -56,6 +56,7 @@ public class RenderTestActivity extends AppCompatActivity { add("overlapping,raster-masking"); add("missing,raster-loading"); add("pitchAndBearing,line-pitch"); + add("overdraw,sparse-tileset"); } }; @@ -292,7 +293,7 @@ public class RenderTestActivity extends AppCompatActivity { } public void onLoadIgnoreList(List<String> ignoreList) { - Timber.e("We loaded %s amount of tests to be ignored", ignoreList.size()); + Timber.e("We loaded %s of tests to be ignored", ignoreList.size()); EXCLUDED_TESTS.addAll(ignoreList); new LoadRenderDefinitionTask(this).execute(); } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterReuseActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterReuseActivity.java index 302fa1ff7..1191b47c1 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterReuseActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterReuseActivity.java @@ -64,14 +64,12 @@ public class MapSnapshotterReuseActivity extends AppCompatActivity implements Ma } private LatLngBounds getRandomBounds() { - return new LatLngBounds.Builder() - .include(new LatLng( - randomInRange(-5, 5), - randomInRange(-5, 5))) - .include(new LatLng( - randomInRange(5, 10), - randomInRange(5, 10)) - ).build(); + return LatLngBounds.from( + randomInRange(5, 10), + randomInRange(-5, 5), + randomInRange(-5, 5), + randomInRange(5, 10) + ); } private CameraPosition getRandomCameraPosition() { diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java index 3a11a7e02..61b4eaad1 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java @@ -94,7 +94,7 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR } private void addSymbolClickListener() { - mapboxMap.setOnMapClickListener(point -> { + mapboxMap.addOnMapClickListener(point -> { PointF screenPoint = mapboxMap.getProjection().toScreenLocation(point); List<Feature> features = mapboxMap.queryRenderedFeatures(screenPoint, LAYER_ID); if (!features.isEmpty()) { diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_arrow.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_arrow.xml new file mode 100644 index 000000000..65c3b4aae --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_arrow.xml @@ -0,0 +1,11 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="36dp" + android:height="36dp" + android:viewportHeight="36.0" + android:viewportWidth="36.0"> + <path + android:fillColor="#FF82C6" + android:pathData="M18,0L23,7L13,7L18,0ZM22.8,7C21.33,6.36 19.71,6 18,6C16.29,6 14.67,6.36 13.2,7L22.8,7Z" + android:strokeColor="#00000000" + android:strokeWidth="1"/> +</vector> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_icon.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_icon.xml new file mode 100644 index 000000000..37f1d4de0 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_icon.xml @@ -0,0 +1,10 @@ +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:width="14dp" + android:height="14dp" + android:viewportHeight="14.0" + android:viewportWidth="14.0"> + <path + android:fillColor="#fff" + android:pathData="M7,7m-7,0a7,7 0,1 1,14 0a7,7 0,1 1,-14 0"/> +</vector> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_puck_icon.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_puck_icon.xml new file mode 100644 index 000000000..31d93f1ed --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_puck_icon.xml @@ -0,0 +1,23 @@ +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:width="75dp" + android:height="75dp" + android:viewportHeight="75.0" + android:viewportWidth="75.0"> + <path + android:fillAlpha="0.16" + android:fillColor="#FF3D57" + android:pathData="M37.5,37.5m-37.5,0a37.5,37.5 0,1 1,75 0a37.5,37.5 0,1 1,-75 0" + android:strokeColor="#00000000" + android:strokeWidth="1"/> + <path + android:fillColor="#000000" + android:pathData="M37.5,37.5m-28.5,0a28.5,28.5 0,1 1,57 0a28.5,28.5 0,1 1,-57 0" + android:strokeColor="#00000000" + android:strokeWidth="1"/> + <path + android:fillColor="#FF82C6" + android:pathData="M39.2,28.46C39.01,27.99 38.54,27.68 38.02,27.69C37.5,27.7 37.02,28.01 36.81,28.49L27.05,45.83C26.83,46.32 26.92,46.89 27.28,47.26C27.65,47.64 28.21,47.75 28.71,47.54L37.07,44.03C37.39,43.89 37.75,43.89 38.06,44.02L46.27,47.34C46.75,47.54 47.33,47.42 47.71,47.03C48.09,46.64 48.21,46.07 48,45.59L39.2,28.46Z" + android:strokeColor="#00000000" + android:strokeWidth="1"/> +</vector> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled.xml new file mode 100644 index 000000000..16f058f32 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06c-1.13,0.12 -2.19,0.46 -3.16,0.97l1.5,1.5C10.16,5.19 11.06,5 12,5c3.87,0 7,3.13 7,7 0,0.94 -0.19,1.84 -0.52,2.65l1.5,1.5c0.5,-0.96 0.84,-2.02 0.97,-3.15L23,13v-2h-2.06zM3,4.27l2.04,2.04C3.97,7.62 3.25,9.23 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c1.77,-0.2 3.38,-0.91 4.69,-1.98L19.73,21 21,19.73 4.27,3 3,4.27zM16.27,17.54C15.09,18.45 13.61,19 12,19c-3.87,0 -7,-3.13 -7,-7 0,-1.61 0.55,-3.09 1.46,-4.27l9.81,9.81z"/> +</vector> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_fragment.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_fragment.xml new file mode 100644 index 000000000..3c1436a1a --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_fragment.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <FrameLayout + android:id="@+id/container" + android:layout_width="match_parent" + android:layout_height="match_parent"/> + + <android.support.design.widget.FloatingActionButton + android:id="@+id/fab" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|end" + android:layout_margin="@dimen/fab_margin" + android:tint="@android:color/white" + app:backgroundTint="@color/accent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:srcCompat="@drawable/ic_layers" /> + +</android.support.constraint.ConstraintLayout>
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_map_change.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_map_change.xml new file mode 100644 index 000000000..54171a073 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_map_change.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.design.widget.CoordinatorLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/coordinator_layout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <com.mapbox.mapboxsdk.maps.MapView + android:id="@+id/mapView" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginBottom="0dp" + app:mapbox_uiAttribution="false"/> + + <android.support.design.widget.FloatingActionButton + android:id="@+id/fabStyles" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end|bottom" + android:layout_marginBottom="16dp" + android:layout_marginEnd="16dp" + android:layout_marginRight="16dp" + android:src="@drawable/ic_layers" + android:tint="@android:color/white" + app:backgroundTint="@color/accent" + app:layout_anchorGravity="top"/> + +</android.support.design.widget.CoordinatorLayout>
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_mode.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_mode.xml new file mode 100644 index 000000000..e23d876e3 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_mode.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <com.mapbox.mapboxsdk.maps.MapView + android:id="@+id/mapView" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginBottom="0dp" + app:layout_constraintBottom_toTopOf="@+id/linearLayout" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:mapbox_uiAttribution="false" /> + + <LinearLayout + android:id="@+id/linearLayout" + style="?android:attr/buttonBarStyle" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:background="@color/primary" + android:orientation="horizontal" + android:weightSum="4" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + tools:layout_constraintBottom_creator="1" + tools:layout_constraintLeft_creator="1" + tools:layout_constraintRight_creator="1"> + + <TextView + android:id="@+id/tv_mode" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight=".75" + android:gravity="center" + android:text="Mode:" + android:textColor="@color/white" + android:textSize="18sp" + android:textStyle="bold" /> + + <Button + android:id="@+id/button_location_mode" + style="?android:attr/buttonBarButtonStyle" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1.25" + android:gravity="center" + android:text="Normal" + android:textColor="@android:color/white" /> + + <TextView + android:id="@+id/tv_tracking" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight=".85" + android:gravity="center" + android:text="Tracking:" + android:textColor="@color/white" + android:textSize="18sp" + android:textStyle="bold" /> + + <Button + android:id="@+id/button_location_tracking" + style="?android:attr/buttonBarButtonStyle" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1.15" + android:gravity="center" + android:text="None" + android:textColor="@android:color/white" /> + + </LinearLayout> + +</android.support.constraint.ConstraintLayout>
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_manual_update.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_manual_update.xml new file mode 100644 index 000000000..3aac74a1e --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_manual_update.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/coordinator_layout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <com.mapbox.mapboxsdk.maps.MapView + android:id="@+id/mapView" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginBottom="0dp" + app:mapbox_uiAttribution="false" /> + + <android.support.design.widget.FloatingActionButton + android:id="@+id/fabToggleManualLocation" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end|bottom" + android:layout_marginBottom="82dp" + android:layout_marginEnd="16dp" + android:layout_marginRight="16dp" + android:tint="@android:color/white" + app:backgroundTint="@color/accent" + app:layout_anchorGravity="top" + app:srcCompat="@drawable/ic_layers" /> + + <android.support.design.widget.FloatingActionButton + android:id="@+id/fabManualLocationChange" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end|bottom" + android:layout_marginBottom="16dp" + android:layout_marginEnd="16dp" + android:layout_marginRight="16dp" + android:alpha="0.5" + android:tint="@android:color/white" + app:backgroundTint="@color/accent" + app:layout_anchorGravity="top" + app:srcCompat="@drawable/ic_my_location" /> + +</android.support.design.widget.CoordinatorLayout>
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_source_features.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_source_features.xml index 1c439a5ec..27c77cf00 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_source_features.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_source_features.xml @@ -1,16 +1,26 @@ <?xml version="1.0" encoding="utf-8"?> -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" +<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/coordinator_layout" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:orientation="vertical"> <com.mapbox.mapboxsdk.maps.MapView android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="match_parent" - app:mapbox_cameraTargetLat="0" - app:mapbox_cameraTargetLng="0" - app:mapbox_cameraZoom="16"/> + app:mapbox_cameraTargetLat="51" + app:mapbox_cameraTargetLng="17.25" + app:mapbox_cameraZoom="8" /> -</RelativeLayout> + <android.support.design.widget.FloatingActionButton + android:id="@+id/fab" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end|bottom" + android:layout_margin="@dimen/fab_margin" + android:src="@drawable/ic_layers" + app:backgroundTint="@android:color/white" /> + +</android.support.design.widget.CoordinatorLayout> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_location_mode.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_location_mode.xml new file mode 100644 index 000000000..302ab33bc --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_location_mode.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <item android:id="@+id/action_style_change" + android:title="Toggle custom LocationLayer style" + app:showAsAction="never"/> + + <item android:id="@+id/action_map_style_change" + android:title="Toggle custom Map style" + app:showAsAction="never"/> + + <item android:id="@+id/action_component_disable" + android:title="Disable Component" + app:showAsAction="never"/> + + <item android:id="@+id/action_component_enabled" + android:title="Enable Component" + app:showAsAction="never"/> + + <item android:id="@+id/action_gestures_management_enabled" + android:title="Enable Gestures Management" + app:showAsAction="never"/> + + <item android:id="@+id/action_gestures_management_disabled" + android:title="Disable Gestures Management" + app:showAsAction="never"/> +</menu>
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml index aafeb1cd9..a4403a34f 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml @@ -14,4 +14,5 @@ <string name="category_features">Features</string> <string name="category_storage">Storage</string> <string name="category_textureview">Texture View</string> + <string name="category_location">Location</string> </resources>
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml index 6c68edc4d..cb9c2043d 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml @@ -71,4 +71,8 @@ <string name="description_heatmaplayer">Use HeatmapLayer to visualise earthquakes</string> <string name="description_gesture_detector">Manipulate gestures detector\'s settings</string> <string name="description_draggable_marker">Click to add a marker, long-click to drag</string> + <string name="description_location_map_change">Change map\'s style while location is displayed</string> + <string name="description_location_modes">Showcases location render and tracking modes</string> + <string name="description_location_fragment">Uses LocationComponent in a Fragment</string> + <string name="description_location_manual">Force location updates and don\'t rely on the engine</string> </resources> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml index 777d8a5f5..a0525171a 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml @@ -38,4 +38,16 @@ <style name="AppTheme" parent="AppBaseTheme" /> + <style name="CustomLocationComponent" parent="mapbox_LocationComponent"> + <item name="mapbox_foregroundDrawable">@drawable/custom_user_icon</item> + + <item name="mapbox_bearingDrawable">@drawable/custom_user_arrow</item> + <item name="mapbox_gpsDrawable">@drawable/custom_user_puck_icon</item> + + <item name="mapbox_accuracyAlpha">0.15</item> + <item name="mapbox_accuracyColor">#FF82C6</item> + + <item name="mapbox_elevation">0dp</item> + </style> + </resources> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml index ddf351886..f094a67b3 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml @@ -71,4 +71,8 @@ <string name="activity_heatmaplayer">Heatmap layer</string> <string name="activity_gesture_detector">Gestures detector</string> <string name="activity_draggable_maker">Draggable marker</string> + <string name="activity_location_map_change">Simple Location Activity</string> + <string name="activity_location_modes">Location Modes Activity</string> + <string name="activity_location_fragment">Location Fragment</string> + <string name="activity_location_manual">Manual Location updates</string> </resources>
\ No newline at end of file diff --git a/platform/android/config.cmake b/platform/android/config.cmake index d6be05095..cc44c2585 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -1,6 +1,5 @@ set(USE_GLES2 ON) -include(cmake/nunicode.cmake) include(cmake/sqlite.cmake) include(cmake/icu.cmake) @@ -49,7 +48,6 @@ macro(mbgl_platform_core) target_add_mason_package(mbgl-core PUBLIC rapidjson) target_link_libraries(mbgl-core - PRIVATE nunicode PRIVATE icu PUBLIC expected PUBLIC -llog @@ -71,6 +69,7 @@ macro(mbgl_filesource) target_add_mason_package(mbgl-filesource PUBLIC jni.hpp) target_link_libraries(mbgl-filesource + PRIVATE codecvt PUBLIC sqlite PUBLIC -llog PUBLIC -landroid @@ -86,6 +85,7 @@ add_library(mapbox-gl SHARED ) target_link_libraries(mapbox-gl + PRIVATE codecvt PRIVATE mbgl-core PRIVATE mbgl-filesource ) @@ -106,6 +106,7 @@ macro(mbgl_platform_test) ) target_link_libraries(mbgl-test + PRIVATE codecvt PRIVATE mbgl-core PRIVATE mbgl-filesource ) diff --git a/platform/android/core-files.txt b/platform/android/core-files.txt index eca7529c0..2e32355dc 100644 --- a/platform/android/core-files.txt +++ b/platform/android/core-files.txt @@ -11,10 +11,10 @@ platform/android/src/text/local_glyph_rasterizer.cpp platform/android/src/text/local_glyph_rasterizer_jni.hpp platform/android/src/logging_android.cpp platform/android/src/thread.cpp -platform/default/string_stdlib.cpp +platform/android/src/string_util.cpp platform/default/bidi.cpp platform/default/thread_local.cpp -platform/default/unaccent.cpp +platform/android/src/unaccent.cpp platform/default/unaccent.hpp platform/default/utf.cpp @@ -55,8 +55,6 @@ platform/android/src/conversion/color.hpp platform/android/src/conversion/constant.cpp platform/android/src/conversion/constant.hpp platform/android/src/conversion/conversion.hpp -platform/android/src/geojson/conversion/feature.cpp -platform/android/src/geojson/conversion/feature.hpp platform/android/src/style/conversion/filter.cpp platform/android/src/style/conversion/filter.hpp platform/android/src/style/conversion/position.cpp @@ -137,8 +135,6 @@ platform/android/src/map_renderer_runnable.cpp platform/android/src/map_renderer_runnable.hpp # Java core classes -platform/android/src/java/lang.cpp -platform/android/src/java/lang.hpp platform/android/src/java/util.cpp platform/android/src/java/util.hpp @@ -217,3 +213,6 @@ platform/android/src/java_types.hpp # Main entry point platform/android/src/jni.hpp platform/android/src/jni.cpp + +# GL +platform/android/mbgl/gl/gl_impl.hpp diff --git a/platform/android/gradle/dependencies.gradle b/platform/android/gradle/dependencies.gradle index 86571bb05..af9b7e00b 100644 --- a/platform/android/gradle/dependencies.gradle +++ b/platform/android/gradle/dependencies.gradle @@ -8,62 +8,64 @@ ext { ] versions = [ - mapboxServices : '3.4.1', - mapboxTelemetry: '3.1.5', - mapboxGestures : '0.2.0', - supportLib : '27.1.1', - espresso : '3.0.2', - testRunner : '1.0.2', - leakCanary : '1.6.1', - junit : '4.12', - mockito : '2.18.3', - robolectric : '3.8', - timber : '4.7.1', - okhttp : '3.11.0', - kotlin : '1.2.51', - licenses : '0.8.41', - lint : '26.1.3' + mapboxServices : '3.4.1', + mapboxTelemetry : '3.1.5', + mapboxGestures : '0.2.0', + supportLib : '27.1.1', + constraintLayout: '1.1.2', + espresso : '3.0.2', + testRunner : '1.0.2', + leakCanary : '1.6.1', + junit : '4.12', + mockito : '2.18.3', + robolectric : '3.8', + timber : '4.7.1', + okhttp : '3.11.0', + kotlin : '1.2.51', + licenses : '0.8.41', + lint : '26.1.3' ] dependenciesList = [ - mapboxJavaServices : "com.mapbox.mapboxsdk:mapbox-sdk-services:${versions.mapboxServices}", - mapboxJavaGeoJSON : "com.mapbox.mapboxsdk:mapbox-sdk-geojson:${versions.mapboxServices}", - mapboxAndroidTelemetry: "com.mapbox.mapboxsdk:mapbox-android-telemetry:${versions.mapboxTelemetry}", - mapboxAndroidGestures : "com.mapbox.mapboxsdk:mapbox-android-gestures:${versions.mapboxGestures}", + mapboxJavaServices : "com.mapbox.mapboxsdk:mapbox-sdk-services:${versions.mapboxServices}", + mapboxJavaGeoJSON : "com.mapbox.mapboxsdk:mapbox-sdk-geojson:${versions.mapboxServices}", + mapboxAndroidTelemetry : "com.mapbox.mapboxsdk:mapbox-android-telemetry:${versions.mapboxTelemetry}", + mapboxAndroidGestures : "com.mapbox.mapboxsdk:mapbox-android-gestures:${versions.mapboxGestures}", // for testApp - mapboxJavaTurf : "com.mapbox.mapboxsdk:mapbox-sdk-turf:${versions.mapboxServices}", + mapboxJavaTurf : "com.mapbox.mapboxsdk:mapbox-sdk-turf:${versions.mapboxServices}", - junit : "junit:junit:${versions.junit}", - mockito : "org.mockito:mockito-core:${versions.mockito}", - robolectric : "org.robolectric:robolectric:${versions.robolectric}", + junit : "junit:junit:${versions.junit}", + mockito : "org.mockito:mockito-core:${versions.mockito}", + robolectric : "org.robolectric:robolectric:${versions.robolectric}", - testRunner : "com.android.support.test:runner:${versions.testRunner}", - testRules : "com.android.support.test:rules:${versions.testRunner}", - testEspressoCore : "com.android.support.test.espresso:espresso-core:${versions.espresso}", - testEspressoIntents : "com.android.support.test.espresso:espresso-intents:${versions.espresso}", - testEspressoContrib : "com.android.support.test.espresso:espresso-contrib:${versions.espresso}", + testRunner : "com.android.support.test:runner:${versions.testRunner}", + testRules : "com.android.support.test:rules:${versions.testRunner}", + testEspressoCore : "com.android.support.test.espresso:espresso-core:${versions.espresso}", + testEspressoIntents : "com.android.support.test.espresso:espresso-intents:${versions.espresso}", + testEspressoContrib : "com.android.support.test.espresso:espresso-contrib:${versions.espresso}", - supportAnnotations : "com.android.support:support-annotations:${versions.supportLib}", - supportAppcompatV7 : "com.android.support:appcompat-v7:${versions.supportLib}", - supportFragmentV4 : "com.android.support:support-fragment:${versions.supportLib}", - supportUtilV4 : "com.android.support:support-core-utils:${versions.supportLib}", - supportDesign : "com.android.support:design:${versions.supportLib}", - supportRecyclerView : "com.android.support:recyclerview-v7:${versions.supportLib}", + supportAnnotations : "com.android.support:support-annotations:${versions.supportLib}", + supportAppcompatV7 : "com.android.support:appcompat-v7:${versions.supportLib}", + supportFragmentV4 : "com.android.support:support-fragment:${versions.supportLib}", + supportUtilV4 : "com.android.support:support-core-utils:${versions.supportLib}", + supportDesign : "com.android.support:design:${versions.supportLib}", + supportRecyclerView : "com.android.support:recyclerview-v7:${versions.supportLib}", + supportConstraintLayout: "com.android.support.constraint:constraint-layout:${versions.constraintLayout}", - gmsLocation : 'com.google.android.gms:play-services-location:11.0.4', - timber : "com.jakewharton.timber:timber:${versions.timber}", - okhttp3 : "com.squareup.okhttp3:okhttp:${versions.okhttp}", - leakCanaryDebug : "com.squareup.leakcanary:leakcanary-android:${versions.leakCanary}", - leakCanaryRelease : "com.squareup.leakcanary:leakcanary-android-no-op:${versions.leakCanary}", + gmsLocation : 'com.google.android.gms:play-services-location:11.0.4', + timber : "com.jakewharton.timber:timber:${versions.timber}", + okhttp3 : "com.squareup.okhttp3:okhttp:${versions.okhttp}", + leakCanaryDebug : "com.squareup.leakcanary:leakcanary-android:${versions.leakCanary}", + leakCanaryRelease : "com.squareup.leakcanary:leakcanary-android-no-op:${versions.leakCanary}", - kotlinLib : "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}", - kotlinPlugin : "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}", - licensesPlugin : "com.jaredsburrows:gradle-license-plugin:${versions.licenses}", + kotlinLib : "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}", + kotlinPlugin : "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}", + licensesPlugin : "com.jaredsburrows:gradle-license-plugin:${versions.licenses}", - lint : "com.android.tools.lint:lint:${versions.lint}", - lintApi : "com.android.tools.lint:lint-api:${versions.lint}", - lintChecks : "com.android.tools.lint:lint-checks:${versions.lint}", - lintTests : "com.android.tools.lint:lint-tests:${versions.lint}" + lint : "com.android.tools.lint:lint:${versions.lint}", + lintApi : "com.android.tools.lint:lint-api:${versions.lint}", + lintChecks : "com.android.tools.lint:lint-checks:${versions.lint}", + lintTests : "com.android.tools.lint:lint-tests:${versions.lint}" ] } diff --git a/platform/android/scripts/exclude-activity-gen.json b/platform/android/scripts/exclude-activity-gen.json index e4418bdc5..2a1fbec49 100644 --- a/platform/android/scripts/exclude-activity-gen.json +++ b/platform/android/scripts/exclude-activity-gen.json @@ -36,5 +36,6 @@ "TextureViewTransparentBackgroundActivity", "SimpleMapActivity", "RenderTestActivity", - "SymbolLayerActivity" + "SymbolLayerActivity", + "LocationFragmentActivity" ] diff --git a/platform/android/scripts/generate-style-code.js b/platform/android/scripts/generate-style-code.js index 0825ef1c2..4a35b2d6a 100755 --- a/platform/android/scripts/generate-style-code.js +++ b/platform/android/scripts/generate-style-code.js @@ -335,12 +335,8 @@ global.supportsPropertyFunction = function (property) { // Template processing // // Java + JNI Light (Peer model) -const lightHpp = ejs.compile(fs.readFileSync('platform/android/src/style/light.hpp.ejs', 'utf8'), {strict: true});; -const lightCpp = ejs.compile(fs.readFileSync('platform/android/src/style/light.cpp.ejs', 'utf8'), {strict: true});; const lightJava = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/light.java.ejs', 'utf8'), {strict: true}); const lightJavaUnitTests = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs', 'utf8'), {strict: true}); -writeIfModified(`platform/android/src/style/light.hpp`, lightHpp({properties: lightProperties})); -writeIfModified(`platform/android/src/style/light.cpp`, lightCpp({properties: lightProperties})); writeIfModified(`platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Light.java`, lightJava({properties: lightProperties})); writeIfModified(`platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java`, lightJavaUnitTests({properties: lightProperties})); diff --git a/platform/android/scripts/run-render-test.py b/platform/android/scripts/run-render-test.py index 1a7289a11..940ae7a3d 100644 --- a/platform/android/scripts/run-render-test.py +++ b/platform/android/scripts/run-render-test.py @@ -3,7 +3,7 @@ import os import shutil -catPath = os.getcwd() + "/platform/android/build/render-test/render/" +catPath = os.getcwd() + "/platform/android/build/render-test/" failCounter = 0 testCounter = 0 for cat in os.listdir(catPath): diff --git a/platform/android/src/annotation/marker.cpp b/platform/android/src/annotation/marker.cpp index a1fe436db..899f87a74 100644 --- a/platform/android/src/annotation/marker.cpp +++ b/platform/android/src/annotation/marker.cpp @@ -3,29 +3,21 @@ namespace mbgl { namespace android { -jni::Class<Marker> Marker::javaClass; - -mbgl::Point<double> Marker::getPosition(jni::JNIEnv& env, jni::Object<Marker> marker) { - static auto positionField = Marker::javaClass.GetField<jni::Object<LatLng>>(env, "position"); - auto jPosition = marker.Get(env, positionField); - auto position = LatLng::getGeometry(env, jPosition); - jni::DeleteLocalRef(env, jPosition); - return position; +mbgl::Point<double> Marker::getPosition(jni::JNIEnv& env, const jni::Object<Marker>& marker) { + static auto& javaClass = jni::Class<Marker>::Singleton(env); + static auto positionField = javaClass.GetField<jni::Object<LatLng>>(env, "position"); + return LatLng::getGeometry(env, marker.Get(env, positionField)); } -std::string Marker::getIconId(jni::JNIEnv& env, jni::Object<Marker> marker) { - static auto iconIdField = Marker::javaClass.GetField<jni::String>(env, "iconId"); - auto jIconId = marker.Get(env, iconIdField); - auto iconId = jni::Make<std::string>(env, jIconId); - jni::DeleteLocalRef(env, jIconId); - return iconId; +std::string Marker::getIconId(jni::JNIEnv& env, const jni::Object<Marker>& marker) { + static auto& javaClass = jni::Class<Marker>::Singleton(env); + static auto iconIdField = javaClass.GetField<jni::String>(env, "iconId"); + return jni::Make<std::string>(env, marker.Get(env, iconIdField)); } void Marker::registerNative(jni::JNIEnv& env) { - // Lookup the class - Marker::javaClass = *jni::Class<Marker>::Find(env).NewGlobalRef(env).release(); + jni::Class<Marker>::Singleton(env); } - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/annotation/marker.hpp b/platform/android/src/annotation/marker.hpp index b11a22524..b38a25b4f 100644 --- a/platform/android/src/annotation/marker.hpp +++ b/platform/android/src/annotation/marker.hpp @@ -15,11 +15,9 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Marker"; }; - static jni::Class<Marker> javaClass; + static mbgl::Point<double> getPosition(jni::JNIEnv&, const jni::Object<Marker>&); - static mbgl::Point<double> getPosition(jni::JNIEnv&, jni::Object<Marker>); - - static std::string getIconId(jni::JNIEnv&, jni::Object<Marker>); + static std::string getIconId(jni::JNIEnv&, const jni::Object<Marker>&); static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/annotation/multi_point.hpp b/platform/android/src/annotation/multi_point.hpp index e1152dfd6..20f1b3eaf 100644 --- a/platform/android/src/annotation/multi_point.hpp +++ b/platform/android/src/annotation/multi_point.hpp @@ -14,10 +14,8 @@ class MultiPoint : protected mbgl::util::noncopyable { protected: template <class Geometry> - static Geometry toGeometry(JNIEnv& env, jni::Object<java::util::List> pointsList) { - NullCheck(env, &pointsList); + static Geometry toGeometry(JNIEnv& env, const jni::Object<java::util::List>& pointsList) { auto jarray = java::util::List::toArray<LatLng>(env, pointsList); - NullCheck(env, &jarray); std::size_t size = jarray.Length(env); @@ -25,15 +23,9 @@ protected: geometry.reserve(size); for (std::size_t i = 0; i < size; i++) { - auto latLng = jarray.Get(env, i); - NullCheck(env, &latLng); - - geometry.push_back(LatLng::getGeometry(env, latLng)); - - jni::DeleteLocalRef(env, latLng); + geometry.push_back(LatLng::getGeometry(env, jarray.Get(env, i))); } - jni::DeleteLocalRef(env, jarray); return geometry; } }; diff --git a/platform/android/src/annotation/polygon.cpp b/platform/android/src/annotation/polygon.cpp index fbd849432..f22cffb10 100644 --- a/platform/android/src/annotation/polygon.cpp +++ b/platform/android/src/annotation/polygon.cpp @@ -5,63 +5,36 @@ namespace mbgl { namespace android { -jni::Class<Polygon> Polygon::javaClass; +mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, const jni::Object<Polygon>& polygon) { + static auto& javaClass = jni::Class<Polygon>::Singleton(env); + static auto points = javaClass.GetField<jni::Object<java::util::List>>(env, "points"); + static auto holes = javaClass.GetField<jni::Object<java::util::List>>(env, "holes"); + static auto alpha = javaClass.GetField<float>(env, "alpha"); + static auto fillColor = javaClass.GetField<int>(env, "fillColor"); + static auto strokeColor = javaClass.GetField<int>(env, "strokeColor"); -mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, jni::Object<Polygon> polygon) { - auto points = Polygon::getPoints(env, polygon); - auto holes = Polygon::getHoles(env, polygon); + mbgl::Polygon<double> geometry { + MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, polygon.Get(env, points)) + }; - mbgl::Polygon<double> geometry { MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, points) }; + auto jHoleListsArray = java::util::List::toArray<java::util::List>(env, polygon.Get(env, holes)); - auto jHoleListsArray = java::util::List::toArray<java::util::List>(env, holes); std::size_t jHoleListsSize = jHoleListsArray.Length(env); for (std::size_t i = 0; i < jHoleListsSize; i++) { - auto jHoleList = jHoleListsArray.Get(env, i); - geometry.push_back(MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, jHoleList)); - jni::DeleteLocalRef(env, jHoleList); + geometry.push_back(MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, jHoleListsArray.Get(env, i))); } - jni::DeleteLocalRef(env, jHoleListsArray); mbgl::FillAnnotation annotation { geometry }; - annotation.opacity = { Polygon::getOpacity(env, polygon) }; - annotation.color = { Polygon::getFillColor(env, polygon) }; - annotation.outlineColor = { Polygon::getOutlineColor(env, polygon) }; - - jni::DeleteLocalRef(env, points); - jni::DeleteLocalRef(env, holes); + annotation.opacity = polygon.Get(env, alpha); + annotation.color = *conversion::convert<mbgl::Color>(env, polygon.Get(env, fillColor)); + annotation.outlineColor = *conversion::convert<mbgl::Color>(env, polygon.Get(env, strokeColor)); return annotation; } -jni::Object<java::util::List> Polygon::getPoints(jni::JNIEnv& env, jni::Object<Polygon> polygon) { - static auto field = Polygon::javaClass.GetField<jni::Object<java::util::List>>(env, "points"); - return polygon.Get(env, field); -} - -jni::Object<java::util::List> Polygon::getHoles(jni::JNIEnv& env, jni::Object<Polygon> polygon) { - static auto field = Polygon::javaClass.GetField<jni::Object<java::util::List>>(env, "holes"); - return polygon.Get(env, field); -} - -float Polygon::getOpacity(jni::JNIEnv& env, jni::Object<Polygon> polygon) { - static auto field = Polygon::javaClass.GetField<float>(env, "alpha"); - return polygon.Get(env, field); -} - -mbgl::Color Polygon::getFillColor(jni::JNIEnv& env, jni::Object<Polygon> polygon) { - static auto field = Polygon::javaClass.GetField<int>(env, "fillColor"); - return *conversion::convert<mbgl::Color, int>(env, polygon.Get(env, field)); -} - -mbgl::Color Polygon::getOutlineColor(jni::JNIEnv& env, jni::Object<Polygon> polygon) { - static auto field = Polygon::javaClass.GetField<int>(env, "strokeColor"); - return *conversion::convert<mbgl::Color, int>(env, polygon.Get(env, field)); -} - void Polygon::registerNative(jni::JNIEnv& env) { - Polygon::javaClass = *jni::Class<Polygon>::Find(env).NewGlobalRef(env).release(); + jni::Class<Polygon>::Singleton(env); } - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/annotation/polygon.hpp b/platform/android/src/annotation/polygon.hpp index a98b2822c..bc21878ef 100644 --- a/platform/android/src/annotation/polygon.hpp +++ b/platform/android/src/annotation/polygon.hpp @@ -1,40 +1,19 @@ #pragma once #include <mbgl/annotation/annotation.hpp> -#include <mbgl/util/color.hpp> - -#include <string> #include "multi_point.hpp" -#include "../geometry/lat_lng.hpp" -#include "../java/util.hpp" - namespace mbgl { namespace android { class Polygon : private MultiPoint { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polygon"; }; - static jni::Class<Polygon> javaClass; - - static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, jni::Object<Polygon>); + static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, const jni::Object<Polygon>&); static void registerNative(jni::JNIEnv&); - -private: - - static jni::Object<java::util::List> getPoints(jni::JNIEnv&, jni::Object<Polygon>); - - static jni::Object<java::util::List> getHoles(jni::JNIEnv&, jni::Object<Polygon>); - - static float getOpacity(jni::JNIEnv&, jni::Object<Polygon>); - - static mbgl::Color getFillColor(jni::JNIEnv&, jni::Object<Polygon>); - - static mbgl::Color getOutlineColor(jni::JNIEnv&, jni::Object<Polygon>); }; diff --git a/platform/android/src/annotation/polyline.cpp b/platform/android/src/annotation/polyline.cpp index 3723dc187..d6161e856 100644 --- a/platform/android/src/annotation/polyline.cpp +++ b/platform/android/src/annotation/polyline.cpp @@ -5,45 +5,27 @@ namespace mbgl { namespace android { -jni::Class<Polyline> Polyline::javaClass; +mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, const jni::Object<Polyline>& polyline) { + static auto& javaClass = jni::Class<Polyline>::Singleton(env); + static auto points = javaClass.GetField<jni::Object<java::util::List>>(env, "points"); + static auto alpha = javaClass.GetField<float>(env, "alpha"); + static auto color = javaClass.GetField<int>(env, "color"); + static auto width = javaClass.GetField<float>(env, "width"); -mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, jni::Object<Polyline> polyline) { - auto points = Polyline::getPoints(env, polyline); + mbgl::LineAnnotation annotation { + MultiPoint::toGeometry<mbgl::LineString<double>>(env, polyline.Get(env, points)) + }; - mbgl::LineAnnotation annotation { MultiPoint::toGeometry<mbgl::LineString<double>>(env, points) }; - annotation.opacity = { Polyline::getOpacity(env, polyline) }; - annotation.color = { Polyline::getColor(env, polyline) }; - annotation.width = { Polyline::getWidth(env, polyline) }; - - jni::DeleteLocalRef(env, points); + annotation.opacity = polyline.Get(env, alpha); + annotation.color = *conversion::convert<mbgl::Color>(env, polyline.Get(env, color)); + annotation.width = polyline.Get(env, width); return annotation; } -jni::Object<java::util::List> Polyline::getPoints(jni::JNIEnv& env, jni::Object<Polyline> polyline) { - static auto field = Polyline::javaClass.GetField<jni::Object<java::util::List>>(env, "points"); - return polyline.Get(env, field); -} - -float Polyline::getOpacity(jni::JNIEnv& env, jni::Object<Polyline> polyline) { - static auto field = Polyline::javaClass.GetField<float>(env, "alpha"); - return polyline.Get(env, field); -} - -mbgl::Color Polyline::getColor(jni::JNIEnv& env, jni::Object<Polyline> polyline) { - static auto field = Polyline::javaClass.GetField<int>(env, "color"); - return *conversion::convert<mbgl::Color, int>(env, polyline.Get(env, field)); -} - -float Polyline::getWidth(jni::JNIEnv& env, jni::Object<Polyline> polyline) { - static auto field = Polyline::javaClass.GetField<float>(env, "width"); - return polyline.Get(env, field); -} - void Polyline::registerNative(jni::JNIEnv& env) { - Polyline::javaClass = *jni::Class<Polyline>::Find(env).NewGlobalRef(env).release(); + jni::Class<Polyline>::Singleton(env); } - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/annotation/polyline.hpp b/platform/android/src/annotation/polyline.hpp index bcc616a5f..6178e98cf 100644 --- a/platform/android/src/annotation/polyline.hpp +++ b/platform/android/src/annotation/polyline.hpp @@ -1,38 +1,19 @@ #pragma once #include <mbgl/annotation/annotation.hpp> -#include <mbgl/util/color.hpp> - -#include <string> #include "multi_point.hpp" -#include "../geometry/lat_lng.hpp" -#include "../java/util.hpp" - namespace mbgl { namespace android { class Polyline : private MultiPoint { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polyline"; }; - static jni::Class<Polyline> javaClass; - - static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, jni::Object<Polyline>); + static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, const jni::Object<Polyline>&); static void registerNative(jni::JNIEnv&); - -private: - - static jni::Object<java::util::List> getPoints(jni::JNIEnv&, jni::Object<Polyline>); - - static float getOpacity(jni::JNIEnv&, jni::Object<Polyline>); - - static mbgl::Color getColor(jni::JNIEnv&, jni::Object<Polyline>); - - static float getWidth(jni::JNIEnv&, jni::Object<Polyline>); }; diff --git a/platform/android/src/asset_manager_file_source.cpp b/platform/android/src/asset_manager_file_source.cpp index aa65e3ff4..b9150deef 100644 --- a/platform/android/src/asset_manager_file_source.cpp +++ b/platform/android/src/asset_manager_file_source.cpp @@ -38,10 +38,10 @@ private: AAssetManager* assetManager; }; -AssetManagerFileSource::AssetManagerFileSource(jni::JNIEnv& env, jni::Object<android::AssetManager> assetManager_) - : assetManager(assetManager_.NewGlobalRef(env)), +AssetManagerFileSource::AssetManagerFileSource(jni::JNIEnv& env, const jni::Object<android::AssetManager>& assetManager_) + : assetManager(jni::NewGlobal(env, assetManager_)), impl(std::make_unique<util::Thread<Impl>>("AssetManagerFileSource", - AAssetManager_fromJava(&env, jni::Unwrap(**assetManager)))) { + AAssetManager_fromJava(&env, jni::Unwrap(assetManager.get())))) { } AssetManagerFileSource::~AssetManagerFileSource() = default; diff --git a/platform/android/src/asset_manager_file_source.hpp b/platform/android/src/asset_manager_file_source.hpp index dcad95664..4ec5b4c30 100644 --- a/platform/android/src/asset_manager_file_source.hpp +++ b/platform/android/src/asset_manager_file_source.hpp @@ -14,7 +14,7 @@ template <typename T> class Thread; class AssetManagerFileSource : public FileSource { public: - AssetManagerFileSource(jni::JNIEnv&, jni::Object<android::AssetManager>); + AssetManagerFileSource(jni::JNIEnv&, const jni::Object<android::AssetManager>&); ~AssetManagerFileSource() override; std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override; @@ -22,7 +22,7 @@ public: private: class Impl; - jni::UniqueObject<android::AssetManager> assetManager; + jni::Global<jni::Object<android::AssetManager>> assetManager; std::unique_ptr<util::Thread<Impl>> impl; }; diff --git a/platform/android/src/bitmap.cpp b/platform/android/src/bitmap.cpp index 0d3670b66..eb7c676b1 100644 --- a/platform/android/src/bitmap.cpp +++ b/platform/android/src/bitmap.cpp @@ -8,13 +8,14 @@ namespace android { class PixelGuard { public: - PixelGuard(jni::JNIEnv& env_, jni::Object<Bitmap> bitmap_) : env(env_), bitmap(bitmap_) { + PixelGuard(jni::JNIEnv& env_, const jni::Object<Bitmap>& bitmap_) : env(env_), bitmap(bitmap_) { const int result = AndroidBitmap_lockPixels(&env, jni::Unwrap(*bitmap), reinterpret_cast<void**>(&address)); if (result != ANDROID_BITMAP_RESULT_SUCCESS) { throw std::runtime_error("bitmap decoding: could not lock pixels"); } } + ~PixelGuard() { const int result = AndroidBitmap_unlockPixels(&env, jni::Unwrap(*bitmap)); if (result != ANDROID_BITMAP_RESULT_SUCCESS) { @@ -26,58 +27,68 @@ public: return address; } - const auto* get() const { - return address; - } - private: jni::JNIEnv& env; - jni::Object<Bitmap> bitmap; + const jni::Object<Bitmap>& bitmap; uint8_t* address; }; -void Bitmap::Config::registerNative(jni::JNIEnv& env) { - _class = *jni::Class<Config>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Bitmap::Config> Bitmap::Config::_class; - -jni::Object<Bitmap::Config> Bitmap::Config::Create(jni::JNIEnv& env, Value value) { +jni::Local<jni::Object<Bitmap::Config>> Bitmap::Config::Create(jni::JNIEnv& env, Value value) { + static auto& _class = jni::Class<Config>::Singleton(env); switch (value) { case ALPHA_8: - return _class.Get(env, - jni::StaticField<Config, jni::Object<Config>>(env, _class, "ALPHA_8")); + return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "ALPHA_8")); case ARGB_4444: - return _class.Get(env, - jni::StaticField<Config, jni::Object<Config>>(env, _class, "ARGB_4444")); + return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "ARGB_4444")); case ARGB_8888: - return _class.Get(env, - jni::StaticField<Config, jni::Object<Config>>(env, _class, "ARGB_8888")); + return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "ARGB_8888")); case RGB_565: - return _class.Get(env, - jni::StaticField<Config, jni::Object<Config>>(env, _class, "RGB_565")); + return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "RGB_565")); default: throw std::runtime_error("invalid enum value for Bitmap.Config"); } } void Bitmap::registerNative(jni::JNIEnv& env) { - _class = *jni::Class<Bitmap>::Find(env).NewGlobalRef(env).release(); - Config::registerNative(env); + jni::Class<Bitmap>::Singleton(env); + jni::Class<Bitmap::Config>::Singleton(env); } -jni::Class<Bitmap> Bitmap::_class; +jni::Local<jni::Object<Bitmap>> Bitmap::CreateBitmap(jni::JNIEnv& env, + jni::jint width, + jni::jint height, + const jni::Object<Config>& config) { + static auto& _class = jni::Class<Bitmap>::Singleton(env); + static auto method = _class.GetStaticMethod<jni::Object<Bitmap> (jni::jint, jni::jint, jni::Object<Config>)>(env, "createBitmap"); -jni::Object<Bitmap> Bitmap::CreateBitmap(jni::JNIEnv& env, - jni::jint width, - jni::jint height, - jni::Object<Config> config) { - using Signature = jni::Object<Bitmap>(jni::jint, jni::jint, jni::Object<Config>); - auto method = _class.GetStaticMethod<Signature>(env, "createBitmap"); return _class.Call(env, method, width, height, config); } -jni::Object<Bitmap> Bitmap::CreateBitmap(jni::JNIEnv& env, const PremultipliedImage& image) { +PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, const jni::Object<Bitmap>& bitmap) { + AndroidBitmapInfo info; + const int result = AndroidBitmap_getInfo(&env, jni::Unwrap(*bitmap), &info); + if (result != ANDROID_BITMAP_RESULT_SUCCESS) { + throw std::runtime_error("bitmap decoding: couldn't get bitmap info"); + } + if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { + return Bitmap::GetImage(env, Bitmap::Copy(env, bitmap)); + } + + PixelGuard guard(env, bitmap); + + // Copy the Android Bitmap into the PremultipliedImage. + auto pixels = + std::make_unique<uint8_t[]>(info.width * info.height * PremultipliedImage::channels); + for (uint32_t y = 0; y < info.height; y++) { + auto begin = guard.get() + y * info.stride; + std::copy(begin, begin + info.width * PremultipliedImage::channels, + pixels.get() + y * info.width * PremultipliedImage::channels); + } + + return { Size{ info.width, info.height }, std::move(pixels) }; +} + +jni::Local<jni::Object<Bitmap>> Bitmap::CreateBitmap(jni::JNIEnv& env, const PremultipliedImage& image) { auto bitmap = CreateBitmap(env, image.size.width, image.size.height, Config::ARGB_8888); AndroidBitmapInfo info; @@ -102,37 +113,11 @@ jni::Object<Bitmap> Bitmap::CreateBitmap(jni::JNIEnv& env, const PremultipliedIm return bitmap; } -PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, jni::Object<Bitmap> bitmap) { - AndroidBitmapInfo info; - const int result = AndroidBitmap_getInfo(&env, jni::Unwrap(*bitmap), &info); - if (result != ANDROID_BITMAP_RESULT_SUCCESS) { - // TODO: more specific information - throw std::runtime_error("bitmap decoding: couldn't get bitmap info"); - } - - if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { - bitmap = Bitmap::Copy(env, bitmap); - } - - const PixelGuard guard(env, bitmap); - - // Copy the Android Bitmap into the PremultipliedImage. - auto pixels = - std::make_unique<uint8_t[]>(info.width * info.height * PremultipliedImage::channels); - for (uint32_t y = 0; y < info.height; y++) { - auto begin = guard.get() + y * info.stride; - std::copy(begin, begin + info.width * PremultipliedImage::channels, - pixels.get() + y * info.width * PremultipliedImage::channels); - } - - return { Size{ info.width, info.height }, std::move(pixels) }; -} +jni::Local<jni::Object<Bitmap>> Bitmap::Copy(jni::JNIEnv& env, const jni::Object<Bitmap>& bitmap) { + static auto& klass = jni::Class<Bitmap>::Singleton(env); + static auto copy = klass.GetMethod<jni::Object<Bitmap> (jni::Object<Config>, jni::jboolean)>(env, "copy"); -jni::Object<Bitmap> Bitmap::Copy(jni::JNIEnv& env, jni::Object<Bitmap> bitmap) { - using Signature = jni::Object<Bitmap>(jni::Object<Config>, jni::jboolean); - auto static method = _class.GetMethod<Signature>(env, "copy"); - auto config = Bitmap::Config::Create(env, Bitmap::Config::Value::ARGB_8888); - return bitmap.Call(env, method, config, (jni::jboolean) false); + return bitmap.Call(env, copy, Bitmap::Config::Create(env, Bitmap::Config::Value::ARGB_8888), jni::jni_false); } } // namespace android diff --git a/platform/android/src/bitmap.hpp b/platform/android/src/bitmap.hpp index c4e41db1e..9d96405c2 100644 --- a/platform/android/src/bitmap.hpp +++ b/platform/android/src/bitmap.hpp @@ -11,10 +11,7 @@ class Bitmap { public: class Config { public: - static constexpr auto Name() { - return "android/graphics/Bitmap$Config"; - }; - static void registerNative(jni::JNIEnv&); + static constexpr auto Name() { return "android/graphics/Bitmap$Config"; }; enum Value { ALPHA_8, @@ -23,30 +20,23 @@ public: RGB_565, }; - static jni::Object<Config> Create(jni::JNIEnv&, Value); - - private: - static jni::Class<Config> _class; + static jni::Local<jni::Object<Config>> Create(jni::JNIEnv&, Value); }; - static constexpr auto Name() { - return "android/graphics/Bitmap"; - }; + static constexpr auto Name() { return "android/graphics/Bitmap"; }; static void registerNative(jni::JNIEnv&); - static jni::Object<Bitmap> - CreateBitmap(jni::JNIEnv&, jni::jint width, jni::jint height, jni::Object<Config>); - static jni::Object<Bitmap> + static jni::Local<jni::Object<Bitmap>> + CreateBitmap(jni::JNIEnv&, jni::jint width, jni::jint height, const jni::Object<Config>&); + + static jni::Local<jni::Object<Bitmap>> CreateBitmap(jni::JNIEnv& env, jni::jint width, jni::jint height, Config::Value config) { return CreateBitmap(env, width, height, Config::Create(env, config)); } - static PremultipliedImage GetImage(jni::JNIEnv&, jni::Object<Bitmap>); - static jni::Object<Bitmap> CreateBitmap(jni::JNIEnv&, const PremultipliedImage&); - static jni::Object<Bitmap> Copy(jni::JNIEnv&, jni::Object<Bitmap>); - -private: - static jni::Class<Bitmap> _class; + static PremultipliedImage GetImage(jni::JNIEnv&, const jni::Object<Bitmap>&); + static jni::Local<jni::Object<Bitmap>> CreateBitmap(jni::JNIEnv&, const PremultipliedImage&); + static jni::Local<jni::Object<Bitmap>> Copy(jni::JNIEnv&, const jni::Object<Bitmap>&); }; } // namespace android diff --git a/platform/android/src/bitmap_factory.cpp b/platform/android/src/bitmap_factory.cpp index 7d9b068b2..170bd52ea 100644 --- a/platform/android/src/bitmap_factory.cpp +++ b/platform/android/src/bitmap_factory.cpp @@ -4,20 +4,20 @@ namespace mbgl { namespace android { void BitmapFactory::registerNative(jni::JNIEnv& env) { - _class = *jni::Class<BitmapFactory>::Find(env).NewGlobalRef(env).release(); + jni::Class<BitmapFactory>::Singleton(env); } -jni::Class<BitmapFactory> BitmapFactory::_class; - -jni::Object<Bitmap> BitmapFactory::DecodeByteArray(jni::JNIEnv& env, - jni::Array<jni::jbyte> data, - jni::jint offset, - jni::jint length) { +jni::Local<jni::Object<Bitmap>> BitmapFactory::DecodeByteArray(jni::JNIEnv& env, + jni::Array<jni::jbyte>& data, + jni::jint offset, + jni::jint length) { + static auto& _class = jni::Class<BitmapFactory>::Singleton(env); // Images are loaded with ARGB_8888 config, and premultiplied by default, which is exactly // what we want, so we're not providing a BitmapFactory.Options object. - using Signature = jni::Object<Bitmap>(jni::Array<jni::jbyte>, jni::jint, jni::jint); - auto method = _class.GetStaticMethod<Signature>(env, "decodeByteArray"); + using Signature = jni::Object<Bitmap> (jni::Array<jni::jbyte>, jni::jint, jni::jint); + static auto method = _class.GetStaticMethod<Signature>(env, "decodeByteArray"); + return _class.Call(env, method, data, offset, length); } diff --git a/platform/android/src/bitmap_factory.hpp b/platform/android/src/bitmap_factory.hpp index b0e719826..f73b7a290 100644 --- a/platform/android/src/bitmap_factory.hpp +++ b/platform/android/src/bitmap_factory.hpp @@ -9,16 +9,11 @@ namespace android { class BitmapFactory { public: - static constexpr auto Name() { - return "android/graphics/BitmapFactory"; - }; + static constexpr auto Name() { return "android/graphics/BitmapFactory"; }; static void registerNative(jni::JNIEnv&); - static jni::Object<Bitmap> - DecodeByteArray(jni::JNIEnv&, jni::Array<jni::jbyte> data, jni::jint offset, jni::jint length); - -private: - static jni::Class<BitmapFactory> _class; + static jni::Local<jni::Object<Bitmap>> + DecodeByteArray(jni::JNIEnv&, jni::Array<jni::jbyte>& data, jni::jint offset, jni::jint length); }; } // namespace android diff --git a/platform/android/src/connectivity_listener.cpp b/platform/android/src/connectivity_listener.cpp index 5b1c0a86e..9c13f1f74 100644 --- a/platform/android/src/connectivity_listener.cpp +++ b/platform/android/src/connectivity_listener.cpp @@ -19,18 +19,16 @@ namespace android { NetworkStatus::Set(connected ? NetworkStatus::Status::Online : NetworkStatus::Status::Offline); } - jni::Class<ConnectivityListener> ConnectivityListener::javaClass; - void ConnectivityListener::registerNative(jni::JNIEnv& env) { // Lookup the class - ConnectivityListener::javaClass = *jni::Class<ConnectivityListener>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<ConnectivityListener>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<ConnectivityListener>( env, - ConnectivityListener::javaClass, + javaClass, "nativePtr", std::make_unique<ConnectivityListener, JNIEnv&>, "initialize", diff --git a/platform/android/src/connectivity_listener.hpp b/platform/android/src/connectivity_listener.hpp index b0d655d02..a09507c0f 100644 --- a/platform/android/src/connectivity_listener.hpp +++ b/platform/android/src/connectivity_listener.hpp @@ -12,8 +12,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/net/NativeConnectivityListener"; }; - static jni::Class<ConnectivityListener> javaClass; - static void registerNative(jni::JNIEnv&); /* diff --git a/platform/android/src/conversion/collection.cpp b/platform/android/src/conversion/collection.cpp index 27b614e8c..954a161ba 100644 --- a/platform/android/src/conversion/collection.cpp +++ b/platform/android/src/conversion/collection.cpp @@ -5,20 +5,28 @@ namespace mbgl { namespace android { namespace conversion { -std::vector<std::string> toVector(JNIEnv& env, jni::Array<jni::String> array) { +std::vector<std::string> toVector(JNIEnv& env, const jni::Array<jni::String>& array) { std::size_t len = array.Length(env); std::vector<std::string> vector; vector.reserve(len); for (std::size_t i = 0; i < len; i++) { - jni::String jstr = array.Get(env, i); - vector.push_back(*convert<std::string, jni::String>(env, jstr)); - jni::DeleteLocalRef(env, jstr); + vector.push_back(jni::Make<std::string>(env, array.Get(env, i))); } return vector; } +jni::Local<jni::Array<jni::String>> toArray(JNIEnv& env, const std::vector<std::string>& vector) { + auto result = jni::Array<jni::String>::New(env, vector.size()); + + for (std::size_t i = 0; i < vector.size(); i++) { + result.Set(env, i, jni::Make<jni::String>(env, vector.at(i))); + } + + return result; +} + } } } diff --git a/platform/android/src/conversion/collection.hpp b/platform/android/src/conversion/collection.hpp index bb8941c98..322ebb62e 100644 --- a/platform/android/src/conversion/collection.hpp +++ b/platform/android/src/conversion/collection.hpp @@ -10,7 +10,8 @@ namespace mbgl { namespace android { namespace conversion { -std::vector<std::string> toVector(JNIEnv& env, jni::Array<jni::String> array); +std::vector<std::string> toVector(JNIEnv& env, const jni::Array<jni::String>& array); +jni::Local<jni::Array<jni::String>> toArray(JNIEnv& env, const std::vector<std::string>&); } } diff --git a/platform/android/src/conversion/constant.cpp b/platform/android/src/conversion/constant.cpp index 16e8b3294..804d5fd14 100644 --- a/platform/android/src/conversion/constant.cpp +++ b/platform/android/src/conversion/constant.cpp @@ -1,4 +1,5 @@ #include "constant.hpp" +#include "collection.hpp" #include <sstream> @@ -6,63 +7,46 @@ namespace mbgl { namespace android { namespace conversion { -Result<jni::jobject*> Converter<jni::jobject*, bool>::operator()(jni::JNIEnv& env, const bool& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Boolean")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Z)V"); - return {&jni::NewObject(env, *javaClass, *constructor, (jboolean) value)}; +Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, bool>::operator()(jni::JNIEnv& env, const bool& value) const { + return jni::Box(env, value ? jni::jni_true : jni::jni_false); } -Result<jni::jobject*> Converter<jni::jobject*, float>::operator()(jni::JNIEnv& env, const float& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Float")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(F)V"); - return {&jni::NewObject(env, *javaClass, *constructor, (jfloat) value)}; +Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, float>::operator()(jni::JNIEnv& env, const float& value) const { + return jni::Box(env, value); } -Result<jni::jobject*> Converter<jni::jobject*, double>::operator()(jni::JNIEnv& env, const double& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Double")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(D)V"); - return {&jni::NewObject(env, *javaClass, *constructor, (jfloat) value)}; +Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, double>::operator()(jni::JNIEnv& env, const double& value) const { + return jni::Box(env, value); } -Result<jni::jobject*> Converter<jni::jobject*, std::string>::operator()(jni::JNIEnv& env, const std::string& value) const { - return {jni::Make<jni::String>(env, value).Get()}; +Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::string>::operator()(jni::JNIEnv& env, const std::string& value) const { + return jni::Make<jni::String>(env, value); } -Result<jni::jobject*> Converter<jni::jobject*, Color>::operator()(jni::JNIEnv& env, const Color& value) const { +Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, Color>::operator()(jni::JNIEnv& env, const Color& value) const { std::stringstream sstream; sstream << "rgba(" << value.r << ", " << value.g << ", " << value.b << ", " << value.a << ")"; - std::string result = sstream.str(); - return convert<jni::jobject*, std::string>(env, result); + return jni::Make<jni::String>(env, sstream.str()); } -Result<jni::jobject*> Converter<jni::jobject*, std::vector<std::string>>::operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const { - static jni::jclass* stringCass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/String")).release(); - jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *stringCass); +Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::vector<std::string>>::operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const { + auto result = jni::Array<jni::String>::New(env, value.size()); - for(size_t i = 0; i < value.size(); i = i + 1) { - Result<jni::jobject*> converted = convert<jni::jobject*, std::string>(env, value.at(i)); - jni::SetObjectArrayElement(env, jarray, i, *converted); + for (std::size_t i = 0; i < value.size(); i++) { + result.Set(env, i, jni::Make<jni::String>(env, value.at(i))); } - return &jarray; + return result; } -Result<jni::jobject*> Converter<jni::jobject*, std::vector<float>>::operator()(jni::JNIEnv& env, const std::vector<float>& value) const { - static jni::jclass* floatClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Float")).release(); - jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *floatClass); +Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::vector<float>>::operator()(jni::JNIEnv& env, const std::vector<float>& value) const { + auto result = jni::Array<jni::Float>::New(env, value.size()); - for(size_t i = 0; i < value.size(); i = i + 1) { - Result<jni::jobject*> converted = convert<jni::jobject*, float>(env, value.at(i)); - jni::SetObjectArrayElement(env, jarray, i, *converted); + for (std::size_t i = 0; i < value.size(); i++) { + result.Set(env, i, jni::Box(env, value.at(i))); } - return &jarray; -} - -// Java -> C++ - -Result<std::string> Converter<std::string, jni::String>::operator()(jni::JNIEnv& env, const jni::String& value) const { - return { jni::Make<std::string>(env, value) }; + return result; } } // namespace conversion diff --git a/platform/android/src/conversion/constant.hpp b/platform/android/src/conversion/constant.hpp index 0e665cf56..c6dafe117 100644 --- a/platform/android/src/conversion/constant.hpp +++ b/platform/android/src/conversion/constant.hpp @@ -16,18 +16,18 @@ namespace android { namespace conversion { template <> -struct Converter<jni::jobject*, bool> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const bool& value) const; +struct Converter<jni::Local<jni::Object<>>, bool> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const bool& value) const; }; template <> -struct Converter<jni::jobject*, float> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const float& value) const; +struct Converter<jni::Local<jni::Object<>>, float> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const float& value) const; }; template <> -struct Converter<jni::jobject*, double> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const double& value) const; +struct Converter<jni::Local<jni::Object<>>, double> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const double& value) const; }; /** @@ -35,61 +35,52 @@ struct Converter<jni::jobject*, double> { * TODO: use BigDecimal for > 64 / unsigned? */ template<typename T> -struct Converter<jni::jobject*, T, typename std::enable_if<std::is_integral<T>::value>::type> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const T& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Long")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(J)V"); - return {&jni::NewObject(env, *javaClass, *constructor, (jlong) value)}; +struct Converter<jni::Local<jni::Object<>>, T, typename std::enable_if<std::is_integral<T>::value>::type> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const T& value) const { + return jni::Box(env, jni::jlong(value)); } }; // TODO: convert integral types to primitive jni types template <> -struct Converter<jni::jobject*, std::string> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::string& value) const; +struct Converter<jni::Local<jni::Object<>>, std::string> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::string& value) const; }; template <> -struct Converter<jni::jobject*, Color> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const Color& value) const; +struct Converter<jni::Local<jni::Object<>>, Color> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const Color& value) const; }; template <std::size_t N> -struct Converter<jni::jobject*, std::array<float, N>> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::array<float, N>& value) const { +struct Converter<jni::Local<jni::Object<>>, std::array<float, N>> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::array<float, N>& value) const { std::vector<float> v; for (const float& id : value) { v.push_back(id); } - return convert<jni::jobject*, std::vector<float>>(env, v); + return convert<jni::Local<jni::Object<>>, std::vector<float>>(env, v); } }; template <> -struct Converter<jni::jobject*, std::vector<std::string>> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const; +struct Converter<jni::Local<jni::Object<>>, std::vector<std::string>> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const; }; template <> -struct Converter<jni::jobject*, std::vector<float>> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::vector<float>& value) const; +struct Converter<jni::Local<jni::Object<>>, std::vector<float>> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<float>& value) const; }; template <class T> -struct Converter<jni::jobject*, T, typename std::enable_if_t<std::is_enum<T>::value>> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const T& value) const { - return convert<jni::jobject*, std::string>(env, Enum<T>::toString(value)); +struct Converter<jni::Local<jni::Object<>>, T, typename std::enable_if_t<std::is_enum<T>::value>> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const T& value) const { + return convert<jni::Local<jni::Object<>>, std::string>(env, Enum<T>::toString(value)); } }; -// Java -> C++ - -template <> -struct Converter<std::string, jni::String> { - Result<std::string> operator()(jni::JNIEnv& env, const jni::String& value) const; -}; - } // namespace conversion -} // namespace style +} // namespace android } // namespace mbgl diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp index 2a6cac3b0..d9b8e12dc 100644 --- a/platform/android/src/file_source.cpp +++ b/platform/android/src/file_source.cpp @@ -1,4 +1,5 @@ #include "file_source.hpp" +#include "attach_env.hpp" #include <mbgl/actor/actor.hpp> #include <mbgl/actor/scheduler.hpp> @@ -6,7 +7,6 @@ #include <mbgl/util/logging.hpp> #include "asset_manager_file_source.hpp" -#include "jni/generic_global_ref_deleter.hpp" namespace mbgl { namespace android { @@ -14,9 +14,9 @@ namespace android { // FileSource // FileSource::FileSource(jni::JNIEnv& _env, - jni::String accessToken, - jni::String _cachePath, - jni::Object<AssetManager> assetManager) { + const jni::String& accessToken, + const jni::String& _cachePath, + const jni::Object<AssetManager>& assetManager) { // Create a core default file source fileSource = std::make_unique<mbgl::DefaultFileSource>( jni::Make<std::string>(_env, _cachePath) + "/mbgl-offline.db", @@ -31,30 +31,31 @@ FileSource::FileSource(jni::JNIEnv& _env, FileSource::~FileSource() { } -jni::String FileSource::getAccessToken(jni::JNIEnv& env) { +jni::Local<jni::String> FileSource::getAccessToken(jni::JNIEnv& env) { return jni::Make<jni::String>(env, fileSource->getAccessToken()); } -void FileSource::setAccessToken(jni::JNIEnv& env, jni::String token) { +void FileSource::setAccessToken(jni::JNIEnv& env, const jni::String& token) { fileSource->setAccessToken(jni::Make<std::string>(env, token)); } -void FileSource::setAPIBaseUrl(jni::JNIEnv& env, jni::String url) { +void FileSource::setAPIBaseUrl(jni::JNIEnv& env, const jni::String& url) { fileSource->setAPIBaseURL(jni::Make<std::string>(env, url)); } -void FileSource::setResourceTransform(jni::JNIEnv& env, jni::Object<FileSource::ResourceTransformCallback> transformCallback) { +void FileSource::setResourceTransform(jni::JNIEnv& env, const jni::Object<FileSource::ResourceTransformCallback>& transformCallback) { if (transformCallback) { + auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, transformCallback); resourceTransform = std::make_unique<Actor<ResourceTransform>>(*Scheduler::GetCurrent(), // Capture the ResourceTransformCallback object as a managed global into // the lambda. It is released automatically when we're setting a new ResourceTransform in // a subsequent call. // Note: we're converting it to shared_ptr because this lambda is converted to a std::function, // which requires copyability of its captured variables. - [callback = std::shared_ptr<jni::jobject>(transformCallback.NewGlobalRef(env).release()->Get(), GenericGlobalRefDeleter())] + [callback = std::make_shared<decltype(global)>(std::move(global))] (mbgl::Resource::Kind kind, const std::string&& url_) { android::UniqueEnv _env = android::AttachEnv(); - return FileSource::ResourceTransformCallback::onURL(*_env, jni::Object<FileSource::ResourceTransformCallback>(*callback), int(kind), url_); + return FileSource::ResourceTransformCallback::onURL(*_env, *callback, int(kind), url_); }); fileSource->setResourceTransform(resourceTransform->self()); } else { @@ -92,30 +93,32 @@ jni::jboolean FileSource::isResumed(jni::JNIEnv&) { return (jboolean) false; } -jni::Class<FileSource> FileSource::javaClass; - -FileSource* FileSource::getNativePeer(jni::JNIEnv& env, jni::Object<FileSource> jFileSource) { - static auto field = FileSource::javaClass.GetField<jlong>(env, "nativePtr"); +FileSource* FileSource::getNativePeer(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) { + static auto& javaClass = jni::Class<FileSource>::Singleton(env); + static auto field = javaClass.GetField<jlong>(env, "nativePtr"); return reinterpret_cast<FileSource *>(jFileSource.Get(env, field)); } -mbgl::DefaultFileSource& FileSource::getDefaultFileSource(jni::JNIEnv& env, jni::Object<FileSource> jFileSource) { +mbgl::DefaultFileSource& FileSource::getDefaultFileSource(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) { FileSource* fileSource = FileSource::getNativePeer(env, jFileSource); assert(fileSource != nullptr); return *fileSource->fileSource; } void FileSource::registerNative(jni::JNIEnv& env) { - //Register classes - FileSource::javaClass = *jni::Class<FileSource>::Find(env).NewGlobalRef(env).release(); - FileSource::ResourceTransformCallback::javaClass = *jni::Class<FileSource::ResourceTransformCallback>::Find(env).NewGlobalRef(env).release(); + // Ensure the class for ResourceTransformCallback is cached. If it's requested for the + // first time on a background thread, Android's class loader heuristics will fail. + // https://developer.android.com/training/articles/perf-jni#faq_FindClass + jni::Class<ResourceTransformCallback>::Singleton(env); + + static auto& javaClass = jni::Class<FileSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<FileSource>( - env, FileSource::javaClass, "nativePtr", - std::make_unique<FileSource, JNIEnv&, jni::String, jni::String, jni::Object<AssetManager>>, + env, javaClass, "nativePtr", + jni::MakePeer<FileSource, const jni::String&, const jni::String&, const jni::Object<AssetManager>&>, "initialize", "finalize", METHOD(&FileSource::getAccessToken, "getAccessToken"), @@ -131,16 +134,13 @@ void FileSource::registerNative(jni::JNIEnv& env) { // FileSource::ResourceTransformCallback // -jni::Class<FileSource::ResourceTransformCallback> FileSource::ResourceTransformCallback::javaClass; - -std::string FileSource::ResourceTransformCallback::onURL(jni::JNIEnv& env, jni::Object<FileSource::ResourceTransformCallback> callback, int kind, std::string url_) { - static auto method = FileSource::ResourceTransformCallback::javaClass.GetMethod<jni::String (jni::jint, jni::String)>(env, "onURL"); - auto url = jni::Make<jni::String>(env, url_); +std::string FileSource::ResourceTransformCallback::onURL(jni::JNIEnv& env, const jni::Object<FileSource::ResourceTransformCallback>& callback, int kind, std::string url_) { + static auto& javaClass = jni::Class<FileSource::ResourceTransformCallback>::Singleton(env); + static auto method = javaClass.GetMethod<jni::String (jni::jint, jni::String)>(env, "onURL"); - url = callback.Call(env, method, kind, url); - auto urlStr = jni::Make<std::string>(env, url); - jni::DeleteLocalRef(env, url); - return urlStr; + return jni::Make<std::string>(env, + callback.Call(env, method, kind, + jni::Make<jni::String>(env, url_))); } } // namespace android diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp index e4295e1b8..572ac647b 100644 --- a/platform/android/src/file_source.hpp +++ b/platform/android/src/file_source.hpp @@ -24,22 +24,20 @@ public: struct ResourceTransformCallback { static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource$ResourceTransformCallback"; } - static std::string onURL(jni::JNIEnv&, jni::Object<FileSource::ResourceTransformCallback>, int, std::string); - - static jni::Class<ResourceTransformCallback> javaClass; + static std::string onURL(jni::JNIEnv&, const jni::Object<FileSource::ResourceTransformCallback>&, int, std::string); }; - FileSource(jni::JNIEnv&, jni::String, jni::String, jni::Object<AssetManager>); + FileSource(jni::JNIEnv&, const jni::String&, const jni::String&, const jni::Object<AssetManager>&); ~FileSource(); - jni::String getAccessToken(jni::JNIEnv&); + jni::Local<jni::String> getAccessToken(jni::JNIEnv&); - void setAccessToken(jni::JNIEnv&, jni::String); + void setAccessToken(jni::JNIEnv&, const jni::String&); - void setAPIBaseUrl(jni::JNIEnv&, jni::String); + void setAPIBaseUrl(jni::JNIEnv&, const jni::String&); - void setResourceTransform(jni::JNIEnv&, jni::Object<FileSource::ResourceTransformCallback>); + void setResourceTransform(jni::JNIEnv&, const jni::Object<FileSource::ResourceTransformCallback>&); void resume(jni::JNIEnv&); @@ -47,11 +45,9 @@ public: jni::jboolean isResumed(jni::JNIEnv&); - static jni::Class<FileSource> javaClass; - - static FileSource* getNativePeer(jni::JNIEnv&, jni::Object<FileSource>); + static FileSource* getNativePeer(jni::JNIEnv&, const jni::Object<FileSource>&); - static mbgl::DefaultFileSource& getDefaultFileSource(jni::JNIEnv&, jni::Object<FileSource>); + static mbgl::DefaultFileSource& getDefaultFileSource(jni::JNIEnv&, const jni::Object<FileSource>&); static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/geojson/conversion/feature.cpp b/platform/android/src/geojson/conversion/feature.cpp deleted file mode 100644 index 3cb6d37b1..000000000 --- a/platform/android/src/geojson/conversion/feature.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include "feature.hpp" - -#include "../../conversion/constant.hpp" -#include "../../conversion/conversion.hpp" -#include "../../jni/local_object.hpp" - -namespace mbgl { -namespace android { -namespace conversion { - -/** - * Turn feature identifier into std::string - */ -class FeatureIdVisitor { -public: - - template<class T> - std::string operator()(const T& i) const { - return std::to_string(i); - } - - std::string operator()(const std::string& i) const { - return i; - } - - std::string operator()(const std::nullptr_t&) const { - return ""; - } - -}; - -/** - * Turn properties into Java GSON JsonObject's - */ -class PropertyValueEvaluator { -public: - jni::JNIEnv& env; - - /** - * null - */ - jni::jobject* operator()(const mapbox::geometry::null_value_t &) const { - return (jni::jobject*) nullptr; - } - - /** - * Boolean primitive - */ - jni::jobject* operator()(const bool& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/Boolean;)V"); - - // Create JsonPrimitive - jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, bool>(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, *converted); - - return object; - } - - /** - * String primitive - */ - jni::jobject* operator()(const std::string& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/String;)V"); - - // Create JsonPrimitive - jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); - - return object; - } - - /** - * Number primitives - */ - template <class Number> - jni::jobject* operator()(const Number& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/Number;)V"); - - // Create JsonPrimitive - jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, Number>(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); - - return object; - } - - - /** - * Json Array - */ - jni::jobject* operator()(const std::vector<mbgl::Value> &values) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonArray")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");; - static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Lcom/google/gson/JsonElement;)V"); - - // Create json array - jni::jobject* jarray = &jni::NewObject(env, *javaClass, *constructor); - - // Add values - for (const auto &v : values) { - jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(v, *this)); - jni::CallMethod<void>(env, jarray, *add, converted.get()); - } - - return jarray; - } - - /** - * Json Object - */ - jni::jobject* operator()(const std::unordered_map<std::string, mbgl::Value> &value) const { - // TODO: clean up duplication here - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");; - static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V"); - - // Create json object - jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor); - - // Add items - for (auto &item : value) { - jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, *this)); - jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first)); - jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get()); - } - - return jsonObject; - } -}; - -Result<jni::jobject*> Converter<jni::jobject*, std::unordered_map<std::string, mbgl::Value>>::operator()(jni::JNIEnv& env, const std::unordered_map<std::string, mbgl::Value>& value) const { - static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release(); - static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");; - static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V"); - - // Create json object - jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor); - - // Add items - PropertyValueEvaluator evaluator {env}; - for (auto &item : value) { - jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, evaluator)); - jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first)); - jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get()); - } - - return {jsonObject}; -} - -Result<jni::Object<android::geojson::Feature>> Converter<jni::Object<android::geojson::Feature>, mbgl::Feature>::operator()(jni::JNIEnv& env, const mbgl::Feature& value) const { - - // Convert Id - FeatureIdVisitor idEvaluator; - std::string id = (value.id) ? mapbox::geometry::identifier::visit(value.id.value(), idEvaluator) : ""; - auto jid = jni::Make<jni::String>(env, id); - - // Convert properties - auto properties = jni::Object<gson::JsonObject>(*convert<jni::jobject*>(env, value.properties)); - - // Convert geometry - auto geometry = android::geojson::Geometry::New(env, value.geometry); - - // Create feature - auto feature = android::geojson::Feature::fromGeometry(env, geometry, properties, jid); - - //Cleanup - jni::DeleteLocalRef(env, jid); - jni::DeleteLocalRef(env, geometry); - jni::DeleteLocalRef(env, properties); - - return feature; -} - -Result<jni::Array<jni::Object<android::geojson::Feature>>> Converter<jni::Array<jni::Object<android::geojson::Feature>>, std::vector<mbgl::Feature>>::operator()(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) const { - using namespace mbgl::android::geojson; - auto features = jni::Array<jni::Object<Feature>>::New(env, value.size(), Feature::javaClass); - - for(size_t i = 0; i < value.size(); i = i + 1) { - auto converted = *convert<jni::Object<android::geojson::Feature>, mbgl::Feature>(env, value.at(i)); - features.Set(env, i, converted); - jni::DeleteLocalRef(env, converted); - } - - return {features}; -} - -} // namespace conversion -} // namespace android -} // namespace mbgl diff --git a/platform/android/src/geojson/conversion/feature.hpp b/platform/android/src/geojson/conversion/feature.hpp deleted file mode 100644 index 031449cd2..000000000 --- a/platform/android/src/geojson/conversion/feature.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "../../conversion/conversion.hpp" -#include "../feature.hpp" - -#include <mbgl/util/feature.hpp> -#include <jni/jni.hpp> - -#include <vector> -#include <unordered_map> - -namespace mbgl { -namespace android { -namespace conversion { - -template <> -struct Converter<jni::jobject*, std::unordered_map<std::string, mbgl::Value>> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::unordered_map<std::string, mbgl::Value>& value) const; -}; - -template <> -struct Converter<jni::Object<android::geojson::Feature>, mbgl::Feature> { - Result<jni::Object<android::geojson::Feature>> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const; -}; - -template <> -struct Converter<jni::Array<jni::Object<android::geojson::Feature>>, std::vector<mbgl::Feature>> { - Result<jni::Array<jni::Object<android::geojson::Feature>>> operator()(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) const; -}; - -} // namespace conversion -} // namespace android -} // namespace mbgl diff --git a/platform/android/src/geojson/feature.cpp b/platform/android/src/geojson/feature.cpp index d8a4e829e..f0ed09784 100644 --- a/platform/android/src/geojson/feature.cpp +++ b/platform/android/src/geojson/feature.cpp @@ -1,63 +1,74 @@ #include "feature.hpp" - #include "geometry.hpp" +#include "../gson/json_object.hpp" + +#include <mbgl/util/string.hpp> namespace mbgl { namespace android { namespace geojson { -mbgl::Feature Feature::convert(jni::JNIEnv& env, jni::Object<Feature> jFeature) { - // Convert - auto jGeometry = geometry(env, jFeature); - auto jProperties = Feature::properties(env, jFeature); +using namespace gson; - std::experimental::optional<mapbox::geometry::identifier> id; - auto jId = Feature::id(env, jFeature); - if (jId) { - id = { jni::Make<std::string>(env, jId) }; - } +mbgl::Feature Feature::convert(jni::JNIEnv& env, const jni::Object<Feature>& jFeature) { + static auto& javaClass = jni::Class<Feature>::Singleton(env); + static auto id = javaClass.GetMethod<jni::String ()>(env, "id"); + static auto geometry = javaClass.GetMethod<jni::Object<Geometry> ()>(env, "geometry"); + static auto properties = javaClass.GetMethod<jni::Object<gson::JsonObject> ()>(env, "properties"); + + auto jId = jFeature.Call(env, id); - auto feature = mbgl::Feature { - Geometry::convert(env, jGeometry), - gson::JsonObject::convert(env, jProperties), - id + return mbgl::Feature { + Geometry::convert(env, jFeature.Call(env, geometry)), + JsonObject::convert(env, jFeature.Call(env, properties)), + jId ? std::experimental::optional<mapbox::geometry::identifier>(jni::Make<std::string>(env, jId)) + : std::experimental::nullopt }; +} - // Cleanup - jni::DeleteLocalRef(env, jGeometry); - jni::DeleteLocalRef(env, jProperties); - jni::DeleteLocalRef(env, jId); +/** + * Turn feature identifier into std::string + */ +class FeatureIdVisitor { +public: + template<class T> + std::string operator()(const T& i) const { + return std::to_string(i); + } - return feature; -} + std::string operator()(const std::string& i) const { + return i; + } -jni::Object<Geometry> Feature::geometry(jni::JNIEnv& env, jni::Object<Feature> jFeature) { - static auto method = Feature::javaClass.GetMethod<jni::Object<Geometry> ()>(env, "geometry"); - return jFeature.Call(env, method); -} + std::string operator()(const std::nullptr_t&) const { + return ""; + } +}; -jni::Object<gson::JsonObject> Feature::properties(jni::JNIEnv& env, jni::Object<Feature> jFeature) { - static auto method = Feature::javaClass.GetMethod<jni::Object<gson::JsonObject> ()>(env, "properties"); - return jFeature.Call(env, method); -} +jni::Local<jni::Object<Feature>> convertFeature(jni::JNIEnv& env, const mbgl::Feature& value) { + static auto& javaClass = jni::Class<Feature>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<Feature> (jni::Object<Geometry>, jni::Object<JsonObject>, jni::String)>(env, "fromGeometry"); -jni::String Feature::id(jni::JNIEnv& env, jni::Object<Feature> jFeature) { - static auto method = Feature::javaClass.GetMethod<jni::String ()>(env, "id"); - return jFeature.Call(env, method); + return javaClass.Call(env, method, + Geometry::New(env, value.geometry), + JsonObject::New(env, value.properties), + jni::Make<jni::String>(env, value.id ? value.id.value().match(FeatureIdVisitor()) : "")); } -jni::Object<Feature> Feature::fromGeometry(jni::JNIEnv& env, jni::Object<Geometry> geometry, jni::Object<gson::JsonObject> properties, jni::String id) { - static auto method = Feature::javaClass.GetStaticMethod<jni::Object<Feature> (jni::Object<Geometry>, jni::Object<gson::JsonObject>, jni::String)>(env, "fromGeometry"); - return Feature::javaClass.Call(env, method, geometry, properties, id); +jni::Local<jni::Array<jni::Object<Feature>>> Feature::convert(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) { + auto features = jni::Array<jni::Object<Feature>>::New(env, value.size()); + + for (size_t i = 0; i < value.size(); i = i + 1) { + features.Set(env, i, convertFeature(env, value.at(i))); + } + + return features; } void Feature::registerNative(jni::JNIEnv& env) { - // Lookup the class - Feature::javaClass = *jni::Class<Feature>::Find(env).NewGlobalRef(env).release(); + jni::Class<Feature>::Singleton(env); } -jni::Class<Feature> Feature::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geojson/feature.hpp b/platform/android/src/geojson/feature.hpp index ab59d783e..fdf5d977b 100644 --- a/platform/android/src/geojson/feature.hpp +++ b/platform/android/src/geojson/feature.hpp @@ -1,37 +1,21 @@ #pragma once #include <mbgl/util/feature.hpp> -#include <mbgl/util/geometry.hpp> -#include <mbgl/util/noncopyable.hpp> #include <jni/jni.hpp> -#include "geometry.hpp" -#include "../gson/json_object.hpp" - namespace mbgl { namespace android { namespace geojson { -class Feature : private mbgl::util::noncopyable { +class Feature { public: - static constexpr auto Name() { return "com/mapbox/geojson/Feature"; }; - static jni::Object<Feature> fromGeometry(jni::JNIEnv&, jni::Object<Geometry>, jni::Object<gson::JsonObject>, jni::String); - - static mbgl::Feature convert(jni::JNIEnv&, jni::Object<Feature>); - - static jni::Object<Geometry> geometry(jni::JNIEnv&, jni::Object<Feature>); - - static jni::String id(jni::JNIEnv&, jni::Object<Feature>); - - static jni::Object<gson::JsonObject> properties(jni::JNIEnv&, jni::Object<Feature>); - - static jni::Class<Feature> javaClass; + static mbgl::Feature convert(jni::JNIEnv&, const jni::Object<Feature>&); + static jni::Local<jni::Array<jni::Object<Feature>>> convert(jni::JNIEnv&, const std::vector<mbgl::Feature>&); static void registerNative(jni::JNIEnv&); - }; } // namespace geojson diff --git a/platform/android/src/geojson/feature_collection.cpp b/platform/android/src/geojson/feature_collection.cpp index 18a41d48f..f90d5226b 100644 --- a/platform/android/src/geojson/feature_collection.cpp +++ b/platform/android/src/geojson/feature_collection.cpp @@ -6,7 +6,7 @@ namespace mbgl { namespace android { namespace geojson { -mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env, jni::Object<FeatureCollection> jCollection) { +mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env, const jni::Object<FeatureCollection>& jCollection) { auto collection = mbgl::FeatureCollection(); if (jCollection) { @@ -16,29 +16,22 @@ mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env, jni::Object collection.reserve(size); for (size_t i = 0; i < size; i++) { - auto jFeature = jFeatures.Get(env, i); - collection.push_back(Feature::convert(env, jFeature)); - jni::DeleteLocalRef(env, jFeature); + collection.push_back(Feature::convert(env, jFeatures.Get(env, i))); } - - jni::DeleteLocalRef(env, jFeatures); - jni::DeleteLocalRef(env, jFeatureList); } return collection; } -jni::Object<java::util::List> FeatureCollection::features(jni::JNIEnv& env, jni::Object<FeatureCollection> jCollection) { - static auto method = FeatureCollection::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "features"); +jni::Local<jni::Object<java::util::List>> FeatureCollection::features(jni::JNIEnv& env, const jni::Object<FeatureCollection>& jCollection) { + static auto& javaClass = jni::Class<FeatureCollection>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "features"); return jCollection.Call(env, method); } void FeatureCollection::registerNative(jni::JNIEnv& env) { - // Lookup the class - javaClass = *jni::Class<FeatureCollection>::Find(env).NewGlobalRef(env).release(); + jni::Class<FeatureCollection>::Singleton(env); } -jni::Class<FeatureCollection> FeatureCollection::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geojson/feature_collection.hpp b/platform/android/src/geojson/feature_collection.hpp index 259ffab37..66e92eaca 100644 --- a/platform/android/src/geojson/feature_collection.hpp +++ b/platform/android/src/geojson/feature_collection.hpp @@ -3,7 +3,6 @@ #include "../java/util.hpp" #include <mbgl/util/geojson.hpp> -#include <mbgl/util/noncopyable.hpp> #include <jni/jni.hpp> @@ -11,15 +10,13 @@ namespace mbgl { namespace android { namespace geojson { -class FeatureCollection : private mbgl::util::noncopyable { +class FeatureCollection { public: static constexpr auto Name() { return "com/mapbox/geojson/FeatureCollection"; }; - static mbgl::FeatureCollection convert(jni::JNIEnv&, jni::Object<FeatureCollection>); + static mbgl::FeatureCollection convert(jni::JNIEnv&, const jni::Object<FeatureCollection>&); - static jni::Object<java::util::List> features(jni::JNIEnv&, jni::Object<FeatureCollection>); - - static jni::Class<FeatureCollection> javaClass; + static jni::Local<jni::Object<java::util::List>> features(jni::JNIEnv&, const jni::Object<FeatureCollection>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/geometry.cpp b/platform/android/src/geojson/geometry.cpp index 5635b5a0f..2356af780 100644 --- a/platform/android/src/geojson/geometry.cpp +++ b/platform/android/src/geojson/geometry.cpp @@ -22,76 +22,71 @@ public: jni::JNIEnv& env; - jni::Object<Geometry> operator()(const mbgl::Point<double> &geometry) const { - return jni::Cast(env, Point::New(env, geometry), Geometry::javaClass); + jni::Local<jni::Object<Geometry>> operator()(const mbgl::Point<double> &geometry) const { + return Point::New(env, geometry); } - jni::Object<Geometry> operator()(const mbgl::LineString<double> &geometry) const { - return jni::Cast(env, LineString::New(env, geometry), Geometry::javaClass); + jni::Local<jni::Object<Geometry>> operator()(const mbgl::LineString<double> &geometry) const { + return LineString::New(env, geometry); } - jni::Object<Geometry> operator()(const mbgl::MultiLineString<double> &geometry) const { - return jni::Cast(env, MultiLineString::New(env, geometry), Geometry::javaClass); + jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiLineString<double> &geometry) const { + return MultiLineString::New(env, geometry); } - jni::Object<Geometry> operator()(const mbgl::MultiPoint<double> &geometry) const { - return jni::Cast(env, MultiPoint::New(env, geometry), Geometry::javaClass); + jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiPoint<double> &geometry) const { + return MultiPoint::New(env, geometry); } - jni::Object<Geometry> operator()(const mbgl::Polygon<double> &geometry) const { - return jni::Cast(env, Polygon::New(env, geometry), Geometry::javaClass); + jni::Local<jni::Object<Geometry>> operator()(const mbgl::Polygon<double> &geometry) const { + return Polygon::New(env, geometry); } - jni::Object<Geometry> operator()(const mbgl::MultiPolygon<double> &geometry) const { - return jni::Cast(env, MultiPolygon::New(env, geometry), Geometry::javaClass); + jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiPolygon<double> &geometry) const { + return MultiPolygon::New(env, geometry); } - jni::Object<Geometry> operator()(const mapbox::geometry::geometry_collection<double> &geometry) const { - return jni::Cast(env, GeometryCollection::New(env, geometry), Geometry::javaClass); + jni::Local<jni::Object<Geometry>> operator()(const mapbox::geometry::geometry_collection<double> &geometry) const { + return GeometryCollection::New(env, geometry); } }; -jni::Object<Geometry> Geometry::New(jni::JNIEnv& env, mbgl::Geometry<double> geometry) { +jni::Local<jni::Object<Geometry>> Geometry::New(jni::JNIEnv& env, mbgl::Geometry<double> geometry) { GeometryEvaluator evaluator { env } ; return mbgl::Geometry<double>::visit(geometry, evaluator); } -mbgl::Geometry<double> Geometry::convert(jni::JNIEnv &env, jni::Object<Geometry> jGeometry) { +mbgl::Geometry<double> Geometry::convert(jni::JNIEnv &env, const jni::Object<Geometry>& jGeometry) { auto type = Geometry::getType(env, jGeometry); if (type == Point::Type()) { - return { Point::convert(env, jni::Object<Point>(jGeometry.Get())) }; + return { Point::convert(env, jni::Cast(env, jni::Class<Point>::Singleton(env), jGeometry)) }; } else if (type == MultiPoint::Type()) { - return { MultiPoint::convert(env, jni::Object<MultiPoint>(jGeometry.Get())) }; + return { MultiPoint::convert(env, jni::Cast(env, jni::Class<MultiPoint>::Singleton(env), jGeometry)) }; } else if (type == LineString::Type()) { - return { LineString::convert(env, jni::Object<LineString>(jGeometry.Get())) }; + return { LineString::convert(env, jni::Cast(env, jni::Class<LineString>::Singleton(env), jGeometry)) }; } else if (type == MultiLineString::Type()) { - return { MultiLineString::convert(env, jni::Object<MultiLineString>(jGeometry.Get())) }; + return { MultiLineString::convert(env, jni::Cast(env, jni::Class<MultiLineString>::Singleton(env), jGeometry)) }; } else if (type == Polygon::Type()) { - return { Polygon::convert(env, jni::Object<Polygon>(jGeometry.Get())) }; + return { Polygon::convert(env, jni::Cast(env, jni::Class<Polygon>::Singleton(env), jGeometry)) }; } else if (type == MultiPolygon::Type()) { - return { MultiPolygon::convert(env, jni::Object<MultiPolygon>(jGeometry.Get())) }; + return { MultiPolygon::convert(env, jni::Cast(env, jni::Class<MultiPolygon>::Singleton(env), jGeometry)) }; } else if (type == GeometryCollection::Type()) { - return { GeometryCollection::convert(env, jni::Object<GeometryCollection>(jGeometry.Get())) }; + return { GeometryCollection::convert(env, jni::Cast(env, jni::Class<GeometryCollection>::Singleton(env), jGeometry)) }; } throw std::runtime_error(std::string {"Unsupported GeoJSON type: " } + type); } -std::string Geometry::getType(jni::JNIEnv &env, jni::Object<Geometry> jGeometry) { - static auto method = Geometry::javaClass.GetMethod<jni::String ()>(env, "type"); - auto jType = jGeometry.Call(env, method); - auto type = jni::Make<std::string>(env, jType); - jni::DeleteLocalRef(env, jType); - return type; +std::string Geometry::getType(jni::JNIEnv &env, const jni::Object<Geometry>& jGeometry) { + static auto& javaClass = jni::Class<Geometry>::Singleton(env); + static auto method = javaClass.GetMethod<jni::String ()>(env, "type"); + return jni::Make<std::string>(env, jGeometry.Call(env, method)); } void Geometry::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Geometry>::Find(env).NewGlobalRef(env).release(); + jni::Class<Geometry>::Singleton(env); } -jni::Class<Geometry> Geometry::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geojson/geometry.hpp b/platform/android/src/geojson/geometry.hpp index a1bb88668..4bf55c858 100644 --- a/platform/android/src/geojson/geometry.hpp +++ b/platform/android/src/geojson/geometry.hpp @@ -1,7 +1,6 @@ #pragma once #include <mbgl/util/geometry.hpp> -#include <mbgl/util/noncopyable.hpp> #include "../java/util.hpp" @@ -11,17 +10,15 @@ namespace mbgl { namespace android { namespace geojson { -class Geometry : private mbgl::util::noncopyable { +class Geometry { public: static constexpr auto Name() { return "com/mapbox/geojson/Geometry"; }; - static jni::Object<Geometry> New(jni::JNIEnv&, mbgl::Geometry<double>); + static jni::Local<jni::Object<Geometry>> New(jni::JNIEnv&, mbgl::Geometry<double>); - static mbgl::Geometry<double> convert(jni::JNIEnv&, jni::Object<Geometry>); + static mbgl::Geometry<double> convert(jni::JNIEnv&, const jni::Object<Geometry>&); - static std::string getType(jni::JNIEnv&, jni::Object<Geometry>); - - static jni::Class<Geometry> javaClass; + static std::string getType(jni::JNIEnv&, const jni::Object<Geometry>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/geometry_collection.cpp b/platform/android/src/geojson/geometry_collection.cpp index 770cb9a5d..cca909126 100644 --- a/platform/android/src/geojson/geometry_collection.cpp +++ b/platform/android/src/geojson/geometry_collection.cpp @@ -5,59 +5,43 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object<GeometryCollection> GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection<double>& collection) { +jni::Local<jni::Object<GeometryCollection>> GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection<double>& collection) { // Create an array of geometries - auto jarray = jni::Array<jni::Object<Geometry>>::New(env, collection.size(), Geometry::javaClass); + auto jarray = jni::Array<jni::Object<Geometry>>::New(env, collection.size()); for (size_t i = 0; i < collection.size(); i++) { - auto& geometry = collection.at(i); - auto jGeometry = Geometry::New(env, geometry); - jarray.Set(env, i, jGeometry); - jni::DeleteLocalRef(env, jGeometry); + jarray.Set(env, i, Geometry::New(env, collection.at(i))); } - // Turn into array list - auto jList = java::util::Arrays::asList(env, jarray); - jni::DeleteLocalRef(env, jarray); - // create the GeometryCollection + static auto& javaClass = jni::Class<GeometryCollection>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<GeometryCollection> (jni::Object<java::util::List>)>(env, "fromGeometries"); - auto jCollection = javaClass.Call(env, method, jList); - - jni::DeleteLocalRef(env, jList); - return jCollection; + return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray)); } -mapbox::geometry::geometry_collection<double> GeometryCollection::convert(jni::JNIEnv &env, jni::Object<GeometryCollection> jCollection) { +mapbox::geometry::geometry_collection<double> GeometryCollection::convert(jni::JNIEnv &env, const jni::Object<GeometryCollection>& jCollection) { // Get geometries + static auto& javaClass = jni::Class<GeometryCollection>::Singleton(env); static auto getGeometries = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "geometries"); - auto jList = jCollection.Call(env, getGeometries); // Turn into array - auto jarray = java::util::List::toArray<Geometry>(env, jList); - jni::DeleteLocalRef(env, jList); + auto jarray = java::util::List::toArray<Geometry>(env, jCollection.Call(env, getGeometries)); // Convert each geometry mapbox::geometry::geometry_collection<double> collection{}; auto size = jarray.Length(env); for (jni::jsize i = 0; i < size; i++) { - auto element = jarray.Get(env, i); - collection.push_back(Geometry::convert(env, element)); - jni::DeleteLocalRef(env, element); + collection.push_back(Geometry::convert(env, jarray.Get(env, i))); } - jni::DeleteLocalRef(env, jarray); return collection; } void GeometryCollection::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<GeometryCollection>::Find(env).NewGlobalRef(env).release(); + jni::Class<GeometryCollection>::Singleton(env); } -jni::Class<GeometryCollection> GeometryCollection::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geojson/geometry_collection.hpp b/platform/android/src/geojson/geometry_collection.hpp index 9ed9953b0..9f02ac848 100644 --- a/platform/android/src/geojson/geometry_collection.hpp +++ b/platform/android/src/geojson/geometry_collection.hpp @@ -8,17 +8,15 @@ namespace mbgl { namespace android { namespace geojson { -class GeometryCollection : public Geometry { +class GeometryCollection { public: + using SuperTag = Geometry; static constexpr auto Name() { return "com/mapbox/geojson/GeometryCollection"; }; - static constexpr auto Type() { return "GeometryCollection"; }; - static jni::Object<GeometryCollection> New(jni::JNIEnv&, const mapbox::geometry::geometry_collection<double>&); - - static mapbox::geometry::geometry_collection<double> convert(jni::JNIEnv&, jni::Object<GeometryCollection>); + static jni::Local<jni::Object<GeometryCollection>> New(jni::JNIEnv&, const mapbox::geometry::geometry_collection<double>&); - static jni::Class<GeometryCollection> javaClass; + static mapbox::geometry::geometry_collection<double> convert(jni::JNIEnv&, const jni::Object<GeometryCollection>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/line_string.cpp b/platform/android/src/geojson/line_string.cpp index a5f1a468c..ae1345c95 100644 --- a/platform/android/src/geojson/line_string.cpp +++ b/platform/android/src/geojson/line_string.cpp @@ -7,29 +7,24 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object<LineString> LineString::New(jni::JNIEnv& env, const mbgl::LineString<double>& lineString) { - auto jList = asPointsList(env, lineString); - +jni::Local<jni::Object<LineString>> LineString::New(jni::JNIEnv& env, const mbgl::LineString<double>& lineString) { + static auto& javaClass = jni::Class<LineString>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<LineString>(jni::Object<java::util::List>)>(env, "fromLngLats"); - auto jLineString = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jLineString; + return javaClass.Call(env, method, asPointsList(env, lineString)); } -mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object<LineString> jLineString) { +mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, const jni::Object<LineString>& jLineString) { mapbox::geojson::line_string lineString; if (jLineString) { - auto jPointList = LineString::coordinates(env, jLineString); - lineString = LineString::convert(env, jPointList); - jni::DeleteLocalRef(env, jPointList); + lineString = LineString::convert(env, LineString::coordinates(env, jLineString)); } return lineString; } -mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object<java::util::List/*<Point>*/> jPointList) { +mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<Point>*/>& jPointList) { mapbox::geojson::line_string lineString; if (jPointList) { @@ -38,29 +33,23 @@ mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object<j lineString.reserve(size); for (std::size_t i = 0; i < size; i++) { - auto jPoint = jPointArray.Get(env, i); - lineString.push_back(Point::convert(env, jPoint)); - jni::DeleteLocalRef(env, jPoint); + lineString.push_back(Point::convert(env, jPointArray.Get(env, i))); } - - jni::DeleteLocalRef(env, jPointArray); } return lineString; } -jni::Object<java::util::List> LineString::coordinates(jni::JNIEnv &env, jni::Object<LineString> jLineString) { - static auto method = LineString::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); +jni::Local<jni::Object<java::util::List>> LineString::coordinates(jni::JNIEnv &env, const jni::Object<LineString>& jLineString) { + static auto& javaClass = jni::Class<LineString>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); return jLineString.Call(env, method); } void LineString::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<LineString>::Find(env).NewGlobalRef(env).release(); + jni::Class<LineString>::Singleton(env); } -jni::Class<LineString> LineString::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geojson/line_string.hpp b/platform/android/src/geojson/line_string.hpp index 98dc41464..906d809fa 100644 --- a/platform/android/src/geojson/line_string.hpp +++ b/platform/android/src/geojson/line_string.hpp @@ -14,21 +14,19 @@ namespace android { namespace geojson { -class LineString : public Geometry { +class LineString { public: + using SuperTag = Geometry; static constexpr auto Name() { return "com/mapbox/geojson/LineString"; }; - static constexpr auto Type() { return "LineString"; }; - static jni::Object<LineString> New(jni::JNIEnv&, const mbgl::LineString<double>&); - - static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object<LineString>); + static jni::Local<jni::Object<LineString>> New(jni::JNIEnv&, const mbgl::LineString<double>&); - static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object<java::util::List/*<Point>*/>); + static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object<LineString>&); - static jni::Object<java::util::List> coordinates(jni::JNIEnv&, jni::Object<LineString>); + static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object<java::util::List/*<Point>*/>&); - static jni::Class<LineString> javaClass; + static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<LineString>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/multi_line_string.cpp b/platform/android/src/geojson/multi_line_string.cpp index 4a6ea37dd..1aaf53c01 100644 --- a/platform/android/src/geojson/multi_line_string.cpp +++ b/platform/android/src/geojson/multi_line_string.cpp @@ -7,29 +7,24 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object<MultiLineString> MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString<double>& multiLineString) { - auto jList = asPointsListsList(env, multiLineString); - +jni::Local<jni::Object<MultiLineString>> MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString<double>& multiLineString) { + static auto& javaClass = jni::Class<MultiLineString>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<MultiLineString> (jni::Object<java::util::List>)>(env, "fromLngLats"); - auto jMultiLineString = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jMultiLineString; + return javaClass.Call(env, method, asPointsListsList(env, multiLineString)); } -mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jni::Object<MultiLineString> jMultiLineString) { +mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, const jni::Object<MultiLineString>& jMultiLineString) { mapbox::geojson::multi_line_string multiLineString; if (jMultiLineString) { - auto jPointListsList = MultiLineString::coordinates(env, jMultiLineString); - multiLineString = MultiLineString::convert(env, jPointListsList); - jni::DeleteLocalRef(env, jPointListsList); + multiLineString = MultiLineString::convert(env, MultiLineString::coordinates(env, jMultiLineString)); } return multiLineString; } -mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jni::Object<java::util::List/*<java::util::List<Point>>*/> jPointListsList) { +mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<java::util::List<Point>>*/>& jPointListsList) { mapbox::geojson::multi_line_string multiLineString; if (jPointListsList) { @@ -39,29 +34,23 @@ mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jn multiLineString.reserve(size); for (std::size_t i = 0; i < size; i++) { - auto jPointsList = jPositionListsArray.Get(env, i); - multiLineString.push_back(LineString::convert(env, jPointsList)); - jni::DeleteLocalRef(env, jPointsList); + multiLineString.push_back(LineString::convert(env, jPositionListsArray.Get(env, i))); } - - jni::DeleteLocalRef(env, jPositionListsArray); } return multiLineString; } -jni::Object<java::util::List> MultiLineString::coordinates(jni::JNIEnv &env, jni::Object<MultiLineString> jLineString) { - static auto method = MultiLineString::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); +jni::Local<jni::Object<java::util::List>> MultiLineString::coordinates(jni::JNIEnv &env, const jni::Object<MultiLineString>& jLineString) { + static auto& javaClass = jni::Class<MultiLineString>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); return jLineString.Call(env, method); } void MultiLineString::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<MultiLineString>::Find(env).NewGlobalRef(env).release(); + jni::Class<MultiLineString>::Singleton(env); } -jni::Class<MultiLineString> MultiLineString::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geojson/multi_line_string.hpp b/platform/android/src/geojson/multi_line_string.hpp index 934a0cb6b..65ce43bd1 100644 --- a/platform/android/src/geojson/multi_line_string.hpp +++ b/platform/android/src/geojson/multi_line_string.hpp @@ -12,21 +12,19 @@ namespace mbgl { namespace android { namespace geojson { -class MultiLineString : public Geometry { +class MultiLineString { public: + using SuperTag = Geometry; static constexpr auto Name() { return "com/mapbox/geojson/MultiLineString"; }; - static constexpr auto Type() { return "MultiLineString"; }; - static jni::Object<MultiLineString> New(jni::JNIEnv&, const mbgl::MultiLineString<double>&); - - static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object<MultiLineString>); + static jni::Local<jni::Object<MultiLineString>> New(jni::JNIEnv&, const mbgl::MultiLineString<double>&); - static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object<java::util::List/*<java::util::List<Point>>*/>); + static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, const jni::Object<MultiLineString>&); - static jni::Object<java::util::List> coordinates(jni::JNIEnv&, jni::Object<MultiLineString>); + static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, const jni::Object<java::util::List/*<java::util::List<Point>>*/>&); - static jni::Class<MultiLineString> javaClass; + static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiLineString>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/multi_point.cpp b/platform/android/src/geojson/multi_point.cpp index 6f6254120..d530ef721 100644 --- a/platform/android/src/geojson/multi_point.cpp +++ b/platform/android/src/geojson/multi_point.cpp @@ -8,40 +8,34 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object<MultiPoint> MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint<double>& multiPoint) { - auto jList = asPointsList(env, multiPoint); - +jni::Local<jni::Object<MultiPoint>> MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint<double>& multiPoint) { + static auto& javaClass = jni::Class<MultiPoint>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<MultiPoint>(jni::Object<java::util::List>)>(env, "fromLngLats"); - auto jMultiPoint = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jMultiPoint; + return javaClass.Call(env, method, asPointsList(env, multiPoint)); } -mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv &env, jni::Object<MultiPoint> jMultiPoint) { +mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv& env, const jni::Object<MultiPoint>& jMultiPoint) { mapbox::geojson::multi_point multiPoint; if (jMultiPoint) { - auto jPointListsList = MultiPoint::coordinates(env, jMultiPoint); - multiPoint = convertExplicit<mapbox::geojson::multi_point>(LineString::convert(env, jPointListsList)); - jni::DeleteLocalRef(env, jPointListsList); + multiPoint = convertExplicit<mapbox::geojson::multi_point>( + LineString::convert(env, MultiPoint::coordinates(env, jMultiPoint))); } return multiPoint; } -jni::Object<java::util::List> MultiPoint::coordinates(jni::JNIEnv &env, jni::Object<MultiPoint> jMultiPoint) { - static auto method = MultiPoint::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); +jni::Local<jni::Object<java::util::List>> MultiPoint::coordinates(jni::JNIEnv& env, const jni::Object<MultiPoint>& jMultiPoint) { + static auto& javaClass = jni::Class<MultiPoint>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); return jMultiPoint.Call(env, method); } void MultiPoint::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<MultiPoint>::Find(env).NewGlobalRef(env).release(); + jni::Class<MultiPoint>::Singleton(env); } -jni::Class<MultiPoint> MultiPoint::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geojson/multi_point.hpp b/platform/android/src/geojson/multi_point.hpp index cfe80cd34..a3ca49b73 100644 --- a/platform/android/src/geojson/multi_point.hpp +++ b/platform/android/src/geojson/multi_point.hpp @@ -13,19 +13,17 @@ namespace mbgl { namespace android { namespace geojson { -class MultiPoint : public Geometry { +class MultiPoint { public: + using SuperTag = Geometry; static constexpr auto Name() { return "com/mapbox/geojson/MultiPoint"; }; - static constexpr auto Type() { return "MultiPoint"; }; - static jni::Object<MultiPoint> New(jni::JNIEnv&, const mbgl::MultiPoint<double>&); - - static mapbox::geojson::multi_point convert(jni::JNIEnv&, jni::Object<MultiPoint>); + static jni::Local<jni::Object<MultiPoint>> New(jni::JNIEnv&, const mbgl::MultiPoint<double>&); - static jni::Object<java::util::List> coordinates(jni::JNIEnv&, jni::Object<MultiPoint>); + static mapbox::geojson::multi_point convert(jni::JNIEnv&, const jni::Object<MultiPoint>&); - static jni::Class<MultiPoint> javaClass; + static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiPoint>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/multi_polygon.cpp b/platform/android/src/geojson/multi_polygon.cpp index cc872d495..3c5c3ec33 100644 --- a/platform/android/src/geojson/multi_polygon.cpp +++ b/platform/android/src/geojson/multi_polygon.cpp @@ -7,29 +7,20 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object<MultiPolygon> MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon<double>& multiPolygon) { - auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, multiPolygon.size(), java::util::List::javaClass); +jni::Local<jni::Object<MultiPolygon>> MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon<double>& multiPolygon) { + static auto& javaClass = jni::Class<MultiPolygon>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<MultiPolygon> (jni::Object<java::util::List>)>(env, "fromLngLats"); + + auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, multiPolygon.size()); for (size_t i = 0; i < multiPolygon.size(); i++) { - auto& geometry = multiPolygon.at(i); - auto jPolygon = asPointsListsList(env, geometry); - jarray.Set(env, i, jPolygon); - jni::DeleteLocalRef(env, jPolygon); + jarray.Set(env, i, asPointsListsList(env, multiPolygon.at(i))); } - // Turn into array list - auto jList = java::util::Arrays::asList(env, jarray); - jni::DeleteLocalRef(env, jarray); - - // create the MultiPolygon - static auto method = javaClass.GetStaticMethod<jni::Object<MultiPolygon> (jni::Object<java::util::List>)>(env, "fromLngLats"); - auto jMultiPolygon = javaClass.Call(env, method, jList); - - jni::DeleteLocalRef(env, jList); - return jMultiPolygon; + return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray)); } -mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv &env, jni::Object<MultiPolygon> jMultiPolygon) { +mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv& env, const jni::Object<MultiPolygon>& jMultiPolygon) { mapbox::geojson::multi_polygon multiPolygon; if (jMultiPolygon) { @@ -40,30 +31,23 @@ mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv &env, jni::Obje multiPolygon.reserve(size); for (size_t i = 0; i < size; i++) { - auto jPositionListsList = jPointListsListArray.Get(env, i); - multiPolygon.push_back(Polygon::convert(env, jPositionListsList)); - jni::DeleteLocalRef(env, jPositionListsList); + multiPolygon.push_back(Polygon::convert(env, jPointListsListArray.Get(env, i))); } - - jni::DeleteLocalRef(env, jPointListsListArray); - jni::DeleteLocalRef(env, jPointListsListList); } return multiPolygon; } -jni::Object<java::util::List> MultiPolygon::coordinates(jni::JNIEnv &env, jni::Object<MultiPolygon> jPolygon) { - static auto method = MultiPolygon::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); +jni::Local<jni::Object<java::util::List>> MultiPolygon::coordinates(jni::JNIEnv& env, const jni::Object<MultiPolygon>& jPolygon) { + static auto& javaClass = jni::Class<MultiPolygon>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); return jPolygon.Call(env, method); } void MultiPolygon::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<MultiPolygon>::Find(env).NewGlobalRef(env).release(); + jni::Class<MultiPolygon>::Singleton(env); } -jni::Class<MultiPolygon> MultiPolygon::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geojson/multi_polygon.hpp b/platform/android/src/geojson/multi_polygon.hpp index b4657af09..fd7b08016 100644 --- a/platform/android/src/geojson/multi_polygon.hpp +++ b/platform/android/src/geojson/multi_polygon.hpp @@ -12,19 +12,17 @@ namespace mbgl { namespace android { namespace geojson { -class MultiPolygon : public Geometry { +class MultiPolygon { public: + using SuperTag = Geometry; static constexpr auto Name() { return "com/mapbox/geojson/MultiPolygon"; }; - static constexpr auto Type() { return "MultiPolygon"; }; - static jni::Object<MultiPolygon> New(jni::JNIEnv&, const mbgl::MultiPolygon<double>&); - - static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, jni::Object<MultiPolygon>); + static jni::Local<jni::Object<MultiPolygon>> New(jni::JNIEnv&, const mbgl::MultiPolygon<double>&); - static jni::Object<java::util::List> coordinates(jni::JNIEnv&, jni::Object<MultiPolygon>); + static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, const jni::Object<MultiPolygon>&); - static jni::Class<MultiPolygon> javaClass; + static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiPolygon>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/point.cpp b/platform/android/src/geojson/point.cpp index 8a9656ea1..2000447c0 100644 --- a/platform/android/src/geojson/point.cpp +++ b/platform/android/src/geojson/point.cpp @@ -1,62 +1,34 @@ #include "point.hpp" -#include "../java/util.hpp" -#include "../java_types.hpp" -#include "../style/value.hpp" namespace mbgl { namespace android { namespace geojson { -jni::Object<Point> Point::New(jni::JNIEnv& env, const mbgl::Point<double>& point) { +jni::Local<jni::Object<Point>> Point::New(jni::JNIEnv& env, const mbgl::Point<double>& point) { + static auto& javaClass = jni::Class<Point>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<Point> (jni::jdouble, jni::jdouble)>(env, "fromLngLat"); return javaClass.Call(env, method, point.x, point.y); } -mapbox::geojson::point Point::convert(jni::JNIEnv &env, jni::Object<Point> jPoint) { - mapbox::geojson::point point; +mbgl::Point<double> Point::convert(jni::JNIEnv &env, const jni::Object<Point>& jPoint) { + static auto& javaClass = jni::Class<Point>::Singleton(env); + static auto longitude = javaClass.GetMethod<jni::jdouble ()>(env, "longitude"); + static auto latitude = javaClass.GetMethod<jni::jdouble ()>(env, "latitude"); - if (jPoint) { - auto jDoubleList = Point::coordinates(env, jPoint); - point = Point::convert(env, jDoubleList); - jni::DeleteLocalRef(env, jDoubleList); + if (!jPoint) { + return {}; } - return point; -} - -mapbox::geojson::point Point::convert(jni::JNIEnv &env, jni::Object<java::util::List/*<Double>*/> jDoubleList) { - mapbox::geojson::point point; - - if (jDoubleList) { - auto jDoubleArray = java::util::List::toArray<jobject>(env, jDoubleList); - - auto lonObject = jDoubleArray.Get(env, 0); - auto latObject = jDoubleArray.Get(env, 1); - - point.x = jni::CallMethod<jni::jdouble>(env, lonObject, - *java::Number::doubleValueMethodId); - point.y = jni::CallMethod<jni::jdouble>(env, latObject, - *java::Number::doubleValueMethodId); - - jni::DeleteLocalRef(env, lonObject); - jni::DeleteLocalRef(env, latObject); - jni::DeleteLocalRef(env, jDoubleArray); - } - return point; -} - -jni::Object<java::util::List> Point::coordinates(jni::JNIEnv &env, jni::Object<Point> jPoint) { - static auto method = Point::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); - return jPoint.Call(env, method); + return { + jPoint.Call(env, longitude), + jPoint.Call(env, latitude) + }; } void Point::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Point>::Find(env).NewGlobalRef(env).release(); + jni::Class<Point>::Singleton(env); } -jni::Class<Point> Point::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl diff --git a/platform/android/src/geojson/point.hpp b/platform/android/src/geojson/point.hpp index 627bd1b64..b5d71ecae 100644 --- a/platform/android/src/geojson/point.hpp +++ b/platform/android/src/geojson/point.hpp @@ -1,9 +1,7 @@ #pragma once -#include <mbgl/util/geojson.hpp> -#include <mbgl/util/noncopyable.hpp> +#include <mbgl/util/geometry.hpp> -#include "../java/util.hpp" #include "geometry.hpp" #include <jni/jni.hpp> @@ -12,21 +10,14 @@ namespace mbgl { namespace android { namespace geojson { -class Point : public Geometry { +class Point { public: + using SuperTag = Geometry; static constexpr auto Name() { return "com/mapbox/geojson/Point"; }; - static constexpr auto Type() { return "Point"; }; - static jni::Object<Point> New(jni::JNIEnv&, const mbgl::Point<double>&); - - static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object<Point>); - - static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object<java::util::List/*<Double>*/>); - - static jni::Object<java::util::List> coordinates(JNIEnv&, jni::Object<Point>); - - static jni::Class<Point> javaClass; + static jni::Local<jni::Object<Point>> New(jni::JNIEnv&, const mbgl::Point<double>&); + static mbgl::Point<double> convert(jni::JNIEnv&, const jni::Object<Point>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/polygon.cpp b/platform/android/src/geojson/polygon.cpp index 96058b63b..4437d134a 100644 --- a/platform/android/src/geojson/polygon.cpp +++ b/platform/android/src/geojson/polygon.cpp @@ -8,29 +8,24 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object<Polygon> Polygon::New(jni::JNIEnv& env, const mbgl::Polygon<double>& polygon) { - auto jList = asPointsListsList(env, polygon); - +jni::Local<jni::Object<Polygon>> Polygon::New(jni::JNIEnv& env, const mbgl::Polygon<double>& polygon) { + static auto& javaClass = jni::Class<Polygon>::Singleton(env); static auto method = javaClass.GetStaticMethod<jni::Object<Polygon> (jni::Object<java::util::List>)>(env, "fromLngLats"); - auto jPolygon = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jPolygon; + return javaClass.Call(env, method, asPointsListsList(env, polygon)); } -mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object<Polygon> jPolygon) { +mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, const jni::Object<Polygon>& jPolygon) { mapbox::geojson::polygon polygon; if (jPolygon) { - auto jPositionListsList = Polygon::coordinates(env, jPolygon); - polygon = Polygon::convert(env, jPositionListsList); - jni::DeleteLocalRef(env, jPositionListsList); + polygon = Polygon::convert(env, Polygon::coordinates(env, jPolygon)); } return polygon; } -mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object<java::util::List/*<java::util::List<Point>>*/> jPointListsList) { +mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<java::util::List<Point>>*/>& jPointListsList) { mapbox::geojson::polygon polygon; if (jPointListsList) { @@ -45,18 +40,16 @@ mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object<java::ut } -jni::Object<java::util::List> Polygon::coordinates(jni::JNIEnv &env, jni::Object<Polygon> jPolygon) { - static auto method = Polygon::javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); +jni::Local<jni::Object<java::util::List>> Polygon::coordinates(jni::JNIEnv &env, const jni::Object<Polygon>& jPolygon) { + static auto& javaClass = jni::Class<Polygon>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates"); return jPolygon.Call(env, method); } void Polygon::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Polygon>::Find(env).NewGlobalRef(env).release(); + jni::Class<Polygon>::Singleton(env); } -jni::Class<Polygon> Polygon::javaClass; - } // namespace geojson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geojson/polygon.hpp b/platform/android/src/geojson/polygon.hpp index f3c23b4d7..8e1761fed 100644 --- a/platform/android/src/geojson/polygon.hpp +++ b/platform/android/src/geojson/polygon.hpp @@ -13,21 +13,19 @@ namespace mbgl { namespace android { namespace geojson { -class Polygon : public Geometry { +class Polygon { public: + using SuperTag = Geometry; static constexpr auto Name() { return "com/mapbox/geojson/Polygon"; }; - static constexpr auto Type() { return "Polygon"; }; - static jni::Object<Polygon> New(jni::JNIEnv&, const mbgl::Polygon<double>&); - - static mapbox::geojson::polygon convert(jni::JNIEnv &, jni::Object<Polygon>); + static jni::Local<jni::Object<Polygon>> New(jni::JNIEnv&, const mbgl::Polygon<double>&); - static mapbox::geojson::polygon convert(jni::JNIEnv&, jni::Object<java::util::List/*<java::util::List<Point>>*/>); + static mapbox::geojson::polygon convert(jni::JNIEnv &, const jni::Object<Polygon>&); - static jni::Object<java::util::List> coordinates(jni::JNIEnv&, jni::Object<Polygon>); + static mapbox::geojson::polygon convert(jni::JNIEnv&, const jni::Object<java::util::List/*<java::util::List<Point>>*/>&); - static jni::Class<Polygon> javaClass; + static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<Polygon>&); static void registerNative(jni::JNIEnv &); }; diff --git a/platform/android/src/geojson/util.hpp b/platform/android/src/geojson/util.hpp index 5e6d90a95..59154516f 100644 --- a/platform/android/src/geojson/util.hpp +++ b/platform/android/src/geojson/util.hpp @@ -23,36 +23,28 @@ To convertExplicit(From&& src) { * Geometry -> List<Point> */ template <class T> -static jni::Object<java::util::List> asPointsList(jni::JNIEnv& env, const T& pointsList) { - auto jarray = jni::Array<jni::Object<Point>>::New(env, pointsList.size(), Point::javaClass); +static jni::Local<jni::Object<java::util::List>> asPointsList(jni::JNIEnv& env, const T& pointsList) { + auto jarray = jni::Array<jni::Object<Point>>::New(env, pointsList.size()); for (jni::jsize i = 0; i < pointsList.size(); i++) { - auto jPoint = Point::New(env, pointsList.at(i)); - jarray.Set(env, i, jPoint); - jni::DeleteLocalRef(env, jPoint); + jarray.Set(env, i, Point::New(env, pointsList.at(i))); } - auto jList = java::util::Arrays::asList(env, jarray); - jni::DeleteLocalRef(env, jarray); - return jList; + return java::util::Arrays::asList(env, jarray); } /** * Geometry -> List<List<Point>> */ template <class SHAPE> -static jni::Object<java::util::List> asPointsListsList(JNIEnv& env, SHAPE value) { - auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, value.size(), java::util::List::javaClass); +static jni::Local<jni::Object<java::util::List>> asPointsListsList(JNIEnv& env, const SHAPE& value) { + auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, value.size()); - for (size_t i = 0; i < value.size(); i = i + 1) { - auto pointsList = asPointsList(env, value[i]); - jarray.Set(env, i, pointsList); - jni::DeleteLocalRef(env, pointsList); + for (size_t i = 0; i < value.size(); i++) { + jarray.Set(env, i, asPointsList(env, value[i])); } - auto jList = java::util::Arrays::asList(env, jarray); - jni::DeleteLocalRef(env, jarray); - return jList; + return java::util::Arrays::asList(env, jarray); } } // namespace geojson diff --git a/platform/android/src/geometry/lat_lng.cpp b/platform/android/src/geometry/lat_lng.cpp index 0bf6ea7ad..5d8313cb2 100644 --- a/platform/android/src/geometry/lat_lng.cpp +++ b/platform/android/src/geometry/lat_lng.cpp @@ -3,29 +3,27 @@ namespace mbgl { namespace android { -jni::Object<LatLng> LatLng::New(jni::JNIEnv& env, const mbgl::LatLng& latLng) { - static auto constructor = LatLng::javaClass.GetConstructor<double, double>(env); - return LatLng::javaClass.New(env, constructor, latLng.latitude(), latLng.longitude()); +jni::Local<jni::Object<LatLng>> LatLng::New(jni::JNIEnv& env, const mbgl::LatLng& latLng) { + static auto& javaClass = jni::Class<LatLng>::Singleton(env); + static auto constructor = javaClass.GetConstructor<double, double>(env); + return javaClass.New(env, constructor, latLng.latitude(), latLng.longitude()); } -mbgl::Point<double> LatLng::getGeometry(jni::JNIEnv& env, jni::Object<LatLng> latLng) { - static auto latitudeField = LatLng::javaClass.GetField<jni::jdouble>(env, "latitude"); - static auto longitudeField = LatLng::javaClass.GetField<jni::jdouble>(env, "longitude"); +mbgl::Point<double> LatLng::getGeometry(jni::JNIEnv& env, const jni::Object<LatLng>& latLng) { + static auto& javaClass = jni::Class<LatLng>::Singleton(env); + static auto latitudeField = javaClass.GetField<jni::jdouble>(env, "latitude"); + static auto longitudeField = javaClass.GetField<jni::jdouble>(env, "longitude"); return mbgl::Point<double>(latLng.Get(env, longitudeField), latLng.Get(env, latitudeField)); } -mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, jni::Object<LatLng> latLng) { +mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, const jni::Object<LatLng>& latLng) { auto point = LatLng::getGeometry(env, latLng); return mbgl::LatLng(point.y, point.x); } void LatLng::registerNative(jni::JNIEnv& env) { - // Lookup the class - LatLng::javaClass = *jni::Class<LatLng>::Find(env).NewGlobalRef(env).release(); + jni::Class<LatLng>::Singleton(env); } -jni::Class<LatLng> LatLng::javaClass; - - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geometry/lat_lng.hpp b/platform/android/src/geometry/lat_lng.hpp index b2f12c8dc..30b7db1ef 100644 --- a/platform/android/src/geometry/lat_lng.hpp +++ b/platform/android/src/geometry/lat_lng.hpp @@ -14,16 +14,14 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLng"; }; - static jni::Object<LatLng> New(jni::JNIEnv&, const mbgl::LatLng&); + static jni::Local<jni::Object<LatLng>> New(jni::JNIEnv&, const mbgl::LatLng&); - static mbgl::Point<double> getGeometry(jni::JNIEnv&, jni::Object<LatLng>); + static mbgl::Point<double> getGeometry(jni::JNIEnv&, const jni::Object<LatLng>&); - static mbgl::LatLng getLatLng(jni::JNIEnv&, jni::Object<LatLng>); + static mbgl::LatLng getLatLng(jni::JNIEnv&, const jni::Object<LatLng>&); - static jni::Class<LatLng> javaClass; static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/geometry/lat_lng_bounds.cpp b/platform/android/src/geometry/lat_lng_bounds.cpp index 827ee52e9..d76ff5b36 100644 --- a/platform/android/src/geometry/lat_lng_bounds.cpp +++ b/platform/android/src/geometry/lat_lng_bounds.cpp @@ -3,16 +3,18 @@ namespace mbgl { namespace android { -jni::Object<LatLngBounds> LatLngBounds::New(jni::JNIEnv& env, mbgl::LatLngBounds bounds) { - static auto constructor = LatLngBounds::javaClass.GetConstructor<double, double, double, double>(env); - return LatLngBounds::javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west()); +jni::Local<jni::Object<LatLngBounds>> LatLngBounds::New(jni::JNIEnv& env, mbgl::LatLngBounds bounds) { + static auto& javaClass = jni::Class<LatLngBounds>::Singleton(env); + static auto constructor = javaClass.GetConstructor<double, double, double, double>(env); + return javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west()); } -mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, jni::Object<LatLngBounds> bounds) { - static auto swLatField = LatLngBounds::javaClass.GetField<jni::jdouble>(env, "latitudeSouth"); - static auto swLonField = LatLngBounds::javaClass.GetField<jni::jdouble>(env, "longitudeWest"); - static auto neLatField = LatLngBounds::javaClass.GetField<jni::jdouble>(env, "latitudeNorth"); - static auto neLonField = LatLngBounds::javaClass.GetField<jni::jdouble>(env, "longitudeEast"); +mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, const jni::Object<LatLngBounds>& bounds) { + static auto& javaClass = jni::Class<LatLngBounds>::Singleton(env); + static auto swLatField = javaClass.GetField<jni::jdouble>(env, "latitudeSouth"); + static auto swLonField = javaClass.GetField<jni::jdouble>(env, "longitudeWest"); + static auto neLatField = javaClass.GetField<jni::jdouble>(env, "latitudeNorth"); + static auto neLonField = javaClass.GetField<jni::jdouble>(env, "longitudeEast"); mbgl::LatLng sw = { bounds.Get(env, swLatField), bounds.Get(env, swLonField) }; mbgl::LatLng ne = { bounds.Get(env, neLatField), bounds.Get(env, neLonField) }; @@ -23,12 +25,8 @@ mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, jni::Object<L } void LatLngBounds::registerNative(jni::JNIEnv& env) { - // Lookup the class - LatLngBounds::javaClass = *jni::Class<LatLngBounds>::Find(env).NewGlobalRef(env).release(); + jni::Class<LatLngBounds>::Singleton(env); } -jni::Class<LatLngBounds> LatLngBounds::javaClass; - - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geometry/lat_lng_bounds.hpp b/platform/android/src/geometry/lat_lng_bounds.hpp index 1c853e4b6..d51026711 100644 --- a/platform/android/src/geometry/lat_lng_bounds.hpp +++ b/platform/android/src/geometry/lat_lng_bounds.hpp @@ -14,14 +14,11 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLngBounds"; }; - static jni::Object<LatLngBounds> New(jni::JNIEnv&, mbgl::LatLngBounds); + static jni::Local<jni::Object<LatLngBounds>> New(jni::JNIEnv&, mbgl::LatLngBounds); - static mbgl::LatLngBounds getLatLngBounds(jni::JNIEnv&, jni::Object<LatLngBounds>); - - static jni::Class<LatLngBounds> javaClass; + static mbgl::LatLngBounds getLatLngBounds(jni::JNIEnv&, const jni::Object<LatLngBounds>&); static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/geometry/lat_lng_quad.cpp b/platform/android/src/geometry/lat_lng_quad.cpp index 2b36139e1..1a1e49048 100644 --- a/platform/android/src/geometry/lat_lng_quad.cpp +++ b/platform/android/src/geometry/lat_lng_quad.cpp @@ -4,20 +4,22 @@ namespace mbgl { namespace android { -jni::Object<LatLngQuad> LatLngQuad::New(jni::JNIEnv& env, std::array<mbgl::LatLng, 4> coordinates) { - static auto quadConstructor = LatLngQuad::javaClass.GetConstructor<jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>>(env); - return LatLngQuad::javaClass.New(env, quadConstructor, +jni::Local<jni::Object<LatLngQuad>> LatLngQuad::New(jni::JNIEnv& env, std::array<mbgl::LatLng, 4> coordinates) { + static auto& javaClass = jni::Class<LatLngQuad>::Singleton(env); + static auto quadConstructor = javaClass.GetConstructor<jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>>(env); + return javaClass.New(env, quadConstructor, LatLng::New(env, coordinates[0]), LatLng::New(env, coordinates[1]), LatLng::New(env, coordinates[2]), LatLng::New(env, coordinates[3])); } -std::array<mbgl::LatLng, 4> LatLngQuad::getLatLngArray(jni::JNIEnv& env, jni::Object<LatLngQuad> quad) { - static auto topLeftField = LatLngQuad::javaClass.GetField <jni::Object<LatLng>>(env, "topLeft"); - static auto topRightField = LatLngQuad::javaClass.GetField <jni::Object<LatLng>>(env, "topRight"); - static auto bottomRightField = LatLngQuad::javaClass.GetField <jni::Object<LatLng>>(env, "bottomRight"); - static auto bottomLeftField = LatLngQuad::javaClass.GetField <jni::Object<LatLng>>(env, "bottomLeft"); +std::array<mbgl::LatLng, 4> LatLngQuad::getLatLngArray(jni::JNIEnv& env, const jni::Object<LatLngQuad>& quad) { + static auto& javaClass = jni::Class<LatLngQuad>::Singleton(env); + static auto topLeftField = javaClass.GetField <jni::Object<LatLng>>(env, "topLeft"); + static auto topRightField = javaClass.GetField <jni::Object<LatLng>>(env, "topRight"); + static auto bottomRightField = javaClass.GetField <jni::Object<LatLng>>(env, "bottomRight"); + static auto bottomLeftField = javaClass.GetField <jni::Object<LatLng>>(env, "bottomLeft"); return std::array < mbgl::LatLng, 4 > {{ LatLng::getLatLng(env, quad.Get(env, topLeftField)), @@ -28,12 +30,8 @@ std::array<mbgl::LatLng, 4> LatLngQuad::getLatLngArray(jni::JNIEnv& env, jni::Ob } void LatLngQuad::registerNative(jni::JNIEnv& env) { - // Lookup the class - LatLngQuad::javaClass = *jni::Class<LatLngQuad>::Find(env).NewGlobalRef(env).release(); + jni::Class<LatLngQuad>::Singleton(env); } -jni::Class<LatLngQuad> LatLngQuad::javaClass; - - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geometry/lat_lng_quad.hpp b/platform/android/src/geometry/lat_lng_quad.hpp index 8f8c9abee..f6560b57b 100644 --- a/platform/android/src/geometry/lat_lng_quad.hpp +++ b/platform/android/src/geometry/lat_lng_quad.hpp @@ -15,14 +15,11 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLngQuad"; }; - static jni::Object<LatLngQuad> New(jni::JNIEnv&, std::array<mbgl::LatLng, 4>); + static jni::Local<jni::Object<LatLngQuad>> New(jni::JNIEnv&, std::array<mbgl::LatLng, 4>); - static std::array<mbgl::LatLng, 4> getLatLngArray(jni::JNIEnv&, jni::Object<LatLngQuad>); - - static jni::Class<LatLngQuad> javaClass; + static std::array<mbgl::LatLng, 4> getLatLngArray(jni::JNIEnv&, const jni::Object<LatLngQuad>&); static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/geometry/projected_meters.cpp b/platform/android/src/geometry/projected_meters.cpp index f3d9d1b0e..e079de006 100644 --- a/platform/android/src/geometry/projected_meters.cpp +++ b/platform/android/src/geometry/projected_meters.cpp @@ -3,18 +3,15 @@ namespace mbgl { namespace android { -jni::Object<ProjectedMeters> ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) { - static auto constructor = ProjectedMeters::javaClass.GetConstructor<double, double>(env); - return ProjectedMeters::javaClass.New(env, constructor, northing, easting); +jni::Local<jni::Object<ProjectedMeters>> ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) { + static auto& javaClass = jni::Class<ProjectedMeters>::Singleton(env); + static auto constructor = javaClass.GetConstructor<double, double>(env); + return javaClass.New(env, constructor, northing, easting); } void ProjectedMeters::registerNative(jni::JNIEnv& env) { - // Lookup the class - ProjectedMeters::javaClass = *jni::Class<ProjectedMeters>::Find(env).NewGlobalRef(env).release(); + jni::Class<ProjectedMeters>::Singleton(env); } -jni::Class<ProjectedMeters> ProjectedMeters::javaClass; - - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/geometry/projected_meters.hpp b/platform/android/src/geometry/projected_meters.hpp index 9b70967b5..baad1efc8 100644 --- a/platform/android/src/geometry/projected_meters.hpp +++ b/platform/android/src/geometry/projected_meters.hpp @@ -10,17 +10,12 @@ namespace android { class ProjectedMeters : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/ProjectedMeters"; }; - static jni::Object<ProjectedMeters> New(jni::JNIEnv&, double, double); - - static jni::Class<ProjectedMeters> javaClass; + static jni::Local<jni::Object<ProjectedMeters>> New(jni::JNIEnv&, double, double); static void registerNative(jni::JNIEnv&); - }; - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/graphics/pointf.cpp b/platform/android/src/graphics/pointf.cpp index 3f854da2e..2fc762d6e 100644 --- a/platform/android/src/graphics/pointf.cpp +++ b/platform/android/src/graphics/pointf.cpp @@ -4,24 +4,22 @@ namespace mbgl { namespace android { -jni::Object<PointF> PointF::New(jni::JNIEnv& env, float x, float y) { - static auto constructor = PointF::javaClass.GetConstructor<float, float>(env); - return PointF::javaClass.New(env, constructor, x, y); +jni::Local<jni::Object<PointF>> PointF::New(jni::JNIEnv& env, float x, float y) { + static auto& javaClass = jni::Class<PointF>::Singleton(env); + static auto constructor = javaClass.GetConstructor<float, float>(env); + return javaClass.New(env, constructor, x, y); } -mbgl::ScreenCoordinate PointF::getScreenCoordinate(jni::JNIEnv& env, jni::Object<PointF> point) { - static auto xField = PointF::javaClass.GetField<jni::jfloat>(env, "x"); - static auto yField = PointF::javaClass.GetField<jni::jfloat>(env, "y"); +mbgl::ScreenCoordinate PointF::getScreenCoordinate(jni::JNIEnv& env, const jni::Object<PointF>& point) { + static auto& javaClass = jni::Class<PointF>::Singleton(env); + static auto xField = javaClass.GetField<jni::jfloat>(env, "x"); + static auto yField = javaClass.GetField<jni::jfloat>(env, "y"); return mbgl::ScreenCoordinate{point.Get(env, xField), point.Get(env, yField)}; } void PointF::registerNative(jni::JNIEnv& env) { - // Lookup the class - PointF::javaClass = *jni::Class<PointF>::Find(env).NewGlobalRef(env).release(); + jni::Class<PointF>::Singleton(env); } -jni::Class<PointF> PointF::javaClass; - - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/graphics/pointf.hpp b/platform/android/src/graphics/pointf.hpp index e3ef24dd6..899468b8e 100644 --- a/platform/android/src/graphics/pointf.hpp +++ b/platform/android/src/graphics/pointf.hpp @@ -12,14 +12,11 @@ public: static constexpr auto Name() { return "android/graphics/PointF"; }; - static jni::Object<PointF> New(jni::JNIEnv&, float, float); + static jni::Local<jni::Object<PointF>> New(jni::JNIEnv&, float, float); - static mbgl::ScreenCoordinate getScreenCoordinate(jni::JNIEnv&, jni::Object<PointF>); - - static jni::Class<PointF> javaClass; + static mbgl::ScreenCoordinate getScreenCoordinate(jni::JNIEnv&, const jni::Object<PointF>&); static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/graphics/rectf.cpp b/platform/android/src/graphics/rectf.cpp index 1b375dad1..8f418da03 100644 --- a/platform/android/src/graphics/rectf.cpp +++ b/platform/android/src/graphics/rectf.cpp @@ -3,33 +3,33 @@ namespace mbgl { namespace android { -float RectF::getLeft(jni::JNIEnv& env, jni::Object<RectF> rectf) { - static auto field = RectF::javaClass.GetField<float>(env, "left"); +float RectF::getLeft(jni::JNIEnv& env, const jni::Object<RectF>& rectf) { + static auto& javaClass = jni::Class<RectF>::Singleton(env); + static auto field = javaClass.GetField<float>(env, "left"); return rectf.Get(env, field); } -float RectF::getTop(jni::JNIEnv& env, jni::Object<RectF> rectf) { - static auto field = RectF::javaClass.GetField<float>(env, "top"); +float RectF::getTop(jni::JNIEnv& env, const jni::Object<RectF>& rectf) { + static auto& javaClass = jni::Class<RectF>::Singleton(env); + static auto field = javaClass.GetField<float>(env, "top"); return rectf.Get(env, field); } -float RectF::getRight(jni::JNIEnv& env, jni::Object<RectF> rectf) { - static auto field = RectF::javaClass.GetField<float>(env, "right"); +float RectF::getRight(jni::JNIEnv& env, const jni::Object<RectF>& rectf) { + static auto& javaClass = jni::Class<RectF>::Singleton(env); + static auto field = javaClass.GetField<float>(env, "right"); return rectf.Get(env, field); } -float RectF::getBottom(jni::JNIEnv& env, jni::Object<RectF> rectf) { - static auto field = RectF::javaClass.GetField<float>(env, "bottom"); +float RectF::getBottom(jni::JNIEnv& env, const jni::Object<RectF>& rectf) { + static auto& javaClass = jni::Class<RectF>::Singleton(env); + static auto field = javaClass.GetField<float>(env, "bottom"); return rectf.Get(env, field); } void RectF::registerNative(jni::JNIEnv& env) { - // Lookup the class - RectF::javaClass = *jni::Class<RectF>::Find(env).NewGlobalRef(env).release(); + jni::Class<RectF>::Singleton(env); } -jni::Class<RectF> RectF::javaClass; - - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/graphics/rectf.hpp b/platform/android/src/graphics/rectf.hpp index 0f3a7756d..ba611f226 100644 --- a/platform/android/src/graphics/rectf.hpp +++ b/platform/android/src/graphics/rectf.hpp @@ -12,18 +12,15 @@ public: static constexpr auto Name() { return "android/graphics/RectF"; }; - static float getLeft(jni::JNIEnv&, jni::Object<RectF>); + static float getLeft(jni::JNIEnv&, const jni::Object<RectF>&); - static float getTop(jni::JNIEnv&, jni::Object<RectF>); + static float getTop(jni::JNIEnv&, const jni::Object<RectF>&); - static float getRight(jni::JNIEnv&, jni::Object<RectF>); + static float getRight(jni::JNIEnv&, const jni::Object<RectF>&); - static float getBottom(jni::JNIEnv&, jni::Object<RectF>); - - static jni::Class<RectF> javaClass; + static float getBottom(jni::JNIEnv&, const jni::Object<RectF>&); static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/gson/json_array.cpp b/platform/android/src/gson/json_array.cpp index e8852d77e..8ffa658b7 100644 --- a/platform/android/src/gson/json_array.cpp +++ b/platform/android/src/gson/json_array.cpp @@ -1,32 +1,31 @@ #include "json_array.hpp" - #include "json_element.hpp" namespace mbgl { namespace android { namespace gson { -jni::Object<JsonArray> JsonArray::New(jni::JNIEnv& env, const std::vector<mapbox::geometry::value>& values){ - static auto constructor = JsonArray::javaClass.GetConstructor(env); - static auto addMethod = JsonArray::javaClass.GetMethod<void (jni::Object<JsonElement>)>(env, "add"); +jni::Local<jni::Object<JsonArray>> JsonArray::New(jni::JNIEnv& env, const std::vector<mbgl::Value>& values){ + static auto& javaClass = jni::Class<JsonArray>::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + static auto addMethod = javaClass.GetMethod<void (jni::Object<JsonElement>)>(env, "add"); - auto jsonArray = JsonArray::javaClass.New(env, constructor); + auto jsonArray = javaClass.New(env, constructor); for (const auto &v : values) { - auto jsonElement = JsonElement::New(env, v); - jsonArray.Call(env, addMethod, jsonElement); - jni::DeleteLocalRef(env, jsonElement); + jsonArray.Call(env, addMethod, JsonElement::New(env, v)); } return jsonArray; } -std::vector<mapbox::geometry::value> JsonArray::convert(jni::JNIEnv& env, const jni::Object<JsonArray> jsonArray) { - std::vector<mapbox::geometry::value> values; +std::vector<mbgl::Value> JsonArray::convert(jni::JNIEnv& env, const jni::Object<JsonArray>& jsonArray) { + std::vector<mbgl::Value> values; if (jsonArray) { - static auto getMethod = JsonArray::javaClass.GetMethod<jni::Object<JsonElement> (jni::jint)>(env, "get"); - static auto sizeMethod = JsonArray::javaClass.GetMethod<jni::jint ()>(env, "size"); + static auto& javaClass = jni::Class<JsonArray>::Singleton(env); + static auto getMethod = javaClass.GetMethod<jni::Object<JsonElement> (jni::jint)>(env, "get"); + static auto sizeMethod = javaClass.GetMethod<jni::jint ()>(env, "size"); int size = jsonArray.Call(env, sizeMethod); values.reserve(uint(size)); @@ -36,7 +35,6 @@ std::vector<mapbox::geometry::value> JsonArray::convert(jni::JNIEnv& env, const if (entry) { values.push_back(JsonElement::convert(env, entry)); } - jni::DeleteLocalRef(env, entry); } } @@ -44,12 +42,9 @@ std::vector<mapbox::geometry::value> JsonArray::convert(jni::JNIEnv& env, const } void JsonArray::registerNative(jni::JNIEnv& env) { - // Lookup the class - javaClass = *jni::Class<JsonArray>::Find(env).NewGlobalRef(env).release(); + jni::Class<JsonArray>::Singleton(env); } -jni::Class<JsonArray> JsonArray::javaClass; - } // namespace gson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/gson/json_array.hpp b/platform/android/src/gson/json_array.hpp index c9ae98692..24d5d3d29 100644 --- a/platform/android/src/gson/json_array.hpp +++ b/platform/android/src/gson/json_array.hpp @@ -1,7 +1,6 @@ #pragma once -#include <mapbox/geometry.hpp> -#include <mbgl/util/noncopyable.hpp> +#include "json_element.hpp" #include <jni/jni.hpp> @@ -9,15 +8,13 @@ namespace mbgl { namespace android { namespace gson { -class JsonArray : private mbgl::util::noncopyable { +class JsonArray { public: + using SuperTag = JsonElement; static constexpr auto Name() { return "com/google/gson/JsonArray"; }; - static jni::Object<JsonArray> New(jni::JNIEnv&, const std::vector<mapbox::geometry::value>&); - - static std::vector<mapbox::geometry::value> convert(JNIEnv&, jni::Object<JsonArray>); - - static jni::Class<JsonArray> javaClass; + static jni::Local<jni::Object<JsonArray>> New(jni::JNIEnv&, const std::vector<mbgl::Value>&); + static std::vector<mbgl::Value> convert(JNIEnv&, const jni::Object<JsonArray>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_element.cpp b/platform/android/src/gson/json_element.cpp index 5eaaf531f..7c9a34c03 100644 --- a/platform/android/src/gson/json_element.cpp +++ b/platform/android/src/gson/json_element.cpp @@ -1,90 +1,88 @@ #include "json_element.hpp" - #include "json_array.hpp" #include "json_object.hpp" #include "json_primitive.hpp" -#include <mapbox/geometry/feature.hpp> -#include <mapbox/variant.hpp> - namespace mbgl { namespace android { namespace gson { -/** - * Turn mapbox::geometry::value into Java Gson JsonElement - */ -class JsonElementEvaluator { -public: - - jni::JNIEnv& env; - - jni::Object<JsonElement> operator()(const JsonPrimitive::value value) const { - return jni::Cast(env, JsonPrimitive::New(env, value), JsonElement::javaClass); - } - - jni::Object<JsonElement> operator()(const std::vector<mapbox::geometry::value> &values) const { - return jni::Cast(env, JsonArray::New(env, values), JsonElement::javaClass); - } - - jni::Object<JsonElement> operator()(const std::unordered_map<std::string, mapbox::geometry::value> &values) const { - return jni::Cast(env, JsonObject::New(env, values), JsonElement::javaClass); - } - -}; - - -jni::Object<JsonElement> JsonElement::New(jni::JNIEnv& env, const mapbox::geometry::value& value) { - JsonElementEvaluator evaluator { env } ; - return mapbox::geometry::value::visit(value, evaluator); +jni::Local<jni::Object<JsonElement>> JsonElement::New(jni::JNIEnv& env, const mbgl::Value& value) { + static auto& primitive = jni::Class<JsonPrimitive>::Singleton(env); + static auto stringConstructor = primitive.GetConstructor<jni::String>(env); + static auto numberConstructor = primitive.GetConstructor<jni::Number>(env); + static auto booleanConstructor = primitive.GetConstructor<jni::Boolean>(env); + + return value.match( + [&] (const mbgl::NullValue&) { + return jni::Local<jni::Object<JsonElement>>(); + }, + [&] (const std::string& value) { + return primitive.New(env, stringConstructor, jni::Make<jni::String>(env, value)); + }, + [&] (const double value) { + return primitive.New(env, numberConstructor, jni::Box(env, value)); + }, + [&] (const int64_t value) { + return primitive.New(env, numberConstructor, jni::Box(env, value)); + }, + [&] (const uint64_t value) { + return primitive.New(env, numberConstructor, jni::Box(env, int64_t(value))); // TODO: should use BigInteger + }, + [&] (const bool value) { + return primitive.New(env, booleanConstructor, jni::Box(env, value ? jni::jni_true : jni::jni_false)); + }, + [&] (const std::vector<mbgl::Value>& values) { + return JsonArray::New(env, values); + }, + [&] (const mbgl::PropertyMap& values) { + return JsonObject::New(env, values); + } + ); } -mapbox::geometry::value JsonElement::convert(jni::JNIEnv &env, jni::Object<JsonElement> jsonElement) { - mapbox::geometry::value value; +mbgl::Value JsonElement::convert(jni::JNIEnv &env, const jni::Object<JsonElement>& jsonElement) { + if (!jsonElement) { + return mbgl::NullValue(); + } - if (jsonElement) { - if (isJsonPrimitive(env, jsonElement)) { - auto primitive = JsonPrimitive::convert(env, jni::Cast(env, jsonElement, JsonPrimitive::javaClass)); - value = mapbox::util::apply_visitor([](auto t) { return mapbox::geometry::value { t }; }, primitive); - } else if (isJsonObject(env, jsonElement)) { - mapbox::geometry::property_map map = JsonObject::convert(env, jni::Cast(env, jsonElement, JsonObject::javaClass)); - value = mapbox::util::recursive_wrapper<std::unordered_map<std::string, mapbox::geometry::value>> { map } ; - } else if (isJsonArray(env, jsonElement)) { - value = JsonArray::convert(env, jni::Cast(env, jsonElement, JsonArray::javaClass)); + static auto& elementClass = jni::Class<JsonElement>::Singleton(env); + static auto isJsonObject = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonObject"); + static auto isJsonArray = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonArray"); + static auto isJsonPrimitive = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonPrimitive"); + + static auto& primitiveClass = jni::Class<JsonPrimitive>::Singleton(env); + static auto isBoolean = primitiveClass.GetMethod<jni::jboolean ()>(env, "isBoolean"); + static auto isString = primitiveClass.GetMethod<jni::jboolean ()>(env, "isString"); + static auto isNumber = primitiveClass.GetMethod<jni::jboolean ()>(env, "isNumber"); + static auto getAsBoolean = primitiveClass.GetMethod<jni::jboolean ()>(env, "getAsBoolean"); + static auto getAsString = primitiveClass.GetMethod<jni::String ()>(env, "getAsString"); + static auto getAsDouble = primitiveClass.GetMethod<jni::jdouble ()>(env, "getAsDouble"); + + if (jsonElement.Call(env, isJsonPrimitive)) { + auto primitive = jni::Cast(env, primitiveClass, jsonElement); + if (primitive.Call(env, isBoolean)) { + return bool(primitive.Call(env, getAsBoolean)); + } else if (primitive.Call(env, isNumber)) { + return primitive.Call(env, getAsDouble); // TODO: how to differentiate types here? + } else if (primitive.Call(env, isString)) { + return jni::Make<std::string>(env, primitive.Call(env, getAsString)); } else { - value = mapbox::geometry::null_value; + return mbgl::NullValue(); } + } else if (jsonElement.Call(env, isJsonObject)) { + return JsonObject::convert(env, jni::Cast(env, jni::Class<JsonObject>::Singleton(env), jsonElement)); + } else if (jsonElement.Call(env, isJsonArray)) { + return JsonArray::convert(env, jni::Cast(env, jni::Class<JsonArray>::Singleton(env), jsonElement)); + } else { + return mbgl::NullValue(); } - return value; -} - -bool JsonElement::isJsonObject(JNIEnv& env, jni::Object<JsonElement> jsonElement) { - static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonObject"); - return jsonElement.Call(env, method); -} - -bool JsonElement::isJsonArray(JNIEnv& env, jni::Object<JsonElement> jsonElement) { - static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonArray"); - return jsonElement.Call(env, method); -} - -bool JsonElement::isJsonPrimitive(JNIEnv& env, jni::Object<JsonElement> jsonElement) { - static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonPrimitive"); - return jsonElement.Call(env, method); -} - -bool JsonElement::isJsonNull(JNIEnv& env, jni::Object<JsonElement> jsonElement) { - static auto method = JsonElement::javaClass.GetMethod<jni::jboolean ()>(env, "isJsonNull"); - return jsonElement.Call(env, method); } void JsonElement::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<JsonElement>::Find(env).NewGlobalRef(env).release(); + jni::Class<JsonElement>::Singleton(env); } -jni::Class<JsonElement> JsonElement::javaClass; - } // namespace gson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/gson/json_element.hpp b/platform/android/src/gson/json_element.hpp index d850caa52..e3b8a0268 100644 --- a/platform/android/src/gson/json_element.hpp +++ b/platform/android/src/gson/json_element.hpp @@ -1,7 +1,6 @@ #pragma once -#include <mapbox/geometry.hpp> -#include <mbgl/util/noncopyable.hpp> +#include <mbgl/util/feature.hpp> #include <jni/jni.hpp> @@ -9,23 +8,13 @@ namespace mbgl { namespace android { namespace gson { -class JsonElement : private mbgl::util::noncopyable { +class JsonElement { public: + using SuperTag = jni::ObjectTag; static constexpr auto Name() { return "com/google/gson/JsonElement"; }; - static jni::Object<JsonElement> New(jni::JNIEnv&, const mapbox::geometry::value&); - - static mapbox::geometry::value convert(JNIEnv&, jni::Object<JsonElement>); - - static bool isJsonObject(JNIEnv&, jni::Object<JsonElement>); - - static bool isJsonArray(JNIEnv&, jni::Object<JsonElement>); - - static bool isJsonPrimitive(JNIEnv&, jni::Object<JsonElement>); - - static bool isJsonNull(JNIEnv&, jni::Object<JsonElement>); - - static jni::Class<JsonElement> javaClass; + static jni::Local<jni::Object<JsonElement>> New(jni::JNIEnv&, const mbgl::Value&); + static mbgl::Value convert(JNIEnv&, const jni::Object<JsonElement>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_object.cpp b/platform/android/src/gson/json_object.cpp index 61b55f8b9..10d244ee4 100644 --- a/platform/android/src/gson/json_object.cpp +++ b/platform/android/src/gson/json_object.cpp @@ -9,59 +9,46 @@ namespace android { namespace gson { -jni::Object<JsonObject> JsonObject::New(jni::JNIEnv& env, const std::unordered_map<std::string, mapbox::geometry::value>& values) { - static auto constructor = JsonObject::javaClass.GetConstructor(env); - static auto addMethod = JsonObject::javaClass.GetMethod<void (jni::String, jni::Object<JsonElement>)>(env, "add"); +jni::Local<jni::Object<JsonObject>> JsonObject::New(jni::JNIEnv& env, const mbgl::PropertyMap& values) { + static auto& javaClass = jni::Class<JsonObject>::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + static auto addMethod = javaClass.GetMethod<void (jni::String, jni::Object<JsonElement>)>(env, "add"); - jni::Object<JsonObject> jsonObject = JsonObject::javaClass.New(env, constructor); + auto jsonObject = javaClass.New(env, constructor); for (auto &item : values) { - jni::Object<JsonElement> jsonElement = JsonElement::New(env, item.second); - jni::String key = jni::Make<jni::String>(env, item.first); - jsonObject.Call(env, addMethod, key, jsonElement); - jni::DeleteLocalRef(env, jsonElement); - jni::DeleteLocalRef(env, key); + jsonObject.Call(env, addMethod, + jni::Make<jni::String>(env, item.first), + JsonElement::New(env, item.second)); } return jsonObject; } template <typename F> // void (jni::String, jni::Object<gson::JsonElement>) -static void iterateEntrySet(jni::JNIEnv& env, jni::Object<JsonObject> jsonObject, F callback) { +static void iterateEntrySet(jni::JNIEnv& env, const jni::Object<JsonObject>& jsonObject, F callback) { // Get Set<Map.Entry<String, JsonElement>> - static auto method = JsonObject::javaClass.GetMethod<jni::Object<java::util::Set> ()>(env, "entrySet"); - auto entrySet = jsonObject.Call(env, method); - jni::Array<jni::Object<java::util::Map::Entry>> entryArray = java::util::Set::toArray<java::util::Map::Entry>(env, entrySet); + static auto& javaClass = jni::Class<JsonObject>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<java::util::Set> ()>(env, "entrySet"); + + auto entryArray = java::util::Set::toArray<java::util::Map::Entry>(env, jsonObject.Call(env, method)); size_t size = entryArray.Length(env); for (size_t i = 0; i < size; i++) { auto entry = entryArray.Get(env, i); if (entry) { - // Convert - auto jKey = java::util::Map::Entry::getKey<jni::ObjectTag>(env, entry); - auto jKeyString = jni::String(reinterpret_cast<jni::jstring*>(jKey.Get())); - auto jValue = java::util::Map::Entry::getValue<gson::JsonElement>(env, entry); - - // Callback - callback(jKeyString, jValue); - - // Cleanup - // Skip jKey as it points to the same as jKeyString - jni::DeleteLocalRef(env, jKeyString); - jni::DeleteLocalRef(env, jValue); + callback( + java::util::Map::Entry::getKey<jni::StringTag>(env, entry), + java::util::Map::Entry::getValue<gson::JsonElement>(env, entry)); } - jni::DeleteLocalRef(env, entry); } - - jni::DeleteLocalRef(env, entrySet); - jni::DeleteLocalRef(env, entryArray); } -mapbox::geometry::property_map JsonObject::convert(jni::JNIEnv &env, jni::Object<JsonObject> jsonObject) { - mapbox::geometry::property_map map; +mbgl::PropertyMap JsonObject::convert(jni::JNIEnv& env, const jni::Object<JsonObject>& jsonObject) { + mbgl::PropertyMap map; if (jsonObject) { - iterateEntrySet(env, jsonObject, [&map, &env](jni::String jId, jni::Object<gson::JsonElement> jsonElement) { + iterateEntrySet(env, jsonObject, [&map, &env](const jni::String& jId, const jni::Object<gson::JsonElement>& jsonElement) { map[jni::Make<std::string>(env, jId)] = JsonElement::convert(env, jsonElement); }); } @@ -70,12 +57,9 @@ mapbox::geometry::property_map JsonObject::convert(jni::JNIEnv &env, jni::Object } void JsonObject::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<JsonObject>::Find(env).NewGlobalRef(env).release(); + jni::Class<JsonObject>::Singleton(env); } -jni::Class<JsonObject> JsonObject::javaClass; - } // namespace gson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/gson/json_object.hpp b/platform/android/src/gson/json_object.hpp index 4bc61e51a..b8916f8ae 100644 --- a/platform/android/src/gson/json_object.hpp +++ b/platform/android/src/gson/json_object.hpp @@ -1,7 +1,6 @@ #pragma once -#include <mapbox/geometry.hpp> -#include <mbgl/util/noncopyable.hpp> +#include "json_element.hpp" #include <jni/jni.hpp> @@ -9,15 +8,13 @@ namespace mbgl { namespace android { namespace gson { -class JsonObject : private mbgl::util::noncopyable { +class JsonObject { public: + using SuperTag = JsonElement; static constexpr auto Name() { return "com/google/gson/JsonObject"; }; - static jni::Object<JsonObject> New(jni::JNIEnv&, const std::unordered_map<std::string, mapbox::geometry::value>&); - - static mapbox::geometry::property_map convert(JNIEnv&, jni::Object<JsonObject>); - - static jni::Class<JsonObject> javaClass; + static jni::Local<jni::Object<JsonObject>> New(jni::JNIEnv&, const mbgl::PropertyMap&); + static mbgl::PropertyMap convert(JNIEnv&, const jni::Object<JsonObject>&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_primitive.cpp b/platform/android/src/gson/json_primitive.cpp index 4e171c484..79d6b0761 100644 --- a/platform/android/src/gson/json_primitive.cpp +++ b/platform/android/src/gson/json_primitive.cpp @@ -1,146 +1,13 @@ #include "json_primitive.hpp" -#include "../java/lang.hpp" namespace mbgl { namespace android { namespace gson { -/** - * Turn mapbox::geometry::value into Java Gson JsonPrimitives - */ -class JsonPrimitiveEvaluator { -public: - - jni::JNIEnv& env; - - /** - * Create a null primitive - */ - jni::Object<JsonPrimitive> operator()(const mapbox::geometry::null_value_t) const { - return jni::Object<JsonPrimitive>(); - } - - /** - * Create a primitive containing a string value - */ - jni::Object<JsonPrimitive> operator()(const std::string value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::String>(env); - auto jvalue = jni::Make<jni::String>(env, value); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, jvalue); - jni::DeleteLocalRef(env, jvalue); - return jsonPrimitive; - } - - /** - * Create a primitive containing a number value with type double - */ - jni::Object<JsonPrimitive> operator()(const double value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Number>>(env); - auto boxedValue = java::lang::Double::valueOf(env, value); - auto number = jni::Cast(env, boxedValue, java::lang::Number::javaClass); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, number); - jni::DeleteLocalRef(env, boxedValue); - return jsonPrimitive; - } - - /** - * Create a primitive containing a number value with type long - */ - jni::Object<JsonPrimitive> operator()(const int64_t value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Number>>(env); - auto boxedValue = java::lang::Long::valueOf(env, value); - auto number = jni::Cast(env, boxedValue, java::lang::Number::javaClass); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, number); - jni::DeleteLocalRef(env, boxedValue); - return jsonPrimitive; - } - - /** - * Create a primitive containing a number value with type long - */ - jni::Object<JsonPrimitive> operator()(const uint64_t value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Number>>(env); - auto boxedValue = java::lang::Long::valueOf(env, value); - auto number = jni::Cast(env, boxedValue, java::lang::Number::javaClass); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, number); - jni::DeleteLocalRef(env, boxedValue); - return jsonPrimitive; - } - - /** - * Create a primitive containing a boolean value - */ - jni::Object<JsonPrimitive> operator()(const bool value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Boolean>>(env); - auto boxedValue = java::lang::Boolean::valueOf(env, value); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, boxedValue); - jni::DeleteLocalRef(env, boxedValue); - return jsonPrimitive; - } -}; - -jni::Object<JsonPrimitive> JsonPrimitive::New(jni::JNIEnv &env, const value& value) { - JsonPrimitiveEvaluator evaluator { env }; - return value::visit(value, evaluator); -} - -JsonPrimitive::value JsonPrimitive::convert(jni::JNIEnv &env, jni::Object<JsonPrimitive> jsonPrimitive) { - value value; - if (jsonPrimitive) { - if (isBoolean(env, jsonPrimitive)) { - value = getAsBoolean(env, jsonPrimitive); - } else if (isNumber(env, jsonPrimitive)) { - //TODO: how to differentiate types here? - value = getAsDouble(env, jsonPrimitive); - } else if (isString(env, jsonPrimitive)) { - value = getAsString(env, jsonPrimitive); - } else { - value = mapbox::geometry::null_value; - } - } - return value; -} - -bool JsonPrimitive::isBoolean(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "isBoolean"); - return jsonPrimitive.Call(env, method); -} - -bool JsonPrimitive::isString(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "isString"); - return jsonPrimitive.Call(env, method); -} - -bool JsonPrimitive::isNumber(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "isNumber"); - return jsonPrimitive.Call(env, method); -} - -bool JsonPrimitive::getAsBoolean(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::jboolean ()>(env, "getAsBoolean"); - return jsonPrimitive.Call(env, method); -} - -std::string JsonPrimitive::getAsString(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::String ()>(env, "getAsString"); - auto jString = jsonPrimitive.Call(env, method); - auto string = jni::Make<std::string>(env, jString); - jni::DeleteLocalRef(env, jString); - return string; -} - -double JsonPrimitive::getAsDouble(JNIEnv& env, jni::Object<JsonPrimitive> jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod<jni::jdouble ()>(env, "getAsDouble"); - return jsonPrimitive.Call(env, method); -} - void JsonPrimitive::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<JsonPrimitive>::Find(env).NewGlobalRef(env).release(); + jni::Class<JsonPrimitive>::Singleton(env); } -jni::Class<JsonPrimitive> JsonPrimitive::javaClass; - } // namespace gson } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/gson/json_primitive.hpp b/platform/android/src/gson/json_primitive.hpp index c418e0ebe..36f138d90 100644 --- a/platform/android/src/gson/json_primitive.hpp +++ b/platform/android/src/gson/json_primitive.hpp @@ -1,7 +1,6 @@ #pragma once -#include <mapbox/geometry.hpp> -#include <mbgl/util/noncopyable.hpp> +#include "json_element.hpp" #include <jni/jni.hpp> @@ -9,30 +8,11 @@ namespace mbgl { namespace android { namespace gson { -class JsonPrimitive : private mbgl::util::noncopyable { +class JsonPrimitive { public: - using value = mapbox::util::variant<mapbox::geometry::null_value_t, bool, uint64_t, int64_t, double, std::string>; - + using SuperTag = JsonElement; static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; }; - static jni::Object<JsonPrimitive> New(jni::JNIEnv&, const value&); - - static value convert(JNIEnv&, jni::Object<JsonPrimitive>); - - static bool isBoolean(JNIEnv&, jni::Object<JsonPrimitive>); - - static bool isString(JNIEnv&, jni::Object<JsonPrimitive>); - - static bool isNumber(JNIEnv&, jni::Object<JsonPrimitive>); - - static bool getAsBoolean(JNIEnv&, jni::Object<JsonPrimitive>); - - static std::string getAsString(JNIEnv&, jni::Object<JsonPrimitive>); - - static double getAsDouble(JNIEnv&, jni::Object<JsonPrimitive>); - - static jni::Class<JsonPrimitive> javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/http_file_source.cpp b/platform/android/src/http_file_source.cpp index fc7ffbec8..e1b3493f0 100644 --- a/platform/android/src/http_file_source.cpp +++ b/platform/android/src/http_file_source.cpp @@ -25,15 +25,14 @@ public: HTTPRequest(jni::JNIEnv&, const Resource&, FileSource::Callback); ~HTTPRequest(); - void onFailure(jni::JNIEnv&, int type, jni::String message); + void onFailure(jni::JNIEnv&, int type, const jni::String& message); void onResponse(jni::JNIEnv&, int code, - jni::String etag, jni::String modified, - jni::String cacheControl, jni::String expires, - jni::String retryAfter, jni::String xRateLimitReset, - jni::Array<jni::jbyte> body); + const jni::String& etag, const jni::String& modified, + const jni::String& cacheControl, const jni::String& expires, + const jni::String& retryAfter, const jni::String& xRateLimitReset, + const jni::Array<jni::jbyte>& body); - static jni::Class<HTTPRequest> javaClass; - jni::UniqueObject<HTTPRequest> javaRequest; + jni::Global<jni::Object<HTTPRequest>> javaRequest; private: Resource resource; @@ -52,16 +51,14 @@ private: static const int permanentError = 2; }; -jni::Class<HTTPRequest> HTTPRequest::javaClass; - namespace android { void RegisterNativeHTTPRequest(jni::JNIEnv& env) { - HTTPRequest::javaClass = *jni::Class<HTTPRequest>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<HTTPRequest>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) - jni::RegisterNativePeer<HTTPRequest>(env, HTTPRequest::javaClass, "nativePtr", + jni::RegisterNativePeer<HTTPRequest>(env, javaClass, "nativePtr", METHOD(&HTTPRequest::onFailure, "nativeOnFailure"), METHOD(&HTTPRequest::onResponse, "nativeOnResponse")); } @@ -82,29 +79,32 @@ HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, FileSource jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 10); + static auto& javaClass = jni::Class<HTTPRequest>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::jlong, jni::String, jni::String, jni::String>(env); - javaRequest = javaClass.New(env, constructor, - reinterpret_cast<jlong>(this), - jni::Make<jni::String>(env, resource.url), - jni::Make<jni::String>(env, etagStr), - jni::Make<jni::String>(env, modifiedStr)).NewGlobalRef(env); + javaRequest = jni::NewGlobal(env, + javaClass.New(env, constructor, + reinterpret_cast<jlong>(this), + jni::Make<jni::String>(env, resource.url), + jni::Make<jni::String>(env, etagStr), + jni::Make<jni::String>(env, modifiedStr))); } HTTPRequest::~HTTPRequest() { android::UniqueEnv env = android::AttachEnv(); + static auto& javaClass = jni::Class<HTTPRequest>::Singleton(*env); static auto cancel = javaClass.GetMethod<void ()>(*env, "cancel"); - javaRequest->Call(*env, cancel); + javaRequest.Call(*env, cancel); } void HTTPRequest::onResponse(jni::JNIEnv& env, int code, - jni::String etag, jni::String modified, - jni::String cacheControl, jni::String expires, - jni::String jRetryAfter, jni::String jXRateLimitReset, - jni::Array<jni::jbyte> body) { + const jni::String& etag, const jni::String& modified, + const jni::String& cacheControl, const jni::String& expires, + const jni::String& jRetryAfter, const jni::String& jXRateLimitReset, + const jni::Array<jni::jbyte>& body) { using Error = Response::Error; @@ -159,7 +159,7 @@ void HTTPRequest::onResponse(jni::JNIEnv& env, int code, async.send(); } -void HTTPRequest::onFailure(jni::JNIEnv& env, int type, jni::String message) { +void HTTPRequest::onFailure(jni::JNIEnv& env, int type, const jni::String& message) { std::string messageStr = jni::Make<std::string>(env, message); using Error = Response::Error; diff --git a/platform/android/src/image.cpp b/platform/android/src/image.cpp index 045638157..31515ff16 100644 --- a/platform/android/src/image.cpp +++ b/platform/android/src/image.cpp @@ -15,13 +15,7 @@ PremultipliedImage decodeImage(const std::string& string) { jni::SetArrayRegion(*env, *array, 0, string.size(), reinterpret_cast<const signed char*>(string.data())); - auto bitmap = android::BitmapFactory::DecodeByteArray(*env, array, 0, string.size()); - jni::DeleteLocalRef(*env, array); - - auto image = android::Bitmap::GetImage(*env, bitmap); - jni::DeleteLocalRef(*env, bitmap); - - return image; + return android::Bitmap::GetImage(*env, android::BitmapFactory::DecodeByteArray(*env, array, 0, string.size())); } } // namespace mbgl diff --git a/platform/android/src/java/lang.cpp b/platform/android/src/java/lang.cpp deleted file mode 100644 index 3c9573716..000000000 --- a/platform/android/src/java/lang.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "lang.hpp" - -namespace mbgl { -namespace android { -namespace java { -namespace lang { - -// Float - -jni::Object<Float> Float::valueOf(JNIEnv &env, jfloat value) { - static auto method = javaClass.GetStaticMethod<jni::Object<Float> (jni::jfloat)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Float::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Float>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Float> Float::javaClass; - -// Long - -jni::Object<Long> Long::valueOf(JNIEnv &env, jlong value) { - static auto method = javaClass.GetStaticMethod<jni::Object<Long> (jni::jlong)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Long::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Long>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Long> Long::javaClass; - -// Double - -jni::Object<Double> Double::valueOf(JNIEnv &env, jdouble value) { - static auto method = javaClass.GetStaticMethod<jni::Object<Double> (jni::jdouble)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Double::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Double>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Double> Double::javaClass; - -// Boolean - -jni::Object<Boolean> Boolean::valueOf(JNIEnv &env, jboolean value) { - static auto method = javaClass.GetStaticMethod<jni::Object<Boolean> (jni::jboolean)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Boolean::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Boolean>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Boolean> Boolean::javaClass; - -// Number - -void Number::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class<Number>::Find(env).NewGlobalRef(env).release(); -} - -jni::Class<Number> Number::javaClass; - -} // namespace lang -} // namespace java -} // namespace android -} // namespace mbgl diff --git a/platform/android/src/java/lang.hpp b/platform/android/src/java/lang.hpp deleted file mode 100644 index 981e3b14b..000000000 --- a/platform/android/src/java/lang.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include <jni/jni.hpp> -#include <mbgl/util/noncopyable.hpp> - -namespace mbgl { -namespace android { -namespace java { -namespace lang { - -class Float : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Float"; }; - - static jni::Object<Float> valueOf(JNIEnv&, jfloat); - - static jni::Class<Float> javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Double : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Double"; }; - - static jni::Object<Double> valueOf(JNIEnv&, jdouble); - - static jni::Class<Double> javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Long : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Long"; }; - - static jni::Object<Long> valueOf(JNIEnv&, jlong); - - static jni::Class<Long> javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Boolean : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Boolean"; }; - - static jni::Object<Boolean> valueOf(JNIEnv&, jboolean); - - static jni::Class<Boolean> javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Number : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Number"; }; - - static jni::Class<Number> javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -} // namespace lang -} // namespace java -} // namespace android -} // namespace mbgl diff --git a/platform/android/src/java/util.cpp b/platform/android/src/java/util.cpp index 89c4c7779..b3aebb36c 100644 --- a/platform/android/src/java/util.cpp +++ b/platform/android/src/java/util.cpp @@ -5,21 +5,14 @@ namespace android { namespace java { namespace util { -jni::Class<Arrays> Arrays::javaClass; -jni::Class<List> List::javaClass; -jni::Class<Set> Set::javaClass; -jni::Class<Map> Map::javaClass; -jni::Class<Map::Entry> Map::Entry::javaClass; - void registerNative(jni::JNIEnv& env) { - Arrays::javaClass = *jni::Class<Arrays>::Find(env).NewGlobalRef(env).release(); - List::javaClass = *jni::Class<List>::Find(env).NewGlobalRef(env).release(); - Set::javaClass = *jni::Class<Set>::Find(env).NewGlobalRef(env).release(); - Map::javaClass = *jni::Class<Map>::Find(env).NewGlobalRef(env).release(); - Map::Entry::javaClass = *jni::Class<Map::Entry>::Find(env).NewGlobalRef(env).release(); + jni::Class<Arrays>::Singleton(env); + jni::Class<List>::Singleton(env); + jni::Class<Set>::Singleton(env); + jni::Class<Map>::Singleton(env); + jni::Class<Map::Entry>::Singleton(env); } - } // namespace util } // namespace java } // namespace android diff --git a/platform/android/src/java/util.hpp b/platform/android/src/java/util.hpp index c6b07acac..9b0c01459 100644 --- a/platform/android/src/java/util.hpp +++ b/platform/android/src/java/util.hpp @@ -11,79 +11,70 @@ namespace util { class List : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "java/util/List"; }; template<class T> - static jni::Array<jni::Object<T>> toArray(jni::JNIEnv& env, jni::Object<List> list) { - static auto toArray = List::javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray"); - return (jni::Array<jni::Object<T>>) list.Call(env, toArray); - }; - - static jni::Class<List> javaClass; + static jni::Local<jni::Array<jni::Object<T>>> toArray(jni::JNIEnv& env, const jni::Object<List>& list) { + static auto& javaClass = jni::Class<List>::Singleton(env); + static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray"); + return jni::Local<jni::Array<jni::Object<T>>>(env, list.Call(env, toArray).release()); + }; }; class Arrays : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "java/util/Arrays"; }; template <class T> - static jni::Object<List> asList(jni::JNIEnv& env, jni::Array<jni::Object<T>> array) { - static auto asList = Arrays::javaClass.GetStaticMethod<jni::Object<List>(jni::Array<jni::Object<>>)>(env, "asList"); - return javaClass.Call(env, asList, (jni::Array<jni::Object<>>) array); - } - - static jni::Class<Arrays> javaClass; + static jni::Local<jni::Object<List>> asList(jni::JNIEnv& env, const jni::Array<jni::Object<T>>& array) { + static auto& javaClass = jni::Class<Arrays>::Singleton(env); + static auto asList = javaClass.GetStaticMethod<jni::Object<List>(jni::Array<jni::Object<>>)>(env, "asList"); + auto typeErasedArray = jni::Local<jni::Array<jni::Object<>>>(env, jni::NewLocal(env, array).release()); + return javaClass.Call(env, asList, typeErasedArray); + } }; class Set : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "java/util/Set"; }; template<class T> - static jni::Array<jni::Object<T>> toArray(jni::JNIEnv& env, jni::Object<Set> list) { - static auto toArray = Set::javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray"); - return (jni::Array<jni::Object<T>>) list.Call(env, toArray); - }; - - static jni::Class<Set> javaClass; + static jni::Local<jni::Array<jni::Object<T>>> toArray(jni::JNIEnv& env, const jni::Object<Set>& list) { + static auto& javaClass = jni::Class<Set>::Singleton(env); + static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray"); + return jni::Local<jni::Array<jni::Object<T>>>(env, list.Call(env, toArray).release()); + }; }; class Map : private mbgl::util::noncopyable { public: + static constexpr auto Name() { return "java/util/Map"; }; class Entry : private mbgl::util::noncopyable { public: static constexpr auto Name() { return "java/util/Map$Entry"; }; template <class T> - static jni::Object<T> getKey(jni::JNIEnv& env, jni::Object<Entry> entry) { - static auto method = Entry::javaClass.GetMethod<jni::Object<> ()>(env, "getKey"); - return (jni::Object<T>) entry.Call(env, method); + static jni::Local<jni::Object<T>> getKey(jni::JNIEnv& env, const jni::Object<Entry>& entry) { + static auto& javaClass = jni::Class<Map::Entry>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<> ()>(env, "getKey"); + return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method)); } template <class T> - static jni::Object<T> getValue(jni::JNIEnv& env, jni::Object<Entry> entry) { - static auto method = Entry::javaClass.GetMethod<jni::Object<> ()>(env, "getValue"); - return (jni::Object<T>) entry.Call(env, method).Get(); + static jni::Local<jni::Object<T>> getValue(jni::JNIEnv& env, const jni::Object<Entry>& entry) { + static auto& javaClass = jni::Class<Map::Entry>::Singleton(env); + static auto method = javaClass.GetMethod<jni::Object<> ()>(env, "getValue"); + return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method)); } - - static jni::Class<Entry> javaClass; }; - - static constexpr auto Name() { return "java/util/Map"; }; - - static jni::Class<Map> javaClass; }; void registerNative(jni::JNIEnv&); - } // namespace util } // namespace java } // namespace android diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index 872d8bc89..e323dc83b 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -48,7 +48,6 @@ #include "snapshotter/map_snapshot.hpp" #include "text/collator_jni.hpp" #include "text/local_glyph_rasterizer_jni.hpp" -#include "java/lang.hpp" #include "logger.hpp" namespace mbgl { @@ -115,11 +114,6 @@ void registerNatives(JavaVM *vm) { java::util::registerNative(env); PointF::registerNative(env); RectF::registerNative(env); - java::lang::Number::registerNative(env); - java::lang::Float::registerNative(env); - java::lang::Boolean::registerNative(env); - java::lang::Double::registerNative(env); - java::lang::Long::registerNative(env); // GeoJSON geojson::Feature::registerNative(env); @@ -193,6 +187,7 @@ void registerNatives(JavaVM *vm) { LocalGlyphRasterizer::registerNative(env); Locale::registerNative(env); Collator::registerNative(env); + StringUtils::registerNative(env); // Logger Logger::registerNative(env); diff --git a/platform/android/src/jni/collection.hpp b/platform/android/src/jni/collection.hpp deleted file mode 100644 index 5f94ec29c..000000000 --- a/platform/android/src/jni/collection.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include <jni/jni.hpp> - -#include <string> -#include <vector> - -namespace jni { - -inline Array<String> MakeAnything(ThingToMake<Array<String>>, JNIEnv& env, const std::vector<std::string>& vector) -{ - static auto clazz = *Class<StringTag>::Find(env).NewGlobalRef(env).release(); - auto result = Array<String>::New(env, vector.size(), clazz); - - std::size_t index = 0; - for (auto&& item : vector) { - auto element = Make<jni::String>(env, item); - result.Set(env, index, element); - DeleteLocalRef(env, element); - index++; - } - - return result; -} - -} diff --git a/platform/android/src/jni/generic_global_ref_deleter.hpp b/platform/android/src/jni/generic_global_ref_deleter.hpp deleted file mode 100644 index 7239e361a..000000000 --- a/platform/android/src/jni/generic_global_ref_deleter.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include <jni/jni.hpp> - -#include "../attach_env.hpp" - -namespace mbgl { -namespace android { - -// A deleter that doesn't retain an JNIEnv handle but instead tries to attach the JVM. This means -// it can be used on any thread to delete a global ref. -struct GenericGlobalRefDeleter { - void operator()(jni::jobject* p) const { - if (p) { - auto env = AttachEnv(); - env->DeleteGlobalRef(jni::Unwrap(p)); - } - } -}; - - -template < class TagType > -class GenericWeakObjectRefDeleter; - -template < class TagType = jni::ObjectTag > -using GenericUniqueWeakObject = std::unique_ptr< const jni::Object<TagType>, GenericWeakObjectRefDeleter<TagType> >; - -template < class TagType > -class GenericWeakObjectRefDeleter -{ -public: - using pointer = jni::PointerToValue< jni::Object<TagType> >; - - void operator()(pointer p) const - { - if (p) - { - auto env = AttachEnv(); - env->DeleteWeakGlobalRef(jni::Unwrap(p->Get())); - } - } -}; - -template < class TagType > -GenericUniqueWeakObject<TagType> SeizeGenericWeakRef(JNIEnv&, jni::Object<TagType>&& object) -{ - return GenericUniqueWeakObject<TagType>(jni::PointerToValue<jni::Object<TagType>>(std::move(object)), GenericWeakObjectRefDeleter<TagType>()); -}; - -} // namespace android -} // namespace mbgl diff --git a/platform/android/src/jni/local_object.hpp b/platform/android/src/jni/local_object.hpp deleted file mode 100644 index 00fc4a193..000000000 --- a/platform/android/src/jni/local_object.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include <jni/jni.hpp> - -namespace jni { - - class LocalRefDeleter { - private: - JNIEnv* env = nullptr; - - public: - LocalRefDeleter() = default; - LocalRefDeleter(JNIEnv& e) : env(&e) {} - - void operator()(jobject* object) const { - if (object) { - assert(env); - DeleteLocalRef(*env, object); - } - } - }; - - template < class T > - using LocalObject = std::unique_ptr< T, LocalRefDeleter >; - - /** - * Use a LocalObject to discard of local references as soon as possible - */ - template < class T > - LocalObject<T> NewLocalObject(JNIEnv& env, T* t) { - return LocalObject<T>(t, LocalRefDeleter(env)); - } -} diff --git a/platform/android/src/logger.cpp b/platform/android/src/logger.cpp index 0ade91460..f5d78cc83 100644 --- a/platform/android/src/logger.cpp +++ b/platform/android/src/logger.cpp @@ -5,12 +5,12 @@ namespace mbgl { namespace android { void Logger::registerNative(jni::JNIEnv& env) { - _class = *jni::Class<Logger>::Find(env).NewGlobalRef(env).release(); + jni::Class<Logger>::Singleton(env); } -jni::Class<Logger> Logger::_class; - void Logger::log(jni::JNIEnv& env, EventSeverity severity, const std::string &msg) { + static auto& _class = jni::Class<Logger>::Singleton(env); + auto tag = jni::Make<jni::String>(env, "Mbgl"); auto message = jni::Make<jni::String>(env, msg); using Signature = void(jni::String, jni::String); @@ -28,9 +28,6 @@ void Logger::log(jni::JNIEnv& env, EventSeverity severity, const std::string &ms auto static error = _class.GetStaticMethod<Signature>(env, "e"); _class.Call(env, error, tag, message); } - - DeleteLocalRef(env, tag); - DeleteLocalRef(env, message); } } // namespace android diff --git a/platform/android/src/logger.hpp b/platform/android/src/logger.hpp index d4805fccd..7481ecb26 100644 --- a/platform/android/src/logger.hpp +++ b/platform/android/src/logger.hpp @@ -15,9 +15,6 @@ public: static void registerNative(jni::JNIEnv&); static void log(jni::JNIEnv&, EventSeverity severity, const std::string &msg); - -private: - static jni::Class<Logger> _class; }; } // namespace android diff --git a/platform/android/src/map/camera_position.cpp b/platform/android/src/map/camera_position.cpp index 01ffc6530..3caf4ea2f 100644 --- a/platform/android/src/map/camera_position.cpp +++ b/platform/android/src/map/camera_position.cpp @@ -4,8 +4,9 @@ namespace mbgl { namespace android { -jni::Object<CameraPosition> CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOptions options) { - static auto constructor = CameraPosition::javaClass.GetConstructor<jni::Object<LatLng>, double, double, double>(env); +jni::Local<jni::Object<CameraPosition>> CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOptions options) { + static auto& javaClass = jni::Class<CameraPosition>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::Object<LatLng>, double, double, double>(env); // wrap LatLng values coming from core auto center = options.center.value(); @@ -24,18 +25,17 @@ jni::Object<CameraPosition> CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOp // convert tilt, core ranges from [0 rad, 1,0472 rad], android ranges from 0 to 60 double tilt_degrees = options.pitch.value_or(0) * util::RAD2DEG; - return CameraPosition::javaClass.New(env, constructor, LatLng::New(env, center), options.zoom.value_or(0), tilt_degrees, bearing_degrees); + return javaClass.New(env, constructor, LatLng::New(env, center), options.zoom.value_or(0), tilt_degrees, bearing_degrees); } -mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env, jni::Object<CameraPosition> position) { - static auto bearing = CameraPosition::javaClass.GetField<jni::jdouble>(env, "bearing"); - static auto target = CameraPosition::javaClass.GetField<jni::Object<LatLng>>(env, "target"); - static auto tilt = CameraPosition::javaClass.GetField<jni::jdouble>(env, "tilt"); - static auto zoom = CameraPosition::javaClass.GetField<jni::jdouble>(env, "zoom"); +mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env, const jni::Object<CameraPosition>& position) { + static auto& javaClass = jni::Class<CameraPosition>::Singleton(env); + static auto bearing = javaClass.GetField<jni::jdouble>(env, "bearing"); + static auto target = javaClass.GetField<jni::Object<LatLng>>(env, "target"); + static auto tilt = javaClass.GetField<jni::jdouble>(env, "tilt"); + static auto zoom = javaClass.GetField<jni::jdouble>(env, "zoom"); - auto jtarget = position.Get(env, target); - auto center = LatLng::getLatLng(env, jtarget); - jni::DeleteLocalRef(env, jtarget); + auto center = LatLng::getLatLng(env, position.Get(env, target)); return mbgl::CameraOptions { center, @@ -48,13 +48,9 @@ mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env, jni::Obje } void CameraPosition::registerNative(jni::JNIEnv &env) { - // Lookup the class - CameraPosition::javaClass = *jni::Class<CameraPosition>::Find(env).NewGlobalRef(env).release(); + jni::Class<CameraPosition>::Singleton(env); } -jni::Class<CameraPosition> CameraPosition::javaClass; - - } // namespace android } // namespace mb diff --git a/platform/android/src/map/camera_position.hpp b/platform/android/src/map/camera_position.hpp index 4eee8be75..7579f9fed 100644 --- a/platform/android/src/map/camera_position.hpp +++ b/platform/android/src/map/camera_position.hpp @@ -10,19 +10,14 @@ namespace android { class CameraPosition : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/camera/CameraPosition"; }; - static jni::Object<CameraPosition> New(jni::JNIEnv&, mbgl::CameraOptions); - - static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, jni::Object<CameraPosition>); + static jni::Local<jni::Object<CameraPosition>> New(jni::JNIEnv&, mbgl::CameraOptions); - static jni::Class<CameraPosition> javaClass; + static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, const jni::Object<CameraPosition>&); static void registerNative(jni::JNIEnv&); - }; - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/map/image.cpp b/platform/android/src/map/image.cpp index ce89e22d7..a91cc938e 100644 --- a/platform/android/src/map/image.cpp +++ b/platform/android/src/map/image.cpp @@ -5,24 +5,23 @@ namespace mbgl { namespace android { -mbgl::style::Image Image::getImage(jni::JNIEnv& env, jni::Object<Image> image) { - static auto widthField = Image::javaClass.GetField<jni::jint>(env, "width"); - static auto heightField = Image::javaClass.GetField<jni::jint>(env, "height"); - static auto pixelRatioField = Image::javaClass.GetField<jni::jfloat>(env, "pixelRatio"); - static auto bufferField = Image::javaClass.GetField<jni::Array<jbyte>>(env, "buffer"); - static auto nameField = Image::javaClass.GetField<jni::String>(env, "name"); - static auto sdfField = Image::javaClass.GetField<jni::jboolean>(env, "sdf"); +mbgl::style::Image Image::getImage(jni::JNIEnv& env, const jni::Object<Image>& image) { + static auto& javaClass = jni::Class<Image>::Singleton(env); + static auto widthField = javaClass.GetField<jni::jint>(env, "width"); + static auto heightField = javaClass.GetField<jni::jint>(env, "height"); + static auto pixelRatioField = javaClass.GetField<jni::jfloat>(env, "pixelRatio"); + static auto bufferField = javaClass.GetField<jni::Array<jbyte>>(env, "buffer"); + static auto nameField = javaClass.GetField<jni::String>(env, "name"); + static auto sdfField = javaClass.GetField<jni::jboolean>(env, "sdf"); auto height = image.Get(env, heightField); auto width = image.Get(env, widthField); auto pixelRatio = image.Get(env, pixelRatioField); auto pixels = image.Get(env, bufferField); - auto jName = image.Get(env, nameField); - auto name = jni::Make<std::string>(env, jName); + auto name = jni::Make<std::string>(env, image.Get(env, nameField)); auto sdf = (bool) image.Get(env, sdfField); - jni::DeleteLocalRef(env, jName); - jni::NullCheck(env, &pixels); + jni::NullCheck(env, pixels.get()); std::size_t size = pixels.Length(env); mbgl::PremultipliedImage premultipliedImage({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) }); @@ -31,18 +30,12 @@ mbgl::style::Image Image::getImage(jni::JNIEnv& env, jni::Object<Image> image) { } jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get())); - jni::DeleteLocalRef(env, pixels); return mbgl::style::Image {name, std::move(premultipliedImage), pixelRatio, sdf}; } void Image::registerNative(jni::JNIEnv &env) { - // Lookup the class - Image::javaClass = *jni::Class<Image>::Find(env).NewGlobalRef(env).release(); + jni::Class<Image>::Singleton(env); } -jni::Class<Image> Image::javaClass; - - } // namespace android } // namespace mb - diff --git a/platform/android/src/map/image.hpp b/platform/android/src/map/image.hpp index 1513e13ee..7549bc646 100644 --- a/platform/android/src/map/image.hpp +++ b/platform/android/src/map/image.hpp @@ -10,17 +10,12 @@ namespace android { class Image : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/Image"; }; - static mbgl::style::Image getImage(jni::JNIEnv&, jni::Object<Image>); - - static jni::Class<Image> javaClass; + static mbgl::style::Image getImage(jni::JNIEnv&, const jni::Object<Image>&); static void registerNative(jni::JNIEnv&); - }; - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/map_renderer.cpp b/platform/android/src/map_renderer.cpp index ba6fdc63b..13790c454 100644 --- a/platform/android/src/map_renderer.cpp +++ b/platform/android/src/map_renderer.cpp @@ -14,14 +14,17 @@ namespace mbgl { namespace android { -MapRenderer::MapRenderer(jni::JNIEnv& _env, jni::Object<MapRenderer> obj, - jni::Object<FileSource> _fileSource, jni::jfloat pixelRatio_, - jni::String programCacheDir_, - jni::String localIdeographFontFamily_) - : javaPeer(SeizeGenericWeakRef(_env, jni::Object<MapRenderer>(jni::NewWeakGlobalRef(_env, obj.Get()).release()))), pixelRatio(pixelRatio_) +MapRenderer::MapRenderer(jni::JNIEnv& _env, + const jni::Object<MapRenderer>& obj, + const jni::Object<FileSource>& _fileSource, + jni::jfloat pixelRatio_, + const jni::String& programCacheDir_, + const jni::String& localIdeographFontFamily_) + : javaPeer(_env, obj) + , pixelRatio(pixelRatio_) , fileSource(FileSource::getDefaultFileSource(_env, _fileSource)) , programCacheDir(jni::Make<std::string>(_env, programCacheDir_)) - , localIdeographFontFamily(localIdeographFontFamily_ == nullptr ? optional<std::string>{} : jni::Make<std::string>(_env, localIdeographFontFamily_ )) + , localIdeographFontFamily(localIdeographFontFamily_ ? jni::Make<std::string>(_env, localIdeographFontFamily_) : optional<std::string>{}) , threadPool(sharedThreadPool()) , mailbox(std::make_shared<Mailbox>(*this)) { } @@ -52,9 +55,10 @@ void MapRenderer::schedule(std::weak_ptr<Mailbox> scheduled) { auto peer = runnable->peer(); // Queue the event on the Java Peer + static auto& javaClass = jni::Class<MapRenderer>::Singleton(*_env); static auto queueEvent = javaClass.GetMethod<void( jni::Object<MapRendererRunnable>)>(*_env, "queueEvent"); - javaPeer->Call(*_env, queueEvent, *peer); + javaPeer.get(*_env).Call(*_env, queueEvent, peer); // Release the c++ peer as it will be destroyed on GC of the Java Peer runnable.release(); @@ -62,8 +66,9 @@ void MapRenderer::schedule(std::weak_ptr<Mailbox> scheduled) { void MapRenderer::requestRender() { android::UniqueEnv _env = android::AttachEnv(); + static auto& javaClass = jni::Class<MapRenderer>::Singleton(*_env); static auto onInvalidate = javaClass.GetMethod<void()>(*_env, "requestRender"); - javaPeer->Call(*_env, onInvalidate); + javaPeer.get(*_env).Call(*_env, onInvalidate); } void MapRenderer::update(std::shared_ptr<UpdateParameters> params) { @@ -179,17 +184,15 @@ void MapRenderer::onSurfaceChanged(JNIEnv&, jint width, jint height) { // Static methods // -jni::Class<MapRenderer> MapRenderer::javaClass; - void MapRenderer::registerNative(jni::JNIEnv& env) { // Lookup the class - MapRenderer::javaClass = *jni::Class<MapRenderer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<MapRenderer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<MapRenderer>(env, MapRenderer::javaClass, "nativePtr", - std::make_unique<MapRenderer, JNIEnv&, jni::Object<MapRenderer>, jni::Object<FileSource>, jni::jfloat, jni::String, jni::String>, + jni::RegisterNativePeer<MapRenderer>(env, javaClass, "nativePtr", + jni::MakePeer<MapRenderer, const jni::Object<MapRenderer>&, const jni::Object<FileSource>&, jni::jfloat, const jni::String&, const jni::String&>, "nativeInitialize", "finalize", METHOD(&MapRenderer::render, "nativeRender"), METHOD(&MapRenderer::onSurfaceCreated, @@ -198,8 +201,9 @@ void MapRenderer::registerNative(jni::JNIEnv& env) { "nativeOnSurfaceChanged")); } -MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, jni::Object<MapRenderer> jObject) { - static auto field = MapRenderer::javaClass.GetField<jlong>(env, "nativePtr"); +MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, const jni::Object<MapRenderer>& jObject) { + static auto& javaClass = jni::Class<MapRenderer>::Singleton(env); + static auto field = javaClass.GetField<jlong>(env, "nativePtr"); MapRenderer* mapRenderer = reinterpret_cast<MapRenderer*>(jObject.Get(env, field)); assert(mapRenderer != nullptr); return *mapRenderer; diff --git a/platform/android/src/map_renderer.hpp b/platform/android/src/map_renderer.hpp index 97d2db4a9..d60447e0e 100644 --- a/platform/android/src/map_renderer.hpp +++ b/platform/android/src/map_renderer.hpp @@ -9,8 +9,6 @@ #include <jni/jni.hpp> #include <mbgl/storage/default_file_source.hpp> -#include "jni/generic_global_ref_deleter.hpp" - namespace mbgl { template <class> @@ -38,18 +36,16 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/renderer/MapRenderer"; }; - static jni::Class<MapRenderer> javaClass; - static void registerNative(jni::JNIEnv&); - static MapRenderer& getNativePeer(JNIEnv&, jni::Object<MapRenderer>); + static MapRenderer& getNativePeer(JNIEnv&, const jni::Object<MapRenderer>&); MapRenderer(jni::JNIEnv& _env, - jni::Object<MapRenderer>, - jni::Object<FileSource>, + const jni::Object<MapRenderer>&, + const jni::Object<FileSource>&, jni::jfloat pixelRatio, - jni::String programCacheDir, - jni::String localIdeographFontFamily); + const jni::String& programCacheDir, + const jni::String& localIdeographFontFamily); ~MapRenderer() override; @@ -99,7 +95,7 @@ private: void onSurfaceChanged(JNIEnv&, jint width, jint height); private: - GenericUniqueWeakObject<MapRenderer> javaPeer; + jni::WeakReference<jni::Object<MapRenderer>, jni::EnvAttachingDeleter> javaPeer; float pixelRatio; DefaultFileSource& fileSource; diff --git a/platform/android/src/map_renderer_runnable.cpp b/platform/android/src/map_renderer_runnable.cpp index 4dc6611c4..77c3aa301 100644 --- a/platform/android/src/map_renderer_runnable.cpp +++ b/platform/android/src/map_renderer_runnable.cpp @@ -12,9 +12,10 @@ MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::weak_ptr<Mailbox // Not using a weak reference here as this might oerflow // the weak reference table on some devices jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 5); + static auto& javaClass = jni::Class<MapRendererRunnable>::Singleton(env); static auto constructor = javaClass.GetConstructor<jlong>(env); auto instance = javaClass.New(env, constructor, reinterpret_cast<jlong>(this)); - javaPeer = instance.NewGlobalRef(env); + javaPeer = jni::NewGlobal(env, instance); } MapRendererRunnable::~MapRendererRunnable() = default; @@ -23,23 +24,21 @@ void MapRendererRunnable::run(jni::JNIEnv&) { Mailbox::maybeReceive(mailbox); } -jni::UniqueObject<MapRendererRunnable> MapRendererRunnable::peer() { +jni::Global<jni::Object<MapRendererRunnable>> MapRendererRunnable::peer() { return std::move(javaPeer); } // Static methods // -jni::Class<MapRendererRunnable> MapRendererRunnable::javaClass; - void MapRendererRunnable::registerNative(jni::JNIEnv& env) { // Lookup the class - MapRendererRunnable::javaClass = *jni::Class<MapRendererRunnable>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<MapRendererRunnable>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) jni::RegisterNativePeer<MapRendererRunnable>( env, - MapRendererRunnable::javaClass, + javaClass, "nativePtr", std::make_unique<MapRendererRunnable, JNIEnv&>, "nativeInitialize", diff --git a/platform/android/src/map_renderer_runnable.hpp b/platform/android/src/map_renderer_runnable.hpp index 46fb028d2..21c4369b6 100644 --- a/platform/android/src/map_renderer_runnable.hpp +++ b/platform/android/src/map_renderer_runnable.hpp @@ -22,8 +22,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/renderer/MapRendererRunnable"; }; - static jni::Class<MapRendererRunnable> javaClass; - static void registerNative(jni::JNIEnv&); MapRendererRunnable(jni::JNIEnv&, std::weak_ptr<Mailbox>); @@ -38,10 +36,10 @@ public: void run(jni::JNIEnv&); // Transfers ownership of the Peer object to the caller - jni::UniqueObject<MapRendererRunnable> peer(); + jni::Global<jni::Object<MapRendererRunnable>> peer(); private: - jni::UniqueObject<MapRendererRunnable> javaPeer; + jni::Global<jni::Object<MapRendererRunnable>> javaPeer; std::weak_ptr<Mailbox> mailbox; }; diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 8c76332b3..25605e09e 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -37,7 +37,7 @@ #include "conversion/conversion.hpp" #include "conversion/collection.hpp" #include "style/conversion/filter.hpp" -#include "geojson/conversion/feature.hpp" +#include "geojson/feature.hpp" #include "jni.hpp" #include "attach_env.hpp" @@ -57,11 +57,11 @@ namespace mbgl { namespace android { NativeMapView::NativeMapView(jni::JNIEnv& _env, - jni::Object<NativeMapView> _obj, - jni::Object<FileSource> jFileSource, - jni::Object<MapRenderer> jMapRenderer, + const jni::Object<NativeMapView>& _obj, + const jni::Object<FileSource>& jFileSource, + const jni::Object<MapRenderer>& jMapRenderer, jni::jfloat _pixelRatio) - : javaPeer(_obj.NewWeakGlobalRef(_env)) + : javaPeer(_env, _obj) , mapRenderer(MapRenderer::getNativePeer(_env, jMapRenderer)) , pixelRatio(_pixelRatio) , threadPool(sharedThreadPool()) { @@ -103,8 +103,9 @@ void NativeMapView::notifyMapChange(mbgl::MapChange change) { assert(vm != nullptr); android::UniqueEnv _env = android::AttachEnv(); + static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env); static auto onMapChanged = javaClass.GetMethod<void (int)>(*_env, "onMapChanged"); - javaPeer->Call(*_env, onMapChanged, (int) change); + javaPeer.get(*_env).Call(*_env, onMapChanged, (int) change); } void NativeMapView::onCameraWillChange(MapObserver::CameraChangeMode mode) { @@ -179,23 +180,23 @@ void NativeMapView::resizeView(jni::JNIEnv&, int w, int h) { map->setSize({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) }); } -jni::String NativeMapView::getStyleUrl(jni::JNIEnv& env) { +jni::Local<jni::String> NativeMapView::getStyleUrl(jni::JNIEnv& env) { return jni::Make<jni::String>(env, map->getStyle().getURL()); } -void NativeMapView::setStyleUrl(jni::JNIEnv& env, jni::String url) { +void NativeMapView::setStyleUrl(jni::JNIEnv& env, const jni::String& url) { map->getStyle().loadURL(jni::Make<std::string>(env, url)); } -jni::String NativeMapView::getStyleJson(jni::JNIEnv& env) { +jni::Local<jni::String> NativeMapView::getStyleJson(jni::JNIEnv& env) { return jni::Make<jni::String>(env, map->getStyle().getJSON()); } -void NativeMapView::setStyleJson(jni::JNIEnv& env, jni::String json) { +void NativeMapView::setStyleJson(jni::JNIEnv& env, const jni::String& json) { map->getStyle().loadJSON(jni::Make<std::string>(env, json)); } -void NativeMapView::setLatLngBounds(jni::JNIEnv& env, jni::Object<mbgl::android::LatLngBounds> jBounds) { +void NativeMapView::setLatLngBounds(jni::JNIEnv& env, const jni::Object<mbgl::android::LatLngBounds>& jBounds) { if (jBounds) { map->setLatLngBounds(mbgl::android::LatLngBounds::getLatLngBounds(env, jBounds)); } else { @@ -280,7 +281,7 @@ void NativeMapView::flyTo(jni::JNIEnv&, jni::jdouble angle, jni::jdouble latitud map->flyTo(cameraOptions, animationOptions); } -jni::Object<LatLng> NativeMapView::getLatLng(JNIEnv& env) { +jni::Local<jni::Object<LatLng>> NativeMapView::getLatLng(JNIEnv& env) { return LatLng::New(env, map->getLatLng(insets)); } @@ -288,12 +289,12 @@ void NativeMapView::setLatLng(jni::JNIEnv&, jni::jdouble latitude, jni::jdouble map->setLatLng(mbgl::LatLng(latitude, longitude), insets, mbgl::AnimationOptions{mbgl::Milliseconds(duration)}); } -jni::Object<CameraPosition> NativeMapView::getCameraForLatLngBounds(jni::JNIEnv& env, jni::Object<LatLngBounds> jBounds, double top, double left, double bottom, double right, double bearing, double tilt) { +jni::Local<jni::Object<CameraPosition>> NativeMapView::getCameraForLatLngBounds(jni::JNIEnv& env, const jni::Object<LatLngBounds>& jBounds, double top, double left, double bottom, double right, double bearing, double tilt) { mbgl::EdgeInsets padding = {top, left, bottom, right}; return CameraPosition::New(env, map->cameraForLatLngBounds(mbgl::android::LatLngBounds::getLatLngBounds(env, jBounds), padding, bearing, tilt)); } -jni::Object<CameraPosition> NativeMapView::getCameraForGeometry(jni::JNIEnv& env, jni::Object<geojson::Geometry> jGeometry, double top, double left, double bottom, double right, double bearing, double tilt) { +jni::Local<jni::Object<CameraPosition>> NativeMapView::getCameraForGeometry(jni::JNIEnv& env, const jni::Object<geojson::Geometry>& jGeometry, double top, double left, double bottom, double right, double bearing, double tilt) { auto geometry = geojson::Geometry::convert(env, jGeometry); mbgl::EdgeInsets padding = {top, left, bottom, right}; return CameraPosition::New(env, map->cameraForGeometry(geometry, padding, bearing, tilt)); @@ -368,7 +369,7 @@ void NativeMapView::resetNorth(jni::JNIEnv&) { map->resetNorth(); } -void NativeMapView::setVisibleCoordinateBounds(JNIEnv& env, jni::Array<jni::Object<LatLng>> coordinates, jni::Object<RectF> padding, jdouble direction, jni::jlong duration) { +void NativeMapView::setVisibleCoordinateBounds(JNIEnv& env, const jni::Array<jni::Object<LatLng>>& coordinates, const jni::Object<RectF>& padding, jdouble direction, jni::jlong duration) { NullCheck(env, &coordinates); std::size_t count = coordinates.Length(env); @@ -376,9 +377,7 @@ void NativeMapView::setVisibleCoordinateBounds(JNIEnv& env, jni::Array<jni::Obje latLngs.reserve(count); for (std::size_t i = 0; i < count; i++) { - auto latLng = coordinates.Get(env, i); - latLngs.push_back(LatLng::getLatLng(env, latLng)); - jni::DeleteLocalRef(env, latLng); + latLngs.push_back(LatLng::getLatLng(env, coordinates.Get(env, i))); } mbgl::EdgeInsets mbglInsets = { RectF::getTop(env, padding), RectF::getLeft(env, padding), RectF::getBottom(env, padding), RectF::getRight(env, padding) }; @@ -409,16 +408,17 @@ void NativeMapView::scheduleSnapshot(jni::JNIEnv&) { auto bitmap = Bitmap::CreateBitmap(*_env, std::move(image)); // invoke Mapview#OnSnapshotReady + static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env); static auto onSnapshotReady = javaClass.GetMethod<void (jni::Object<Bitmap>)>(*_env, "onSnapshotReady"); - javaPeer->Call(*_env, onSnapshotReady, bitmap); + javaPeer.get(*_env).Call(*_env, onSnapshotReady, bitmap); }); } -jni::Object<CameraPosition> NativeMapView::getCameraPosition(jni::JNIEnv& env) { +jni::Local<jni::Object<CameraPosition>> NativeMapView::getCameraPosition(jni::JNIEnv& env) { return CameraPosition::New(env, map->getCameraOptions(insets)); } -void NativeMapView::updateMarker(jni::JNIEnv& env, jni::jlong markerId, jni::jdouble lat, jni::jdouble lon, jni::String jid) { +void NativeMapView::updateMarker(jni::JNIEnv& env, jni::jlong markerId, jni::jdouble lat, jni::jdouble lon, const jni::String& jid) { if (markerId == -1) { return; } @@ -428,7 +428,7 @@ void NativeMapView::updateMarker(jni::JNIEnv& env, jni::jlong markerId, jni::jdo map->updateAnnotation(markerId, mbgl::SymbolAnnotation { mbgl::Point<double>(lon, lat), iconId }); } -jni::Array<jni::jlong> NativeMapView::addMarkers(jni::JNIEnv& env, jni::Array<jni::Object<Marker>> jmarkers) { +jni::Local<jni::Array<jni::jlong>> NativeMapView::addMarkers(jni::JNIEnv& env, const jni::Array<jni::Object<Marker>>& jmarkers) { jni::NullCheck(env, &jmarkers); std::size_t len = jmarkers.Length(env); @@ -436,13 +436,11 @@ jni::Array<jni::jlong> NativeMapView::addMarkers(jni::JNIEnv& env, jni::Array<jn ids.reserve(len); for (std::size_t i = 0; i < len; i++) { - jni::Object<Marker> marker = jmarkers.Get(env, i); + auto marker = jmarkers.Get(env, i); ids.push_back(map->addAnnotation(mbgl::SymbolAnnotation { Marker::getPosition(env, marker), Marker::getIconId(env, marker) })); - - jni::DeleteLocalRef(env, marker); } auto result = jni::Array<jni::jlong>::New(env, len); @@ -479,25 +477,25 @@ jni::jdouble NativeMapView::getMetersPerPixelAtLatitude(JNIEnv&, jni::jdouble la return mbgl::Projection::getMetersPerPixelAtLatitude(lat, zoom); } -jni::Object<ProjectedMeters> NativeMapView::projectedMetersForLatLng(JNIEnv& env, jni::jdouble latitude, jni::jdouble longitude) { +jni::Local<jni::Object<ProjectedMeters>> NativeMapView::projectedMetersForLatLng(JNIEnv& env, jni::jdouble latitude, jni::jdouble longitude) { mbgl::ProjectedMeters projectedMeters = mbgl::Projection::projectedMetersForLatLng(mbgl::LatLng(latitude, longitude)); return ProjectedMeters::New(env, projectedMeters.northing(), projectedMeters.easting()); } -jni::Object<LatLng> NativeMapView::latLngForProjectedMeters(JNIEnv& env, jdouble northing, jdouble easting) { +jni::Local<jni::Object<LatLng>> NativeMapView::latLngForProjectedMeters(JNIEnv& env, jdouble northing, jdouble easting) { return LatLng::New(env, mbgl::Projection::latLngForProjectedMeters(mbgl::ProjectedMeters(northing, easting))); } -jni::Object<PointF> NativeMapView::pixelForLatLng(JNIEnv& env, jdouble latitude, jdouble longitude) { +jni::Local<jni::Object<PointF>> NativeMapView::pixelForLatLng(JNIEnv& env, jdouble latitude, jdouble longitude) { mbgl::ScreenCoordinate pixel = map->pixelForLatLng(mbgl::LatLng(latitude, longitude)); return PointF::New(env, static_cast<float>(pixel.x), static_cast<float>(pixel.y)); } -jni::Object<LatLng> NativeMapView::latLngForPixel(JNIEnv& env, jfloat x, jfloat y) { +jni::Local<jni::Object<LatLng>> NativeMapView::latLngForPixel(JNIEnv& env, jfloat x, jfloat y) { return LatLng::New(env, map->latLngForPixel(mbgl::ScreenCoordinate(x, y))); } -jni::Array<jlong> NativeMapView::addPolylines(JNIEnv& env, jni::Array<jni::Object<Polyline>> polylines) { +jni::Local<jni::Array<jlong>> NativeMapView::addPolylines(JNIEnv& env, const jni::Array<jni::Object<Polyline>>& polylines) { NullCheck(env, &polylines); std::size_t len = polylines.Length(env); @@ -505,12 +503,8 @@ jni::Array<jlong> NativeMapView::addPolylines(JNIEnv& env, jni::Array<jni::Objec ids.reserve(len); for (std::size_t i = 0; i < len; i++) { - auto polyline = polylines.Get(env, i); - - mbgl::LineAnnotation annotation = Polyline::toAnnotation(env, polyline); + mbgl::LineAnnotation annotation = Polyline::toAnnotation(env, polylines.Get(env, i)); ids.push_back(map->addAnnotation(annotation)); - - jni::DeleteLocalRef(env, polyline); } auto result = jni::Array<jni::jlong>::New(env, len); @@ -520,7 +514,7 @@ jni::Array<jlong> NativeMapView::addPolylines(JNIEnv& env, jni::Array<jni::Objec } -jni::Array<jlong> NativeMapView::addPolygons(JNIEnv& env, jni::Array<jni::Object<Polygon>> polygons) { +jni::Local<jni::Array<jlong>> NativeMapView::addPolygons(JNIEnv& env, const jni::Array<jni::Object<Polygon>>& polygons) { NullCheck(env, &polygons); std::size_t len = polygons.Length(env); @@ -528,12 +522,8 @@ jni::Array<jlong> NativeMapView::addPolygons(JNIEnv& env, jni::Array<jni::Object ids.reserve(len); for (std::size_t i = 0; i < len; i++) { - auto polygon = polygons.Get(env, i); - - mbgl::FillAnnotation annotation = Polygon::toAnnotation(env, polygon); + mbgl::FillAnnotation annotation = Polygon::toAnnotation(env, polygons.Get(env, i)); ids.push_back(map->addAnnotation(annotation)); - - jni::DeleteLocalRef(env, polygon); } auto result = jni::Array<jni::jlong>::New(env, len); @@ -543,18 +533,18 @@ jni::Array<jlong> NativeMapView::addPolygons(JNIEnv& env, jni::Array<jni::Object } //TODO: Move to Polyline class and make native peer -void NativeMapView::updatePolyline(JNIEnv& env, jlong polylineId, jni::Object<Polyline> polyline) { +void NativeMapView::updatePolyline(JNIEnv& env, jlong polylineId, const jni::Object<Polyline>& polyline) { mbgl::LineAnnotation annotation = Polyline::toAnnotation(env, polyline); map->updateAnnotation(polylineId, annotation); } //TODO: Move to Polygon class and make native peer -void NativeMapView::updatePolygon(JNIEnv& env, jlong polygonId, jni::Object<Polygon> polygon) { +void NativeMapView::updatePolygon(JNIEnv& env, jlong polygonId, const jni::Object<Polygon>& polygon) { mbgl::FillAnnotation annotation = Polygon::toAnnotation(env, polygon); map->updateAnnotation(polygonId, annotation); } -void NativeMapView::removeAnnotations(JNIEnv& env, jni::Array<jlong> ids) { +void NativeMapView::removeAnnotations(JNIEnv& env, const jni::Array<jlong>& ids) { NullCheck(env, &ids); std::size_t len = ids.Length(env); auto elements = jni::GetArrayElements(env, *ids); @@ -568,7 +558,7 @@ void NativeMapView::removeAnnotations(JNIEnv& env, jni::Array<jlong> ids) { } } -void NativeMapView::addAnnotationIcon(JNIEnv& env, jni::String symbol, jint w, jint h, jfloat scale, jni::Array<jbyte> jpixels) { +void NativeMapView::addAnnotationIcon(JNIEnv& env, const jni::String& symbol, jint w, jint h, jfloat scale, const jni::Array<jbyte>& jpixels) { const std::string symbolName = jni::Make<std::string>(env, symbol); NullCheck(env, &jpixels); @@ -584,12 +574,12 @@ void NativeMapView::addAnnotationIcon(JNIEnv& env, jni::String symbol, jint w, j symbolName, std::move(premultipliedImage), float(scale))); } -void NativeMapView::removeAnnotationIcon(JNIEnv& env, jni::String symbol) { +void NativeMapView::removeAnnotationIcon(JNIEnv& env, const jni::String& symbol) { const std::string symbolName = jni::Make<std::string>(env, symbol); map->removeAnnotationImage(symbolName); } -jdouble NativeMapView::getTopOffsetPixelsForAnnotationSymbol(JNIEnv& env, jni::String symbolName) { +jdouble NativeMapView::getTopOffsetPixelsForAnnotationSymbol(JNIEnv& env, const jni::String& symbolName) { return map->getTopOffsetPixelsForAnnotationImage(jni::Make<std::string>(env, symbolName)); } @@ -615,7 +605,7 @@ void NativeMapView::setTransitionDelay(JNIEnv&, jlong delay) { map->getStyle().setTransitionOptions(transitionOptions); } -jni::Array<jlong> NativeMapView::queryPointAnnotations(JNIEnv& env, jni::Object<RectF> rect) { +jni::Local<jni::Array<jlong>> NativeMapView::queryPointAnnotations(JNIEnv& env, const jni::Object<RectF>& rect) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -636,7 +626,7 @@ jni::Array<jlong> NativeMapView::queryPointAnnotations(JNIEnv& env, jni::Object< return result; } -jni::Array<jlong> NativeMapView::queryShapeAnnotations(JNIEnv &env, jni::Object<RectF> rect) { +jni::Local<jni::Array<jlong>> NativeMapView::queryShapeAnnotations(JNIEnv& env, const jni::Object<RectF>& rect) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -656,31 +646,31 @@ jni::Array<jlong> NativeMapView::queryShapeAnnotations(JNIEnv &env, jni::Object< return result; } -jni::Array<jni::Object<geojson::Feature>> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y, - jni::Array<jni::String> layerIds, - jni::Array<jni::Object<>> jfilter) { +jni::Local<jni::Array<jni::Object<geojson::Feature>>> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y, + const jni::Array<jni::String>& layerIds, + const jni::Array<jni::Object<>>& jfilter) { using namespace mbgl::android::conversion; using namespace mbgl::android::geojson; mbgl::optional<std::vector<std::string>> layers; - if (layerIds != nullptr && layerIds.Length(env) > 0) { + if (layerIds && layerIds.Length(env) > 0) { layers = android::conversion::toVector(env, layerIds); } mapbox::geometry::point<double> point = {x, y}; - return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>( + return Feature::convert( env, rendererFrontend->queryRenderedFeatures(point, { layers, toFilter(env, jfilter) })); } -jni::Array<jni::Object<geojson::Feature>> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, - jni::jfloat right, jni::jfloat bottom, jni::Array<jni::String> layerIds, - jni::Array<jni::Object<>> jfilter) { +jni::Local<jni::Array<jni::Object<geojson::Feature>>> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, + jni::jfloat right, jni::jfloat bottom, const jni::Array<jni::String>& layerIds, + const jni::Array<jni::Object<>>& jfilter) { using namespace mbgl::android::conversion; using namespace mbgl::android::geojson; mbgl::optional<std::vector<std::string>> layers; - if (layerIds != nullptr && layerIds.Length(env) > 0) { + if (layerIds && layerIds.Length(env) > 0) { layers = toVector(env, layerIds); } mapbox::geometry::box<double> box = { @@ -688,52 +678,50 @@ jni::Array<jni::Object<geojson::Feature>> NativeMapView::queryRenderedFeaturesFo mapbox::geometry::point<double>{ right, bottom } }; - return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>( + return Feature::convert( env, rendererFrontend->queryRenderedFeatures(box, { layers, toFilter(env, jfilter) })); } -jni::Object<Light> NativeMapView::getLight(JNIEnv& env) { +jni::Local<jni::Object<Light>> NativeMapView::getLight(JNIEnv& env) { mbgl::style::Light* light = map->getStyle().getLight(); if (light) { - return jni::Object<Light>(Light::createJavaLightPeer(env, *map, *light)); + return Light::createJavaLightPeer(env, *map, *light); } else { - return jni::Object<Light>(); + return jni::Local<jni::Object<Light>>(); } } -jni::Array<jni::Object<Layer>> NativeMapView::getLayers(JNIEnv& env) { +jni::Local<jni::Array<jni::Object<Layer>>> NativeMapView::getLayers(JNIEnv& env) { // Get the core layers std::vector<style::Layer*> layers = map->getStyle().getLayers(); // Convert - jni::Array<jni::Object<Layer>> jLayers = jni::Array<jni::Object<Layer>>::New(env, layers.size(), Layer::javaClass); + auto jLayers = jni::Array<jni::Object<Layer>>::New(env, layers.size()); int index = 0; for (auto layer : layers) { - auto jLayer = jni::Object<Layer>(createJavaLayerPeer(env, *map, *layer)); - jLayers.Set(env, index, jLayer); - jni::DeleteLocalRef(env, jLayer); + jLayers.Set(env, index, createJavaLayerPeer(env, *map, *layer)); index++; } return jLayers; } -jni::Object<Layer> NativeMapView::getLayer(JNIEnv& env, jni::String layerId) { +jni::Local<jni::Object<Layer>> NativeMapView::getLayer(JNIEnv& env, const jni::String& layerId) { // Find the layer mbgl::style::Layer* coreLayer = map->getStyle().getLayer(jni::Make<std::string>(env, layerId)); if (!coreLayer) { mbgl::Log::Debug(mbgl::Event::JNI, "No layer found"); - return jni::Object<Layer>(); + return jni::Local<jni::Object<Layer>>(); } // Create and return the layer's native peer - return jni::Object<Layer>(createJavaLayerPeer(env, *map, *coreLayer)); + return createJavaLayerPeer(env, *map, *coreLayer); } -void NativeMapView::addLayer(JNIEnv& env, jlong nativeLayerPtr, jni::String before) { +void NativeMapView::addLayer(JNIEnv& env, jlong nativeLayerPtr, const jni::String& before) { assert(nativeLayerPtr != 0); Layer *layer = reinterpret_cast<Layer *>(nativeLayerPtr); @@ -744,7 +732,7 @@ void NativeMapView::addLayer(JNIEnv& env, jlong nativeLayerPtr, jni::String befo } } -void NativeMapView::addLayerAbove(JNIEnv& env, jlong nativeLayerPtr, jni::String above) { +void NativeMapView::addLayerAbove(JNIEnv& env, jlong nativeLayerPtr, const jni::String& above) { assert(nativeLayerPtr != 0); Layer *layer = reinterpret_cast<Layer *>(nativeLayerPtr); @@ -807,33 +795,33 @@ void NativeMapView::addLayerAt(JNIEnv& env, jlong nativeLayerPtr, jni::jint inde /** * Remove by layer id. */ -jni::Object<Layer> NativeMapView::removeLayerById(JNIEnv& env, jni::String id) { +jni::Local<jni::Object<Layer>> NativeMapView::removeLayerById(JNIEnv& env, const jni::String& id) { std::unique_ptr<mbgl::style::Layer> coreLayer = map->getStyle().removeLayer(jni::Make<std::string>(env, id)); if (coreLayer) { - return jni::Object<Layer>(createJavaLayerPeer(env, *map, std::move(coreLayer))); + return createJavaLayerPeer(env, *map, std::move(coreLayer)); } else { - return jni::Object<Layer>(); + return jni::Local<jni::Object<Layer>>(); } } /** * Remove layer at index. */ -jni::Object<Layer> NativeMapView::removeLayerAt(JNIEnv& env, jni::jint index) { +jni::Local<jni::Object<Layer>> NativeMapView::removeLayerAt(JNIEnv& env, jni::jint index) { auto layers = map->getStyle().getLayers(); // Check index int numLayers = layers.size() - 1; if (index > numLayers || index < 0) { Log::Warning(Event::JNI, "Index out of range: %i", index); - return jni::Object<Layer>(); + return jni::Local<jni::Object<Layer>>(); } std::unique_ptr<mbgl::style::Layer> coreLayer = map->getStyle().removeLayer(layers.at(index)->getID()); if (coreLayer) { - return jni::Object<Layer>(createJavaLayerPeer(env, *map, std::move(coreLayer))); + return createJavaLayerPeer(env, *map, std::move(coreLayer)); } else { - return jni::Object<Layer>(); + return jni::Local<jni::Object<Layer>>(); } } @@ -850,12 +838,12 @@ void NativeMapView::removeLayer(JNIEnv&, jlong layerPtr) { } } -jni::Array<jni::Object<Source>> NativeMapView::getSources(JNIEnv& env) { +jni::Local<jni::Array<jni::Object<Source>>> NativeMapView::getSources(JNIEnv& env) { // Get the core sources std::vector<style::Source*> sources = map->getStyle().getSources(); // Convert - jni::Array<jni::Object<Source>> jSources = jni::Array<jni::Object<Source>>::New(env, sources.size(), Source::javaClass); + auto jSources = jni::Array<jni::Object<Source>>::New(env, sources.size()); int index = 0; for (auto source : sources) { jSources.Set(env, index, Source::peerForCoreSource(env, *source, *rendererFrontend)); @@ -865,19 +853,19 @@ jni::Array<jni::Object<Source>> NativeMapView::getSources(JNIEnv& env) { return jSources; } -jni::Object<Source> NativeMapView::getSource(JNIEnv& env, jni::String sourceId) { +jni::Local<jni::Object<Source>> NativeMapView::getSource(JNIEnv& env, const jni::String& sourceId) { // Find the source mbgl::style::Source* coreSource = map->getStyle().getSource(jni::Make<std::string>(env, sourceId)); if (!coreSource) { mbgl::Log::Debug(mbgl::Event::JNI, "No source found"); - return jni::Object<Source>(); + return jni::Local<jni::Object<Source>>(); } // Create and return the source's native peer - return Source::peerForCoreSource(env, *coreSource, *rendererFrontend); + return jni::NewLocal(env, Source::peerForCoreSource(env, *coreSource, *rendererFrontend)); } -void NativeMapView::addSource(JNIEnv& env, jni::Object<Source> obj, jlong sourcePtr) { +void NativeMapView::addSource(JNIEnv& env, const jni::Object<Source>& obj, jlong sourcePtr) { assert(sourcePtr != 0); Source *source = reinterpret_cast<Source *>(sourcePtr); @@ -888,7 +876,7 @@ void NativeMapView::addSource(JNIEnv& env, jni::Object<Source> obj, jlong source } } -void NativeMapView::removeSource(JNIEnv& env, jni::Object<Source> obj, jlong sourcePtr) { +void NativeMapView::removeSource(JNIEnv& env, const jni::Object<Source>& obj, jlong sourcePtr) { assert(sourcePtr != 0); mbgl::android::Source *source = reinterpret_cast<mbgl::android::Source *>(sourcePtr); @@ -897,7 +885,7 @@ void NativeMapView::removeSource(JNIEnv& env, jni::Object<Source> obj, jlong sou } } -void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::Object<Bitmap> bitmap, jni::jfloat scale, jni::jboolean sdf) { +void NativeMapView::addImage(JNIEnv& env, const jni::String& name, const jni::Object<Bitmap>& bitmap, jni::jfloat scale, jni::jboolean sdf) { jni::NullCheck(env, &bitmap); mbgl::PremultipliedImage premultipliedImage = Bitmap::GetImage(env, bitmap); @@ -909,28 +897,26 @@ void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::Object<Bitmap> ); } -void NativeMapView::addImages(JNIEnv& env, jni::Array<jni::Object<mbgl::android::Image>> jimages) { +void NativeMapView::addImages(JNIEnv& env, const jni::Array<jni::Object<mbgl::android::Image>>& jimages) { jni::NullCheck(env, &jimages); std::size_t len = jimages.Length(env); for (std::size_t i = 0; i < len; i++) { - jni::Object<mbgl::android::Image> jimage = jimages.Get(env, i); - auto image = mbgl::android::Image::getImage(env, jimage); + auto image = mbgl::android::Image::getImage(env, jimages.Get(env, i)); map->getStyle().addImage(std::make_unique<mbgl::style::Image>(image)); - jni::DeleteLocalRef(env, jimage); } } -void NativeMapView::removeImage(JNIEnv& env, jni::String name) { +void NativeMapView::removeImage(JNIEnv& env, const jni::String& name) { map->getStyle().removeImage(jni::Make<std::string>(env, name)); } -jni::Object<Bitmap> NativeMapView::getImage(JNIEnv& env, jni::String name) { +jni::Local<jni::Object<Bitmap>> NativeMapView::getImage(JNIEnv& env, const jni::String& name) { const mbgl::style::Image *image = map->getStyle().getImage(jni::Make<std::string>(env, name)); if (image) { return Bitmap::CreateBitmap(env, image->getImage()); } else { - return jni::Object<Bitmap>(); + return jni::Local<jni::Object<Bitmap>>(); } } @@ -948,17 +934,15 @@ mbgl::Map& NativeMapView::getMap() { // Static methods // -jni::Class<NativeMapView> NativeMapView::javaClass; - void NativeMapView::registerNative(jni::JNIEnv& env) { // Lookup the class - NativeMapView::javaClass = *jni::Class<NativeMapView>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<NativeMapView>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<NativeMapView>(env, NativeMapView::javaClass, "nativePtr", - std::make_unique<NativeMapView, JNIEnv&, jni::Object<NativeMapView>, jni::Object<FileSource>, jni::Object<MapRenderer>, jni::jfloat>, + jni::RegisterNativePeer<NativeMapView>(env, javaClass, "nativePtr", + jni::MakePeer<NativeMapView, const jni::Object<NativeMapView>&, const jni::Object<FileSource>&, const jni::Object<MapRenderer>&, jni::jfloat>, "nativeInitialize", "nativeDestroy", METHOD(&NativeMapView::resizeView, "nativeResizeView"), diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index e57767032..969833a25 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -45,14 +45,12 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/NativeMapView"; }; - static jni::Class<NativeMapView> javaClass; - static void registerNative(jni::JNIEnv&); NativeMapView(jni::JNIEnv&, - jni::Object<NativeMapView>, - jni::Object<FileSource>, - jni::Object<MapRenderer>, + const jni::Object<NativeMapView>&, + const jni::Object<FileSource>&, + const jni::Object<MapRenderer>&, jni::jfloat pixelRatio); virtual ~NativeMapView(); @@ -78,15 +76,15 @@ public: void resizeView(jni::JNIEnv&, int, int); - jni::String getStyleUrl(jni::JNIEnv&); + jni::Local<jni::String> getStyleUrl(jni::JNIEnv&); - void setStyleUrl(jni::JNIEnv&, jni::String); + void setStyleUrl(jni::JNIEnv&, const jni::String&); - jni::String getStyleJson(jni::JNIEnv&); + jni::Local<jni::String> getStyleJson(jni::JNIEnv&); - void setStyleJson(jni::JNIEnv&, jni::String); + void setStyleJson(jni::JNIEnv&, const jni::String&); - void setLatLngBounds(jni::JNIEnv&, jni::Object<mbgl::android::LatLngBounds>); + void setLatLngBounds(jni::JNIEnv&, const jni::Object<mbgl::android::LatLngBounds>&); void cancelTransitions(jni::JNIEnv&); @@ -100,13 +98,13 @@ public: void flyTo(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong, jni::jdouble, jni::jdouble); - jni::Object<LatLng> getLatLng(JNIEnv&); + jni::Local<jni::Object<LatLng>> getLatLng(JNIEnv&); void setLatLng(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jlong); - jni::Object<CameraPosition> getCameraForLatLngBounds(jni::JNIEnv&, jni::Object<mbgl::android::LatLngBounds>, double top, double left, double bottom, double right, double bearing, double tilt); + jni::Local<jni::Object<CameraPosition>> getCameraForLatLngBounds(jni::JNIEnv&, const jni::Object<mbgl::android::LatLngBounds>&, double top, double left, double bottom, double right, double bearing, double tilt); - jni::Object<CameraPosition> getCameraForGeometry(jni::JNIEnv&, jni::Object<geojson::Geometry>, double top, double left, double bottom, double right, double bearing, double tilt); + jni::Local<jni::Object<CameraPosition>> getCameraForGeometry(jni::JNIEnv&, const jni::Object<geojson::Geometry>&, double top, double left, double bottom, double right, double bearing, double tilt); void setReachability(jni::JNIEnv&, jni::jboolean); @@ -140,17 +138,17 @@ public: void resetNorth(jni::JNIEnv&); - void setVisibleCoordinateBounds(JNIEnv&, jni::Array<jni::Object<LatLng>>, jni::Object<RectF>, jni::jdouble, jni::jlong); + void setVisibleCoordinateBounds(JNIEnv&, const jni::Array<jni::Object<LatLng>>&, const jni::Object<RectF>&, jni::jdouble, jni::jlong); void setContentPadding(JNIEnv&, double, double, double, double); void scheduleSnapshot(jni::JNIEnv&); - jni::Object<CameraPosition> getCameraPosition(jni::JNIEnv&); + jni::Local<jni::Object<CameraPosition>> getCameraPosition(jni::JNIEnv&); - void updateMarker(jni::JNIEnv&, jni::jlong, jni::jdouble, jni::jdouble, jni::String); + void updateMarker(jni::JNIEnv&, jni::jlong, jni::jdouble, jni::jdouble, const jni::String&); - jni::Array<jni::jlong> addMarkers(jni::JNIEnv&, jni::Array<jni::Object<Marker>>); + jni::Local<jni::Array<jni::jlong>> addMarkers(jni::JNIEnv&, const jni::Array<jni::Object<Marker>>&); void onLowMemory(JNIEnv& env); @@ -164,29 +162,29 @@ public: jni::jdouble getMetersPerPixelAtLatitude(JNIEnv&, jni::jdouble, jni::jdouble); - jni::Object<ProjectedMeters> projectedMetersForLatLng(JNIEnv&, jni::jdouble, jni::jdouble); + jni::Local<jni::Object<ProjectedMeters>> projectedMetersForLatLng(JNIEnv&, jni::jdouble, jni::jdouble); - jni::Object<PointF> pixelForLatLng(JNIEnv&, jdouble, jdouble); + jni::Local<jni::Object<PointF>> pixelForLatLng(JNIEnv&, jdouble, jdouble); - jni::Object<LatLng> latLngForProjectedMeters(JNIEnv&, jdouble, jdouble); + jni::Local<jni::Object<LatLng>> latLngForProjectedMeters(JNIEnv&, jdouble, jdouble); - jni::Object<LatLng> latLngForPixel(JNIEnv&, jfloat, jfloat); + jni::Local<jni::Object<LatLng>> latLngForPixel(JNIEnv&, jfloat, jfloat); - jni::Array<jlong> addPolylines(JNIEnv&, jni::Array<jni::Object<Polyline>>); + jni::Local<jni::Array<jlong>> addPolylines(JNIEnv&, const jni::Array<jni::Object<Polyline>>&); - jni::Array<jlong> addPolygons(JNIEnv&, jni::Array<jni::Object<Polygon>>); + jni::Local<jni::Array<jlong>> addPolygons(JNIEnv&, const jni::Array<jni::Object<Polygon>>&); - void updatePolyline(JNIEnv&, jlong, jni::Object<Polyline>); + void updatePolyline(JNIEnv&, jlong, const jni::Object<Polyline>&); - void updatePolygon(JNIEnv&, jlong, jni::Object<Polygon>); + void updatePolygon(JNIEnv&, jlong, const jni::Object<Polygon>&); - void removeAnnotations(JNIEnv&, jni::Array<jlong>); + void removeAnnotations(JNIEnv&, const jni::Array<jlong>&); - void addAnnotationIcon(JNIEnv&, jni::String, jint, jint, jfloat, jni::Array<jbyte>); + void addAnnotationIcon(JNIEnv&, const jni::String&, jint, jint, jfloat, const jni::Array<jbyte>&); - void removeAnnotationIcon(JNIEnv&, jni::String); + void removeAnnotationIcon(JNIEnv&, const jni::String&); - jni::jdouble getTopOffsetPixelsForAnnotationSymbol(JNIEnv&, jni::String); + jni::jdouble getTopOffsetPixelsForAnnotationSymbol(JNIEnv&, const jni::String&); jni::jlong getTransitionDuration(JNIEnv&); @@ -196,53 +194,53 @@ public: void setTransitionDelay(JNIEnv&, jni::jlong); - jni::Array<jlong> queryPointAnnotations(JNIEnv&, jni::Object<RectF>); + jni::Local<jni::Array<jlong>> queryPointAnnotations(JNIEnv&, const jni::Object<RectF>&); - jni::Array<jlong> queryShapeAnnotations(JNIEnv&, jni::Object<RectF>); + jni::Local<jni::Array<jlong>> queryShapeAnnotations(JNIEnv&, const jni::Object<RectF>&); - jni::Array<jni::Object<geojson::Feature>> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat, - jni::Array<jni::String>, - jni::Array<jni::Object<>> jfilter); + jni::Local<jni::Array<jni::Object<geojson::Feature>>> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat, + const jni::Array<jni::String>&, + const jni::Array<jni::Object<>>& jfilter); - jni::Array<jni::Object<geojson::Feature>> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat, - jni::jfloat, jni::Array<jni::String>, - jni::Array<jni::Object<>> jfilter); + jni::Local<jni::Array<jni::Object<geojson::Feature>>> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat, + jni::jfloat, const jni::Array<jni::String>&, + const jni::Array<jni::Object<>>& jfilter); - jni::Object<Light> getLight(JNIEnv&); + jni::Local<jni::Object<Light>> getLight(JNIEnv&); - jni::Array<jni::Object<Layer>> getLayers(JNIEnv&); + jni::Local<jni::Array<jni::Object<Layer>>> getLayers(JNIEnv&); - jni::Object<Layer> getLayer(JNIEnv&, jni::String); + jni::Local<jni::Object<Layer>> getLayer(JNIEnv&, const jni::String&); - void addLayer(JNIEnv&, jlong, jni::String); + void addLayer(JNIEnv&, jlong, const jni::String&); - void addLayerAbove(JNIEnv&, jlong, jni::String); + void addLayerAbove(JNIEnv&, jlong, const jni::String&); void addLayerAt(JNIEnv&, jni::jlong, jni::jint); - jni::Object<Layer> removeLayerById(JNIEnv&, jni::String); + jni::Local<jni::Object<Layer>> removeLayerById(JNIEnv&, const jni::String&); - jni::Object<Layer> removeLayerAt(JNIEnv&, jni::jint); + jni::Local<jni::Object<Layer>> removeLayerAt(JNIEnv&, jni::jint); void removeLayer(JNIEnv&, jlong); - jni::Array<jni::Object<Source>> getSources(JNIEnv&); + jni::Local<jni::Array<jni::Object<Source>>> getSources(JNIEnv&); - jni::Object<Source> getSource(JNIEnv&, jni::String); + jni::Local<jni::Object<Source>> getSource(JNIEnv&, const jni::String&); - void addSource(JNIEnv&, jni::Object<Source>, jlong nativePtr); + void addSource(JNIEnv&, const jni::Object<Source>&, jlong nativePtr); - jni::Object<Source> removeSourceById(JNIEnv&, jni::String); + jni::Local<jni::Object<Source>> removeSourceById(JNIEnv&, const jni::String&); - void removeSource(JNIEnv&, jni::Object<Source>, jlong nativePtr); + void removeSource(JNIEnv&, const jni::Object<Source>&, jlong nativePtr); - void addImage(JNIEnv&, jni::String, jni::Object<Bitmap> bitmap, jni::jfloat, jni::jboolean); + void addImage(JNIEnv&, const jni::String&, const jni::Object<Bitmap>& bitmap, jni::jfloat, jni::jboolean); - void addImages(JNIEnv&, jni::Array<jni::Object<mbgl::android::Image>>); + void addImages(JNIEnv&, const jni::Array<jni::Object<mbgl::android::Image>>&); - void removeImage(JNIEnv&, jni::String); + void removeImage(JNIEnv&, const jni::String&); - jni::Object<Bitmap> getImage(JNIEnv&, jni::String); + jni::Local<jni::Object<Bitmap>> getImage(JNIEnv&, const jni::String&); void setPrefetchesTiles(JNIEnv&, jni::jboolean); @@ -254,7 +252,7 @@ private: std::unique_ptr<AndroidRendererFrontend> rendererFrontend; JavaVM *vm = nullptr; - jni::UniqueWeakObject<NativeMapView> javaPeer; + jni::WeakReference<jni::Object<NativeMapView>> javaPeer; MapRenderer& mapRenderer; diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp index e96ed7e4d..b27af8bda 100644 --- a/platform/android/src/offline/offline_manager.cpp +++ b/platform/android/src/offline/offline_manager.cpp @@ -3,14 +3,13 @@ #include <mbgl/util/string.hpp> #include "../attach_env.hpp" -#include "../jni/generic_global_ref_deleter.hpp" namespace mbgl { namespace android { // OfflineManager // -OfflineManager::OfflineManager(jni::JNIEnv& env, jni::Object<FileSource> jFileSource) +OfflineManager::OfflineManager(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) : fileSource(mbgl::android::FileSource::getDefaultFileSource(env, jFileSource)) { } @@ -20,12 +19,14 @@ void OfflineManager::setOfflineMapboxTileCountLimit(jni::JNIEnv&, jni::jlong lim fileSource.setOfflineMapboxTileCountLimit(limit); } -void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, jni::Object<FileSource> jFileSource_, jni::Object<ListOfflineRegionsCallback> callback_) { - // list regions +void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, const jni::Object<FileSource>& jFileSource_, const jni::Object<ListOfflineRegionsCallback>& callback_) { + auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_); + auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_); + fileSource.listOfflineRegions([ //Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile - callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()), - jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)), + jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource)) ](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> regions) mutable { // Reattach, the callback comes from a different thread @@ -33,20 +34,19 @@ void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, jni::Object<FileSourc if (regions) { OfflineManager::ListOfflineRegionsCallback::onList( - *env, jni::Object<FileSource>(*jFileSource), - jni::Object<ListOfflineRegionsCallback>(*callback), std::move(*regions)); + *env, *jFileSource, *callback, std::move(*regions)); } else { OfflineManager::ListOfflineRegionsCallback::onError( - *env, jni::Object<ListOfflineRegionsCallback>(*callback), regions.error()); + *env, *callback, regions.error()); } }); } void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, - jni::Object<FileSource> jFileSource_, - jni::Object<OfflineRegionDefinition> definition_, - jni::Array<jni::jbyte> metadata_, - jni::Object<CreateOfflineRegionCallback> callback_) { + const jni::Object<FileSource>& jFileSource_, + const jni::Object<OfflineRegionDefinition>& definition_, + const jni::Array<jni::jbyte>& metadata_, + const jni::Object<CreateOfflineRegionCallback>& callback_) { // Convert auto definition = OfflineRegionDefinition::getDefinition(env_, definition_); @@ -55,11 +55,14 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, metadata = OfflineRegion::metadata(env_, metadata_); } + auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_); + auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_); + // Create region fileSource.createOfflineRegion(definition, metadata, [ //Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile - callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()), - jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)), + jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource)) ](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> region) mutable { // Reattach, the callback comes from a different thread @@ -67,28 +70,25 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, if (region) { OfflineManager::CreateOfflineRegionCallback::onCreate( - *env, - jni::Object<FileSource>(*jFileSource), - jni::Object<CreateOfflineRegionCallback>(*callback), std::move(*region) + *env, *jFileSource, *callback, std::move(*region) ); } else { - OfflineManager::CreateOfflineRegionCallback::onError(*env, jni::Object<CreateOfflineRegionCallback>(*callback), region.error()); + OfflineManager::CreateOfflineRegionCallback::onError( + *env, *callback, region.error()); } }); } -jni::Class<OfflineManager> OfflineManager::javaClass; - void OfflineManager::registerNative(jni::JNIEnv& env) { - OfflineManager::ListOfflineRegionsCallback::registerNative(env); - OfflineManager::CreateOfflineRegionCallback::registerNative(env); + jni::Class<ListOfflineRegionsCallback>::Singleton(env); + jni::Class<CreateOfflineRegionCallback>::Singleton(env); - javaClass = *jni::Class<OfflineManager>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<OfflineManager>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) jni::RegisterNativePeer<OfflineManager>( env, javaClass, "nativePtr", - std::make_unique<OfflineManager, JNIEnv&, jni::Object<FileSource>>, + jni::MakePeer<OfflineManager, const jni::Object<FileSource>&>, "initialize", "finalize", METHOD(&OfflineManager::setOfflineMapboxTileCountLimit, "setOfflineMapboxTileCountLimit"), @@ -99,70 +99,50 @@ void OfflineManager::registerNative(jni::JNIEnv& env) { // OfflineManager::ListOfflineRegionsCallback // void OfflineManager::ListOfflineRegionsCallback::onError(jni::JNIEnv& env, - jni::Object<OfflineManager::ListOfflineRegionsCallback> callback, + const jni::Object<OfflineManager::ListOfflineRegionsCallback>& callback, std::exception_ptr error) { + static auto& javaClass = jni::Class<OfflineManager::ListOfflineRegionsCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error))); } void OfflineManager::ListOfflineRegionsCallback::onList(jni::JNIEnv& env, - jni::Object<FileSource> jFileSource, - jni::Object<OfflineManager::ListOfflineRegionsCallback> callback, + const jni::Object<FileSource>& jFileSource, + const jni::Object<OfflineManager::ListOfflineRegionsCallback>& callback, mbgl::optional<std::vector<mbgl::OfflineRegion>> regions) { - //Convert the regions to java peer objects + static auto& javaClass = jni::Class<OfflineManager::ListOfflineRegionsCallback>::Singleton(env); + static auto method = javaClass.GetMethod<void (jni::Array<jni::Object<OfflineRegion>>)>(env, "onList"); + std::size_t index = 0; - auto jregions = jni::Array<jni::Object<OfflineRegion>>::New(env, regions->size(), OfflineRegion::javaClass); + auto jregions = jni::Array<jni::Object<OfflineRegion>>::New(env, regions->size()); for (auto& region : *regions) { - auto jregion = OfflineRegion::New(env, jFileSource, std::move(region)); - jregions.Set(env, index, jregion); - jni::DeleteLocalRef(env, jregion); + jregions.Set(env, index, OfflineRegion::New(env, jFileSource, std::move(region))); index++; } - // Trigger callback - static auto method = javaClass.GetMethod<void (jni::Array<jni::Object<OfflineRegion>>)>(env, "onList"); callback.Call(env, method, jregions); - jni::DeleteLocalRef(env, jregions); -} - -jni::Class<OfflineManager::ListOfflineRegionsCallback> OfflineManager::ListOfflineRegionsCallback::javaClass; - -void OfflineManager::ListOfflineRegionsCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineManager::ListOfflineRegionsCallback>::Find(env).NewGlobalRef(env).release(); } // OfflineManager::CreateOfflineRegionCallback // void OfflineManager::CreateOfflineRegionCallback::onError(jni::JNIEnv& env, - jni::Object<OfflineManager::CreateOfflineRegionCallback> callback, + const jni::Object<OfflineManager::CreateOfflineRegionCallback>& callback, std::exception_ptr error) { + static auto& javaClass = jni::Class<OfflineManager::CreateOfflineRegionCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error))); } void OfflineManager::CreateOfflineRegionCallback::onCreate(jni::JNIEnv& env, - jni::Object<FileSource> jFileSource, - jni::Object<OfflineManager::CreateOfflineRegionCallback> callback, + const jni::Object<FileSource>& jFileSource, + const jni::Object<OfflineManager::CreateOfflineRegionCallback>& callback, mbgl::optional<mbgl::OfflineRegion> region) { - // Convert the region to java peer object - auto jregion = OfflineRegion::New(env, jFileSource, std::move(*region)); - - // Trigger callback + static auto& javaClass = jni::Class<OfflineManager::CreateOfflineRegionCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegion>)>(env, "onCreate"); - callback.Call(env, method, jregion); - jni::DeleteLocalRef(env, jregion); -} - -jni::Class<OfflineManager::CreateOfflineRegionCallback> OfflineManager::CreateOfflineRegionCallback::javaClass; -void OfflineManager::CreateOfflineRegionCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineManager::CreateOfflineRegionCallback>::Find(env).NewGlobalRef(env).release(); + callback.Call(env, method, OfflineRegion::New(env, jFileSource, std::move(*region))); } } // namespace android diff --git a/platform/android/src/offline/offline_manager.hpp b/platform/android/src/offline/offline_manager.hpp index 9ae2714ca..21ca5ca9c 100644 --- a/platform/android/src/offline/offline_manager.hpp +++ b/platform/android/src/offline/offline_manager.hpp @@ -20,52 +20,42 @@ public: public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$ListOfflineRegionsCallback";} - static void onError(jni::JNIEnv&, jni::Object<OfflineManager::ListOfflineRegionsCallback>, std::exception_ptr); + static void onError(jni::JNIEnv&, const jni::Object<OfflineManager::ListOfflineRegionsCallback>&, std::exception_ptr); static void onList(jni::JNIEnv&, - jni::Object<FileSource>, - jni::Object<OfflineManager::ListOfflineRegionsCallback>, + const jni::Object<FileSource>&, + const jni::Object<OfflineManager::ListOfflineRegionsCallback>&, mbgl::optional<std::vector<mbgl::OfflineRegion>>); - - static jni::Class<OfflineManager::ListOfflineRegionsCallback> javaClass; - - static void registerNative(jni::JNIEnv&); }; class CreateOfflineRegionCallback { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$CreateOfflineRegionCallback"; } - static void onError(jni::JNIEnv&, jni::Object<OfflineManager::CreateOfflineRegionCallback>, std::exception_ptr); + static void onError(jni::JNIEnv&, const jni::Object<OfflineManager::CreateOfflineRegionCallback>&, std::exception_ptr); static void onCreate(jni::JNIEnv&, - jni::Object<FileSource>, - jni::Object<OfflineManager::CreateOfflineRegionCallback>, + const jni::Object<FileSource>&, + const jni::Object<OfflineManager::CreateOfflineRegionCallback>&, mbgl::optional<mbgl::OfflineRegion>); - - static jni::Class<OfflineManager::CreateOfflineRegionCallback> javaClass; - - static void registerNative(jni::JNIEnv&); }; static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager"; }; - static jni::Class<OfflineManager> javaClass; - static void registerNative(jni::JNIEnv&); - OfflineManager(jni::JNIEnv&, jni::Object<FileSource>); + OfflineManager(jni::JNIEnv&, const jni::Object<FileSource>&); ~OfflineManager(); void setOfflineMapboxTileCountLimit(jni::JNIEnv&, jni::jlong limit); - void listOfflineRegions(jni::JNIEnv&, jni::Object<FileSource>, jni::Object<ListOfflineRegionsCallback> callback); + void listOfflineRegions(jni::JNIEnv&, const jni::Object<FileSource>&, const jni::Object<ListOfflineRegionsCallback>& callback); void createOfflineRegion(jni::JNIEnv&, - jni::Object<FileSource> jFileSource_, - jni::Object<OfflineRegionDefinition> definition, - jni::Array<jni::jbyte> metadata, - jni::Object<OfflineManager::CreateOfflineRegionCallback> callback); + const jni::Object<FileSource>& jFileSource_, + const jni::Object<OfflineRegionDefinition>& definition, + const jni::Array<jni::jbyte>& metadata, + const jni::Object<OfflineManager::CreateOfflineRegionCallback>& callback); private: mbgl::DefaultFileSource& fileSource; diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp index 5ed37eda7..1cd73a7c7 100644 --- a/platform/android/src/offline/offline_region.cpp +++ b/platform/android/src/offline/offline_region.cpp @@ -7,81 +7,62 @@ #include "offline_region_error.hpp" #include "offline_region_status.hpp" #include "../attach_env.hpp" -#include "../jni/generic_global_ref_deleter.hpp" namespace mbgl { namespace android { // OfflineRegion // -OfflineRegion::OfflineRegion(jni::JNIEnv& env, jni::jlong offlineRegionPtr, jni::Object<FileSource> jFileSource) +OfflineRegion::OfflineRegion(jni::JNIEnv& env, jni::jlong offlineRegionPtr, const jni::Object<FileSource>& jFileSource) : region(reinterpret_cast<mbgl::OfflineRegion *>(offlineRegionPtr)), fileSource(mbgl::android::FileSource::getDefaultFileSource(env, jFileSource)) {} OfflineRegion::~OfflineRegion() {} -void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, jni::Object<OfflineRegion::OfflineRegionObserver> callback) { +void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, const jni::Object<OfflineRegion::OfflineRegionObserver>& callback) { // Define the observer class Observer : public mbgl::OfflineRegionObserver { public: - Observer(jni::UniqueObject<OfflineRegion::OfflineRegionObserver>&& callback_) - //TODO add a generic deleter for jni::Object - : callback(callback_.release()->Get()) { - } - - ~Observer() override { - android::UniqueEnv env = android::AttachEnv(); - env->DeleteGlobalRef(Unwrap(*callback)); + Observer(jni::Global<jni::Object<OfflineRegion::OfflineRegionObserver>, jni::EnvAttachingDeleter> callback_) + : callback(std::move(callback_)) { } void statusChanged(mbgl::OfflineRegionStatus status) override { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); - // Status object - auto jStatus = OfflineRegionStatus::New(*env, status); + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env); + static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegionStatus>)>(*env, "onStatusChanged"); - // Call - static auto method = OfflineRegion::OfflineRegionObserver::javaClass - .GetMethod<void (jni::Object<OfflineRegionStatus>)>(*env, "onStatusChanged"); - callback.Call(*env, method, jStatus); - - // Delete references - jni::DeleteLocalRef(*env, jStatus); + callback.Call(*env, method, OfflineRegionStatus::New(*env, status)); } void responseError(mbgl::Response::Error error) override { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); - // Error object - auto jError = OfflineRegionError::New(*env, error); - - // Call - static auto method = OfflineRegion::OfflineRegionObserver::javaClass - .GetMethod<void (jni::Object<mbgl::android::OfflineRegionError>)>(*env, "onError"); - callback.Call(*env, method, jError); + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env); + static auto method = javaClass.GetMethod<void (jni::Object<mbgl::android::OfflineRegionError>)>(*env, "onError"); - // Delete references - jni::DeleteLocalRef(*env, jError); + callback.Call(*env, method, OfflineRegionError::New(*env, error)); } void mapboxTileCountLimitExceeded(uint64_t limit) override { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); - // Send limit - static auto method = OfflineRegion::OfflineRegionObserver::javaClass - .GetMethod<void (jni::jlong)>(*env, "mapboxTileCountLimitExceeded"); + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env); + static auto method = javaClass.GetMethod<void (jni::jlong)>(*env, "mapboxTileCountLimitExceeded"); + callback.Call(*env, method, jlong(limit)); } - jni::Object<OfflineRegion::OfflineRegionObserver> callback; + jni::Global<jni::Object<OfflineRegion::OfflineRegionObserver>, jni::EnvAttachingDeleter> callback; }; // Set the observer - fileSource.setOfflineRegionObserver(*region, std::make_unique<Observer>(callback.NewGlobalRef(env_))); + fileSource.setOfflineRegionObserver(*region, std::make_unique<Observer>(jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback))); } void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState) { @@ -102,89 +83,84 @@ void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState fileSource.setOfflineRegionDownloadState(*region, state); } -void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, jni::Object<OfflineRegionStatusCallback> callback_) { +void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, const jni::Object<OfflineRegionStatusCallback>& callback_) { + auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_); fileSource.getOfflineRegionStatus(*region, [ //Ensure the object is not gc'd in the meanwhile - callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)) ](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); if (status) { - OfflineRegionStatusCallback::onStatus(*env, jni::Object<OfflineRegionStatusCallback>(*callback), std::move(*status)); + OfflineRegionStatusCallback::onStatus(*env, *callback, std::move(*status)); } else { - OfflineRegionStatusCallback::onError(*env, jni::Object<OfflineRegionStatusCallback>(*callback), status.error()); + OfflineRegionStatusCallback::onError(*env, *callback, status.error()); } }); } -void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, jni::Object<OfflineRegionDeleteCallback> callback_) { - // Delete +void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, const jni::Object<OfflineRegionDeleteCallback>& callback_) { + auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_); + fileSource.deleteOfflineRegion(std::move(*region), [ //Ensure the object is not gc'd in the meanwhile - callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)) ](std::exception_ptr error) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); if (error) { - OfflineRegionDeleteCallback::onError(*env, jni::Object<OfflineRegionDeleteCallback>(*callback), error); + OfflineRegionDeleteCallback::onError(*env, *callback, error); } else { - OfflineRegionDeleteCallback::onDelete(*env, jni::Object<OfflineRegionDeleteCallback>(*callback)); + OfflineRegionDeleteCallback::onDelete(*env, *callback); } }); } -void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::Array<jni::jbyte> jMetadata, jni::Object<OfflineRegionUpdateMetadataCallback> callback_) { - - // Convert +void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, const jni::Array<jni::jbyte>& jMetadata, const jni::Object<OfflineRegionUpdateMetadataCallback>& callback_) { auto metadata = OfflineRegion::metadata(env_, jMetadata); + auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_); fileSource.updateOfflineMetadata(region->getID(), metadata, [ //Ensure the object is not gc'd in the meanwhile - callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)) ](mbgl::expected<mbgl::OfflineRegionMetadata, std::exception_ptr> data) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); if (data) { - OfflineRegionUpdateMetadataCallback::onUpdate(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), std::move(*data)); + OfflineRegionUpdateMetadataCallback::onUpdate(*env, *callback, std::move(*data)); } else { - OfflineRegionUpdateMetadataCallback::onError(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), data.error()); + OfflineRegionUpdateMetadataCallback::onError(*env, *callback, data.error()); } }); } -jni::Object<OfflineRegion> OfflineRegion::New(jni::JNIEnv& env, jni::Object<FileSource> jFileSource, mbgl::OfflineRegion region) { +jni::Local<jni::Object<OfflineRegion>> OfflineRegion::New(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource, mbgl::OfflineRegion region) { // Definition auto definition = region.getDefinition().match( [&](const mbgl::OfflineTilePyramidRegionDefinition def) { - return jni::Object<OfflineRegionDefinition>( - *OfflineTilePyramidRegionDefinition::New(env, def)); + return OfflineTilePyramidRegionDefinition::New(env, def); }, [&](const mbgl::OfflineGeometryRegionDefinition def) { - return jni::Object<OfflineRegionDefinition>( - *OfflineGeometryRegionDefinition::New(env, def)); + return OfflineGeometryRegionDefinition::New(env, def); }); - // Metadata - auto metadata = OfflineRegion::metadata(env, region.getMetadata()); - // Create region java object - static auto constructor = OfflineRegion::javaClass.GetConstructor<jni::jlong, jni::Object<FileSource>, jni::jlong, jni::Object<OfflineRegionDefinition>, jni::Array<jni::jbyte>>(env); - auto jregion = OfflineRegion::javaClass.New(env, constructor, - reinterpret_cast<jni::jlong>(new mbgl::OfflineRegion(std::move(region))), //Copy a region to the heap - jFileSource, jni::jlong(region.getID()), definition, metadata); - - //Delete references - jni::DeleteLocalRef(env, definition); - jni::DeleteLocalRef(env, metadata); + static auto& javaClass = jni::Class<OfflineRegion>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong, jni::Object<FileSource>, jni::jlong, jni::Object<OfflineRegionDefinition>, jni::Array<jni::jbyte>>(env); - return jregion; + return javaClass.New(env, constructor, + reinterpret_cast<jni::jlong>(new mbgl::OfflineRegion(std::move(region))), //Copy a region to the heap + jFileSource, + jni::jlong(region.getID()), + definition, + OfflineRegion::metadata(env, region.getMetadata())); } -jni::Array<jni::jbyte> OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRegionMetadata metadata_) { +jni::Local<jni::Array<jni::jbyte>> OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRegionMetadata metadata_) { std::vector<jni::jbyte> convertedMetadata(metadata_.begin(), metadata_.end()); std::size_t length = static_cast<std::size_t>(convertedMetadata.size()); auto metadata = jni::Array<jni::jbyte>::New(env, length); @@ -192,7 +168,7 @@ jni::Array<jni::jbyte> OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRe return metadata; } -mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, jni::Array<jni::jbyte> metadata_) { +mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, const jni::Array<jni::jbyte>& metadata_) { std::size_t length = metadata_.Length(env); auto metadata_tmp = std::vector<jni::jbyte>(); metadata_tmp.resize(length); @@ -201,20 +177,18 @@ mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, jni::Array return metadata; } -jni::Class<OfflineRegion> OfflineRegion::javaClass; - void OfflineRegion::registerNative(jni::JNIEnv& env) { - OfflineRegion::OfflineRegionObserver::registerNative(env); - OfflineRegion::OfflineRegionStatusCallback::registerNative(env); - OfflineRegion::OfflineRegionDeleteCallback::registerNative(env); - OfflineRegion::OfflineRegionUpdateMetadataCallback::registerNative(env); + jni::Class<OfflineRegionObserver>::Singleton(env); + jni::Class<OfflineRegionStatusCallback>::Singleton(env); + jni::Class<OfflineRegionDeleteCallback>::Singleton(env); + jni::Class<OfflineRegionUpdateMetadataCallback>::Singleton(env); - javaClass = *jni::Class<OfflineRegion>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<OfflineRegion>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) jni::RegisterNativePeer<OfflineRegion>( env, javaClass, "nativePtr", - std::make_unique<OfflineRegion, JNIEnv&, jni::jlong, jni::Object<FileSource>>, + jni::MakePeer<OfflineRegion, jni::jlong, const jni::Object<FileSource>&>, "initialize", "finalize", METHOD(&OfflineRegion::setOfflineRegionObserver, "setOfflineRegionObserver"), @@ -227,94 +201,63 @@ void OfflineRegion::registerNative(jni::JNIEnv& env) { // OfflineRegionObserver // -jni::Class<OfflineRegion::OfflineRegionObserver> OfflineRegion::OfflineRegionObserver::javaClass; - -void OfflineRegion::OfflineRegionObserver::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegion::OfflineRegionObserver>::Find(env).NewGlobalRef(env).release(); -} - // OfflineRegionStatusCallback // -jni::Class<OfflineRegion::OfflineRegionStatusCallback> OfflineRegion::OfflineRegionStatusCallback::javaClass; - -void OfflineRegion::OfflineRegionStatusCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionStatusCallback>::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionStatusCallback::onError(jni::JNIEnv& env, - jni::Object<OfflineRegion::OfflineRegionStatusCallback> callback, + const jni::Object<OfflineRegion::OfflineRegionStatusCallback>& callback, std::exception_ptr error) { + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionStatusCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error))); } void OfflineRegion::OfflineRegionStatusCallback::onStatus(jni::JNIEnv& env, - jni::Object<OfflineRegion::OfflineRegionStatusCallback> callback, + const jni::Object<OfflineRegion::OfflineRegionStatusCallback>& callback, mbgl::optional<mbgl::OfflineRegionStatus> status) { - //Convert to java peer object - auto jStatus = OfflineRegionStatus::New(env, std::move(*status)); - - // Trigger callback + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionStatusCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegionStatus>)>(env, "onStatus"); - callback.Call(env, method, jStatus); - jni::DeleteLocalRef(env, jStatus); + + callback.Call(env, method, OfflineRegionStatus::New(env, std::move(*status))); } // OfflineRegionDeleteCallback // -jni::Class<OfflineRegion::OfflineRegionDeleteCallback> OfflineRegion::OfflineRegionDeleteCallback::javaClass; - -void OfflineRegion::OfflineRegionDeleteCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionDeleteCallback>::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionDeleteCallback::onError(jni::JNIEnv& env, - jni::Object<OfflineRegion::OfflineRegionDeleteCallback> callback, + const jni::Object<OfflineRegion::OfflineRegionDeleteCallback>& callback, std::exception_ptr error) { + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionDeleteCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error))); } -void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, jni::Object<OfflineRegion::OfflineRegionDeleteCallback> callback) { +void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, const jni::Object<OfflineRegion::OfflineRegionDeleteCallback>& callback) { // Trigger callback + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionDeleteCallback>::Singleton(env); static auto method = javaClass.GetMethod<void ()>(env, "onDelete"); + callback.Call(env, method); } // OfflineRegionUpdateMetadataCallback // -jni::Class<OfflineRegion::OfflineRegionUpdateMetadataCallback> OfflineRegion::OfflineRegionUpdateMetadataCallback::javaClass; - -void OfflineRegion::OfflineRegionUpdateMetadataCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionUpdateMetadataCallback>::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionUpdateMetadataCallback::onError(jni::JNIEnv& env, - jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback> callback, + const jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback>& callback, std::exception_ptr error) { + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionUpdateMetadataCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error))); } void OfflineRegion::OfflineRegionUpdateMetadataCallback::onUpdate(jni::JNIEnv& env, - jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback> callback, + const jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback>& callback, mbgl::optional<mbgl::OfflineRegionMetadata> metadata) { - //Convert to java peer object - auto jMetadata = OfflineRegion::metadata(env, std::move(*metadata)); - - // Trigger callback + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionUpdateMetadataCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::Array<jni::jbyte>)>(env, "onUpdate"); - callback.Call(env, method, jMetadata); - jni::DeleteLocalRef(env, jMetadata); + + callback.Call(env, method, OfflineRegion::metadata(env, std::move(*metadata))); } } // namespace android diff --git a/platform/android/src/offline/offline_region.hpp b/platform/android/src/offline/offline_region.hpp index c05383a91..49fa0c8ff 100644 --- a/platform/android/src/offline/offline_region.hpp +++ b/platform/android/src/offline/offline_region.hpp @@ -15,78 +15,60 @@ public: class OfflineRegionObserver { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionObserver"; }; - - static jni::Class<OfflineRegionObserver> javaClass; - - static void registerNative(jni::JNIEnv&); }; class OfflineRegionStatusCallback { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionStatusCallback"; }; - static void onError(jni::JNIEnv&, jni::Object<OfflineRegionStatusCallback>, std::exception_ptr); + static void onError(jni::JNIEnv&, const jni::Object<OfflineRegionStatusCallback>&, std::exception_ptr); static void onStatus(jni::JNIEnv&, - jni::Object<OfflineRegionStatusCallback>, + const jni::Object<OfflineRegionStatusCallback>&, mbgl::optional<mbgl::OfflineRegionStatus>); - - static jni::Class<OfflineRegionStatusCallback> javaClass; - - static void registerNative(jni::JNIEnv&); }; class OfflineRegionDeleteCallback { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionDeleteCallback"; }; - static void onError(jni::JNIEnv&, jni::Object<OfflineRegionDeleteCallback>, std::exception_ptr); - - static void onDelete(jni::JNIEnv&, jni::Object<OfflineRegionDeleteCallback>); + static void onError(jni::JNIEnv&, const jni::Object<OfflineRegionDeleteCallback>&, std::exception_ptr); - static jni::Class<OfflineRegionDeleteCallback> javaClass; - - static void registerNative(jni::JNIEnv&); + static void onDelete(jni::JNIEnv&, const jni::Object<OfflineRegionDeleteCallback>&); }; class OfflineRegionUpdateMetadataCallback { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionUpdateMetadataCallback"; }; - static void onError(jni::JNIEnv&, jni::Object<OfflineRegionUpdateMetadataCallback>, std::exception_ptr); + static void onError(jni::JNIEnv&, const jni::Object<OfflineRegionUpdateMetadataCallback>&, std::exception_ptr); static void onUpdate(jni::JNIEnv&, - jni::Object<OfflineRegionUpdateMetadataCallback>, + const jni::Object<OfflineRegionUpdateMetadataCallback>&, mbgl::optional<mbgl::OfflineRegionMetadata>); - - static jni::Class<OfflineRegionUpdateMetadataCallback> javaClass; - - static void registerNative(jni::JNIEnv&); }; static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion"; }; - OfflineRegion(jni::JNIEnv&, jni::jlong, jni::Object<FileSource>); + OfflineRegion(jni::JNIEnv&, jni::jlong, const jni::Object<FileSource>&); ~OfflineRegion(); - void setOfflineRegionObserver(jni::JNIEnv&, jni::Object<OfflineRegion::OfflineRegionObserver>); + void setOfflineRegionObserver(jni::JNIEnv&, const jni::Object<OfflineRegion::OfflineRegionObserver>&); void setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint); - void getOfflineRegionStatus(jni::JNIEnv&, jni::Object<OfflineRegion::OfflineRegionStatusCallback>); - - void deleteOfflineRegion(jni::JNIEnv&, jni::Object<OfflineRegionDeleteCallback>); + void getOfflineRegionStatus(jni::JNIEnv&, const jni::Object<OfflineRegion::OfflineRegionStatusCallback>&); - void updateOfflineRegionMetadata(jni::JNIEnv&, jni::Array<jni::jbyte>, jni::Object<OfflineRegionUpdateMetadataCallback>); + void deleteOfflineRegion(jni::JNIEnv&, const jni::Object<OfflineRegionDeleteCallback>&); - static jni::Object<OfflineRegion> New(jni::JNIEnv&, jni::Object<FileSource>, mbgl::OfflineRegion); + void updateOfflineRegionMetadata(jni::JNIEnv&, const jni::Array<jni::jbyte>&, const jni::Object<OfflineRegionUpdateMetadataCallback>&); - static jni::Array<jni::jbyte> metadata(jni::JNIEnv&, mbgl::OfflineRegionMetadata); + static jni::Local<jni::Object<OfflineRegion>> New(jni::JNIEnv&, const jni::Object<FileSource>&, mbgl::OfflineRegion); - static mbgl::OfflineRegionMetadata metadata(jni::JNIEnv&, jni::Array<jni::jbyte>); + static jni::Local<jni::Array<jni::jbyte>> metadata(jni::JNIEnv&, mbgl::OfflineRegionMetadata); - static jni::Class<OfflineRegion> javaClass; + static mbgl::OfflineRegionMetadata metadata(jni::JNIEnv&, const jni::Array<jni::jbyte>&); static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/offline/offline_region_definition.cpp b/platform/android/src/offline/offline_region_definition.cpp index a85667290..23e5b7466 100644 --- a/platform/android/src/offline/offline_region_definition.cpp +++ b/platform/android/src/offline/offline_region_definition.cpp @@ -10,19 +10,16 @@ namespace android { // OfflineRegionDefinition // -jni::Class<OfflineRegionDefinition> OfflineRegionDefinition::javaClass; - void OfflineRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionDefinition>::Find(env).NewGlobalRef(env).release(); + jni::Class<OfflineRegionDefinition>::Singleton(env); } mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env, - jni::Object<OfflineRegionDefinition> jDefinition) { - - if (jDefinition.IsInstanceOf(env, OfflineTilePyramidRegionDefinition::javaClass)) { - return OfflineTilePyramidRegionDefinition::getDefinition(env, jni::Object<OfflineTilePyramidRegionDefinition>(*jDefinition)); - } else if (jDefinition.IsInstanceOf(env, OfflineGeometryRegionDefinition::javaClass)) { - return OfflineGeometryRegionDefinition::getDefinition(env, jni::Object<OfflineGeometryRegionDefinition>(*jDefinition)); + const jni::Object<OfflineRegionDefinition>& jDefinition) { + if (jDefinition.IsInstanceOf(env, jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env))) { + return OfflineTilePyramidRegionDefinition::getDefinition(env, jni::Cast(env, jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env), jDefinition)); + } else if (jDefinition.IsInstanceOf(env, jni::Class<OfflineGeometryRegionDefinition>::Singleton(env))) { + return OfflineGeometryRegionDefinition::getDefinition(env, jni::Cast(env, jni::Class<OfflineGeometryRegionDefinition>::Singleton(env), jDefinition)); } throw std::runtime_error("Unknown offline region definition java class"); @@ -30,105 +27,74 @@ mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env // OfflineTilePyramidRegionDefinition // -jni::Object<OfflineTilePyramidRegionDefinition> OfflineTilePyramidRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineTilePyramidRegionDefinition& definition) { - - //Convert objects - auto styleURL = jni::Make<jni::String>(env, definition.styleURL); - auto bounds = LatLngBounds::New(env, definition.bounds); - +jni::Local<jni::Object<OfflineRegionDefinition>> OfflineTilePyramidRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineTilePyramidRegionDefinition& definition) { + static auto& javaClass = jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::String, jni::Object<LatLngBounds>, jni::jdouble, jni::jdouble, jni::jfloat>(env); - auto jdefinition = javaClass.New(env, constructor, styleURL, bounds, definition.minZoom, definition.maxZoom, definition.pixelRatio); - - //Delete References - jni::DeleteLocalRef(env, styleURL); - jni::DeleteLocalRef(env, bounds); - return jdefinition; + return javaClass.New(env, constructor, + jni::Make<jni::String>(env, definition.styleURL), + LatLngBounds::New(env, definition.bounds), + definition.minZoom, + definition.maxZoom, + definition.pixelRatio); } -mbgl::OfflineTilePyramidRegionDefinition OfflineTilePyramidRegionDefinition::getDefinition(jni::JNIEnv& env, jni::Object<OfflineTilePyramidRegionDefinition> jDefinition) { +mbgl::OfflineTilePyramidRegionDefinition OfflineTilePyramidRegionDefinition::getDefinition(jni::JNIEnv& env, const jni::Object<OfflineTilePyramidRegionDefinition>& jDefinition) { // Field references + static auto& javaClass = jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env); static auto styleURLF = javaClass.GetField<jni::String>(env, "styleURL"); static auto boundsF = javaClass.GetField<jni::Object<LatLngBounds>>(env, "bounds"); static auto minZoomF = javaClass.GetField<jni::jdouble>(env, "minZoom"); static auto maxZoomF = javaClass.GetField<jni::jdouble>(env, "maxZoom"); static auto pixelRatioF = javaClass.GetField<jni::jfloat>(env, "pixelRatio"); - // Get objects - auto jStyleURL = jDefinition.Get(env, styleURLF); - auto jBounds = jDefinition.Get(env, boundsF); - - // Create definition - mbgl::OfflineTilePyramidRegionDefinition definition( - jni::Make<std::string>(env, jStyleURL), - LatLngBounds::getLatLngBounds(env, jBounds), + return mbgl::OfflineTilePyramidRegionDefinition( + jni::Make<std::string>(env, jDefinition.Get(env, styleURLF)), + LatLngBounds::getLatLngBounds(env, jDefinition.Get(env, boundsF)), jDefinition.Get(env, minZoomF), jDefinition.Get(env, maxZoomF), jDefinition.Get(env, pixelRatioF) ); - - // Delete references - jni::DeleteLocalRef(env, jStyleURL); - jni::DeleteLocalRef(env, jBounds); - - return definition; } -jni::Class<OfflineTilePyramidRegionDefinition> OfflineTilePyramidRegionDefinition::javaClass; - void OfflineTilePyramidRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineTilePyramidRegionDefinition>::Find(env).NewGlobalRef(env).release(); + jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env); } // OfflineGeometryRegionDefinition // -jni::Object<OfflineGeometryRegionDefinition> OfflineGeometryRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineGeometryRegionDefinition& definition) { - //Convert objects - auto styleURL = jni::Make<jni::String>(env, definition.styleURL); - auto geometry = geojson::Geometry::New(env, definition.geometry); - +jni::Local<jni::Object<OfflineRegionDefinition>> OfflineGeometryRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineGeometryRegionDefinition& definition) { + static auto& javaClass = jni::Class<OfflineGeometryRegionDefinition>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::String, jni::Object<geojson::Geometry>, jni::jdouble, jni::jdouble, jni::jfloat>(env); - auto jdefinition = javaClass.New(env, constructor, styleURL, geometry, definition.minZoom, definition.maxZoom, definition.pixelRatio); - - //Delete References - jni::DeleteLocalRef(env, styleURL); - jni::DeleteLocalRef(env, geometry); - return jdefinition; + return javaClass.New(env, constructor, + jni::Make<jni::String>(env, definition.styleURL), + geojson::Geometry::New(env, definition.geometry), + definition.minZoom, + definition.maxZoom, + definition.pixelRatio); } -mbgl::OfflineGeometryRegionDefinition OfflineGeometryRegionDefinition::getDefinition(jni::JNIEnv& env, jni::Object<OfflineGeometryRegionDefinition> jDefinition) { +mbgl::OfflineGeometryRegionDefinition OfflineGeometryRegionDefinition::getDefinition(jni::JNIEnv& env, const jni::Object<OfflineGeometryRegionDefinition>& jDefinition) { // Field references + static auto& javaClass = jni::Class<OfflineGeometryRegionDefinition>::Singleton(env); static auto styleURLF = javaClass.GetField<jni::String>(env, "styleURL"); static auto geometryF = javaClass.GetField<jni::Object<geojson::Geometry>>(env, "geometry"); static auto minZoomF = javaClass.GetField<jni::jdouble>(env, "minZoom"); static auto maxZoomF = javaClass.GetField<jni::jdouble>(env, "maxZoom"); static auto pixelRatioF = javaClass.GetField<jni::jfloat>(env, "pixelRatio"); - // Get objects - auto jStyleURL = jDefinition.Get(env, styleURLF); - auto jGeometry = jDefinition.Get(env, geometryF); - - // Create definition - mbgl::OfflineGeometryRegionDefinition definition( - jni::Make<std::string>(env, jStyleURL), - geojson::Geometry::convert(env, jGeometry), - jDefinition.Get(env, minZoomF), - jDefinition.Get(env, maxZoomF), - jDefinition.Get(env, pixelRatioF) + return mbgl::OfflineGeometryRegionDefinition( + jni::Make<std::string>(env, jDefinition.Get(env, styleURLF)), + geojson::Geometry::convert(env, jDefinition.Get(env, geometryF)), + jDefinition.Get(env, minZoomF), + jDefinition.Get(env, maxZoomF), + jDefinition.Get(env, pixelRatioF) ); - - // Delete references - jni::DeleteLocalRef(env, jStyleURL); - jni::DeleteLocalRef(env, jGeometry); - - return definition; } -jni::Class<OfflineGeometryRegionDefinition> OfflineGeometryRegionDefinition::javaClass; - void OfflineGeometryRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineGeometryRegionDefinition>::Find(env).NewGlobalRef(env).release(); + jni::Class<OfflineGeometryRegionDefinition>::Singleton(env); } } // namespace android diff --git a/platform/android/src/offline/offline_region_definition.hpp b/platform/android/src/offline/offline_region_definition.hpp index a9dfb5463..827fac0a8 100644 --- a/platform/android/src/offline/offline_region_definition.hpp +++ b/platform/android/src/offline/offline_region_definition.hpp @@ -10,39 +10,33 @@ class OfflineRegionDefinition { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegionDefinition"; }; - static jni::Class<OfflineRegionDefinition> javaClass; - static void registerNative(jni::JNIEnv&); - static mbgl::OfflineRegionDefinition getDefinition(JNIEnv& env, jni::Object<OfflineRegionDefinition> jDefinition); + static mbgl::OfflineRegionDefinition getDefinition(JNIEnv& env, const jni::Object<OfflineRegionDefinition>& jDefinition); }; -class OfflineTilePyramidRegionDefinition: public OfflineRegionDefinition { +class OfflineTilePyramidRegionDefinition { public: + using SuperTag = OfflineRegionDefinition; static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition"; }; - static jni::Object<OfflineTilePyramidRegionDefinition> New(jni::JNIEnv&, const mbgl::OfflineTilePyramidRegionDefinition&); - - static mbgl::OfflineTilePyramidRegionDefinition getDefinition(jni::JNIEnv&, jni::Object<OfflineTilePyramidRegionDefinition>); + static jni::Local<jni::Object<OfflineRegionDefinition>> New(jni::JNIEnv&, const mbgl::OfflineTilePyramidRegionDefinition&); - static jni::Class<OfflineTilePyramidRegionDefinition> javaClass; + static mbgl::OfflineTilePyramidRegionDefinition getDefinition(jni::JNIEnv&, const jni::Object<OfflineTilePyramidRegionDefinition>&); static void registerNative(jni::JNIEnv&); - }; -class OfflineGeometryRegionDefinition: public OfflineRegionDefinition { +class OfflineGeometryRegionDefinition { public: + using SuperTag = OfflineRegionDefinition; static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineGeometryRegionDefinition"; }; - static jni::Object<OfflineGeometryRegionDefinition> New(jni::JNIEnv&, const mbgl::OfflineGeometryRegionDefinition&); + static jni::Local<jni::Object<OfflineRegionDefinition>> New(jni::JNIEnv&, const mbgl::OfflineGeometryRegionDefinition&); - static mbgl::OfflineGeometryRegionDefinition getDefinition(jni::JNIEnv&, jni::Object<OfflineGeometryRegionDefinition>); - - static jni::Class<OfflineGeometryRegionDefinition> javaClass; + static mbgl::OfflineGeometryRegionDefinition getDefinition(jni::JNIEnv&, const jni::Object<OfflineGeometryRegionDefinition>&); static void registerNative(jni::JNIEnv&); - }; } // namespace android diff --git a/platform/android/src/offline/offline_region_error.cpp b/platform/android/src/offline/offline_region_error.cpp index b0a19f934..199bbafa6 100644 --- a/platform/android/src/offline/offline_region_error.cpp +++ b/platform/android/src/offline/offline_region_error.cpp @@ -3,7 +3,7 @@ namespace mbgl { namespace android { -jni::Object<OfflineRegionError> OfflineRegionError::New(jni::JNIEnv& env, mbgl::Response::Error error) { +jni::Local<jni::Object<OfflineRegionError>> OfflineRegionError::New(jni::JNIEnv& env, mbgl::Response::Error error) { // Handle the value of reason independently of the underlying int value std::string reason; @@ -28,25 +28,16 @@ jni::Object<OfflineRegionError> OfflineRegionError::New(jni::JNIEnv& env, mbgl:: break; } - // Convert - auto jReason = jni::Make<jni::String>(env, reason); - auto jMessage = jni::Make<jni::String>(env, error.message); - - // Create java object + static auto& javaClass = jni::Class<OfflineRegionError>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::String, jni::String>(env); - auto jError = javaClass.New(env, constructor, jReason, jMessage); - - // Delete references - jni::DeleteLocalRef(env, jReason); - jni::DeleteLocalRef(env, jMessage); - return jError; + return javaClass.New(env, constructor, + jni::Make<jni::String>(env, reason), + jni::Make<jni::String>(env, error.message)); } -jni::Class<OfflineRegionError> OfflineRegionError::javaClass; - void OfflineRegionError::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionError>::Find(env).NewGlobalRef(env).release(); + jni::Class<OfflineRegionError>::Singleton(env); } } // namespace android diff --git a/platform/android/src/offline/offline_region_error.hpp b/platform/android/src/offline/offline_region_error.hpp index 61efaca67..151e05ab1 100644 --- a/platform/android/src/offline/offline_region_error.hpp +++ b/platform/android/src/offline/offline_region_error.hpp @@ -10,9 +10,7 @@ class OfflineRegionError { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegionError"; }; - static jni::Object<OfflineRegionError> New(jni::JNIEnv&, mbgl::Response::Error); - - static jni::Class<OfflineRegionError> javaClass; + static jni::Local<jni::Object<OfflineRegionError>> New(jni::JNIEnv&, mbgl::Response::Error); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/offline/offline_region_status.cpp b/platform/android/src/offline/offline_region_status.cpp index d0bbae124..5dd9f20a7 100644 --- a/platform/android/src/offline/offline_region_status.cpp +++ b/platform/android/src/offline/offline_region_status.cpp @@ -3,7 +3,7 @@ namespace mbgl { namespace android { -jni::Object<OfflineRegionStatus> OfflineRegionStatus::New(jni::JNIEnv& env, mbgl::OfflineRegionStatus status) { +jni::Local<jni::Object<OfflineRegionStatus>> OfflineRegionStatus::New(jni::JNIEnv& env, mbgl::OfflineRegionStatus status) { // Convert to jint jint downloadState; @@ -17,6 +17,7 @@ jni::Object<OfflineRegionStatus> OfflineRegionStatus::New(jni::JNIEnv& env, mbgl } // Create java object + static auto& javaClass = jni::Class<OfflineRegionStatus>::Singleton(env); static auto constructor = javaClass.GetConstructor<jint, jlong, jlong, jlong, jlong, jlong, jboolean>(env); return javaClass.New(env, constructor, downloadState, @@ -29,10 +30,8 @@ jni::Object<OfflineRegionStatus> OfflineRegionStatus::New(jni::JNIEnv& env, mbgl ); } -jni::Class<OfflineRegionStatus> OfflineRegionStatus::javaClass; - void OfflineRegionStatus::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<OfflineRegionStatus>::Find(env).NewGlobalRef(env).release(); + jni::Class<OfflineRegionStatus>::Singleton(env); } } // namespace android diff --git a/platform/android/src/offline/offline_region_status.hpp b/platform/android/src/offline/offline_region_status.hpp index b29a65365..9ef48ec35 100644 --- a/platform/android/src/offline/offline_region_status.hpp +++ b/platform/android/src/offline/offline_region_status.hpp @@ -10,9 +10,7 @@ class OfflineRegionStatus { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegionStatus"; }; - static jni::Object<OfflineRegionStatus> New(jni::JNIEnv&, mbgl::OfflineRegionStatus status); - - static jni::Class<OfflineRegionStatus> javaClass; + static jni::Local<jni::Object<OfflineRegionStatus>> New(jni::JNIEnv&, mbgl::OfflineRegionStatus status); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/snapshotter/map_snapshot.cpp b/platform/android/src/snapshotter/map_snapshot.cpp index 42c1c16ca..1650f72dc 100644 --- a/platform/android/src/snapshotter/map_snapshot.cpp +++ b/platform/android/src/snapshotter/map_snapshot.cpp @@ -1,7 +1,7 @@ #include "map_snapshot.hpp" #include "../bitmap.hpp" -#include "../jni/collection.hpp" +#include "../conversion/collection.hpp" #include <memory> @@ -16,18 +16,18 @@ MapSnapshot::MapSnapshot(float pixelRatio_, MapSnapshot::PointForFn pointForFn_, MapSnapshot::~MapSnapshot() = default; -jni::Object<PointF> MapSnapshot::pixelForLatLng(jni::JNIEnv& env, jni::Object<LatLng> jLatLng) { +jni::Local<jni::Object<PointF>> MapSnapshot::pixelForLatLng(jni::JNIEnv& env, jni::Object<LatLng>& jLatLng) { ScreenCoordinate point = pointForFn(LatLng::getLatLng(env, jLatLng)); return PointF::New(env, point.x * pixelRatio, point.y * pixelRatio); } -jni::Object<LatLng> MapSnapshot::latLngForPixel(jni::JNIEnv& env, jni::Object<PointF>jPoint) { +jni::Local<jni::Object<LatLng>> MapSnapshot::latLngForPixel(jni::JNIEnv& env, jni::Object<PointF>& jPoint) { return LatLng::New(env, latLngForFn(PointF::getScreenCoordinate(env, jPoint))); } // Static methods // -jni::Object<MapSnapshot> MapSnapshot::New(JNIEnv& env, +jni::Local<jni::Object<MapSnapshot>> MapSnapshot::New(JNIEnv& env, PremultipliedImage&& image, float pixelRatio, std::vector<std::string> attributions, @@ -38,21 +38,20 @@ jni::Object<MapSnapshot> MapSnapshot::New(JNIEnv& env, auto bitmap = Bitmap::CreateBitmap(env, std::move(image)); // Create the Mapsnapshot peers + static auto& javaClass = jni::Class<MapSnapshot>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::jlong, jni::Object<Bitmap>, jni::Array<jni::String>, jni::jboolean>(env); auto nativePeer = std::make_unique<MapSnapshot>(pixelRatio, pointForFn, latLngForFn); - return javaClass.New(env, constructor, reinterpret_cast<jlong>(nativePeer.release()), bitmap, jni::Make<jni::Array<jni::String>>(env, attributions), (jni::jboolean) showLogo); + return javaClass.New(env, constructor, reinterpret_cast<jlong>(nativePeer.release()), bitmap, conversion::toArray(env, attributions), (jni::jboolean) showLogo); } -jni::Class<MapSnapshot> MapSnapshot::javaClass; - void MapSnapshot::registerNative(jni::JNIEnv& env) { // Lookup the class - MapSnapshot::javaClass = *jni::Class<MapSnapshot>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<MapSnapshot>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<MapSnapshot>(env, MapSnapshot::javaClass, + jni::RegisterNativePeer<MapSnapshot>(env, javaClass, "nativePtr", std::make_unique<MapSnapshot, JNIEnv&>, "initialize", diff --git a/platform/android/src/snapshotter/map_snapshot.hpp b/platform/android/src/snapshotter/map_snapshot.hpp index f168be85b..6b82d0283 100644 --- a/platform/android/src/snapshotter/map_snapshot.hpp +++ b/platform/android/src/snapshotter/map_snapshot.hpp @@ -23,7 +23,7 @@ public: static void registerNative(jni::JNIEnv&); - static jni::Object<MapSnapshot> New(JNIEnv& env, + static jni::Local<jni::Object<MapSnapshot>> New(JNIEnv& env, PremultipliedImage&& image, float pixelRatio, std::vector<std::string> attributions, @@ -35,12 +35,10 @@ public: MapSnapshot(float pixelRatio, PointForFn, LatLngForFn); ~MapSnapshot(); - jni::Object<PointF> pixelForLatLng(jni::JNIEnv&, jni::Object<LatLng>); - jni::Object<LatLng> latLngForPixel(jni::JNIEnv&, jni::Object<PointF>); + jni::Local<jni::Object<PointF>> pixelForLatLng(jni::JNIEnv&, jni::Object<LatLng>&); + jni::Local<jni::Object<LatLng>> latLngForPixel(jni::JNIEnv&, jni::Object<PointF>&); private: - static jni::Class<MapSnapshot> javaClass; - float pixelRatio; mbgl::MapSnapshotter::PointForFn pointForFn; mbgl::MapSnapshotter::LatLngForFn latLngForFn; diff --git a/platform/android/src/snapshotter/map_snapshotter.cpp b/platform/android/src/snapshotter/map_snapshotter.cpp index a93404dbf..e2e01f4e3 100644 --- a/platform/android/src/snapshotter/map_snapshotter.cpp +++ b/platform/android/src/snapshotter/map_snapshotter.cpp @@ -14,18 +14,18 @@ namespace mbgl { namespace android { MapSnapshotter::MapSnapshotter(jni::JNIEnv& _env, - jni::Object<MapSnapshotter> _obj, - jni::Object<FileSource> _jFileSource, + const jni::Object<MapSnapshotter>& _obj, + const jni::Object<FileSource>& _jFileSource, jni::jfloat _pixelRatio, jni::jint width, jni::jint height, - jni::String styleURL, - jni::String styleJSON, - jni::Object<LatLngBounds> region, - jni::Object<CameraPosition> position, + const jni::String& styleURL, + const jni::String& styleJSON, + const jni::Object<LatLngBounds>& region, + const jni::Object<CameraPosition>& position, jni::jboolean _showLogo, - jni::String _programCacheDir) - : javaPeer(SeizeGenericWeakRef(_env, jni::Object<MapSnapshotter>(jni::NewWeakGlobalRef(_env, _obj.Get()).release()))) + const jni::String& _programCacheDir) + : javaPeer(_env, _obj) , pixelRatio(_pixelRatio) , threadPool(sharedThreadPool()) { @@ -80,20 +80,19 @@ void MapSnapshotter::start(JNIEnv& env) { [this](std::exception_ptr err, PremultipliedImage image, std::vector<std::string> attributions, mbgl::MapSnapshotter::PointForFn pointForFn, mbgl::MapSnapshotter::LatLngForFn latLngForFn) { MBGL_VERIFY_THREAD(tid); android::UniqueEnv _env = android::AttachEnv(); + static auto& javaClass = jni::Class<MapSnapshotter>::Singleton(*_env); if (err) { // error handler callback static auto onSnapshotFailed = javaClass.GetMethod<void (jni::String)>(*_env, "onSnapshotFailed"); - auto message = jni::Make<jni::String>(*_env, util::toString(err)); - javaPeer->Call(*_env, onSnapshotFailed, message); - jni::DeleteLocalRef(*_env, message); + javaPeer.get(*_env).Call(*_env, onSnapshotFailed, jni::Make<jni::String>(*_env, util::toString(err))); } else { // Create the wrapper auto mapSnapshot = android::MapSnapshot::New(*_env, std::move(image), pixelRatio, attributions, showLogo, pointForFn, latLngForFn); // invoke callback static auto onSnapshotReady = javaClass.GetMethod<void (jni::Object<MapSnapshot>)>(*_env, "onSnapshotReady"); - javaPeer->Call(*_env, onSnapshotReady, mapSnapshot); + javaPeer.get(*_env).Call(*_env, onSnapshotReady, mapSnapshot); } deactivateFilesource(*_env); @@ -108,11 +107,11 @@ void MapSnapshotter::cancel(JNIEnv& env) { deactivateFilesource(env); } -void MapSnapshotter::setStyleUrl(JNIEnv& env, jni::String styleURL) { +void MapSnapshotter::setStyleUrl(JNIEnv& env, const jni::String& styleURL) { snapshotter->setStyleURL(jni::Make<std::string>(env, styleURL)); } -void MapSnapshotter::setStyleJson(JNIEnv& env, jni::String styleJSON) { +void MapSnapshotter::setStyleJson(JNIEnv& env, const jni::String& styleJSON) { snapshotter->setStyleJSON(jni::Make<std::string>(env, styleJSON)); } @@ -121,12 +120,12 @@ void MapSnapshotter::setSize(JNIEnv&, jni::jint width, jni::jint height) { snapshotter->setSize(size); } -void MapSnapshotter::setCameraPosition(JNIEnv& env, jni::Object<CameraPosition> position) { +void MapSnapshotter::setCameraPosition(JNIEnv& env, const jni::Object<CameraPosition>& position) { auto options = CameraPosition::getCameraOptions(env, position); snapshotter->setCameraOptions(options); } -void MapSnapshotter::setRegion(JNIEnv& env, jni::Object<LatLngBounds> region) { +void MapSnapshotter::setRegion(JNIEnv& env, const jni::Object<LatLngBounds>& region) { snapshotter->setRegion(LatLngBounds::getLatLngBounds(env, region)); } @@ -149,17 +148,15 @@ void MapSnapshotter::deactivateFilesource(JNIEnv& env) { // Static methods // -jni::Class<MapSnapshotter> MapSnapshotter::javaClass; - void MapSnapshotter::registerNative(jni::JNIEnv& env) { // Lookup the class - MapSnapshotter::javaClass = *jni::Class<MapSnapshotter>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<MapSnapshotter>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<MapSnapshotter>(env, MapSnapshotter::javaClass, "nativePtr", - std::make_unique<MapSnapshotter, JNIEnv&, jni::Object<MapSnapshotter>, jni::Object<FileSource>, jni::jfloat, jni::jint, jni::jint, jni::String, jni::String, jni::Object<LatLngBounds>, jni::Object<CameraPosition>, jni::jboolean, jni::String>, + jni::RegisterNativePeer<MapSnapshotter>(env, javaClass, "nativePtr", + jni::MakePeer<MapSnapshotter, const jni::Object<MapSnapshotter>&, const jni::Object<FileSource>&, jni::jfloat, jni::jint, jni::jint, const jni::String&, const jni::String&, const jni::Object<LatLngBounds>&, const jni::Object<CameraPosition>&, jni::jboolean, const jni::String&>, "nativeInitialize", "finalize", METHOD(&MapSnapshotter::setStyleUrl, "setStyleUrl"), diff --git a/platform/android/src/snapshotter/map_snapshotter.hpp b/platform/android/src/snapshotter/map_snapshotter.hpp index 7b72452c4..e20acf4f1 100644 --- a/platform/android/src/snapshotter/map_snapshotter.hpp +++ b/platform/android/src/snapshotter/map_snapshotter.hpp @@ -9,7 +9,6 @@ #include "../map/camera_position.hpp" #include <jni/jni.hpp> -#include "../jni/generic_global_ref_deleter.hpp" #include <memory> @@ -23,34 +22,32 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/snapshotter/MapSnapshotter"; }; - static jni::Class<MapSnapshotter> javaClass; - static void registerNative(jni::JNIEnv&); MapSnapshotter(jni::JNIEnv&, - jni::Object<MapSnapshotter>, - jni::Object<FileSource>, + const jni::Object<MapSnapshotter>&, + const jni::Object<FileSource>&, jni::jfloat pixelRatio, jni::jint width, jni::jint height, - jni::String styleURL, - jni::String styleJSON, - jni::Object<LatLngBounds> region, - jni::Object<CameraPosition> position, + const jni::String& styleURL, + const jni::String& styleJSON, + const jni::Object<LatLngBounds>& region, + const jni::Object<CameraPosition>& position, jni::jboolean showLogo, - jni::String programCacheDir); + const jni::String& programCacheDir); ~MapSnapshotter(); - void setStyleUrl(JNIEnv&, jni::String styleURL); + void setStyleUrl(JNIEnv&, const jni::String& styleURL); - void setStyleJson(JNIEnv&, jni::String styleJSON); + void setStyleJson(JNIEnv&, const jni::String& styleJSON); void setSize(JNIEnv&, jni::jint width, jni::jint height); - void setCameraPosition(JNIEnv&, jni::Object<CameraPosition> position); + void setCameraPosition(JNIEnv&, const jni::Object<CameraPosition>& position); - void setRegion(JNIEnv&, jni::Object<LatLngBounds> region); + void setRegion(JNIEnv&, const jni::Object<LatLngBounds>& region); void start(JNIEnv&); @@ -60,7 +57,7 @@ private: MBGL_STORE_THREAD(tid); JavaVM *vm = nullptr; - GenericUniqueWeakObject<MapSnapshotter> javaPeer; + jni::WeakReference<jni::Object<MapSnapshotter>, jni::EnvAttachingDeleter> javaPeer; float pixelRatio; bool showLogo; diff --git a/platform/android/src/string_util.cpp b/platform/android/src/string_util.cpp new file mode 100644 index 000000000..f02155caf --- /dev/null +++ b/platform/android/src/string_util.cpp @@ -0,0 +1,25 @@ +#include <mbgl/util/platform.hpp> +#include "attach_env.hpp" +#include <jni/jni.hpp> + +namespace mbgl { +namespace platform { + +std::string uppercase(const std::string& str) { + auto env{ android::AttachEnv() }; + jni::Local<jni::String> value = jni::Make<jni::String>(*env, str.c_str()); + static auto toUpperCase = jni::Class<jni::StringTag>::Singleton(*env).GetMethod<jni::String()>(*env, "toUpperCase"); + auto result = value.Call(*env, toUpperCase); + return jni::Make<std::string>(*env, result); +} + +std::string lowercase(const std::string& str) { + auto env{ android::AttachEnv() }; + jni::Local<jni::String> value = jni::Make<jni::String>(*env, str.c_str()); + static auto toLowerCase = jni::Class<jni::StringTag>::Singleton(*env).GetMethod<jni::String()>(*env, "toLowerCase"); + auto result = value.Call(*env, toLowerCase); + return jni::Make<std::string>(*env, result); +} + +} // namespace platform +} // namespace mbgl diff --git a/platform/android/src/style/conversion/filter.cpp b/platform/android/src/style/conversion/filter.cpp index 4eac0cf82..d15e2747a 100644 --- a/platform/android/src/style/conversion/filter.cpp +++ b/platform/android/src/style/conversion/filter.cpp @@ -8,7 +8,7 @@ namespace mbgl { namespace android { namespace conversion { -optional<mbgl::style::Filter> toFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter) { +optional<mbgl::style::Filter> toFilter(jni::JNIEnv& env, const jni::Array<jni::Object<>>& jfilter) { mbgl::optional<mbgl::style::Filter> filter; if (jfilter) { mbgl::style::conversion::Error error; @@ -23,4 +23,4 @@ optional<mbgl::style::Filter> toFilter(jni::JNIEnv& env, jni::Array<jni::Object< } // namespace conversion } // namespace android -} // namespace mbgl
\ No newline at end of file +} // namespace mbgl diff --git a/platform/android/src/style/conversion/filter.hpp b/platform/android/src/style/conversion/filter.hpp index df482de8f..920d336a1 100644 --- a/platform/android/src/style/conversion/filter.hpp +++ b/platform/android/src/style/conversion/filter.hpp @@ -9,7 +9,7 @@ namespace mbgl { namespace android { namespace conversion { -optional<mbgl::style::Filter> toFilter(jni::JNIEnv&, jni::Array<jni::Object<>>); +optional<mbgl::style::Filter> toFilter(jni::JNIEnv&, const jni::Array<jni::Object<>>&); } // namespace conversion } // namespace android diff --git a/platform/android/src/style/conversion/position.cpp b/platform/android/src/style/conversion/position.cpp index 9b3925914..e3c334afd 100644 --- a/platform/android/src/style/conversion/position.cpp +++ b/platform/android/src/style/conversion/position.cpp @@ -4,7 +4,7 @@ namespace mbgl { namespace android { namespace conversion { -Result<jni::Object<Position>> Converter<jni::Object<Position>, mbgl::style::Position>::operator()(jni::JNIEnv &env, const mbgl::style::Position &value) const { +Result<jni::Local<jni::Object<Position>>> Converter<jni::Local<jni::Object<Position>>, mbgl::style::Position>::operator()(jni::JNIEnv &env, const mbgl::style::Position &value) const { std::array<float, 3> cartPosition = value.getSpherical(); return Position::fromPosition(env, cartPosition[0], cartPosition[1], cartPosition[2]); } diff --git a/platform/android/src/style/conversion/position.hpp b/platform/android/src/style/conversion/position.hpp index 2ef4bf439..90409d527 100644 --- a/platform/android/src/style/conversion/position.hpp +++ b/platform/android/src/style/conversion/position.hpp @@ -11,8 +11,8 @@ namespace android { namespace conversion { template <> -struct Converter<jni::Object<Position>, mbgl::style::Position> { - Result<jni::Object<Position>> operator()(jni::JNIEnv &env, const mbgl::style::Position &value) const; +struct Converter<jni::Local<jni::Object<Position>>, mbgl::style::Position> { + Result<jni::Local<jni::Object<Position>>> operator()(jni::JNIEnv &env, const mbgl::style::Position &value) const; }; template <> diff --git a/platform/android/src/style/conversion/property_expression.hpp b/platform/android/src/style/conversion/property_expression.hpp index 08429960c..4e26b11f9 100644 --- a/platform/android/src/style/conversion/property_expression.hpp +++ b/platform/android/src/style/conversion/property_expression.hpp @@ -12,8 +12,8 @@ namespace android { namespace conversion { template <class T> -struct Converter<jni::Object<android::gson::JsonElement>, mbgl::style::PropertyExpression<T>> { - Result<jni::Object<android::gson::JsonElement>> operator()(jni::JNIEnv& env, const mbgl::style::PropertyExpression<T>& value) const { +struct Converter<jni::Local<jni::Object<android::gson::JsonElement>>, mbgl::style::PropertyExpression<T>> { + Result<jni::Local<jni::Object<android::gson::JsonElement>>> operator()(jni::JNIEnv& env, const mbgl::style::PropertyExpression<T>& value) const { return gson::JsonElement::New(env, value.getExpression().serialize()); } }; diff --git a/platform/android/src/style/conversion/property_value.hpp b/platform/android/src/style/conversion/property_value.hpp index 8150285c8..317705a28 100644 --- a/platform/android/src/style/conversion/property_value.hpp +++ b/platform/android/src/style/conversion/property_value.hpp @@ -19,16 +19,16 @@ class PropertyValueEvaluator { public: PropertyValueEvaluator(jni::JNIEnv& _env) : env(_env) {} - jni::jobject* operator()(const mbgl::style::Undefined) const { - return nullptr; + jni::Local<jni::Object<>> operator()(const mbgl::style::Undefined) const { + return jni::Local<jni::Object<>>(env, nullptr); } - jni::jobject* operator()(const T& value) const { - return *convert<jni::jobject*>(env, value); + jni::Local<jni::Object<>> operator()(const T& value) const { + return std::move(*convert<jni::Local<jni::Object<>>>(env, value)); } - jni::jobject* operator()(const mbgl::style::PropertyExpression<T>& value) const { - return *convert<jni::Object<android::gson::JsonElement>>(env, value); + jni::Local<jni::Object<>> operator()(const mbgl::style::PropertyExpression<T>& value) const { + return std::move(*convert<jni::Local<jni::Object<android::gson::JsonElement>>>(env, value)); } private: @@ -39,8 +39,8 @@ private: * Convert core property values to java */ template <class T> -struct Converter<jni::jobject*, mbgl::style::PropertyValue<T>> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::PropertyValue<T>& value) const { +struct Converter<jni::Local<jni::Object<>>, mbgl::style::PropertyValue<T>> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const mbgl::style::PropertyValue<T>& value) const { PropertyValueEvaluator<T> evaluator(env); return value.evaluate(evaluator); } @@ -50,10 +50,10 @@ struct Converter<jni::jobject*, mbgl::style::PropertyValue<T>> { * Convert core heat map color property value to java */ template <> -struct Converter<jni::jobject*, mbgl::style::ColorRampPropertyValue> { - Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::ColorRampPropertyValue& value) const { +struct Converter<jni::Local<jni::Object<>>, mbgl::style::ColorRampPropertyValue> { + Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const mbgl::style::ColorRampPropertyValue& value) const { PropertyValueEvaluator<mbgl::style::ColorRampPropertyValue> evaluator(env); - return *convert<jni::jobject*>(env, value.evaluate(evaluator)); + return std::move(*convert<jni::Local<jni::Object<>>>(env, value.evaluate(evaluator))); } }; diff --git a/platform/android/src/style/conversion/transition_options.cpp b/platform/android/src/style/conversion/transition_options.cpp index 313333ad1..66ddc7414 100644 --- a/platform/android/src/style/conversion/transition_options.cpp +++ b/platform/android/src/style/conversion/transition_options.cpp @@ -4,7 +4,7 @@ namespace mbgl { namespace android { namespace conversion { -Result<jni::Object<TransitionOptions>> Converter<jni::Object<TransitionOptions>, mbgl::style::TransitionOptions>::operator()(jni::JNIEnv& env, const mbgl::style::TransitionOptions& value) const { +Result<jni::Local<jni::Object<TransitionOptions>>> Converter<jni::Local<jni::Object<TransitionOptions>>, mbgl::style::TransitionOptions>::operator()(jni::JNIEnv& env, const mbgl::style::TransitionOptions& value) const { return TransitionOptions::fromTransitionOptions(env, std::chrono::duration_cast<std::chrono::milliseconds>(value.duration.value_or(mbgl::Duration::zero())).count(), std::chrono::duration_cast<std::chrono::milliseconds>(value.delay.value_or(mbgl::Duration::zero())).count() diff --git a/platform/android/src/style/conversion/transition_options.hpp b/platform/android/src/style/conversion/transition_options.hpp index 6630456d3..06c042922 100644 --- a/platform/android/src/style/conversion/transition_options.hpp +++ b/platform/android/src/style/conversion/transition_options.hpp @@ -12,8 +12,8 @@ namespace android { namespace conversion { template<> -struct Converter<jni::Object<TransitionOptions>, mbgl::style::TransitionOptions> { - Result<jni::Object<TransitionOptions>> operator()(jni::JNIEnv&, const mbgl::style::TransitionOptions&) const; +struct Converter<jni::Local<jni::Object<TransitionOptions>>, mbgl::style::TransitionOptions> { + Result<jni::Local<jni::Object<TransitionOptions>>> operator()(jni::JNIEnv&, const mbgl::style::TransitionOptions&) const; }; } diff --git a/platform/android/src/style/layers/background_layer.cpp b/platform/android/src/style/layers/background_layer.cpp index a8f013b23..c806e8471 100644 --- a/platform/android/src/style/layers/background_layer.cpp +++ b/platform/android/src/style/layers/background_layer.cpp @@ -13,7 +13,7 @@ namespace android { /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ - BackgroundLayer::BackgroundLayer(jni::JNIEnv& env, jni::String layerId) + BackgroundLayer::BackgroundLayer(jni::JNIEnv& env, jni::String& layerId) : Layer(env, std::make_unique<mbgl::style::BackgroundLayer>(jni::Make<std::string>(env, layerId))) { } @@ -35,16 +35,15 @@ namespace android { // Property getters - jni::Object<jni::ObjectTag> BackgroundLayer::getBackgroundColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> BackgroundLayer::getBackgroundColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::BackgroundLayer>()->BackgroundLayer::getBackgroundColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::BackgroundLayer>()->BackgroundLayer::getBackgroundColor())); } - jni::Object<TransitionOptions> BackgroundLayer::getBackgroundColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> BackgroundLayer::getBackgroundColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::BackgroundLayer>()->BackgroundLayer::getBackgroundColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void BackgroundLayer::setBackgroundColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -54,16 +53,15 @@ namespace android { layer.as<mbgl::style::BackgroundLayer>()->BackgroundLayer::setBackgroundColorTransition(options); } - jni::Object<jni::ObjectTag> BackgroundLayer::getBackgroundPattern(jni::JNIEnv& env) { + jni::Local<jni::Object<>> BackgroundLayer::getBackgroundPattern(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::BackgroundLayer>()->BackgroundLayer::getBackgroundPattern()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::BackgroundLayer>()->BackgroundLayer::getBackgroundPattern())); } - jni::Object<TransitionOptions> BackgroundLayer::getBackgroundPatternTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> BackgroundLayer::getBackgroundPatternTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::BackgroundLayer>()->BackgroundLayer::getBackgroundPatternTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void BackgroundLayer::setBackgroundPatternTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -73,16 +71,15 @@ namespace android { layer.as<mbgl::style::BackgroundLayer>()->BackgroundLayer::setBackgroundPatternTransition(options); } - jni::Object<jni::ObjectTag> BackgroundLayer::getBackgroundOpacity(jni::JNIEnv& env) { + jni::Local<jni::Object<>> BackgroundLayer::getBackgroundOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::BackgroundLayer>()->BackgroundLayer::getBackgroundOpacity()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::BackgroundLayer>()->BackgroundLayer::getBackgroundOpacity())); } - jni::Object<TransitionOptions> BackgroundLayer::getBackgroundOpacityTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> BackgroundLayer::getBackgroundOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::BackgroundLayer>()->BackgroundLayer::getBackgroundOpacityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void BackgroundLayer::setBackgroundOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -93,23 +90,22 @@ namespace android { } - jni::Class<BackgroundLayer> BackgroundLayer::javaClass; - - jni::jobject* BackgroundLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = BackgroundLayer::javaClass.template GetConstructor<jni::jlong>(env); - return BackgroundLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> BackgroundLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<BackgroundLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void BackgroundLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - BackgroundLayer::javaClass = *jni::Class<BackgroundLayer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<BackgroundLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<BackgroundLayer>( - env, BackgroundLayer::javaClass, "nativePtr", - std::make_unique<BackgroundLayer, JNIEnv&, jni::String>, + env, javaClass, "nativePtr", + jni::MakePeer<BackgroundLayer, jni::String&>, "initialize", "finalize", METHOD(&BackgroundLayer::getBackgroundColorTransition, "nativeGetBackgroundColorTransition"), diff --git a/platform/android/src/style/layers/background_layer.hpp b/platform/android/src/style/layers/background_layer.hpp index 95555a2d7..78cd5659f 100644 --- a/platform/android/src/style/layers/background_layer.hpp +++ b/platform/android/src/style/layers/background_layer.hpp @@ -12,14 +12,12 @@ namespace android { class BackgroundLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/BackgroundLayer"; }; - static jni::Class<BackgroundLayer> javaClass; - static void registerNative(jni::JNIEnv&); - BackgroundLayer(jni::JNIEnv&, jni::String); + BackgroundLayer(jni::JNIEnv&, jni::String&); BackgroundLayer(mbgl::Map&, mbgl::style::BackgroundLayer&); @@ -29,18 +27,18 @@ public: // Properties - jni::Object<jni::ObjectTag> getBackgroundColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getBackgroundColor(jni::JNIEnv&); void setBackgroundColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getBackgroundColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getBackgroundColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getBackgroundPattern(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getBackgroundPattern(jni::JNIEnv&); void setBackgroundPatternTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getBackgroundPatternTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getBackgroundPatternTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getBackgroundOpacity(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getBackgroundOpacity(jni::JNIEnv&); void setBackgroundOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getBackgroundOpacityTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getBackgroundOpacityTransition(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class BackgroundLayer diff --git a/platform/android/src/style/layers/circle_layer.cpp b/platform/android/src/style/layers/circle_layer.cpp index 4c7f69e95..9ec48d7b1 100644 --- a/platform/android/src/style/layers/circle_layer.cpp +++ b/platform/android/src/style/layers/circle_layer.cpp @@ -13,7 +13,7 @@ namespace android { /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ - CircleLayer::CircleLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + CircleLayer::CircleLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) : Layer(env, std::make_unique<mbgl::style::CircleLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { } @@ -35,16 +35,15 @@ namespace android { // Property getters - jni::Object<jni::ObjectTag> CircleLayer::getCircleRadius(jni::JNIEnv& env) { + jni::Local<jni::Object<>> CircleLayer::getCircleRadius(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleRadius()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleRadius())); } - jni::Object<TransitionOptions> CircleLayer::getCircleRadiusTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> CircleLayer::getCircleRadiusTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleRadiusTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void CircleLayer::setCircleRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -54,16 +53,15 @@ namespace android { layer.as<mbgl::style::CircleLayer>()->CircleLayer::setCircleRadiusTransition(options); } - jni::Object<jni::ObjectTag> CircleLayer::getCircleColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> CircleLayer::getCircleColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleColor())); } - jni::Object<TransitionOptions> CircleLayer::getCircleColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> CircleLayer::getCircleColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void CircleLayer::setCircleColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -73,16 +71,15 @@ namespace android { layer.as<mbgl::style::CircleLayer>()->CircleLayer::setCircleColorTransition(options); } - jni::Object<jni::ObjectTag> CircleLayer::getCircleBlur(jni::JNIEnv& env) { + jni::Local<jni::Object<>> CircleLayer::getCircleBlur(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleBlur()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleBlur())); } - jni::Object<TransitionOptions> CircleLayer::getCircleBlurTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> CircleLayer::getCircleBlurTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleBlurTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void CircleLayer::setCircleBlurTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -92,16 +89,15 @@ namespace android { layer.as<mbgl::style::CircleLayer>()->CircleLayer::setCircleBlurTransition(options); } - jni::Object<jni::ObjectTag> CircleLayer::getCircleOpacity(jni::JNIEnv& env) { + jni::Local<jni::Object<>> CircleLayer::getCircleOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleOpacity()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleOpacity())); } - jni::Object<TransitionOptions> CircleLayer::getCircleOpacityTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> CircleLayer::getCircleOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleOpacityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void CircleLayer::setCircleOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -111,16 +107,15 @@ namespace android { layer.as<mbgl::style::CircleLayer>()->CircleLayer::setCircleOpacityTransition(options); } - jni::Object<jni::ObjectTag> CircleLayer::getCircleTranslate(jni::JNIEnv& env) { + jni::Local<jni::Object<>> CircleLayer::getCircleTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleTranslate()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleTranslate())); } - jni::Object<TransitionOptions> CircleLayer::getCircleTranslateTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> CircleLayer::getCircleTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleTranslateTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void CircleLayer::setCircleTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -130,34 +125,30 @@ namespace android { layer.as<mbgl::style::CircleLayer>()->CircleLayer::setCircleTranslateTransition(options); } - jni::Object<jni::ObjectTag> CircleLayer::getCircleTranslateAnchor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> CircleLayer::getCircleTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleTranslateAnchor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleTranslateAnchor())); } - jni::Object<jni::ObjectTag> CircleLayer::getCirclePitchScale(jni::JNIEnv& env) { + jni::Local<jni::Object<>> CircleLayer::getCirclePitchScale(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCirclePitchScale()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCirclePitchScale())); } - jni::Object<jni::ObjectTag> CircleLayer::getCirclePitchAlignment(jni::JNIEnv& env) { + jni::Local<jni::Object<>> CircleLayer::getCirclePitchAlignment(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCirclePitchAlignment()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCirclePitchAlignment())); } - jni::Object<jni::ObjectTag> CircleLayer::getCircleStrokeWidth(jni::JNIEnv& env) { + jni::Local<jni::Object<>> CircleLayer::getCircleStrokeWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeWidth()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeWidth())); } - jni::Object<TransitionOptions> CircleLayer::getCircleStrokeWidthTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> CircleLayer::getCircleStrokeWidthTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeWidthTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void CircleLayer::setCircleStrokeWidthTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -167,16 +158,15 @@ namespace android { layer.as<mbgl::style::CircleLayer>()->CircleLayer::setCircleStrokeWidthTransition(options); } - jni::Object<jni::ObjectTag> CircleLayer::getCircleStrokeColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> CircleLayer::getCircleStrokeColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeColor())); } - jni::Object<TransitionOptions> CircleLayer::getCircleStrokeColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> CircleLayer::getCircleStrokeColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void CircleLayer::setCircleStrokeColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -186,16 +176,15 @@ namespace android { layer.as<mbgl::style::CircleLayer>()->CircleLayer::setCircleStrokeColorTransition(options); } - jni::Object<jni::ObjectTag> CircleLayer::getCircleStrokeOpacity(jni::JNIEnv& env) { + jni::Local<jni::Object<>> CircleLayer::getCircleStrokeOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeOpacity()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeOpacity())); } - jni::Object<TransitionOptions> CircleLayer::getCircleStrokeOpacityTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> CircleLayer::getCircleStrokeOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeOpacityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void CircleLayer::setCircleStrokeOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -206,23 +195,22 @@ namespace android { } - jni::Class<CircleLayer> CircleLayer::javaClass; - - jni::jobject* CircleLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CircleLayer::javaClass.template GetConstructor<jni::jlong>(env); - return CircleLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> CircleLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<CircleLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void CircleLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - CircleLayer::javaClass = *jni::Class<CircleLayer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<CircleLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<CircleLayer>( - env, CircleLayer::javaClass, "nativePtr", - std::make_unique<CircleLayer, JNIEnv&, jni::String, jni::String>, + env, javaClass, "nativePtr", + jni::MakePeer<CircleLayer, jni::String&, jni::String&>, "initialize", "finalize", METHOD(&CircleLayer::getCircleRadiusTransition, "nativeGetCircleRadiusTransition"), diff --git a/platform/android/src/style/layers/circle_layer.hpp b/platform/android/src/style/layers/circle_layer.hpp index 9d323e92b..0ff34094e 100644 --- a/platform/android/src/style/layers/circle_layer.hpp +++ b/platform/android/src/style/layers/circle_layer.hpp @@ -12,14 +12,12 @@ namespace android { class CircleLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/CircleLayer"; }; - static jni::Class<CircleLayer> javaClass; - static void registerNative(jni::JNIEnv&); - CircleLayer(jni::JNIEnv&, jni::String, jni::String); + CircleLayer(jni::JNIEnv&, jni::String&, jni::String&); CircleLayer(mbgl::Map&, mbgl::style::CircleLayer&); @@ -29,44 +27,44 @@ public: // Properties - jni::Object<jni::ObjectTag> getCircleRadius(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getCircleRadius(jni::JNIEnv&); void setCircleRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getCircleRadiusTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getCircleRadiusTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getCircleColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getCircleColor(jni::JNIEnv&); void setCircleColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getCircleColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getCircleColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getCircleBlur(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getCircleBlur(jni::JNIEnv&); void setCircleBlurTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getCircleBlurTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getCircleBlurTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getCircleOpacity(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getCircleOpacity(jni::JNIEnv&); void setCircleOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getCircleOpacityTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getCircleOpacityTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getCircleTranslate(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getCircleTranslate(jni::JNIEnv&); void setCircleTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getCircleTranslateTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getCircleTranslateTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getCircleTranslateAnchor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getCircleTranslateAnchor(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getCirclePitchScale(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getCirclePitchScale(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getCirclePitchAlignment(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getCirclePitchAlignment(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getCircleStrokeWidth(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getCircleStrokeWidth(jni::JNIEnv&); void setCircleStrokeWidthTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getCircleStrokeWidthTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getCircleStrokeWidthTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getCircleStrokeColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getCircleStrokeColor(jni::JNIEnv&); void setCircleStrokeColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getCircleStrokeColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getCircleStrokeColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getCircleStrokeOpacity(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getCircleStrokeOpacity(jni::JNIEnv&); void setCircleStrokeOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getCircleStrokeOpacityTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getCircleStrokeOpacityTransition(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class CircleLayer diff --git a/platform/android/src/style/layers/custom_layer.cpp b/platform/android/src/style/layers/custom_layer.cpp index 61e74a9cf..f6f3bb249 100644 --- a/platform/android/src/style/layers/custom_layer.cpp +++ b/platform/android/src/style/layers/custom_layer.cpp @@ -7,7 +7,7 @@ namespace mbgl { namespace android { - CustomLayer::CustomLayer(jni::JNIEnv& env, jni::String layerId, jni::jlong host) + CustomLayer::CustomLayer(jni::JNIEnv& env, const jni::String& layerId, jni::jlong host) : Layer(env, std::make_unique<mbgl::style::CustomLayer>( jni::Make<std::string>(env, layerId), std::unique_ptr<mbgl::style::CustomLayerHost>(reinterpret_cast<mbgl::style::CustomLayerHost*>(host))) @@ -33,23 +33,22 @@ namespace android { } } - jni::Class<CustomLayer> CustomLayer::javaClass; - - jni::jobject* CustomLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CustomLayer::javaClass.template GetConstructor<jni::jlong>(env); - return CustomLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> CustomLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<CustomLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void CustomLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - CustomLayer::javaClass = *jni::Class<CustomLayer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<CustomLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<CustomLayer>( - env, CustomLayer::javaClass, "nativePtr", - std::make_unique<CustomLayer, JNIEnv&, jni::String, jni::jlong>, + env, javaClass, "nativePtr", + jni::MakePeer<CustomLayer, const jni::String&, jni::jlong>, "initialize", "finalize", METHOD(&CustomLayer::update, "nativeUpdate")); diff --git a/platform/android/src/style/layers/custom_layer.hpp b/platform/android/src/style/layers/custom_layer.hpp index 7eb649d92..950fcef9c 100644 --- a/platform/android/src/style/layers/custom_layer.hpp +++ b/platform/android/src/style/layers/custom_layer.hpp @@ -9,24 +9,19 @@ namespace android { class CustomLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/CustomLayer"; }; - static jni::Class<CustomLayer> javaClass; - static void registerNative(jni::JNIEnv&); - CustomLayer(jni::JNIEnv&, jni::String, jni::jlong); - + CustomLayer(jni::JNIEnv&, const jni::String&, jni::jlong); CustomLayer(mbgl::Map&, mbgl::style::CustomLayer&); - CustomLayer(mbgl::Map&, std::unique_ptr<mbgl::style::CustomLayer>); - ~CustomLayer(); void update(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class CustomLayer diff --git a/platform/android/src/style/layers/fill_extrusion_layer.cpp b/platform/android/src/style/layers/fill_extrusion_layer.cpp index 492e1729b..cf53e774a 100644 --- a/platform/android/src/style/layers/fill_extrusion_layer.cpp +++ b/platform/android/src/style/layers/fill_extrusion_layer.cpp @@ -13,7 +13,7 @@ namespace android { /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ - FillExtrusionLayer::FillExtrusionLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + FillExtrusionLayer::FillExtrusionLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) : Layer(env, std::make_unique<mbgl::style::FillExtrusionLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { } @@ -35,16 +35,15 @@ namespace android { // Property getters - jni::Object<jni::ObjectTag> FillExtrusionLayer::getFillExtrusionOpacity(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillExtrusionLayer::getFillExtrusionOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionOpacity()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionOpacity())); } - jni::Object<TransitionOptions> FillExtrusionLayer::getFillExtrusionOpacityTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> FillExtrusionLayer::getFillExtrusionOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionOpacityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void FillExtrusionLayer::setFillExtrusionOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -54,16 +53,15 @@ namespace android { layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::setFillExtrusionOpacityTransition(options); } - jni::Object<jni::ObjectTag> FillExtrusionLayer::getFillExtrusionColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillExtrusionLayer::getFillExtrusionColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionColor())); } - jni::Object<TransitionOptions> FillExtrusionLayer::getFillExtrusionColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> FillExtrusionLayer::getFillExtrusionColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void FillExtrusionLayer::setFillExtrusionColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -73,16 +71,15 @@ namespace android { layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::setFillExtrusionColorTransition(options); } - jni::Object<jni::ObjectTag> FillExtrusionLayer::getFillExtrusionTranslate(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillExtrusionLayer::getFillExtrusionTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionTranslate()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionTranslate())); } - jni::Object<TransitionOptions> FillExtrusionLayer::getFillExtrusionTranslateTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> FillExtrusionLayer::getFillExtrusionTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionTranslateTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void FillExtrusionLayer::setFillExtrusionTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -92,22 +89,20 @@ namespace android { layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::setFillExtrusionTranslateTransition(options); } - jni::Object<jni::ObjectTag> FillExtrusionLayer::getFillExtrusionTranslateAnchor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillExtrusionLayer::getFillExtrusionTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionTranslateAnchor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionTranslateAnchor())); } - jni::Object<jni::ObjectTag> FillExtrusionLayer::getFillExtrusionPattern(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillExtrusionLayer::getFillExtrusionPattern(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionPattern()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionPattern())); } - jni::Object<TransitionOptions> FillExtrusionLayer::getFillExtrusionPatternTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> FillExtrusionLayer::getFillExtrusionPatternTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionPatternTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void FillExtrusionLayer::setFillExtrusionPatternTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -117,16 +112,15 @@ namespace android { layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::setFillExtrusionPatternTransition(options); } - jni::Object<jni::ObjectTag> FillExtrusionLayer::getFillExtrusionHeight(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillExtrusionLayer::getFillExtrusionHeight(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionHeight()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionHeight())); } - jni::Object<TransitionOptions> FillExtrusionLayer::getFillExtrusionHeightTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> FillExtrusionLayer::getFillExtrusionHeightTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionHeightTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void FillExtrusionLayer::setFillExtrusionHeightTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -136,16 +130,15 @@ namespace android { layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::setFillExtrusionHeightTransition(options); } - jni::Object<jni::ObjectTag> FillExtrusionLayer::getFillExtrusionBase(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillExtrusionLayer::getFillExtrusionBase(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionBase()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionBase())); } - jni::Object<TransitionOptions> FillExtrusionLayer::getFillExtrusionBaseTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> FillExtrusionLayer::getFillExtrusionBaseTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::FillExtrusionLayer>()->FillExtrusionLayer::getFillExtrusionBaseTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void FillExtrusionLayer::setFillExtrusionBaseTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -156,23 +149,22 @@ namespace android { } - jni::Class<FillExtrusionLayer> FillExtrusionLayer::javaClass; - - jni::jobject* FillExtrusionLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = FillExtrusionLayer::javaClass.template GetConstructor<jni::jlong>(env); - return FillExtrusionLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> FillExtrusionLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<FillExtrusionLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void FillExtrusionLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - FillExtrusionLayer::javaClass = *jni::Class<FillExtrusionLayer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<FillExtrusionLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<FillExtrusionLayer>( - env, FillExtrusionLayer::javaClass, "nativePtr", - std::make_unique<FillExtrusionLayer, JNIEnv&, jni::String, jni::String>, + env, javaClass, "nativePtr", + jni::MakePeer<FillExtrusionLayer, jni::String&, jni::String&>, "initialize", "finalize", METHOD(&FillExtrusionLayer::getFillExtrusionOpacityTransition, "nativeGetFillExtrusionOpacityTransition"), diff --git a/platform/android/src/style/layers/fill_extrusion_layer.hpp b/platform/android/src/style/layers/fill_extrusion_layer.hpp index 11a74bc8e..abc30b584 100644 --- a/platform/android/src/style/layers/fill_extrusion_layer.hpp +++ b/platform/android/src/style/layers/fill_extrusion_layer.hpp @@ -12,14 +12,12 @@ namespace android { class FillExtrusionLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer"; }; - static jni::Class<FillExtrusionLayer> javaClass; - static void registerNative(jni::JNIEnv&); - FillExtrusionLayer(jni::JNIEnv&, jni::String, jni::String); + FillExtrusionLayer(jni::JNIEnv&, jni::String&, jni::String&); FillExtrusionLayer(mbgl::Map&, mbgl::style::FillExtrusionLayer&); @@ -29,32 +27,32 @@ public: // Properties - jni::Object<jni::ObjectTag> getFillExtrusionOpacity(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillExtrusionOpacity(jni::JNIEnv&); void setFillExtrusionOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getFillExtrusionOpacityTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getFillExtrusionOpacityTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillExtrusionColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillExtrusionColor(jni::JNIEnv&); void setFillExtrusionColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getFillExtrusionColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getFillExtrusionColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillExtrusionTranslate(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillExtrusionTranslate(jni::JNIEnv&); void setFillExtrusionTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getFillExtrusionTranslateTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getFillExtrusionTranslateTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillExtrusionTranslateAnchor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillExtrusionTranslateAnchor(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillExtrusionPattern(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillExtrusionPattern(jni::JNIEnv&); void setFillExtrusionPatternTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getFillExtrusionPatternTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getFillExtrusionPatternTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillExtrusionHeight(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillExtrusionHeight(jni::JNIEnv&); void setFillExtrusionHeightTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getFillExtrusionHeightTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getFillExtrusionHeightTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillExtrusionBase(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillExtrusionBase(jni::JNIEnv&); void setFillExtrusionBaseTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getFillExtrusionBaseTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getFillExtrusionBaseTransition(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class FillExtrusionLayer diff --git a/platform/android/src/style/layers/fill_layer.cpp b/platform/android/src/style/layers/fill_layer.cpp index f4cddc885..555f8eb3c 100644 --- a/platform/android/src/style/layers/fill_layer.cpp +++ b/platform/android/src/style/layers/fill_layer.cpp @@ -13,7 +13,7 @@ namespace android { /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ - FillLayer::FillLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + FillLayer::FillLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) : Layer(env, std::make_unique<mbgl::style::FillLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { } @@ -35,22 +35,20 @@ namespace android { // Property getters - jni::Object<jni::ObjectTag> FillLayer::getFillAntialias(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillLayer::getFillAntialias(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillAntialias()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillAntialias())); } - jni::Object<jni::ObjectTag> FillLayer::getFillOpacity(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillLayer::getFillOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillOpacity()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillOpacity())); } - jni::Object<TransitionOptions> FillLayer::getFillOpacityTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> FillLayer::getFillOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::FillLayer>()->FillLayer::getFillOpacityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void FillLayer::setFillOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -60,16 +58,15 @@ namespace android { layer.as<mbgl::style::FillLayer>()->FillLayer::setFillOpacityTransition(options); } - jni::Object<jni::ObjectTag> FillLayer::getFillColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillLayer::getFillColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillColor())); } - jni::Object<TransitionOptions> FillLayer::getFillColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> FillLayer::getFillColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::FillLayer>()->FillLayer::getFillColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void FillLayer::setFillColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -79,16 +76,15 @@ namespace android { layer.as<mbgl::style::FillLayer>()->FillLayer::setFillColorTransition(options); } - jni::Object<jni::ObjectTag> FillLayer::getFillOutlineColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillLayer::getFillOutlineColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillOutlineColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillOutlineColor())); } - jni::Object<TransitionOptions> FillLayer::getFillOutlineColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> FillLayer::getFillOutlineColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::FillLayer>()->FillLayer::getFillOutlineColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void FillLayer::setFillOutlineColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -98,16 +94,15 @@ namespace android { layer.as<mbgl::style::FillLayer>()->FillLayer::setFillOutlineColorTransition(options); } - jni::Object<jni::ObjectTag> FillLayer::getFillTranslate(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillLayer::getFillTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillTranslate()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillTranslate())); } - jni::Object<TransitionOptions> FillLayer::getFillTranslateTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> FillLayer::getFillTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::FillLayer>()->FillLayer::getFillTranslateTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void FillLayer::setFillTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -117,22 +112,20 @@ namespace android { layer.as<mbgl::style::FillLayer>()->FillLayer::setFillTranslateTransition(options); } - jni::Object<jni::ObjectTag> FillLayer::getFillTranslateAnchor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillLayer::getFillTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillTranslateAnchor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillTranslateAnchor())); } - jni::Object<jni::ObjectTag> FillLayer::getFillPattern(jni::JNIEnv& env) { + jni::Local<jni::Object<>> FillLayer::getFillPattern(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillPattern()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::FillLayer>()->FillLayer::getFillPattern())); } - jni::Object<TransitionOptions> FillLayer::getFillPatternTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> FillLayer::getFillPatternTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::FillLayer>()->FillLayer::getFillPatternTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void FillLayer::setFillPatternTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -143,23 +136,22 @@ namespace android { } - jni::Class<FillLayer> FillLayer::javaClass; - - jni::jobject* FillLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = FillLayer::javaClass.template GetConstructor<jni::jlong>(env); - return FillLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> FillLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<FillLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void FillLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - FillLayer::javaClass = *jni::Class<FillLayer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<FillLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<FillLayer>( - env, FillLayer::javaClass, "nativePtr", - std::make_unique<FillLayer, JNIEnv&, jni::String, jni::String>, + env, javaClass, "nativePtr", + jni::MakePeer<FillLayer, jni::String&, jni::String&>, "initialize", "finalize", METHOD(&FillLayer::getFillAntialias, "nativeGetFillAntialias"), diff --git a/platform/android/src/style/layers/fill_layer.hpp b/platform/android/src/style/layers/fill_layer.hpp index a773cf785..ea9632057 100644 --- a/platform/android/src/style/layers/fill_layer.hpp +++ b/platform/android/src/style/layers/fill_layer.hpp @@ -12,14 +12,12 @@ namespace android { class FillLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/FillLayer"; }; - static jni::Class<FillLayer> javaClass; - static void registerNative(jni::JNIEnv&); - FillLayer(jni::JNIEnv&, jni::String, jni::String); + FillLayer(jni::JNIEnv&, jni::String&, jni::String&); FillLayer(mbgl::Map&, mbgl::style::FillLayer&); @@ -29,30 +27,30 @@ public: // Properties - jni::Object<jni::ObjectTag> getFillAntialias(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillAntialias(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillOpacity(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillOpacity(jni::JNIEnv&); void setFillOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getFillOpacityTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getFillOpacityTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillColor(jni::JNIEnv&); void setFillColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getFillColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getFillColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillOutlineColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillOutlineColor(jni::JNIEnv&); void setFillOutlineColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getFillOutlineColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getFillOutlineColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillTranslate(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillTranslate(jni::JNIEnv&); void setFillTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getFillTranslateTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getFillTranslateTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillTranslateAnchor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillTranslateAnchor(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getFillPattern(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getFillPattern(jni::JNIEnv&); void setFillPatternTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getFillPatternTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getFillPatternTransition(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class FillLayer diff --git a/platform/android/src/style/layers/heatmap_layer.cpp b/platform/android/src/style/layers/heatmap_layer.cpp index b3d90faab..b72b37292 100644 --- a/platform/android/src/style/layers/heatmap_layer.cpp +++ b/platform/android/src/style/layers/heatmap_layer.cpp @@ -13,7 +13,7 @@ namespace android { /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ - HeatmapLayer::HeatmapLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + HeatmapLayer::HeatmapLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) : Layer(env, std::make_unique<mbgl::style::HeatmapLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { } @@ -35,16 +35,15 @@ namespace android { // Property getters - jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapRadius(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HeatmapLayer::getHeatmapRadius(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapRadius()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapRadius())); } - jni::Object<TransitionOptions> HeatmapLayer::getHeatmapRadiusTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> HeatmapLayer::getHeatmapRadiusTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapRadiusTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void HeatmapLayer::setHeatmapRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -54,22 +53,20 @@ namespace android { layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::setHeatmapRadiusTransition(options); } - jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapWeight(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HeatmapLayer::getHeatmapWeight(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapWeight()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapWeight())); } - jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapIntensity(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HeatmapLayer::getHeatmapIntensity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapIntensity()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapIntensity())); } - jni::Object<TransitionOptions> HeatmapLayer::getHeatmapIntensityTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> HeatmapLayer::getHeatmapIntensityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapIntensityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void HeatmapLayer::setHeatmapIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -79,26 +76,24 @@ namespace android { layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::setHeatmapIntensityTransition(options); } - jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HeatmapLayer::getHeatmapColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; auto propertyValue = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapColor(); if (propertyValue.isUndefined()) { propertyValue = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getDefaultHeatmapColor(); } - Result<jni::jobject*> converted = convert<jni::jobject*>(env, propertyValue); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, propertyValue)); } - jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapOpacity(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HeatmapLayer::getHeatmapOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapOpacity()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapOpacity())); } - jni::Object<TransitionOptions> HeatmapLayer::getHeatmapOpacityTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> HeatmapLayer::getHeatmapOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapOpacityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void HeatmapLayer::setHeatmapOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -109,23 +104,22 @@ namespace android { } - jni::Class<HeatmapLayer> HeatmapLayer::javaClass; - - jni::jobject* HeatmapLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = HeatmapLayer::javaClass.template GetConstructor<jni::jlong>(env); - return HeatmapLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> HeatmapLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<HeatmapLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void HeatmapLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - HeatmapLayer::javaClass = *jni::Class<HeatmapLayer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<HeatmapLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<HeatmapLayer>( - env, HeatmapLayer::javaClass, "nativePtr", - std::make_unique<HeatmapLayer, JNIEnv&, jni::String, jni::String>, + env, javaClass, "nativePtr", + jni::MakePeer<HeatmapLayer, jni::String&, jni::String&>, "initialize", "finalize", METHOD(&HeatmapLayer::getHeatmapRadiusTransition, "nativeGetHeatmapRadiusTransition"), diff --git a/platform/android/src/style/layers/heatmap_layer.hpp b/platform/android/src/style/layers/heatmap_layer.hpp index 9e8908b06..2976e6c48 100644 --- a/platform/android/src/style/layers/heatmap_layer.hpp +++ b/platform/android/src/style/layers/heatmap_layer.hpp @@ -12,14 +12,12 @@ namespace android { class HeatmapLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HeatmapLayer"; }; - static jni::Class<HeatmapLayer> javaClass; - static void registerNative(jni::JNIEnv&); - HeatmapLayer(jni::JNIEnv&, jni::String, jni::String); + HeatmapLayer(jni::JNIEnv&, jni::String&, jni::String&); HeatmapLayer(mbgl::Map&, mbgl::style::HeatmapLayer&); @@ -29,22 +27,22 @@ public: // Properties - jni::Object<jni::ObjectTag> getHeatmapRadius(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getHeatmapRadius(jni::JNIEnv&); void setHeatmapRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getHeatmapRadiusTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getHeatmapRadiusTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getHeatmapWeight(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getHeatmapWeight(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getHeatmapIntensity(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getHeatmapIntensity(jni::JNIEnv&); void setHeatmapIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getHeatmapIntensityTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getHeatmapIntensityTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getHeatmapColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getHeatmapColor(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getHeatmapOpacity(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getHeatmapOpacity(jni::JNIEnv&); void setHeatmapOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getHeatmapOpacityTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getHeatmapOpacityTransition(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class HeatmapLayer diff --git a/platform/android/src/style/layers/hillshade_layer.cpp b/platform/android/src/style/layers/hillshade_layer.cpp index d98e3ee07..5cd616257 100644 --- a/platform/android/src/style/layers/hillshade_layer.cpp +++ b/platform/android/src/style/layers/hillshade_layer.cpp @@ -13,7 +13,7 @@ namespace android { /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ - HillshadeLayer::HillshadeLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + HillshadeLayer::HillshadeLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) : Layer(env, std::make_unique<mbgl::style::HillshadeLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { } @@ -35,28 +35,25 @@ namespace android { // Property getters - jni::Object<jni::ObjectTag> HillshadeLayer::getHillshadeIlluminationDirection(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HillshadeLayer::getHillshadeIlluminationDirection(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeIlluminationDirection()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeIlluminationDirection())); } - jni::Object<jni::ObjectTag> HillshadeLayer::getHillshadeIlluminationAnchor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HillshadeLayer::getHillshadeIlluminationAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeIlluminationAnchor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeIlluminationAnchor())); } - jni::Object<jni::ObjectTag> HillshadeLayer::getHillshadeExaggeration(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HillshadeLayer::getHillshadeExaggeration(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeExaggeration()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeExaggeration())); } - jni::Object<TransitionOptions> HillshadeLayer::getHillshadeExaggerationTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> HillshadeLayer::getHillshadeExaggerationTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeExaggerationTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void HillshadeLayer::setHillshadeExaggerationTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -66,16 +63,15 @@ namespace android { layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::setHillshadeExaggerationTransition(options); } - jni::Object<jni::ObjectTag> HillshadeLayer::getHillshadeShadowColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HillshadeLayer::getHillshadeShadowColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeShadowColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeShadowColor())); } - jni::Object<TransitionOptions> HillshadeLayer::getHillshadeShadowColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> HillshadeLayer::getHillshadeShadowColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeShadowColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void HillshadeLayer::setHillshadeShadowColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -85,16 +81,15 @@ namespace android { layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::setHillshadeShadowColorTransition(options); } - jni::Object<jni::ObjectTag> HillshadeLayer::getHillshadeHighlightColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HillshadeLayer::getHillshadeHighlightColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeHighlightColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeHighlightColor())); } - jni::Object<TransitionOptions> HillshadeLayer::getHillshadeHighlightColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> HillshadeLayer::getHillshadeHighlightColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeHighlightColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void HillshadeLayer::setHillshadeHighlightColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -104,16 +99,15 @@ namespace android { layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::setHillshadeHighlightColorTransition(options); } - jni::Object<jni::ObjectTag> HillshadeLayer::getHillshadeAccentColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HillshadeLayer::getHillshadeAccentColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeAccentColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeAccentColor())); } - jni::Object<TransitionOptions> HillshadeLayer::getHillshadeAccentColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> HillshadeLayer::getHillshadeAccentColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::HillshadeLayer>()->HillshadeLayer::getHillshadeAccentColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void HillshadeLayer::setHillshadeAccentColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -124,23 +118,22 @@ namespace android { } - jni::Class<HillshadeLayer> HillshadeLayer::javaClass; - - jni::jobject* HillshadeLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = HillshadeLayer::javaClass.template GetConstructor<jni::jlong>(env); - return HillshadeLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> HillshadeLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<HillshadeLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void HillshadeLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - HillshadeLayer::javaClass = *jni::Class<HillshadeLayer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<HillshadeLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<HillshadeLayer>( - env, HillshadeLayer::javaClass, "nativePtr", - std::make_unique<HillshadeLayer, JNIEnv&, jni::String, jni::String>, + env, javaClass, "nativePtr", + jni::MakePeer<HillshadeLayer, jni::String&, jni::String&>, "initialize", "finalize", METHOD(&HillshadeLayer::getHillshadeIlluminationDirection, "nativeGetHillshadeIlluminationDirection"), diff --git a/platform/android/src/style/layers/hillshade_layer.hpp b/platform/android/src/style/layers/hillshade_layer.hpp index 4b6825177..9ca0e33cf 100644 --- a/platform/android/src/style/layers/hillshade_layer.hpp +++ b/platform/android/src/style/layers/hillshade_layer.hpp @@ -12,14 +12,12 @@ namespace android { class HillshadeLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HillshadeLayer"; }; - static jni::Class<HillshadeLayer> javaClass; - static void registerNative(jni::JNIEnv&); - HillshadeLayer(jni::JNIEnv&, jni::String, jni::String); + HillshadeLayer(jni::JNIEnv&, jni::String&, jni::String&); HillshadeLayer(mbgl::Map&, mbgl::style::HillshadeLayer&); @@ -29,26 +27,26 @@ public: // Properties - jni::Object<jni::ObjectTag> getHillshadeIlluminationDirection(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getHillshadeIlluminationDirection(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getHillshadeIlluminationAnchor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getHillshadeIlluminationAnchor(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getHillshadeExaggeration(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getHillshadeExaggeration(jni::JNIEnv&); void setHillshadeExaggerationTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getHillshadeExaggerationTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getHillshadeExaggerationTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getHillshadeShadowColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getHillshadeShadowColor(jni::JNIEnv&); void setHillshadeShadowColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getHillshadeShadowColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getHillshadeShadowColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getHillshadeHighlightColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getHillshadeHighlightColor(jni::JNIEnv&); void setHillshadeHighlightColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getHillshadeHighlightColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getHillshadeHighlightColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getHillshadeAccentColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getHillshadeAccentColor(jni::JNIEnv&); void setHillshadeAccentColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getHillshadeAccentColorTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getHillshadeAccentColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class HillshadeLayer diff --git a/platform/android/src/style/layers/layer.cpp b/platform/android/src/style/layers/layer.cpp index 48e09674e..5726873f4 100644 --- a/platform/android/src/style/layers/layer.cpp +++ b/platform/android/src/style/layers/layer.cpp @@ -83,7 +83,7 @@ namespace android { return std::move(ownedLayer); } - jni::String Layer::getId(jni::JNIEnv& env) { + jni::Local<jni::String> Layer::getId(jni::JNIEnv& env) { return jni::Make<jni::String>(env, layer.getID()); } @@ -91,7 +91,7 @@ namespace android { return layer; } - void Layer::setLayoutProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) { + void Layer::setLayoutProperty(jni::JNIEnv& env, const jni::String& jname, const jni::Object<>& jvalue) { // Convert and set property optional<mbgl::style::conversion::Error> error = layer.setLayoutProperty(jni::Make<std::string>(env, jname), Value(env, jvalue)); if (error) { @@ -100,7 +100,7 @@ namespace android { } } - void Layer::setPaintProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) { + void Layer::setPaintProperty(jni::JNIEnv& env, const jni::String& jname, const jni::Object<>& jvalue) { // Convert and set property optional<mbgl::style::conversion::Error> error = layer.setPaintProperty(jni::Make<std::string>(env, jname), Value(env, jvalue)); if (error) { @@ -123,7 +123,7 @@ namespace android { } }; - void Layer::setFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter) { + void Layer::setFilter(jni::JNIEnv& env, const jni::Array<jni::Object<>>& jfilter) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -154,7 +154,7 @@ namespace android { } }; - jni::Object<gson::JsonElement> Layer::getFilter(jni::JNIEnv& env) { + jni::Local<jni::Object<gson::JsonElement>> Layer::getFilter(jni::JNIEnv& env) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -163,7 +163,7 @@ namespace android { mbgl::Value expressionValue = (*filter.expression)->serialize(); return gson::JsonElement::New(env, expressionValue); } else { - return jni::Object<gson::JsonElement>(); + return jni::Local<jni::Object<gson::JsonElement>>(env, nullptr); } } @@ -181,7 +181,7 @@ namespace android { } }; - void Layer::setSourceLayer(jni::JNIEnv& env, jni::String sourceLayer) { + void Layer::setSourceLayer(jni::JNIEnv& env, const jni::String& sourceLayer) { layer.accept(SetSourceLayerEvaluator {jni::Make<std::string>(env, sourceLayer)}); } @@ -202,7 +202,7 @@ namespace android { } }; - jni::String Layer::getSourceLayer(jni::JNIEnv& env) { + jni::Local<jni::String> Layer::getSourceLayer(jni::JNIEnv& env) { return jni::Make<jni::String>(env, layer.accept(GetSourceLayerEvaluator())); } @@ -221,7 +221,7 @@ namespace android { } }; - jni::String Layer::getSourceId(jni::JNIEnv& env) { + jni::Local<jni::String> Layer::getSourceId(jni::JNIEnv& env) { return jni::Make<jni::String>(env, layer.accept(GetSourceIdEvaluator())); } @@ -241,21 +241,19 @@ namespace android { layer.setMaxZoom(zoom); } - jni::Object<jni::ObjectTag> Layer::getVisibility(jni::JNIEnv& env) { + jni::Local<jni::Object<>> Layer::getVisibility(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - return jni::Object<jni::ObjectTag>(*convert<jni::jobject*>(env, layer.getVisibility())); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.getVisibility())); } - jni::Class<Layer> Layer::javaClass; - void Layer::registerNative(jni::JNIEnv& env) { // Lookup the class - Layer::javaClass = *jni::Class<Layer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<Layer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<Layer>(env, Layer::javaClass, "nativePtr", + jni::RegisterNativePeer<Layer>(env, javaClass, "nativePtr", METHOD(&Layer::getId, "nativeGetId"), METHOD(&Layer::setLayoutProperty, "nativeSetLayoutProperty"), METHOD(&Layer::setPaintProperty, "nativeSetPaintProperty"), diff --git a/platform/android/src/style/layers/layer.cpp.ejs b/platform/android/src/style/layers/layer.cpp.ejs index b08f0ec4d..875bc88bc 100644 --- a/platform/android/src/style/layers/layer.cpp.ejs +++ b/platform/android/src/style/layers/layer.cpp.ejs @@ -18,13 +18,13 @@ namespace android { /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ - <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(jni::JNIEnv& env, jni::String layerId) + <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(jni::JNIEnv& env, jni::String& layerId) : Layer(env, std::make_unique<mbgl::style::<%- camelize(type) %>Layer>(jni::Make<std::string>(env, layerId))) { <% } else { -%> /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ - <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) : Layer(env, std::make_unique<mbgl::style::<%- camelize(type) %>Layer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { <% } -%> } @@ -49,29 +49,27 @@ namespace android { <% for (const property of properties) { -%> <% if (property.name != 'heatmap-color') { -%> - jni::Object<jni::ObjectTag> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>(jni::JNIEnv& env) { + jni::Local<jni::Object<>> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::<%- camelize(type) %>Layer>()-><%- camelize(type) %>Layer::get<%- camelize(property.name) %>()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::<%- camelize(type) %>Layer>()-><%- camelize(type) %>Layer::get<%- camelize(property.name) %>())); } <% } else { -%> - jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> HeatmapLayer::getHeatmapColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; auto propertyValue = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapColor(); if (propertyValue.isUndefined()) { propertyValue = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getDefaultHeatmapColor(); } - Result<jni::jobject*> converted = convert<jni::jobject*>(env, propertyValue); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, propertyValue)); } <% } -%> <% if (property.transition) { -%> - jni::Object<TransitionOptions> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>Transition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>Transition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::<%- camelize(type) %>Layer>()-><%- camelize(type) %>Layer::get<%- camelize(property.name) %>Transition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>Transition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -84,26 +82,25 @@ namespace android { <% } -%> <% } -%> - jni::Class<<%- camelize(type) %>Layer> <%- camelize(type) %>Layer::javaClass; - - jni::jobject* <%- camelize(type) %>Layer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = <%- camelize(type) %>Layer::javaClass.template GetConstructor<jni::jlong>(env); - return <%- camelize(type) %>Layer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> <%- camelize(type) %>Layer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void <%- camelize(type) %>Layer::registerNative(jni::JNIEnv& env) { // Lookup the class - <%- camelize(type) %>Layer::javaClass = *jni::Class<<%- camelize(type) %>Layer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<<%- camelize(type) %>Layer>( - env, <%- camelize(type) %>Layer::javaClass, "nativePtr", + env, javaClass, "nativePtr", <% if (type === 'background') { -%> - std::make_unique<<%- camelize(type) %>Layer, JNIEnv&, jni::String>, + jni::MakePeer<<%- camelize(type) %>Layer, jni::String&>, <% } else { -%> - std::make_unique<<%- camelize(type) %>Layer, JNIEnv&, jni::String, jni::String>, + jni::MakePeer<<%- camelize(type) %>Layer, jni::String&, jni::String&>, <% } -%> "initialize", "finalize",<% for(var i = 0; i < properties.length; i++) {%> diff --git a/platform/android/src/style/layers/layer.hpp b/platform/android/src/style/layers/layer.hpp index 41022bf74..cee1b5a64 100644 --- a/platform/android/src/style/layers/layer.hpp +++ b/platform/android/src/style/layers/layer.hpp @@ -17,8 +17,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/Layer"; }; - static jni::Class<Layer> javaClass; - static void registerNative(jni::JNIEnv&); /* @@ -38,7 +36,7 @@ public: virtual ~Layer(); - virtual jni::jobject* createJavaPeer(jni::JNIEnv&) = 0; + virtual jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&) = 0; /** * Set core layer (ie return ownership after remove) @@ -47,15 +45,15 @@ public: void addToMap(mbgl::Map&, mbgl::optional<std::string>); - jni::String getId(jni::JNIEnv&); + jni::Local<jni::String> getId(jni::JNIEnv&); - jni::String getSourceId(jni::JNIEnv&); + jni::Local<jni::String> getSourceId(jni::JNIEnv&); style::Layer& get(); - void setLayoutProperty(jni::JNIEnv&, jni::String, jni::Object<> value); + void setLayoutProperty(jni::JNIEnv&, const jni::String&, const jni::Object<>& value); - void setPaintProperty(jni::JNIEnv&, jni::String, jni::Object<> value); + void setPaintProperty(jni::JNIEnv&, const jni::String&, const jni::Object<>& value); // Zoom @@ -69,17 +67,17 @@ public: /* common properties, but not shared by all */ - void setFilter(jni::JNIEnv&, jni::Array<jni::Object<>>); + void setFilter(jni::JNIEnv&, const jni::Array<jni::Object<>>&); - jni::Object<gson::JsonElement> getFilter(jni::JNIEnv&); + jni::Local<jni::Object<gson::JsonElement>> getFilter(jni::JNIEnv&); - void setSourceLayer(jni::JNIEnv&, jni::String); + void setSourceLayer(jni::JNIEnv&, const jni::String&); - jni::String getSourceLayer(jni::JNIEnv&); + jni::Local<jni::String> getSourceLayer(jni::JNIEnv&); // Property getters - jni::Object<jni::ObjectTag> getVisibility(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getVisibility(jni::JNIEnv&); protected: // Release the owned view and return it diff --git a/platform/android/src/style/layers/layer.hpp.ejs b/platform/android/src/style/layers/layer.hpp.ejs index 837049b4c..5ceab0dcf 100644 --- a/platform/android/src/style/layers/layer.hpp.ejs +++ b/platform/android/src/style/layers/layer.hpp.ejs @@ -16,17 +16,15 @@ namespace android { class <%- camelize(type) %>Layer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/<%- camelize(type) %>Layer"; }; - static jni::Class<<%- camelize(type) %>Layer> javaClass; - static void registerNative(jni::JNIEnv&); <% if (type === 'background') { -%> - <%- camelize(type) %>Layer(jni::JNIEnv&, jni::String); + <%- camelize(type) %>Layer(jni::JNIEnv&, jni::String&); <% } else { -%> - <%- camelize(type) %>Layer(jni::JNIEnv&, jni::String, jni::String); + <%- camelize(type) %>Layer(jni::JNIEnv&, jni::String&, jni::String&); <% } -%> <%- camelize(type) %>Layer(mbgl::Map&, mbgl::style::<%- camelize(type) %>Layer&); @@ -38,13 +36,13 @@ public: // Properties <% for (const property of properties) { -%> - jni::Object<jni::ObjectTag> get<%- camelize(property.name) %>(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> get<%- camelize(property.name) %>(jni::JNIEnv&); <% if (property.transition) { -%> void set<%- camelize(property.name) %>Transition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> get<%- camelize(property.name) %>Transition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> get<%- camelize(property.name) %>Transition(jni::JNIEnv&); <% } -%> <% } -%> - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class <%- camelize(type) %>Layer diff --git a/platform/android/src/style/layers/layers.cpp b/platform/android/src/style/layers/layers.cpp index 5df689b45..232e92a7c 100644 --- a/platform/android/src/style/layers/layers.cpp +++ b/platform/android/src/style/layers/layers.cpp @@ -77,16 +77,16 @@ static Layer* initializeLayerPeer(Map& map, std::unique_ptr<mbgl::style::Layer> return layer ? layer : new UnknownLayer(map, std::move(coreLayer)); } -jni::jobject* createJavaLayerPeer(jni::JNIEnv& env, Map& map, style::Layer& coreLayer) { +jni::Local<jni::Object<Layer>> createJavaLayerPeer(jni::JNIEnv& env, Map& map, style::Layer& coreLayer) { std::unique_ptr<Layer> peerLayer = std::unique_ptr<Layer>(initializeLayerPeer(map, coreLayer)); - jni::jobject* result = peerLayer->createJavaPeer(env); + jni::Local<jni::Object<Layer>> result = peerLayer->createJavaPeer(env); peerLayer.release(); return result; } -jni::jobject* createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr<mbgl::style::Layer> coreLayer) { +jni::Local<jni::Object<Layer>> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr<mbgl::style::Layer> coreLayer) { std::unique_ptr<Layer> peerLayer = std::unique_ptr<Layer>(initializeLayerPeer(map, std::move(coreLayer))); - jni::jobject* result = peerLayer->createJavaPeer(env); + jni::Local<jni::Object<Layer>> result = peerLayer->createJavaPeer(env); peerLayer.release(); return result; } diff --git a/platform/android/src/style/layers/layers.hpp b/platform/android/src/style/layers/layers.hpp index 75863a324..c9a6ba2e6 100644 --- a/platform/android/src/style/layers/layers.hpp +++ b/platform/android/src/style/layers/layers.hpp @@ -13,12 +13,12 @@ namespace android { /** * Create a non-owning peer */ -jni::jobject* createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&); +jni::Local<jni::Object<Layer>> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&); /** * Create an owning peer */ -jni::jobject* createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr<mbgl::style::Layer>); +jni::Local<jni::Object<Layer>> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr<mbgl::style::Layer>); void registerNativeLayers(jni::JNIEnv&); diff --git a/platform/android/src/style/layers/line_layer.cpp b/platform/android/src/style/layers/line_layer.cpp index f143ecc23..376e4aafc 100644 --- a/platform/android/src/style/layers/line_layer.cpp +++ b/platform/android/src/style/layers/line_layer.cpp @@ -13,7 +13,7 @@ namespace android { /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ - LineLayer::LineLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + LineLayer::LineLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) : Layer(env, std::make_unique<mbgl::style::LineLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { } @@ -35,40 +35,35 @@ namespace android { // Property getters - jni::Object<jni::ObjectTag> LineLayer::getLineCap(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineCap(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineCap()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineCap())); } - jni::Object<jni::ObjectTag> LineLayer::getLineJoin(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineJoin(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineJoin()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineJoin())); } - jni::Object<jni::ObjectTag> LineLayer::getLineMiterLimit(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineMiterLimit(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineMiterLimit()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineMiterLimit())); } - jni::Object<jni::ObjectTag> LineLayer::getLineRoundLimit(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineRoundLimit(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineRoundLimit()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineRoundLimit())); } - jni::Object<jni::ObjectTag> LineLayer::getLineOpacity(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineOpacity()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineOpacity())); } - jni::Object<TransitionOptions> LineLayer::getLineOpacityTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> LineLayer::getLineOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::LineLayer>()->LineLayer::getLineOpacityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void LineLayer::setLineOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -78,16 +73,15 @@ namespace android { layer.as<mbgl::style::LineLayer>()->LineLayer::setLineOpacityTransition(options); } - jni::Object<jni::ObjectTag> LineLayer::getLineColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineColor())); } - jni::Object<TransitionOptions> LineLayer::getLineColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> LineLayer::getLineColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::LineLayer>()->LineLayer::getLineColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void LineLayer::setLineColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -97,16 +91,15 @@ namespace android { layer.as<mbgl::style::LineLayer>()->LineLayer::setLineColorTransition(options); } - jni::Object<jni::ObjectTag> LineLayer::getLineTranslate(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineTranslate()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineTranslate())); } - jni::Object<TransitionOptions> LineLayer::getLineTranslateTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> LineLayer::getLineTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::LineLayer>()->LineLayer::getLineTranslateTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void LineLayer::setLineTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -116,22 +109,20 @@ namespace android { layer.as<mbgl::style::LineLayer>()->LineLayer::setLineTranslateTransition(options); } - jni::Object<jni::ObjectTag> LineLayer::getLineTranslateAnchor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineTranslateAnchor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineTranslateAnchor())); } - jni::Object<jni::ObjectTag> LineLayer::getLineWidth(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineWidth()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineWidth())); } - jni::Object<TransitionOptions> LineLayer::getLineWidthTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> LineLayer::getLineWidthTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::LineLayer>()->LineLayer::getLineWidthTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void LineLayer::setLineWidthTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -141,16 +132,15 @@ namespace android { layer.as<mbgl::style::LineLayer>()->LineLayer::setLineWidthTransition(options); } - jni::Object<jni::ObjectTag> LineLayer::getLineGapWidth(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineGapWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineGapWidth()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineGapWidth())); } - jni::Object<TransitionOptions> LineLayer::getLineGapWidthTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> LineLayer::getLineGapWidthTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::LineLayer>()->LineLayer::getLineGapWidthTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void LineLayer::setLineGapWidthTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -160,16 +150,15 @@ namespace android { layer.as<mbgl::style::LineLayer>()->LineLayer::setLineGapWidthTransition(options); } - jni::Object<jni::ObjectTag> LineLayer::getLineOffset(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineOffset(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineOffset()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineOffset())); } - jni::Object<TransitionOptions> LineLayer::getLineOffsetTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> LineLayer::getLineOffsetTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::LineLayer>()->LineLayer::getLineOffsetTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void LineLayer::setLineOffsetTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -179,16 +168,15 @@ namespace android { layer.as<mbgl::style::LineLayer>()->LineLayer::setLineOffsetTransition(options); } - jni::Object<jni::ObjectTag> LineLayer::getLineBlur(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineBlur(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineBlur()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineBlur())); } - jni::Object<TransitionOptions> LineLayer::getLineBlurTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> LineLayer::getLineBlurTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::LineLayer>()->LineLayer::getLineBlurTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void LineLayer::setLineBlurTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -198,16 +186,15 @@ namespace android { layer.as<mbgl::style::LineLayer>()->LineLayer::setLineBlurTransition(options); } - jni::Object<jni::ObjectTag> LineLayer::getLineDasharray(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineDasharray(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineDasharray()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineDasharray())); } - jni::Object<TransitionOptions> LineLayer::getLineDasharrayTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> LineLayer::getLineDasharrayTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::LineLayer>()->LineLayer::getLineDasharrayTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void LineLayer::setLineDasharrayTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -217,16 +204,15 @@ namespace android { layer.as<mbgl::style::LineLayer>()->LineLayer::setLineDasharrayTransition(options); } - jni::Object<jni::ObjectTag> LineLayer::getLinePattern(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLinePattern(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLinePattern()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLinePattern())); } - jni::Object<TransitionOptions> LineLayer::getLinePatternTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> LineLayer::getLinePatternTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::LineLayer>()->LineLayer::getLinePatternTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void LineLayer::setLinePatternTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -236,30 +222,28 @@ namespace android { layer.as<mbgl::style::LineLayer>()->LineLayer::setLinePatternTransition(options); } - jni::Object<jni::ObjectTag> LineLayer::getLineGradient(jni::JNIEnv& env) { + jni::Local<jni::Object<>> LineLayer::getLineGradient(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineGradient()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::LineLayer>()->LineLayer::getLineGradient())); } - jni::Class<LineLayer> LineLayer::javaClass; - - jni::jobject* LineLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = LineLayer::javaClass.template GetConstructor<jni::jlong>(env); - return LineLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> LineLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<LineLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void LineLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - LineLayer::javaClass = *jni::Class<LineLayer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<LineLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<LineLayer>( - env, LineLayer::javaClass, "nativePtr", - std::make_unique<LineLayer, JNIEnv&, jni::String, jni::String>, + env, javaClass, "nativePtr", + jni::MakePeer<LineLayer, jni::String&, jni::String&>, "initialize", "finalize", METHOD(&LineLayer::getLineCap, "nativeGetLineCap"), diff --git a/platform/android/src/style/layers/line_layer.hpp b/platform/android/src/style/layers/line_layer.hpp index 9eef1349c..01be48195 100644 --- a/platform/android/src/style/layers/line_layer.hpp +++ b/platform/android/src/style/layers/line_layer.hpp @@ -12,14 +12,12 @@ namespace android { class LineLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/LineLayer"; }; - static jni::Class<LineLayer> javaClass; - static void registerNative(jni::JNIEnv&); - LineLayer(jni::JNIEnv&, jni::String, jni::String); + LineLayer(jni::JNIEnv&, jni::String&, jni::String&); LineLayer(mbgl::Map&, mbgl::style::LineLayer&); @@ -29,54 +27,54 @@ public: // Properties - jni::Object<jni::ObjectTag> getLineCap(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineCap(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineJoin(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineJoin(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineMiterLimit(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineMiterLimit(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineRoundLimit(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineRoundLimit(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineOpacity(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineOpacity(jni::JNIEnv&); void setLineOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getLineOpacityTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getLineOpacityTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineColor(jni::JNIEnv&); void setLineColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getLineColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getLineColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineTranslate(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineTranslate(jni::JNIEnv&); void setLineTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getLineTranslateTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getLineTranslateTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineTranslateAnchor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineTranslateAnchor(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineWidth(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineWidth(jni::JNIEnv&); void setLineWidthTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getLineWidthTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getLineWidthTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineGapWidth(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineGapWidth(jni::JNIEnv&); void setLineGapWidthTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getLineGapWidthTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getLineGapWidthTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineOffset(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineOffset(jni::JNIEnv&); void setLineOffsetTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getLineOffsetTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getLineOffsetTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineBlur(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineBlur(jni::JNIEnv&); void setLineBlurTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getLineBlurTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getLineBlurTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineDasharray(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineDasharray(jni::JNIEnv&); void setLineDasharrayTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getLineDasharrayTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getLineDasharrayTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLinePattern(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLinePattern(jni::JNIEnv&); void setLinePatternTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getLinePatternTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getLinePatternTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getLineGradient(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getLineGradient(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class LineLayer diff --git a/platform/android/src/style/layers/raster_layer.cpp b/platform/android/src/style/layers/raster_layer.cpp index 53086951e..5a3579bc3 100644 --- a/platform/android/src/style/layers/raster_layer.cpp +++ b/platform/android/src/style/layers/raster_layer.cpp @@ -13,7 +13,7 @@ namespace android { /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ - RasterLayer::RasterLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + RasterLayer::RasterLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) : Layer(env, std::make_unique<mbgl::style::RasterLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { } @@ -35,16 +35,15 @@ namespace android { // Property getters - jni::Object<jni::ObjectTag> RasterLayer::getRasterOpacity(jni::JNIEnv& env) { + jni::Local<jni::Object<>> RasterLayer::getRasterOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterOpacity()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterOpacity())); } - jni::Object<TransitionOptions> RasterLayer::getRasterOpacityTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> RasterLayer::getRasterOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterOpacityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void RasterLayer::setRasterOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -54,16 +53,15 @@ namespace android { layer.as<mbgl::style::RasterLayer>()->RasterLayer::setRasterOpacityTransition(options); } - jni::Object<jni::ObjectTag> RasterLayer::getRasterHueRotate(jni::JNIEnv& env) { + jni::Local<jni::Object<>> RasterLayer::getRasterHueRotate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterHueRotate()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterHueRotate())); } - jni::Object<TransitionOptions> RasterLayer::getRasterHueRotateTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> RasterLayer::getRasterHueRotateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterHueRotateTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void RasterLayer::setRasterHueRotateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -73,16 +71,15 @@ namespace android { layer.as<mbgl::style::RasterLayer>()->RasterLayer::setRasterHueRotateTransition(options); } - jni::Object<jni::ObjectTag> RasterLayer::getRasterBrightnessMin(jni::JNIEnv& env) { + jni::Local<jni::Object<>> RasterLayer::getRasterBrightnessMin(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterBrightnessMin()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterBrightnessMin())); } - jni::Object<TransitionOptions> RasterLayer::getRasterBrightnessMinTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> RasterLayer::getRasterBrightnessMinTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterBrightnessMinTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void RasterLayer::setRasterBrightnessMinTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -92,16 +89,15 @@ namespace android { layer.as<mbgl::style::RasterLayer>()->RasterLayer::setRasterBrightnessMinTransition(options); } - jni::Object<jni::ObjectTag> RasterLayer::getRasterBrightnessMax(jni::JNIEnv& env) { + jni::Local<jni::Object<>> RasterLayer::getRasterBrightnessMax(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterBrightnessMax()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterBrightnessMax())); } - jni::Object<TransitionOptions> RasterLayer::getRasterBrightnessMaxTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> RasterLayer::getRasterBrightnessMaxTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterBrightnessMaxTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void RasterLayer::setRasterBrightnessMaxTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -111,16 +107,15 @@ namespace android { layer.as<mbgl::style::RasterLayer>()->RasterLayer::setRasterBrightnessMaxTransition(options); } - jni::Object<jni::ObjectTag> RasterLayer::getRasterSaturation(jni::JNIEnv& env) { + jni::Local<jni::Object<>> RasterLayer::getRasterSaturation(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterSaturation()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterSaturation())); } - jni::Object<TransitionOptions> RasterLayer::getRasterSaturationTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> RasterLayer::getRasterSaturationTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterSaturationTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void RasterLayer::setRasterSaturationTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -130,16 +125,15 @@ namespace android { layer.as<mbgl::style::RasterLayer>()->RasterLayer::setRasterSaturationTransition(options); } - jni::Object<jni::ObjectTag> RasterLayer::getRasterContrast(jni::JNIEnv& env) { + jni::Local<jni::Object<>> RasterLayer::getRasterContrast(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterContrast()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterContrast())); } - jni::Object<TransitionOptions> RasterLayer::getRasterContrastTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> RasterLayer::getRasterContrastTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterContrastTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void RasterLayer::setRasterContrastTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -149,36 +143,33 @@ namespace android { layer.as<mbgl::style::RasterLayer>()->RasterLayer::setRasterContrastTransition(options); } - jni::Object<jni::ObjectTag> RasterLayer::getRasterResampling(jni::JNIEnv& env) { + jni::Local<jni::Object<>> RasterLayer::getRasterResampling(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterResampling()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterResampling())); } - jni::Object<jni::ObjectTag> RasterLayer::getRasterFadeDuration(jni::JNIEnv& env) { + jni::Local<jni::Object<>> RasterLayer::getRasterFadeDuration(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterFadeDuration()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::RasterLayer>()->RasterLayer::getRasterFadeDuration())); } - jni::Class<RasterLayer> RasterLayer::javaClass; - - jni::jobject* RasterLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterLayer::javaClass.template GetConstructor<jni::jlong>(env); - return RasterLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> RasterLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<RasterLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void RasterLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterLayer::javaClass = *jni::Class<RasterLayer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<RasterLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<RasterLayer>( - env, RasterLayer::javaClass, "nativePtr", - std::make_unique<RasterLayer, JNIEnv&, jni::String, jni::String>, + env, javaClass, "nativePtr", + jni::MakePeer<RasterLayer, jni::String&, jni::String&>, "initialize", "finalize", METHOD(&RasterLayer::getRasterOpacityTransition, "nativeGetRasterOpacityTransition"), diff --git a/platform/android/src/style/layers/raster_layer.hpp b/platform/android/src/style/layers/raster_layer.hpp index d1c1b4523..40cc47634 100644 --- a/platform/android/src/style/layers/raster_layer.hpp +++ b/platform/android/src/style/layers/raster_layer.hpp @@ -12,14 +12,12 @@ namespace android { class RasterLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/RasterLayer"; }; - static jni::Class<RasterLayer> javaClass; - static void registerNative(jni::JNIEnv&); - RasterLayer(jni::JNIEnv&, jni::String, jni::String); + RasterLayer(jni::JNIEnv&, jni::String&, jni::String&); RasterLayer(mbgl::Map&, mbgl::style::RasterLayer&); @@ -29,34 +27,34 @@ public: // Properties - jni::Object<jni::ObjectTag> getRasterOpacity(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getRasterOpacity(jni::JNIEnv&); void setRasterOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getRasterOpacityTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getRasterOpacityTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getRasterHueRotate(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getRasterHueRotate(jni::JNIEnv&); void setRasterHueRotateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getRasterHueRotateTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getRasterHueRotateTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getRasterBrightnessMin(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getRasterBrightnessMin(jni::JNIEnv&); void setRasterBrightnessMinTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getRasterBrightnessMinTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getRasterBrightnessMinTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getRasterBrightnessMax(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getRasterBrightnessMax(jni::JNIEnv&); void setRasterBrightnessMaxTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getRasterBrightnessMaxTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getRasterBrightnessMaxTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getRasterSaturation(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getRasterSaturation(jni::JNIEnv&); void setRasterSaturationTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getRasterSaturationTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getRasterSaturationTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getRasterContrast(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getRasterContrast(jni::JNIEnv&); void setRasterContrastTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getRasterContrastTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getRasterContrastTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getRasterResampling(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getRasterResampling(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getRasterFadeDuration(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getRasterFadeDuration(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class RasterLayer diff --git a/platform/android/src/style/layers/symbol_layer.cpp b/platform/android/src/style/layers/symbol_layer.cpp index d44744a6c..f1c77c61a 100644 --- a/platform/android/src/style/layers/symbol_layer.cpp +++ b/platform/android/src/style/layers/symbol_layer.cpp @@ -13,7 +13,7 @@ namespace android { /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ - SymbolLayer::SymbolLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + SymbolLayer::SymbolLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) : Layer(env, std::make_unique<mbgl::style::SymbolLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { } @@ -35,232 +35,200 @@ namespace android { // Property getters - jni::Object<jni::ObjectTag> SymbolLayer::getSymbolPlacement(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getSymbolPlacement(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getSymbolPlacement()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getSymbolPlacement())); } - jni::Object<jni::ObjectTag> SymbolLayer::getSymbolSpacing(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getSymbolSpacing(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getSymbolSpacing()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getSymbolSpacing())); } - jni::Object<jni::ObjectTag> SymbolLayer::getSymbolAvoidEdges(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getSymbolAvoidEdges(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getSymbolAvoidEdges()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getSymbolAvoidEdges())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconAllowOverlap(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getSymbolZOrder(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconAllowOverlap()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getSymbolZOrder())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconIgnorePlacement(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconAllowOverlap(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconIgnorePlacement()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconAllowOverlap())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconOptional(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconIgnorePlacement(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconOptional()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconIgnorePlacement())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconRotationAlignment(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconOptional(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconRotationAlignment()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconOptional())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconSize(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconRotationAlignment(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconSize()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconRotationAlignment())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconTextFit(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconSize(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconTextFit()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconSize())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconTextFitPadding(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconTextFit(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconTextFitPadding()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconTextFit())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconImage(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconTextFitPadding(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconImage()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconTextFitPadding())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconRotate(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconImage(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconRotate()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconImage())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconPadding(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconRotate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconPadding()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconRotate())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconKeepUpright(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconPadding(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconKeepUpright()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconPadding())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconOffset(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconKeepUpright(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconOffset()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconKeepUpright())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconAnchor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconOffset(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconAnchor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconOffset())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconPitchAlignment(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconPitchAlignment()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconAnchor())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextPitchAlignment(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconPitchAlignment(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextPitchAlignment()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconPitchAlignment())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextRotationAlignment(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextPitchAlignment(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextRotationAlignment()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextPitchAlignment())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextField(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextRotationAlignment(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextField()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextRotationAlignment())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextFont(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextField(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextFont()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextField())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextSize(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextFont(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextSize()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextFont())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextMaxWidth(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextSize(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextMaxWidth()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextSize())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextLineHeight(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextMaxWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextLineHeight()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextMaxWidth())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextLetterSpacing(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextLineHeight(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextLetterSpacing()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextLineHeight())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextJustify(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextLetterSpacing(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextJustify()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextLetterSpacing())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextAnchor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextJustify(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextAnchor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextJustify())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextMaxAngle(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextMaxAngle()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextAnchor())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextRotate(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextMaxAngle(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextRotate()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextMaxAngle())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextPadding(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextRotate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextPadding()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextRotate())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextKeepUpright(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextPadding(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextKeepUpright()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextPadding())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextTransform(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextKeepUpright(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextTransform()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextKeepUpright())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextOffset(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextTransform(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextOffset()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextTransform())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextAllowOverlap(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextOffset(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextAllowOverlap()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextOffset())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextIgnorePlacement(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextAllowOverlap(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextIgnorePlacement()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextAllowOverlap())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextOptional(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextIgnorePlacement(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextOptional()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextIgnorePlacement())); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconOpacity(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextOptional(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconOpacity()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextOptional())); } - jni::Object<TransitionOptions> SymbolLayer::getIconOpacityTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconOpacity(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconOpacity())); + } + + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getIconOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconOpacityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setIconOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -270,16 +238,15 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setIconOpacityTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconColor())); } - jni::Object<TransitionOptions> SymbolLayer::getIconColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getIconColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setIconColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -289,16 +256,15 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setIconColorTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconHaloColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconHaloColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconHaloColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconHaloColor())); } - jni::Object<TransitionOptions> SymbolLayer::getIconHaloColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getIconHaloColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconHaloColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setIconHaloColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -308,16 +274,15 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setIconHaloColorTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconHaloWidth(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconHaloWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconHaloWidth()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconHaloWidth())); } - jni::Object<TransitionOptions> SymbolLayer::getIconHaloWidthTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getIconHaloWidthTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconHaloWidthTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setIconHaloWidthTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -327,16 +292,15 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setIconHaloWidthTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconHaloBlur(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconHaloBlur(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconHaloBlur()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconHaloBlur())); } - jni::Object<TransitionOptions> SymbolLayer::getIconHaloBlurTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getIconHaloBlurTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconHaloBlurTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setIconHaloBlurTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -346,16 +310,15 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setIconHaloBlurTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconTranslate(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconTranslate()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconTranslate())); } - jni::Object<TransitionOptions> SymbolLayer::getIconTranslateTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getIconTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconTranslateTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setIconTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -365,22 +328,20 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setIconTranslateTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getIconTranslateAnchor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getIconTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconTranslateAnchor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconTranslateAnchor())); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextOpacity(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextOpacity()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextOpacity())); } - jni::Object<TransitionOptions> SymbolLayer::getTextOpacityTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getTextOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextOpacityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setTextOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -390,16 +351,15 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setTextOpacityTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextColor())); } - jni::Object<TransitionOptions> SymbolLayer::getTextColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getTextColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setTextColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -409,16 +369,15 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setTextColorTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextHaloColor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextHaloColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextHaloColor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextHaloColor())); } - jni::Object<TransitionOptions> SymbolLayer::getTextHaloColorTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getTextHaloColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextHaloColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setTextHaloColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -428,16 +387,15 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setTextHaloColorTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextHaloWidth(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextHaloWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextHaloWidth()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextHaloWidth())); } - jni::Object<TransitionOptions> SymbolLayer::getTextHaloWidthTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getTextHaloWidthTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextHaloWidthTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setTextHaloWidthTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -447,16 +405,15 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setTextHaloWidthTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextHaloBlur(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextHaloBlur(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextHaloBlur()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextHaloBlur())); } - jni::Object<TransitionOptions> SymbolLayer::getTextHaloBlurTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getTextHaloBlurTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextHaloBlurTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setTextHaloBlurTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -466,16 +423,15 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setTextHaloBlurTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextTranslate(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextTranslate()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextTranslate())); } - jni::Object<TransitionOptions> SymbolLayer::getTextTranslateTransition(jni::JNIEnv& env) { + jni::Local<jni::Object<TransitionOptions>> SymbolLayer::getTextTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextTranslateTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void SymbolLayer::setTextTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -485,35 +441,34 @@ namespace android { layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::setTextTranslateTransition(options); } - jni::Object<jni::ObjectTag> SymbolLayer::getTextTranslateAnchor(jni::JNIEnv& env) { + jni::Local<jni::Object<>> SymbolLayer::getTextTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextTranslateAnchor()); - return jni::Object<jni::ObjectTag>(*converted); + return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getTextTranslateAnchor())); } - jni::Class<SymbolLayer> SymbolLayer::javaClass; - - jni::jobject* SymbolLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = SymbolLayer::javaClass.template GetConstructor<jni::jlong>(env); - return SymbolLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> SymbolLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<SymbolLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void SymbolLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - SymbolLayer::javaClass = *jni::Class<SymbolLayer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<SymbolLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<SymbolLayer>( - env, SymbolLayer::javaClass, "nativePtr", - std::make_unique<SymbolLayer, JNIEnv&, jni::String, jni::String>, + env, javaClass, "nativePtr", + jni::MakePeer<SymbolLayer, jni::String&, jni::String&>, "initialize", "finalize", METHOD(&SymbolLayer::getSymbolPlacement, "nativeGetSymbolPlacement"), METHOD(&SymbolLayer::getSymbolSpacing, "nativeGetSymbolSpacing"), METHOD(&SymbolLayer::getSymbolAvoidEdges, "nativeGetSymbolAvoidEdges"), + METHOD(&SymbolLayer::getSymbolZOrder, "nativeGetSymbolZOrder"), METHOD(&SymbolLayer::getIconAllowOverlap, "nativeGetIconAllowOverlap"), METHOD(&SymbolLayer::getIconIgnorePlacement, "nativeGetIconIgnorePlacement"), METHOD(&SymbolLayer::getIconOptional, "nativeGetIconOptional"), diff --git a/platform/android/src/style/layers/symbol_layer.hpp b/platform/android/src/style/layers/symbol_layer.hpp index 417e5e143..9887fd8fb 100644 --- a/platform/android/src/style/layers/symbol_layer.hpp +++ b/platform/android/src/style/layers/symbol_layer.hpp @@ -12,14 +12,12 @@ namespace android { class SymbolLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/SymbolLayer"; }; - static jni::Class<SymbolLayer> javaClass; - static void registerNative(jni::JNIEnv&); - SymbolLayer(jni::JNIEnv&, jni::String, jni::String); + SymbolLayer(jni::JNIEnv&, jni::String&, jni::String&); SymbolLayer(mbgl::Map&, mbgl::style::SymbolLayer&); @@ -29,130 +27,132 @@ public: // Properties - jni::Object<jni::ObjectTag> getSymbolPlacement(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getSymbolPlacement(jni::JNIEnv&); + + jni::Local<jni::Object<jni::ObjectTag>> getSymbolSpacing(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getSymbolSpacing(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getSymbolAvoidEdges(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getSymbolAvoidEdges(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getSymbolZOrder(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconAllowOverlap(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconAllowOverlap(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconIgnorePlacement(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconIgnorePlacement(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconOptional(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconOptional(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconRotationAlignment(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconRotationAlignment(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconSize(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconSize(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconTextFit(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconTextFit(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconTextFitPadding(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconTextFitPadding(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconImage(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconImage(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconRotate(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconRotate(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconPadding(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconPadding(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconKeepUpright(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconKeepUpright(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconOffset(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconOffset(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconAnchor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconAnchor(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconPitchAlignment(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconPitchAlignment(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextPitchAlignment(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextPitchAlignment(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextRotationAlignment(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextRotationAlignment(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextField(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextField(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextFont(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextFont(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextSize(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextSize(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextMaxWidth(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextMaxWidth(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextLineHeight(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextLineHeight(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextLetterSpacing(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextLetterSpacing(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextJustify(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextJustify(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextAnchor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextAnchor(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextMaxAngle(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextMaxAngle(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextRotate(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextRotate(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextPadding(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextPadding(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextKeepUpright(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextKeepUpright(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextTransform(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextTransform(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextOffset(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextOffset(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextAllowOverlap(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextAllowOverlap(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextIgnorePlacement(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextIgnorePlacement(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextOptional(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextOptional(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconOpacity(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconOpacity(jni::JNIEnv&); void setIconOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getIconOpacityTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getIconOpacityTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconColor(jni::JNIEnv&); void setIconColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getIconColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getIconColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconHaloColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconHaloColor(jni::JNIEnv&); void setIconHaloColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getIconHaloColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getIconHaloColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconHaloWidth(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconHaloWidth(jni::JNIEnv&); void setIconHaloWidthTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getIconHaloWidthTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getIconHaloWidthTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconHaloBlur(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconHaloBlur(jni::JNIEnv&); void setIconHaloBlurTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getIconHaloBlurTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getIconHaloBlurTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconTranslate(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconTranslate(jni::JNIEnv&); void setIconTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getIconTranslateTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getIconTranslateTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getIconTranslateAnchor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getIconTranslateAnchor(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextOpacity(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextOpacity(jni::JNIEnv&); void setTextOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getTextOpacityTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getTextOpacityTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextColor(jni::JNIEnv&); void setTextColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getTextColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getTextColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextHaloColor(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextHaloColor(jni::JNIEnv&); void setTextHaloColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getTextHaloColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getTextHaloColorTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextHaloWidth(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextHaloWidth(jni::JNIEnv&); void setTextHaloWidthTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getTextHaloWidthTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getTextHaloWidthTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextHaloBlur(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextHaloBlur(jni::JNIEnv&); void setTextHaloBlurTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getTextHaloBlurTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getTextHaloBlurTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextTranslate(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextTranslate(jni::JNIEnv&); void setTextTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getTextTranslateTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getTextTranslateTransition(jni::JNIEnv&); - jni::Object<jni::ObjectTag> getTextTranslateAnchor(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<jni::ObjectTag>> getTextTranslateAnchor(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class SymbolLayer diff --git a/platform/android/src/style/layers/unknown_layer.cpp b/platform/android/src/style/layers/unknown_layer.cpp index 8ffda82bf..5c770012b 100644 --- a/platform/android/src/style/layers/unknown_layer.cpp +++ b/platform/android/src/style/layers/unknown_layer.cpp @@ -22,16 +22,15 @@ namespace android { : Layer(map, std::move(coreLayer)) { } - jni::Class<UnknownLayer> UnknownLayer::javaClass; - - jni::jobject* UnknownLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = UnknownLayer::javaClass.template GetConstructor<jni::jlong>(env); - return UnknownLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + jni::Local<jni::Object<Layer>> UnknownLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<UnknownLayer>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void UnknownLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - UnknownLayer::javaClass = *jni::Class<UnknownLayer>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<UnknownLayer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) @@ -39,7 +38,7 @@ namespace android { // Register the peer jni::RegisterNativePeer<UnknownLayer>( - env, UnknownLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", init, "initialize", "finalize"); diff --git a/platform/android/src/style/layers/unknown_layer.hpp b/platform/android/src/style/layers/unknown_layer.hpp index 67992ea00..692e2f5db 100644 --- a/platform/android/src/style/layers/unknown_layer.hpp +++ b/platform/android/src/style/layers/unknown_layer.hpp @@ -9,11 +9,9 @@ namespace android { class UnknownLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/UnknownLayer"; }; - static jni::Class<UnknownLayer> javaClass; - static void registerNative(jni::JNIEnv&); UnknownLayer(mbgl::Map&, mbgl::style::Layer&); @@ -22,7 +20,7 @@ public: ~UnknownLayer() = default; - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv&); }; // class UnknownLayer diff --git a/platform/android/src/style/light.cpp b/platform/android/src/style/light.cpp index 71f1cb076..d8ed4d9d9 100644 --- a/platform/android/src/style/light.cpp +++ b/platform/android/src/style/light.cpp @@ -1,5 +1,3 @@ -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. - #include <mbgl/map/map.hpp> #include "light.hpp" #include "conversion/transition_options.hpp" @@ -16,21 +14,20 @@ static Light* initializeLightPeer(mbgl::Map& map, mbgl::style::Light& coreLight) return new Light(map, coreLight); } -jni::jobject* Light::createJavaLightPeer(jni::JNIEnv& env, Map& map, mbgl::style::Light& coreLight) { +jni::Local<jni::Object<Light>> Light::createJavaLightPeer(jni::JNIEnv& env, Map& map, mbgl::style::Light& coreLight) { std::unique_ptr<Light> peerLight = std::unique_ptr<Light>(initializeLightPeer(map, coreLight)); - jni::jobject* result = peerLight->createJavaPeer(env); + auto result = peerLight->createJavaPeer(env); peerLight.release(); return result; } -jni::Class<Light> Light::javaClass; - -jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = Light::javaClass.template GetConstructor<jni::jlong>(env); - return Light::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); +jni::Local<jni::Object<Light>> Light::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<Light>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } -void Light::setAnchor(jni::JNIEnv& env, jni::String property) { +void Light::setAnchor(jni::JNIEnv& env, const jni::String& property) { std::string anchorStr = jni::Make<std::string>(env, property); if (anchorStr.compare("map") == 0) { light.setAnchor(LightAnchorType::Map); @@ -39,7 +36,7 @@ void Light::setAnchor(jni::JNIEnv& env, jni::String property) { } } -jni::String Light::getAnchor(jni::JNIEnv& env) { +jni::Local<jni::String> Light::getAnchor(jni::JNIEnv& env) { auto anchorType = light.getAnchor(); if (anchorType == LightAnchorType::Map) { return jni::Make<jni::String>(env, "map"); @@ -48,22 +45,22 @@ jni::String Light::getAnchor(jni::JNIEnv& env) { } } -void Light::setPosition(jni::JNIEnv& env, jni::Object<Position> jposition) { +void Light::setPosition(jni::JNIEnv& env, const jni::Object<Position>& jposition) { using namespace mbgl::android::conversion; auto position = *convert<mbgl::style::Position>(env, jposition); light.setPosition(position); } -jni::Object<Position> Light::getPosition(jni::JNIEnv& env) { +jni::Local<jni::Object<Position>> Light::getPosition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::Position position = light.getPosition().asConstant(); - return *convert<jni::Object<Position>>(env, position); + return std::move(*convert<jni::Local<jni::Object<Position>>>(env, position)); } -jni::Object<TransitionOptions> Light::getPositionTransition(jni::JNIEnv& env) { +jni::Local<jni::Object<TransitionOptions>> Light::getPositionTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = light.getPositionTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void Light::setPositionTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -73,22 +70,22 @@ void Light::setPositionTransition(jni::JNIEnv&, jlong duration, jlong delay) { light.setPositionTransition(options); } -void Light::setColor(jni::JNIEnv& env, jni::String property) { +void Light::setColor(jni::JNIEnv& env, const jni::String& property) { auto color = Color::parse(jni::Make<std::string>(env, property)); if (color) { light.setColor(color.value()); } } -jni::String Light::getColor(jni::JNIEnv &env) { +jni::Local<jni::String> Light::getColor(jni::JNIEnv &env) { auto color = light.getColor().asConstant(); return jni::Make<jni::String>(env, color.stringify()); } -jni::Object<TransitionOptions> Light::getColorTransition(jni::JNIEnv& env) { +jni::Local<jni::Object<TransitionOptions>> Light::getColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = light.getColorTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void Light::setColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -106,10 +103,10 @@ jni::jfloat Light::getIntensity(jni::JNIEnv&) { return light.getIntensity().asConstant(); } -jni::Object<TransitionOptions> Light::getIntensityTransition(jni::JNIEnv& env) { +jni::Local<jni::Object<TransitionOptions>> Light::getIntensityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = light.getIntensityTransition(); - return *convert<jni::Object<TransitionOptions>>(env, options); + return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options)); } void Light::setIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -121,11 +118,11 @@ void Light::setIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay) { void Light::registerNative(jni::JNIEnv& env) { // Lookup the class - Light::javaClass = *jni::Class<Light>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<Light>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<Light>(env, Light::javaClass, "nativePtr", + jni::RegisterNativePeer<Light>(env, javaClass, "nativePtr", METHOD(&Light::getAnchor, "nativeGetAnchor"), METHOD(&Light::setAnchor, "nativeSetAnchor"), METHOD(&Light::getPositionTransition, "nativeGetPositionTransition"), diff --git a/platform/android/src/style/light.cpp.ejs b/platform/android/src/style/light.cpp.ejs deleted file mode 100644 index 17f0bba09..000000000 --- a/platform/android/src/style/light.cpp.ejs +++ /dev/null @@ -1,123 +0,0 @@ -<% - const properties = locals.properties; --%> -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. - -#include <mbgl/map/map.hpp> -#include "light.hpp" -#include "conversion/transition_options.hpp" -#include "conversion/position.hpp" - -namespace mbgl { -namespace android { - -Light::Light(mbgl::Map& coreMap, mbgl::style::Light& coreLight) - : light(coreLight) , map(&coreMap) { -} - -static Light* initializeLightPeer(mbgl::Map& map, mbgl::style::Light& coreLight) { - return new Light(map, coreLight); -} - -jni::jobject* Light::createJavaLightPeer(jni::JNIEnv& env, Map& map, mbgl::style::Light& coreLight) { - std::unique_ptr<Light> peerLight = std::unique_ptr<Light>(initializeLightPeer(map, coreLight)); - jni::jobject* result = peerLight->createJavaPeer(env); - peerLight.release(); - return result; -} - -jni::Class<Light> Light::javaClass; - -jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = Light::javaClass.template GetConstructor<jni::jlong>(env); - return Light::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); -} - -<% for (const property of properties) { -%> -<% if (property.name == "position") { -%> -void Light::set<%- camelize(property.name) %>(jni::JNIEnv& env, jni::Object<<%- camelize(property.name) %>> j<%- property.name %>) { - using namespace mbgl::android::conversion; - auto position = *convert<mbgl::style::<%- camelize(property.name) %>>(env, jposition); - light.set<%- camelize(property.name) %>(<%- property.name %>); -} - -jni::Object<Position> Light::get<%- camelize(property.name) %>(jni::JNIEnv& env) { - using namespace mbgl::android::conversion; - mbgl::style::<%- camelize(property.name) %> <%- property.name %> = light.get<%- camelize(property.name) %>().asConstant(); - return *convert<jni::Object<<%- camelize(property.name) %>>>(env, <%- property.name %>); -} -<% } else { -%> -<% if(property.name == "color") {-%> -void Light::set<%- camelize(property.name) %>(jni::JNIEnv& env, jni::<%- propertyJNIType(property) %> property) { - auto color = Color::parse(jni::Make<std::string>(env, property)); - if (color) { - light.set<%- camelize(property.name) %>(color.value()); - } -} - -jni::String Light::get<%- camelize(property.name) %>(jni::JNIEnv &env) { - auto color = light.get<%- camelize(property.name) %>().asConstant(); - return jni::Make<jni::String>(env, color.stringify()); -} -<% } else if(property.name == "anchor"){ -%> -void Light::set<%- camelize(property.name) %>(jni::JNIEnv& env, jni::<%- propertyJNIType(property) %> property) { - std::string anchorStr = jni::Make<std::string>(env, property); - if (anchorStr.compare("map") == 0) { - light.setAnchor(LightAnchorType::Map); - } else if (anchorStr.compare("viewport") == 0) { - light.setAnchor(LightAnchorType::Viewport); - } -} - -jni::String Light::getAnchor(jni::JNIEnv& env) { - auto anchorType = light.getAnchor(); - if (anchorType == LightAnchorType::Map) { - return jni::Make<jni::String>(env, "map"); - } else { - return jni::Make<jni::String>(env, "viewport"); - } -} -<% } else { -%> -void Light::set<%- camelize(property.name) %>(jni::JNIEnv&, jni::<%- propertyJNIType(property) %> property) { - light.set<%- camelize(property.name) %>(property); -} - -jni::<%- propertyJNIType(property) %> Light::get<%- camelize(property.name) %>(jni::JNIEnv&) { - return light.get<%- camelize(property.name) %>().asConstant(); -} -<% } -%> -<% } -%> - -<% if (property.transition) { -%> -jni::Object<TransitionOptions> Light::get<%- camelize(property.name) %>Transition(jni::JNIEnv& env) { - using namespace mbgl::android::conversion; - mbgl::style::TransitionOptions options = light.get<%- camelize(property.name) %>Transition(); - return *convert<jni::Object<TransitionOptions>>(env, options); -} - -void Light::set<%- camelize(property.name) %>Transition(jni::JNIEnv&, jlong duration, jlong delay) { - mbgl::style::TransitionOptions options; - options.duration.emplace(mbgl::Milliseconds(duration)); - options.delay.emplace(mbgl::Milliseconds(delay)); - light.set<%- camelize(property.name) %>Transition(options); -} - -<% } -%> -<% } -%> -void Light::registerNative(jni::JNIEnv& env) { - // Lookup the class - Light::javaClass = *jni::Class<Light>::Find(env).NewGlobalRef(env).release(); - -#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) - // Register the peer - jni::RegisterNativePeer<Light>(env, Light::javaClass, "nativePtr",<% for(var i = 0; i < properties.length; i++) {%> -<% if (properties[i].transition) { -%> - METHOD(&Light::get<%- camelize(properties[i].name) %>Transition, "nativeGet<%- camelize(properties[i].name) %>Transition"), - METHOD(&Light::set<%- camelize(properties[i].name) %>Transition, "nativeSet<%- camelize(properties[i].name) %>Transition"), -<% } -%> - METHOD(&Light::get<%- camelize(properties[i].name) %>, "nativeGet<%- camelize(properties[i].name) %>"), - METHOD(&Light::set<%- camelize(properties[i].name) %>, "nativeSet<%- camelize(properties[i].name) %>")<% if(i != (properties.length -1)) {-%>,<% } -%><% } -%>); -} - -} // namespace android -} // namespace mb diff --git a/platform/android/src/style/light.hpp b/platform/android/src/style/light.hpp index 2c314067b..97767c4f7 100644 --- a/platform/android/src/style/light.hpp +++ b/platform/android/src/style/light.hpp @@ -1,5 +1,3 @@ -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. - #pragma once #include <mbgl/util/noncopyable.hpp> @@ -21,29 +19,27 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/light/Light"; }; - static jni::Class<Light> javaClass; - static void registerNative(jni::JNIEnv&); - static jni::jobject* createJavaLightPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Light&); + static jni::Local<jni::Object<Light>> createJavaLightPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Light&); Light(mbgl::Map&, mbgl::style::Light&); - void setAnchor(jni::JNIEnv&, jni::String); - jni::String getAnchor(jni::JNIEnv&); - void setPosition(jni::JNIEnv&, jni::Object<Position>); - jni::Object<Position> getPosition(jni::JNIEnv&); + void setAnchor(jni::JNIEnv&, const jni::String&); + jni::Local<jni::String> getAnchor(jni::JNIEnv&); + void setPosition(jni::JNIEnv&, const jni::Object<Position>&); + jni::Local<jni::Object<Position>> getPosition(jni::JNIEnv&); void setPositionTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getPositionTransition(jni::JNIEnv&); - void setColor(jni::JNIEnv&, jni::String); - jni::String getColor(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getPositionTransition(jni::JNIEnv&); + void setColor(jni::JNIEnv&, const jni::String&); + jni::Local<jni::String> getColor(jni::JNIEnv&); void setColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getColorTransition(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getColorTransition(jni::JNIEnv&); void setIntensity(jni::JNIEnv&, jni::jfloat); jni::jfloat getIntensity(jni::JNIEnv&); void setIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> getIntensityTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<TransitionOptions>> getIntensityTransition(jni::JNIEnv&); + jni::Local<jni::Object<Light>> createJavaPeer(jni::JNIEnv&); protected: diff --git a/platform/android/src/style/light.hpp.ejs b/platform/android/src/style/light.hpp.ejs deleted file mode 100644 index 18f961b9e..000000000 --- a/platform/android/src/style/light.hpp.ejs +++ /dev/null @@ -1,59 +0,0 @@ -<% - const properties = locals.properties; --%> -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. - -#pragma once - -#include <mbgl/util/noncopyable.hpp> - -#include <jni/jni.hpp> -#include <mbgl/style/light.hpp> -#include "transition_options.hpp" -#include "position.hpp" -#include <mbgl/style/types.hpp> -#include <mbgl/style/property_value.hpp> - -namespace mbgl { -namespace android { - -using namespace style; - -class Light : private mbgl::util::noncopyable { -public: - - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/light/Light"; }; - - static jni::Class<Light> javaClass; - - static void registerNative(jni::JNIEnv&); - - static jni::jobject* createJavaLightPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Light&); - - Light(mbgl::Map&, mbgl::style::Light&); - -<% for (const property of properties) { -%> -<% if (property.name=="position") {-%> - void set<%- camelize(property.name) %>(jni::JNIEnv&, jni::Object<Position>); - jni::Object<<%- camelize(property.name) %>> get<%- camelize(property.name) %>(jni::JNIEnv&); -<% } else { -%> - void set<%- camelize(property.name) %>(jni::JNIEnv&, jni::<%- propertyJNIType(property) %>); - jni::<%- propertyJNIType(property) %> get<%- camelize(property.name) %>(jni::JNIEnv&); -<% } -%> -<% if (property.transition) { -%> - void set<%- camelize(property.name) %>Transition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object<TransitionOptions> get<%- camelize(property.name) %>Transition(jni::JNIEnv&); -<% } -%> -<% } -%> - jni::jobject* createJavaPeer(jni::JNIEnv&); - -protected: - - // Raw reference to the light - mbgl::style::Light& light; - - // Map is set when the light is retrieved - mbgl::Map* map; -}; -} // namespace android -} // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/style/position.cpp b/platform/android/src/style/position.cpp index 0bbcefcbc..20a0c47df 100644 --- a/platform/android/src/style/position.cpp +++ b/platform/android/src/style/position.cpp @@ -3,30 +3,31 @@ namespace mbgl { namespace android { -jni::Object<Position> Position::fromPosition(jni::JNIEnv& env, jfloat radialCoordinate, jfloat azimuthalAngle, jfloat polarAngle) { - static auto method = Position::javaClass.GetStaticMethod<jni::Object<Position> (jfloat, jfloat, jfloat)>(env, "fromPosition"); - return Position::javaClass.Call(env, method, radialCoordinate, azimuthalAngle, polarAngle); +jni::Local<jni::Object<Position>> Position::fromPosition(jni::JNIEnv& env, jfloat radialCoordinate, jfloat azimuthalAngle, jfloat polarAngle) { + static auto& javaClass = jni::Class<Position>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<Position> (jfloat, jfloat, jfloat)>(env, "fromPosition"); + return javaClass.Call(env, method, radialCoordinate, azimuthalAngle, polarAngle); } void Position::registerNative(jni::JNIEnv& env) { - // Lookup the class - Position::javaClass = *jni::Class<Position>::Find(env).NewGlobalRef(env).release(); + jni::Class<Position>::Singleton(env); } -jni::Class<Position> Position::javaClass; - -float Position::getRadialCoordinate(jni::JNIEnv& env, jni::Object<Position> position){ - static auto field = Position::javaClass.GetField<jfloat>(env, "radialCoordinate"); +float Position::getRadialCoordinate(jni::JNIEnv& env, const jni::Object<Position>& position) { + static auto& javaClass = jni::Class<Position>::Singleton(env); + static auto field = javaClass.GetField<jfloat>(env, "radialCoordinate"); return position.Get(env, field); } -float Position::getAzimuthalAngle(jni::JNIEnv& env, jni::Object<Position> position){ - static auto field = Position::javaClass.GetField<jfloat>(env, "azimuthalAngle"); +float Position::getAzimuthalAngle(jni::JNIEnv& env, const jni::Object<Position>& position) { + static auto& javaClass = jni::Class<Position>::Singleton(env); + static auto field = javaClass.GetField<jfloat>(env, "azimuthalAngle"); return position.Get(env, field); } -float Position::getPolarAngle(jni::JNIEnv& env, jni::Object<Position> position){ - static auto field = Position::javaClass.GetField<jfloat>(env, "polarAngle"); +float Position::getPolarAngle(jni::JNIEnv& env, const jni::Object<Position>& position) { + static auto& javaClass = jni::Class<Position>::Singleton(env); + static auto field = javaClass.GetField<jfloat>(env, "polarAngle"); return position.Get(env, field); } diff --git a/platform/android/src/style/position.hpp b/platform/android/src/style/position.hpp index 4aafa853d..eb4f5ac67 100644 --- a/platform/android/src/style/position.hpp +++ b/platform/android/src/style/position.hpp @@ -9,21 +9,16 @@ namespace android { class Position : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/light/Position"; }; - static jni::Object<Position> fromPosition(jni::JNIEnv&, jfloat, jfloat, jfloat); - - static jni::Class<Position> javaClass; + static jni::Local<jni::Object<Position>> fromPosition(jni::JNIEnv&, jfloat, jfloat, jfloat); static void registerNative(jni::JNIEnv&); - static float getRadialCoordinate(jni::JNIEnv&, jni::Object<Position>); - static float getAzimuthalAngle(jni::JNIEnv&, jni::Object<Position>); - static float getPolarAngle(jni::JNIEnv&, jni::Object<Position>); - + static float getRadialCoordinate(jni::JNIEnv&, const jni::Object<Position>&); + static float getAzimuthalAngle(jni::JNIEnv&, const jni::Object<Position>&); + static float getPolarAngle(jni::JNIEnv&, const jni::Object<Position>&); }; - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/style/sources/custom_geometry_source.cpp b/platform/android/src/style/sources/custom_geometry_source.cpp index e9a530f75..057f5c99b 100644 --- a/platform/android/src/style/sources/custom_geometry_source.cpp +++ b/platform/android/src/style/sources/custom_geometry_source.cpp @@ -1,4 +1,5 @@ #include "custom_geometry_source.hpp" +#include "../../attach_env.hpp" #include <mbgl/renderer/query.hpp> @@ -9,7 +10,7 @@ // C++ -> Java conversion #include "../../conversion/conversion.hpp" #include "../../conversion/collection.hpp" -#include "../../geojson/conversion/feature.hpp" +#include "../../geojson/feature.hpp" #include <mbgl/style/conversion/custom_geometry_source_options.hpp> #include <string> @@ -21,7 +22,7 @@ namespace android { // the value was originally a CustomGeometrySourceOptions object on the Java side. If it fails // to convert, it's a bug in our serialization or Java-side static typing. static style::CustomGeometrySource::Options convertCustomGeometrySourceOptions(jni::JNIEnv& env, - jni::Object<> options, + const jni::Object<>& options, style::TileFunction fetchFn, style::TileFunction cancelFn) { using namespace mbgl::style::conversion; @@ -39,8 +40,8 @@ namespace android { } CustomGeometrySource::CustomGeometrySource(jni::JNIEnv& env, - jni::String sourceId, - jni::Object<> options) + const jni::String& sourceId, + const jni::Object<>& options) : Source(env, std::make_unique<mbgl::style::CustomGeometrySource>( jni::Make<std::string>(env, sourceId), convertCustomGeometrySourceOptions(env, options, @@ -61,44 +62,48 @@ namespace android { void CustomGeometrySource::fetchTile (const mbgl::CanonicalTileID& tileID) { android::UniqueEnv _env = android::AttachEnv(); + static auto& javaClass = jni::Class<CustomGeometrySource>::Singleton(*_env); static auto fetchTile = javaClass.GetMethod<void (jni::jint, jni::jint, jni::jint)>(*_env, "fetchTile"); assert(javaPeer); - auto peer = jni::Cast(*_env, *javaPeer, javaClass); + auto peer = jni::Cast(*_env, javaClass, javaPeer); peer.Call(*_env, fetchTile, (int)tileID.z, (int)tileID.x, (int)tileID.y); }; void CustomGeometrySource::cancelTile(const mbgl::CanonicalTileID& tileID) { android::UniqueEnv _env = android::AttachEnv(); + static auto& javaClass = jni::Class<CustomGeometrySource>::Singleton(*_env); static auto cancelTile = javaClass.GetMethod<void (jni::jint, jni::jint, jni::jint)>(*_env, "cancelTile"); assert(javaPeer); - auto peer = jni::Cast(*_env, *javaPeer, javaClass); + auto peer = jni::Cast(*_env, javaClass, javaPeer); peer.Call(*_env, cancelTile, (int)tileID.z, (int)tileID.x, (int)tileID.y); }; void CustomGeometrySource::startThreads() { android::UniqueEnv _env = android::AttachEnv(); + static auto& javaClass = jni::Class<CustomGeometrySource>::Singleton(*_env); static auto startThreads = javaClass.GetMethod<void ()>(*_env, "startThreads"); assert(javaPeer); - auto peer = jni::Cast(*_env, *javaPeer, javaClass); + auto peer = jni::Cast(*_env, javaClass, javaPeer); peer.Call(*_env, startThreads); } void CustomGeometrySource::releaseThreads() { android::UniqueEnv _env = android::AttachEnv(); + static auto& javaClass = jni::Class<CustomGeometrySource>::Singleton(*_env); static auto releaseThreads = javaClass.GetMethod<void ()>(*_env, "releaseThreads"); assert(javaPeer); - auto peer = jni::Cast(*_env, *javaPeer, javaClass); + auto peer = jni::Cast(*_env, javaClass, javaPeer); peer.Call(*_env, releaseThreads); }; @@ -107,11 +112,12 @@ namespace android { jni::jint y) { android::UniqueEnv _env = android::AttachEnv(); + static auto& javaClass = jni::Class<CustomGeometrySource>::Singleton(*_env); static auto isCancelled = javaClass.GetMethod<jboolean (jni::jint, jni::jint, jni::jint)>(*_env, "isCancelled"); assert(javaPeer); - auto peer = jni::Cast(*_env, *javaPeer, javaClass); + auto peer = jni::Cast(*_env, javaClass, javaPeer); return peer.Call(*_env, isCancelled, z, x, y); }; @@ -119,7 +125,7 @@ namespace android { jni::jint z, jni::jint x, jni::jint y, - jni::Object<geojson::FeatureCollection> jFeatures) { + const jni::Object<geojson::FeatureCollection>& jFeatures) { using namespace mbgl::android::geojson; // Convert the jni object @@ -135,13 +141,13 @@ namespace android { source.as<mbgl::style::CustomGeometrySource>()->CustomGeometrySource::invalidateTile(CanonicalTileID(z, x, y)); } - void CustomGeometrySource::invalidateBounds(jni::JNIEnv& env, jni::Object<LatLngBounds> jBounds) { + void CustomGeometrySource::invalidateBounds(jni::JNIEnv& env, const jni::Object<LatLngBounds>& jBounds) { auto bounds = LatLngBounds::getLatLngBounds(env, jBounds); source.as<mbgl::style::CustomGeometrySource>()->CustomGeometrySource::invalidateRegion(bounds); } - jni::Array<jni::Object<geojson::Feature>> CustomGeometrySource::querySourceFeatures(jni::JNIEnv& env, - jni::Array<jni::Object<>> jfilter) { + jni::Local<jni::Array<jni::Object<geojson::Feature>>> CustomGeometrySource::querySourceFeatures(jni::JNIEnv& env, + const jni::Array<jni::Object<>>& jfilter) { using namespace mbgl::android::conversion; using namespace mbgl::android::geojson; @@ -149,22 +155,21 @@ namespace android { if (rendererFrontend) { features = rendererFrontend->querySourceFeatures(source.getID(), { {}, toFilter(env, jfilter) }); } - return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, features); + return Feature::convert(env, features); } - jni::Class<CustomGeometrySource> CustomGeometrySource::javaClass; - - jni::Object<Source> CustomGeometrySource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CustomGeometrySource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(CustomGeometrySource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + jni::Local<jni::Object<Source>> CustomGeometrySource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<CustomGeometrySource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } - void CustomGeometrySource::addToMap(JNIEnv& env, jni::Object<Source> obj, mbgl::Map& map, AndroidRendererFrontend& frontend) { + void CustomGeometrySource::addToMap(JNIEnv& env, const jni::Object<Source>& obj, mbgl::Map& map, AndroidRendererFrontend& frontend) { Source::addToMap(env, obj, map, frontend); startThreads(); } - bool CustomGeometrySource::removeFromMap(JNIEnv& env, jni::Object<Source> source, mbgl::Map& map) { + bool CustomGeometrySource::removeFromMap(JNIEnv& env, const jni::Object<Source>& source, mbgl::Map& map) { bool successfullyRemoved = Source::removeFromMap(env, source, map); if (successfullyRemoved) { releaseThreads(); @@ -174,14 +179,14 @@ namespace android { void CustomGeometrySource::registerNative(jni::JNIEnv& env) { // Lookup the class - CustomGeometrySource::javaClass = *jni::Class<CustomGeometrySource>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<CustomGeometrySource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<CustomGeometrySource>( - env, CustomGeometrySource::javaClass, "nativePtr", - std::make_unique<CustomGeometrySource, JNIEnv&, jni::String, jni::Object<>>, + env, javaClass, "nativePtr", + jni::MakePeer<CustomGeometrySource, const jni::String&, const jni::Object<>&>, "initialize", "finalize", METHOD(&CustomGeometrySource::querySourceFeatures, "querySourceFeatures"), diff --git a/platform/android/src/style/sources/custom_geometry_source.hpp b/platform/android/src/style/sources/custom_geometry_source.hpp index 801f81b08..52e4027dd 100644 --- a/platform/android/src/style/sources/custom_geometry_source.hpp +++ b/platform/android/src/style/sources/custom_geometry_source.hpp @@ -15,37 +15,34 @@ namespace android { class CustomGeometrySource : public Source { public: - + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/CustomGeometrySource"; }; - static jni::Class<CustomGeometrySource> javaClass; - static void registerNative(jni::JNIEnv&); - CustomGeometrySource(jni::JNIEnv&, jni::String, jni::Object<>); - + CustomGeometrySource(jni::JNIEnv&, const jni::String&, const jni::Object<>&); CustomGeometrySource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~CustomGeometrySource(); - bool removeFromMap(JNIEnv&, jni::Object<Source>, mbgl::Map&) override; - void addToMap(JNIEnv&, jni::Object<Source>, mbgl::Map&, AndroidRendererFrontend&) override; + bool removeFromMap(JNIEnv&, const jni::Object<Source>&, mbgl::Map&) override; + void addToMap(JNIEnv&, const jni::Object<Source>&, mbgl::Map&, AndroidRendererFrontend&) override; void fetchTile(const mbgl::CanonicalTileID& tileID); void cancelTile(const mbgl::CanonicalTileID& tileID); bool isCancelled(jni::jint z, jni::jint x, jni::jint y); void startThreads(); void releaseThreads(); - void setTileData(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y, jni::Object<geojson::FeatureCollection> jf); + +private: + void setTileData(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y, const jni::Object<geojson::FeatureCollection>& jf); void invalidateTile(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y); - void invalidateBounds(jni::JNIEnv& env, jni::Object<LatLngBounds> bounds); + void invalidateBounds(jni::JNIEnv& env, const jni::Object<LatLngBounds>& bounds); - jni::Array<jni::Object<geojson::Feature>> querySourceFeatures(jni::JNIEnv&, - jni::Array<jni::Object<>> ); + jni::Local<jni::Array<jni::Object<geojson::Feature>>> querySourceFeatures(jni::JNIEnv&, + const jni::Array<jni::Object<>>& ); -private: - jni::Object<Source> createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<Source>> createJavaPeer(jni::JNIEnv&); }; // class CustomGeometrySource diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp index 9d6ca704e..d0ad5fb69 100644 --- a/platform/android/src/style/sources/geojson_source.cpp +++ b/platform/android/src/style/sources/geojson_source.cpp @@ -1,4 +1,5 @@ #include "geojson_source.hpp" +#include "../../attach_env.hpp" #include <mbgl/renderer/query.hpp> @@ -12,7 +13,7 @@ // C++ -> Java conversion #include "../../conversion/conversion.hpp" #include "../../conversion/collection.hpp" -#include "../../geojson/conversion/feature.hpp" +#include "../../geojson/feature.hpp" #include "../conversion/url_or_tileset.hpp" #include <string> @@ -29,20 +30,21 @@ namespace android { // This conversion is expected not to fail because it's used only in contexts where // the value was originally a GeoJsonOptions object on the Java side. If it fails // to convert, it's a bug in our serialization or Java-side static typing. - static style::GeoJSONOptions convertGeoJSONOptions(jni::JNIEnv& env, jni::Object<> options) { + static style::GeoJSONOptions convertGeoJSONOptions(jni::JNIEnv& env, const jni::Object<>& options) { using namespace mbgl::style::conversion; if (!options) { return style::GeoJSONOptions(); } Error error; - optional<style::GeoJSONOptions> result = convert<style::GeoJSONOptions>(mbgl::android::Value(env, options), error); + optional<style::GeoJSONOptions> result = convert<style::GeoJSONOptions>( + mbgl::android::Value(env, options), error); if (!result) { throw std::logic_error(error.message); } return *result; } - GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, jni::String sourceId, jni::Object<> options) + GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, const jni::String& sourceId, const jni::Object<>& options) : Source(env, std::make_unique<mbgl::style::GeoJSONSource>( jni::Make<std::string>(env, sourceId), convertGeoJSONOptions(env, options))) @@ -60,7 +62,7 @@ namespace android { GeoJSONSource::~GeoJSONSource() = default; - void GeoJSONSource::setGeoJSONString(jni::JNIEnv& env, jni::String jString) { + void GeoJSONSource::setGeoJSONString(jni::JNIEnv& env, const jni::String& jString) { std::shared_ptr<std::string> json = std::make_shared<std::string>(jni::Make<std::string>(env, jString)); @@ -71,54 +73,54 @@ namespace android { setAsync(converterFn); } - void GeoJSONSource::setFeatureCollection(jni::JNIEnv& env, jni::Object<geojson::FeatureCollection> jFeatures) { + void GeoJSONSource::setFeatureCollection(jni::JNIEnv& env, const jni::Object<geojson::FeatureCollection>& jFeatures) { setCollectionAsync(env, jFeatures); } - void GeoJSONSource::setFeature(jni::JNIEnv& env, jni::Object<geojson::Feature> jFeature) { + void GeoJSONSource::setFeature(jni::JNIEnv& env, const jni::Object<geojson::Feature>& jFeature) { setCollectionAsync(env, jFeature); } - void GeoJSONSource::setGeometry(jni::JNIEnv& env, jni::Object<geojson::Geometry> jGeometry) { + void GeoJSONSource::setGeometry(jni::JNIEnv& env, const jni::Object<geojson::Geometry>& jGeometry) { setCollectionAsync(env, jGeometry); } - void GeoJSONSource::setURL(jni::JNIEnv& env, jni::String url) { + void GeoJSONSource::setURL(jni::JNIEnv& env, const jni::String& url) { // Update the core source source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setURL(jni::Make<std::string>(env, url)); } - jni::String GeoJSONSource::getURL(jni::JNIEnv& env) { + jni::Local<jni::String> GeoJSONSource::getURL(jni::JNIEnv& env) { optional<std::string> url = source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::getURL(); - return url ? jni::Make<jni::String>(env, *url) : jni::String(); + return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>(); } - jni::Array<jni::Object<geojson::Feature>> GeoJSONSource::querySourceFeatures(jni::JNIEnv& env, - jni::Array<jni::Object<>> jfilter) { + jni::Local<jni::Array<jni::Object<geojson::Feature>>> GeoJSONSource::querySourceFeatures(jni::JNIEnv& env, + const jni::Array<jni::Object<>>& jfilter) { using namespace mbgl::android::conversion; using namespace mbgl::android::geojson; std::vector<mbgl::Feature> features; if (rendererFrontend) { - features = rendererFrontend->querySourceFeatures(source.getID(), { {}, toFilter(env, jfilter) }); + features = rendererFrontend->querySourceFeatures(source.getID(), + { {}, toFilter(env, jfilter) }); } - return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, features); + return Feature::convert(env, features); } - jni::Class<GeoJSONSource> GeoJSONSource::javaClass; - - jni::Object<Source> GeoJSONSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = GeoJSONSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(GeoJSONSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + jni::Local<jni::Object<Source>> GeoJSONSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<GeoJSONSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } template <class JNIType> - void GeoJSONSource::setCollectionAsync(jni::JNIEnv& env, jni::Object<JNIType> jObject) { - - std::shared_ptr<jni::jobject> object = std::shared_ptr<jni::jobject>(jObject.NewGlobalRef(env).release()->Get(), GenericGlobalRefDeleter()); + void GeoJSONSource::setCollectionAsync(jni::JNIEnv& env, const jni::Object<JNIType>& jObject) { + auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, jObject); + auto object = std::make_shared<decltype(global)>(std::move(global)); Update::Converter converterFn = [this, object](ActorRef<Callback> _callback) { - converter->self().invoke(&FeatureConverter::convertObject<JNIType>, jni::Object<JNIType>(*object), _callback); + converter->self().invoke(&FeatureConverter::convertObject<JNIType>, object, _callback); }; setAsync(converterFn); @@ -158,14 +160,14 @@ namespace android { void GeoJSONSource::registerNative(jni::JNIEnv& env) { // Lookup the class - GeoJSONSource::javaClass = *jni::Class<GeoJSONSource>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<GeoJSONSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<GeoJSONSource>( - env, GeoJSONSource::javaClass, "nativePtr", - std::make_unique<GeoJSONSource, JNIEnv&, jni::String, jni::Object<>>, + env, javaClass, "nativePtr", + jni::MakePeer<GeoJSONSource, const jni::String&, const jni::Object<>&>, "initialize", "finalize", METHOD(&GeoJSONSource::setGeoJSONString, "nativeSetGeoJsonString"), @@ -195,13 +197,13 @@ namespace android { callback.invoke(&Callback::operator(), *converted); } - template<class JNIType> - void FeatureConverter::convertObject(jni::Object<JNIType> jObject, ActorRef<Callback> callback) { + template <class JNIType> + void FeatureConverter::convertObject(std::shared_ptr<jni::Global<jni::Object<JNIType>, jni::EnvAttachingDeleter>> jObject, ActorRef<Callback> callback) { using namespace mbgl::android::geojson; android::UniqueEnv _env = android::AttachEnv(); // Convert the jni object - auto geometry = JNIType::convert(*_env, jObject); + auto geometry = JNIType::convert(*_env, *jObject); callback.invoke(&Callback::operator(), GeoJSON(geometry)); } diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp index 24ea3c73f..20e8b6873 100644 --- a/platform/android/src/style/sources/geojson_source.hpp +++ b/platform/android/src/style/sources/geojson_source.hpp @@ -16,7 +16,7 @@ struct FeatureConverter { void convertJson(std::shared_ptr<std::string>, ActorRef<Callback>); template <class JNIType> - void convertObject(jni::Object<JNIType>, ActorRef<Callback>); + void convertObject(std::shared_ptr<jni::Global<jni::Object<JNIType>, jni::EnvAttachingDeleter>>, ActorRef<Callback>); }; struct Update { @@ -30,43 +30,35 @@ struct Update { class GeoJSONSource : public Source { public: - + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/GeoJsonSource"; }; - static jni::Class<GeoJSONSource> javaClass; - static void registerNative(jni::JNIEnv&); - GeoJSONSource(jni::JNIEnv&, jni::String, jni::Object<>); - + GeoJSONSource(jni::JNIEnv&, const jni::String&, const jni::Object<>&); GeoJSONSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~GeoJSONSource(); - void setGeoJSONString(jni::JNIEnv&, jni::String); - - void setFeatureCollection(jni::JNIEnv&, jni::Object<geojson::FeatureCollection>); - - void setFeature(jni::JNIEnv&, jni::Object<geojson::Feature>); - - void setGeometry(jni::JNIEnv&, jni::Object<geojson::Geometry>); - - void setURL(jni::JNIEnv&, jni::String); +private: + void setGeoJSONString(jni::JNIEnv&, const jni::String&); + void setFeatureCollection(jni::JNIEnv&, const jni::Object<geojson::FeatureCollection>&); + void setFeature(jni::JNIEnv&, const jni::Object<geojson::Feature>&); + void setGeometry(jni::JNIEnv&, const jni::Object<geojson::Geometry>&); + void setURL(jni::JNIEnv&, const jni::String&); - jni::String getURL(jni::JNIEnv&); + jni::Local<jni::Array<jni::Object<geojson::Feature>>> querySourceFeatures(jni::JNIEnv&, + const jni::Array<jni::Object<>>&); - jni::Array<jni::Object<geojson::Feature>> querySourceFeatures(jni::JNIEnv&, - jni::Array<jni::Object<>> jfilter); + jni::Local<jni::String> getURL(jni::JNIEnv&); -private: - jni::Object<Source> createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<Source>> createJavaPeer(jni::JNIEnv&); std::unique_ptr<Update> awaitingUpdate; std::unique_ptr<Update> update; std::shared_ptr<ThreadPool> threadPool; std::unique_ptr<Actor<FeatureConverter>> converter; template <class JNIType> - void setCollectionAsync(jni::JNIEnv&, jni::Object<JNIType>); + void setCollectionAsync(jni::JNIEnv&, const jni::Object<JNIType>&); void setAsync(Update::Converter); diff --git a/platform/android/src/style/sources/image_source.cpp b/platform/android/src/style/sources/image_source.cpp index 278564485..b42e0e5a5 100644 --- a/platform/android/src/style/sources/image_source.cpp +++ b/platform/android/src/style/sources/image_source.cpp @@ -15,7 +15,7 @@ namespace mbgl { namespace android { - ImageSource::ImageSource(jni::JNIEnv& env, jni::String sourceId, jni::Object<LatLngQuad> coordinatesObject) + ImageSource::ImageSource(jni::JNIEnv& env, const jni::String& sourceId, const jni::Object<LatLngQuad>& coordinatesObject) : Source(env, std::make_unique<mbgl::style::ImageSource>( jni::Make<std::string>(env, sourceId), LatLngQuad::getLatLngArray(env, coordinatesObject) @@ -31,42 +31,41 @@ namespace android { ImageSource::~ImageSource() = default; - void ImageSource::setURL(jni::JNIEnv& env, jni::String url) { + void ImageSource::setURL(jni::JNIEnv& env, const jni::String& url) { // Update the core source source.as<mbgl::style::ImageSource>()->ImageSource::setURL(jni::Make<std::string>(env, url)); } - jni::String ImageSource::getURL(jni::JNIEnv& env) { + jni::Local<jni::String> ImageSource::getURL(jni::JNIEnv& env) { optional<std::string> url = source.as<mbgl::style::ImageSource>()->ImageSource::getURL(); - return url ? jni::Make<jni::String>(env, *url) : jni::String(); + return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>(); } - void ImageSource::setImage(jni::JNIEnv& env, jni::Object<Bitmap> bitmap) { + void ImageSource::setImage(jni::JNIEnv& env, const jni::Object<Bitmap>& bitmap) { source.as<mbgl::style::ImageSource>()->setImage(Bitmap::GetImage(env, bitmap)); } - void ImageSource::setCoordinates(jni::JNIEnv& env, jni::Object<LatLngQuad> coordinatesObject) { + void ImageSource::setCoordinates(jni::JNIEnv& env, const jni::Object<LatLngQuad>& coordinatesObject) { source.as<mbgl::style::ImageSource>()->setCoordinates( LatLngQuad::getLatLngArray(env, coordinatesObject)); } - jni::Class<ImageSource> ImageSource::javaClass; - - jni::Object<Source> ImageSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = ImageSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(ImageSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + jni::Local<jni::Object<Source>> ImageSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<ImageSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void ImageSource::registerNative(jni::JNIEnv& env) { // Lookup the class - ImageSource::javaClass = *jni::Class<ImageSource>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<ImageSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<ImageSource>( - env, ImageSource::javaClass, "nativePtr", - std::make_unique<ImageSource, JNIEnv&, jni::String, jni::Object<LatLngQuad>>, + env, javaClass, "nativePtr", + jni::MakePeer<ImageSource, const jni::String&, const jni::Object<LatLngQuad>&>, "initialize", "finalize", METHOD(&ImageSource::setURL, "nativeSetUrl"), diff --git a/platform/android/src/style/sources/image_source.hpp b/platform/android/src/style/sources/image_source.hpp index 6021a03dc..6c359bf0e 100644 --- a/platform/android/src/style/sources/image_source.hpp +++ b/platform/android/src/style/sources/image_source.hpp @@ -12,28 +12,26 @@ class Bitmap; class ImageSource : public Source { public: - + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/ImageSource"; }; - static jni::Class<ImageSource> javaClass; - static void registerNative(jni::JNIEnv&); - ImageSource(jni::JNIEnv&, jni::String, jni::Object<LatLngQuad>); + ImageSource(jni::JNIEnv&, const jni::String&, const jni::Object<LatLngQuad>&); ImageSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); ~ImageSource(); - void setURL(jni::JNIEnv&, jni::String); - jni::String getURL(jni::JNIEnv&); + void setURL(jni::JNIEnv&, const jni::String&); + jni::Local<jni::String> getURL(jni::JNIEnv&); - void setImage(jni::JNIEnv&, jni::Object<Bitmap>); + void setImage(jni::JNIEnv&, const jni::Object<Bitmap>&); - void setCoordinates(jni::JNIEnv&, jni::Object<LatLngQuad>); + void setCoordinates(jni::JNIEnv&, const jni::Object<LatLngQuad>&); private: - jni::Object<Source> createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<Source>> createJavaPeer(jni::JNIEnv&); }; // class ImageSource diff --git a/platform/android/src/style/sources/raster_dem_source.cpp b/platform/android/src/style/sources/raster_dem_source.cpp index 75e0159d7..f60526a9b 100644 --- a/platform/android/src/style/sources/raster_dem_source.cpp +++ b/platform/android/src/style/sources/raster_dem_source.cpp @@ -12,7 +12,7 @@ namespace mbgl { namespace android { - RasterDEMSource::RasterDEMSource(jni::JNIEnv& env, jni::String sourceId, jni::Object<> urlOrTileSet, jni::jint tileSize) + RasterDEMSource::RasterDEMSource(jni::JNIEnv& env, const jni::String& sourceId, const jni::Object<>& urlOrTileSet, jni::jint tileSize) : Source( env, std::make_unique<mbgl::style::RasterDEMSource>( @@ -31,28 +31,27 @@ namespace android { RasterDEMSource::~RasterDEMSource() = default; - jni::String RasterDEMSource::getURL(jni::JNIEnv& env) { + jni::Local<jni::String> RasterDEMSource::getURL(jni::JNIEnv& env) { optional<std::string> url = source.as<mbgl::style::RasterDEMSource>()->RasterDEMSource::getURL(); - return url ? jni::Make<jni::String>(env, *url) : jni::String(); + return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>(); } - jni::Class<RasterDEMSource> RasterDEMSource::javaClass; - - jni::Object<Source> RasterDEMSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterDEMSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(RasterDEMSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + jni::Local<jni::Object<Source>> RasterDEMSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<RasterDEMSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void RasterDEMSource::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterDEMSource::javaClass = *jni::Class<RasterDEMSource>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<RasterDEMSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<RasterDEMSource>( - env, RasterDEMSource::javaClass, "nativePtr", - std::make_unique<RasterDEMSource, JNIEnv&, jni::String, jni::Object<>, jni::jint>, + env, javaClass, "nativePtr", + jni::MakePeer<RasterDEMSource, const jni::String&, const jni::Object<>&, jni::jint>, "initialize", "finalize", METHOD(&RasterDEMSource::getURL, "nativeGetUrl") diff --git a/platform/android/src/style/sources/raster_dem_source.hpp b/platform/android/src/style/sources/raster_dem_source.hpp index 56924c1f8..0b31c4ecd 100644 --- a/platform/android/src/style/sources/raster_dem_source.hpp +++ b/platform/android/src/style/sources/raster_dem_source.hpp @@ -9,23 +9,19 @@ namespace android { class RasterDEMSource : public Source { public: - + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/RasterDemSource"; }; - static jni::Class<RasterDEMSource> javaClass; - static void registerNative(jni::JNIEnv&); - RasterDEMSource(jni::JNIEnv&, jni::String, jni::Object<>, jni::jint); - + RasterDEMSource(jni::JNIEnv&, const jni::String&, const jni::Object<>&, jni::jint); RasterDEMSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~RasterDEMSource(); - jni::String getURL(jni::JNIEnv&); + jni::Local<jni::String> getURL(jni::JNIEnv&); private: - jni::Object<Source> createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<Source>> createJavaPeer(jni::JNIEnv&); }; // class RasterDEMSource diff --git a/platform/android/src/style/sources/raster_source.cpp b/platform/android/src/style/sources/raster_source.cpp index 33223a5b6..535f899c9 100644 --- a/platform/android/src/style/sources/raster_source.cpp +++ b/platform/android/src/style/sources/raster_source.cpp @@ -11,7 +11,7 @@ namespace mbgl { namespace android { - RasterSource::RasterSource(jni::JNIEnv& env, jni::String sourceId, jni::Object<> urlOrTileSet, jni::jint tileSize) + RasterSource::RasterSource(jni::JNIEnv& env, const jni::String& sourceId, const jni::Object<>& urlOrTileSet, jni::jint tileSize) : Source( env, std::make_unique<mbgl::style::RasterSource>( @@ -30,28 +30,27 @@ namespace android { RasterSource::~RasterSource() = default; - jni::String RasterSource::getURL(jni::JNIEnv& env) { + jni::Local<jni::String> RasterSource::getURL(jni::JNIEnv& env) { optional<std::string> url = source.as<mbgl::style::RasterSource>()->RasterSource::getURL(); - return url ? jni::Make<jni::String>(env, *url) : jni::String(); + return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>(); } - jni::Class<RasterSource> RasterSource::javaClass; - - jni::Object<Source> RasterSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(RasterSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + jni::Local<jni::Object<Source>> RasterSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<RasterSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void RasterSource::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterSource::javaClass = *jni::Class<RasterSource>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<RasterSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<RasterSource>( - env, RasterSource::javaClass, "nativePtr", - std::make_unique<RasterSource, JNIEnv&, jni::String, jni::Object<>, jni::jint>, + env, javaClass, "nativePtr", + jni::MakePeer<RasterSource, const jni::String&, const jni::Object<>&, jni::jint>, "initialize", "finalize", METHOD(&RasterSource::getURL, "nativeGetUrl") diff --git a/platform/android/src/style/sources/raster_source.hpp b/platform/android/src/style/sources/raster_source.hpp index a1da22f40..08648f79a 100644 --- a/platform/android/src/style/sources/raster_source.hpp +++ b/platform/android/src/style/sources/raster_source.hpp @@ -9,23 +9,19 @@ namespace android { class RasterSource : public Source { public: - + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/RasterSource"; }; - static jni::Class<RasterSource> javaClass; - static void registerNative(jni::JNIEnv&); - RasterSource(jni::JNIEnv&, jni::String, jni::Object<>, jni::jint); - + RasterSource(jni::JNIEnv&, const jni::String&, const jni::Object<>&, jni::jint); RasterSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~RasterSource(); - jni::String getURL(jni::JNIEnv&); + jni::Local<jni::String> getURL(jni::JNIEnv&); private: - jni::Object<Source> createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<Source>> createJavaPeer(jni::JNIEnv&); }; // class RasterSource diff --git a/platform/android/src/style/sources/source.cpp b/platform/android/src/style/sources/source.cpp index d2e2426c0..e13f55aff 100644 --- a/platform/android/src/style/sources/source.cpp +++ b/platform/android/src/style/sources/source.cpp @@ -1,5 +1,6 @@ #include "source.hpp" #include "../android_conversion.hpp" +#include "../../attach_env.hpp" #include <jni/jni.hpp> @@ -47,16 +48,16 @@ namespace android { } } - jni::Object<Source> Source::peerForCoreSource(jni::JNIEnv& env, mbgl::style::Source& coreSource, AndroidRendererFrontend& frontend) { + const jni::Object<Source>& Source::peerForCoreSource(jni::JNIEnv& env, mbgl::style::Source& coreSource, AndroidRendererFrontend& frontend) { if (!coreSource.peer.has_value()) { coreSource.peer = createSourcePeer(env, coreSource, frontend); } - return *coreSource.peer.get<std::unique_ptr<Source>>()->javaPeer; + return coreSource.peer.get<std::unique_ptr<Source>>()->javaPeer; } - Source::Source(jni::JNIEnv& env, mbgl::style::Source& coreSource, jni::Object<Source> obj, AndroidRendererFrontend& frontend) + Source::Source(jni::JNIEnv& env, mbgl::style::Source& coreSource, const jni::Object<Source>& obj, AndroidRendererFrontend& frontend) : source(coreSource) - , javaPeer(obj.NewGlobalRef(env)) + , javaPeer(jni::NewGlobal(env, obj)) , rendererFrontend(&frontend) { } @@ -76,22 +77,23 @@ namespace android { if (ownedSource.get() == nullptr && javaPeer.get() != nullptr) { // Manually clear the java peer android::UniqueEnv env = android::AttachEnv(); + static auto& javaClass = jni::Class<Source>::Singleton(*env); static auto nativePtrField = javaClass.GetField<jlong>(*env, "nativePtr"); - javaPeer->Set(*env, nativePtrField, (jlong) 0); + javaPeer.Set(*env, nativePtrField, (jlong) 0); javaPeer.reset(); } } - jni::String Source::getId(jni::JNIEnv& env) { + jni::Local<jni::String> Source::getId(jni::JNIEnv& env) { return jni::Make<jni::String>(env, source.getID()); } - jni::String Source::getAttribution(jni::JNIEnv& env) { + jni::Local<jni::String> Source::getAttribution(jni::JNIEnv& env) { auto attribution = source.getAttribution(); return attribution ? jni::Make<jni::String>(env, attribution.value()) : jni::Make<jni::String>(env,""); } - void Source::addToMap(JNIEnv& env, jni::Object<Source> obj, mbgl::Map& map, AndroidRendererFrontend& frontend) { + void Source::addToMap(JNIEnv& env, const jni::Object<Source>& obj, mbgl::Map& map, AndroidRendererFrontend& frontend) { // Check to see if we own the source first if (!ownedSource) { throw std::runtime_error("Cannot add source twice"); @@ -104,12 +106,12 @@ namespace android { source.peer = std::unique_ptr<Source>(this); // Add strong reference to java source - javaPeer = obj.NewGlobalRef(env); + javaPeer = jni::NewGlobal(env, obj); rendererFrontend = &frontend; } - bool Source::removeFromMap(JNIEnv&, jni::Object<Source>, mbgl::Map& map) { + bool Source::removeFromMap(JNIEnv&, const jni::Object<Source>&, mbgl::Map& map) { // Cannot remove if not attached yet if (ownedSource) { throw std::runtime_error("Cannot remove detached source"); @@ -140,16 +142,14 @@ namespace android { rendererFrontend = nullptr; } - jni::Class<Source> Source::javaClass; - void Source::registerNative(jni::JNIEnv& env) { // Lookup the class - Source::javaClass = *jni::Class<Source>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<Source>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer - jni::RegisterNativePeer<Source>(env, Source::javaClass, "nativePtr", + jni::RegisterNativePeer<Source>(env, javaClass, "nativePtr", METHOD(&Source::getId, "nativeGetId"), METHOD(&Source::getAttribution, "nativeGetAttribution") ); diff --git a/platform/android/src/style/sources/source.hpp b/platform/android/src/style/sources/source.hpp index 6b906eb9c..93b706425 100644 --- a/platform/android/src/style/sources/source.hpp +++ b/platform/android/src/style/sources/source.hpp @@ -17,16 +17,14 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/Source"; }; - static jni::Class<Source> javaClass; - static void registerNative(jni::JNIEnv&); - static jni::Object<Source> peerForCoreSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); + static const jni::Object<Source>& peerForCoreSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); /* * Called when a Java object is created for a core source that belongs to a map. */ - Source(jni::JNIEnv&, mbgl::style::Source&, jni::Object<Source>, AndroidRendererFrontend&); + Source(jni::JNIEnv&, mbgl::style::Source&, const jni::Object<Source>&, AndroidRendererFrontend&); /* * Called when a Java object is created for a new core source that does not belong to a map. @@ -35,15 +33,15 @@ public: virtual ~Source(); - virtual void addToMap(JNIEnv&, jni::Object<Source>, mbgl::Map&, AndroidRendererFrontend&); + virtual void addToMap(JNIEnv&, const jni::Object<Source>&, mbgl::Map&, AndroidRendererFrontend&); - virtual bool removeFromMap(JNIEnv&, jni::Object<Source>, mbgl::Map&); + virtual bool removeFromMap(JNIEnv&, const jni::Object<Source>&, mbgl::Map&); void releaseJavaPeer(); - jni::String getId(jni::JNIEnv&); + jni::Local<jni::String> getId(jni::JNIEnv&); - jni::String getAttribution(jni::JNIEnv&); + jni::Local<jni::String> getAttribution(jni::JNIEnv&); protected: // Set on newly created sources until added to the map. @@ -53,7 +51,7 @@ protected: mbgl::style::Source& source; // Set when the source is added to a map. - jni::UniqueObject<Source> javaPeer; + jni::Global<jni::Object<Source>> javaPeer; // RendererFrontend pointer is valid only when added to the map. AndroidRendererFrontend* rendererFrontend { nullptr }; diff --git a/platform/android/src/style/sources/unknown_source.cpp b/platform/android/src/style/sources/unknown_source.cpp index 4b5510c1d..b5285a5f9 100644 --- a/platform/android/src/style/sources/unknown_source.cpp +++ b/platform/android/src/style/sources/unknown_source.cpp @@ -18,22 +18,21 @@ namespace android { : Source(env, coreSource, createJavaPeer(env), frontend) { } - jni::Class<UnknownSource> UnknownSource::javaClass; - - jni::Object<Source> UnknownSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = UnknownSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(UnknownSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + jni::Local<jni::Object<Source>> UnknownSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<UnknownSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void UnknownSource::registerNative(jni::JNIEnv& env) { // Lookup the class - UnknownSource::javaClass = *jni::Class<UnknownSource>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<UnknownSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<UnknownSource>( - env, UnknownSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", init, "initialize", "finalize" diff --git a/platform/android/src/style/sources/unknown_source.hpp b/platform/android/src/style/sources/unknown_source.hpp index 414d420c6..f042e2042 100644 --- a/platform/android/src/style/sources/unknown_source.hpp +++ b/platform/android/src/style/sources/unknown_source.hpp @@ -9,11 +9,9 @@ namespace android { class UnknownSource : public Source { public: - + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/UnknownSource"; }; - static jni::Class<UnknownSource> javaClass; - static void registerNative(jni::JNIEnv&); UnknownSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); @@ -21,7 +19,7 @@ public: ~UnknownSource() = default; private: - jni::Object<Source> createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<Source>> createJavaPeer(jni::JNIEnv&); }; // class UnknownSource diff --git a/platform/android/src/style/sources/vector_source.cpp b/platform/android/src/style/sources/vector_source.cpp index 9a9548d28..e46fc1a94 100644 --- a/platform/android/src/style/sources/vector_source.cpp +++ b/platform/android/src/style/sources/vector_source.cpp @@ -9,7 +9,7 @@ // C++ -> Java conversion #include "../../conversion/conversion.hpp" #include "../../conversion/collection.hpp" -#include "../../geojson/conversion/feature.hpp" +#include "../../geojson/feature.hpp" #include "../conversion/url_or_tileset.hpp" #include <mbgl/util/variant.hpp> @@ -20,7 +20,7 @@ namespace mbgl { namespace android { - VectorSource::VectorSource(jni::JNIEnv& env, jni::String sourceId, jni::Object<> urlOrTileSet) + VectorSource::VectorSource(jni::JNIEnv& env, const jni::String& sourceId, const jni::Object<>& urlOrTileSet) : Source( env, std::make_unique<mbgl::style::VectorSource>( @@ -38,41 +38,41 @@ namespace android { VectorSource::~VectorSource() = default; - jni::String VectorSource::getURL(jni::JNIEnv& env) { + jni::Local<jni::String> VectorSource::getURL(jni::JNIEnv& env) { optional<std::string> url = source.as<mbgl::style::VectorSource>()->VectorSource::getURL(); - return url ? jni::Make<jni::String>(env, *url) : jni::String(); + return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>(); } - jni::Array<jni::Object<geojson::Feature>> VectorSource::querySourceFeatures(jni::JNIEnv& env, - jni::Array<jni::String> jSourceLayerIds, - jni::Array<jni::Object<>> jfilter) { + jni::Local<jni::Array<jni::Object<geojson::Feature>>> VectorSource::querySourceFeatures(jni::JNIEnv& env, + const jni::Array<jni::String>& jSourceLayerIds, + const jni::Array<jni::Object<>>& jfilter) { using namespace mbgl::android::conversion; using namespace mbgl::android::geojson; std::vector<mbgl::Feature> features; if (rendererFrontend) { - features = rendererFrontend->querySourceFeatures(source.getID(), { toVector(env, jSourceLayerIds), toFilter(env, jfilter) }); + features = rendererFrontend->querySourceFeatures(source.getID(), + { toVector(env, jSourceLayerIds), toFilter(env, jfilter) }); } - return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, features); + return Feature::convert(env, features); } - jni::Class<VectorSource> VectorSource::javaClass; - - jni::Object<Source> VectorSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = VectorSource::javaClass.template GetConstructor<jni::jlong>(env); - return jni::Object<Source>(VectorSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get()); + jni::Local<jni::Object<Source>> VectorSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<VectorSource>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong>(env); + return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); } void VectorSource::registerNative(jni::JNIEnv& env) { // Lookup the class - VectorSource::javaClass = *jni::Class<VectorSource>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<VectorSource>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) // Register the peer jni::RegisterNativePeer<VectorSource>( - env, VectorSource::javaClass, "nativePtr", - std::make_unique<VectorSource, JNIEnv&, jni::String, jni::Object<>>, + env, javaClass, "nativePtr", + jni::MakePeer<VectorSource, const jni::String&, const jni::Object<>&>, "initialize", "finalize", METHOD(&VectorSource::querySourceFeatures, "querySourceFeatures"), diff --git a/platform/android/src/style/sources/vector_source.hpp b/platform/android/src/style/sources/vector_source.hpp index 16049f5c7..4cb46c6c6 100644 --- a/platform/android/src/style/sources/vector_source.hpp +++ b/platform/android/src/style/sources/vector_source.hpp @@ -10,26 +10,22 @@ namespace android { class VectorSource : public Source { public: - + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/VectorSource"; }; - static jni::Class<VectorSource> javaClass; - static void registerNative(jni::JNIEnv&); - VectorSource(jni::JNIEnv&, jni::String, jni::Object<>); - + VectorSource(jni::JNIEnv&, const jni::String&, const jni::Object<>&); VectorSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~VectorSource(); - jni::Array<jni::Object<geojson::Feature>> querySourceFeatures(jni::JNIEnv&, jni::Array<jni::String>, - jni::Array<jni::Object<>> jfilter); +private: + jni::Local<jni::Array<jni::Object<geojson::Feature>>> querySourceFeatures(jni::JNIEnv&, const jni::Array<jni::String>&, + const jni::Array<jni::Object<>>& jfilter); - jni::String getURL(jni::JNIEnv&); + jni::Local<jni::String> getURL(jni::JNIEnv&); -private: - jni::Object<Source> createJavaPeer(jni::JNIEnv&); + jni::Local<jni::Object<Source>> createJavaPeer(jni::JNIEnv&); }; // class VectorSource diff --git a/platform/android/src/style/transition_options.cpp b/platform/android/src/style/transition_options.cpp index c70aa5fe2..b908c3708 100644 --- a/platform/android/src/style/transition_options.cpp +++ b/platform/android/src/style/transition_options.cpp @@ -3,18 +3,15 @@ namespace mbgl { namespace android { -jni::Object<TransitionOptions> TransitionOptions::fromTransitionOptions(jni::JNIEnv& env, jlong duration, jlong delay) { - static auto method = TransitionOptions::javaClass.GetStaticMethod<jni::Object<TransitionOptions> (jlong, jlong)>(env, "fromTransitionOptions"); - return TransitionOptions::javaClass.Call(env, method, duration, delay); +jni::Local<jni::Object<TransitionOptions>> TransitionOptions::fromTransitionOptions(jni::JNIEnv& env, jlong duration, jlong delay) { + static auto& javaClass = jni::Class<TransitionOptions>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<TransitionOptions> (jlong, jlong)>(env, "fromTransitionOptions"); + return javaClass.Call(env, method, duration, delay); } void TransitionOptions::registerNative(jni::JNIEnv& env) { - // Lookup the class - TransitionOptions::javaClass = *jni::Class<TransitionOptions>::Find(env).NewGlobalRef(env).release(); + jni::Class<TransitionOptions>::Singleton(env); } -jni::Class<TransitionOptions> TransitionOptions::javaClass; - - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/style/transition_options.hpp b/platform/android/src/style/transition_options.hpp index 3e6b0bc48..0bac43fa1 100644 --- a/platform/android/src/style/transition_options.hpp +++ b/platform/android/src/style/transition_options.hpp @@ -9,17 +9,12 @@ namespace android { class TransitionOptions : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/TransitionOptions"; }; - static jni::Object<TransitionOptions> fromTransitionOptions(jni::JNIEnv&, jlong duration, jlong offset); - - static jni::Class<TransitionOptions> javaClass; + static jni::Local<jni::Object<TransitionOptions>> fromTransitionOptions(jni::JNIEnv&, jlong duration, jlong offset); static void registerNative(jni::JNIEnv&); - }; - } // namespace android } // namespace mbgl
\ No newline at end of file diff --git a/platform/android/src/style/value.cpp b/platform/android/src/style/value.cpp index 70bdea667..f91690968 100644 --- a/platform/android/src/style/value.cpp +++ b/platform/android/src/style/value.cpp @@ -4,28 +4,18 @@ namespace mbgl { namespace android { - - class ObjectDeleter { - public: - ObjectDeleter() = default; - ObjectDeleter(JNIEnv& e) : env(e) {} - - void operator()(jni::jobject* p) const { - if (p) { - jni::DeleteLocalRef(env, p); - } - } - - private: - JNIEnv& env; - }; - // Instance - Value::Value(jni::JNIEnv& _env, jni::jobject* _value) : env(_env), value(_value, ObjectDeleter(env)) {} + Value::Value(jni::JNIEnv& _env, jni::Local<jni::Object<>> _value) + : env(_env), + value(std::move(_value)) {} + + Value::Value(jni::JNIEnv& _env, const jni::Object<>& _value) + : env(_env), + value(jni::NewLocal(_env, _value)) {} bool Value::isNull() const { - return value == nullptr; + return !value; } bool Value::isArray() const { @@ -33,7 +23,7 @@ namespace android { } bool Value::isObject() const { - return jni::IsInstanceOf(env, value.get(), *java::Map::jclass);; + return jni::IsInstanceOf(env, value.get(), *java::Map::jclass); } bool Value::isString() const { @@ -49,8 +39,7 @@ namespace android { } std::string Value::toString() const { - jni::jstring* string = reinterpret_cast<jni::jstring*>(value.get()); - return jni::Make<std::string>(env, jni::String(string)); + return jni::Make<std::string>(env, jni::Cast(env, jni::Class<jni::StringTag>::Singleton(env), value)); } float Value::toFloat() const { @@ -70,8 +59,8 @@ namespace android { } Value Value::get(const char* key) const { - jni::jobject* member = jni::CallMethod<jni::jobject*>(env, value.get(), *java::Map::getMethodId, jni::Make<jni::String>(env, std::string(key)).Get()); - return Value(env, member); + jni::jobject* member = jni::CallMethod<jni::jobject*>(env, value.get(), *java::Map::getMethodId, jni::Make<jni::String>(env, std::string(key)).get()); + return Value(env, jni::Local<jni::Object<>>(env, member)); } int Value::getLength() const { @@ -81,7 +70,7 @@ namespace android { Value Value::get(const int index) const { auto array = (jni::jarray<jni::jobject>*) value.get(); - return Value(env, jni::GetObjectArrayElement(env, *array, index)); + return Value(env, jni::Local<jni::Object<>>(env, jni::GetObjectArrayElement(env, *array, index))); } } } diff --git a/platform/android/src/style/value.hpp b/platform/android/src/style/value.hpp index 2057b9345..b3e665e57 100644 --- a/platform/android/src/style/value.hpp +++ b/platform/android/src/style/value.hpp @@ -9,7 +9,8 @@ namespace android { class Value { public: - Value(jni::JNIEnv&, jni::jobject*); + Value(jni::JNIEnv&, jni::Local<jni::Object<>>); + Value(jni::JNIEnv&, const jni::Object<>&); Value(Value&&) = default; Value& operator=(Value&&) = default; @@ -34,7 +35,7 @@ public: Value get(const int index ) const; jni::JNIEnv& env; - std::shared_ptr<jni::jobject> value; + jni::Local<jni::Object<>> value; }; } diff --git a/platform/android/src/test/main.jni.cpp b/platform/android/src/test/main.jni.cpp index f96dd6aa5..1cd0d26d2 100644 --- a/platform/android/src/test/main.jni.cpp +++ b/platform/android/src/test/main.jni.cpp @@ -18,7 +18,7 @@ struct Main { /** * JNI Bound to Main#runAllTests() */ - static void runAllTests(jni::JNIEnv& env, jni::Object<Main>, jni::Array<jni::String> args) { + static void runAllTests(jni::JNIEnv& env, const jni::Object<Main>&, const jni::Array<jni::String>& args) { mbgl::Log::Warning(mbgl::Event::JNI, "Starting tests"); // We need to create a copy of the argv data since Java-internals are stored in UTF-16. @@ -69,7 +69,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *) { // Load the test library jni bindings mbgl::Log::Info(mbgl::Event::JNI, "Registering test JNI Methods"); - jni::RegisterNatives(env, jni::Class<Main>::Find(env), + jni::RegisterNatives(env, *jni::Class<Main>::Find(env), jni::MakeNativeMethod<decltype(Main::runAllTests), &Main::runAllTests>("runAllTests")); return JNI_VERSION_1_6; diff --git a/platform/android/src/text/collator.cpp b/platform/android/src/text/collator.cpp index 37af0a1c5..381851eff 100644 --- a/platform/android/src/text/collator.cpp +++ b/platform/android/src/text/collator.cpp @@ -13,34 +13,42 @@ namespace mbgl { namespace android { void Collator::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<Collator>::Find(env).NewGlobalRef(env).release(); + jni::Class<Collator>::Singleton(env); } -jni::Class<Collator> Collator::javaClass; - -jni::Object<Collator> Collator::getInstance(jni::JNIEnv& env, jni::Object<Locale> locale) { - using Signature = jni::Object<Collator>(jni::Object<Locale>); - auto method = javaClass.GetStaticMethod<Signature>(env, "getInstance"); +jni::Local<jni::Object<Collator>> Collator::getInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) { + static auto& javaClass = jni::Class<Collator>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<Collator> (jni::Object<Locale>)>(env, "getInstance"); return javaClass.Call(env, method, locale); } -void Collator::setStrength(jni::JNIEnv& env, jni::Object<Collator> collator, jni::jint strength) { - using Signature = void(jni::jint); - auto static method = javaClass.GetMethod<Signature>(env, "setStrength"); +void Collator::setStrength(jni::JNIEnv& env, const jni::Object<Collator>& collator, jni::jint strength) { + static auto& javaClass = jni::Class<Collator>::Singleton(env); + static auto method = javaClass.GetMethod<void (jni::jint)>(env, "setStrength"); collator.Call(env, method, strength); } -jni::jint Collator::compare(jni::JNIEnv& env, jni::Object<Collator> collator, jni::String lhs, jni::String rhs) { - using Signature = jni::jint(jni::String, jni::String); - auto static method = javaClass.GetMethod<Signature>(env, "compare"); +jni::jint Collator::compare(jni::JNIEnv& env, const jni::Object<Collator>& collator, const jni::String& lhs, const jni::String& rhs) { + static auto& javaClass = jni::Class<Collator>::Singleton(env); + static auto method = javaClass.GetMethod<jni::jint (jni::String, jni::String)>(env, "compare"); return collator.Call(env, method, lhs, rhs); } +void StringUtils::registerNative(jni::JNIEnv& env) { + jni::Class<StringUtils>::Singleton(env); +} + +jni::Local<jni::String> StringUtils::unaccent(jni::JNIEnv& env, const jni::String& value) { + static auto& javaClass = jni::Class<StringUtils>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::String (jni::String)>(env, "unaccent"); + return javaClass.Call(env, method, value); +} + void Locale::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<Locale>::Find(env).NewGlobalRef(env).release(); + jni::Class<Locale>::Singleton(env); } - /* +/* We would prefer to use for/toLanguageTag, but they're only available in API level 21+ jni::Object<Locale> Locale::forLanguageTag(jni::JNIEnv& env, jni::String languageTag) { @@ -54,39 +62,38 @@ jni::String Locale::toLanguageTag(jni::JNIEnv& env, jni::Object<Locale> locale) auto static method = javaClass.GetMethod<Signature>(env, "toLanguageTag"); return locale.Call(env, method); } - */ - +*/ -jni::String Locale::getLanguage(jni::JNIEnv& env, jni::Object<Locale> locale) { - using Signature = jni::String(); - auto static method = javaClass.GetMethod<Signature>(env, "getLanguage"); +jni::Local<jni::String> Locale::getLanguage(jni::JNIEnv& env, const jni::Object<Locale>& locale) { + static auto& javaClass = jni::Class<Locale>::Singleton(env); + static auto method = javaClass.GetMethod<jni::String ()>(env, "getLanguage"); return locale.Call(env, method); } -jni::String Locale::getCountry(jni::JNIEnv& env, jni::Object<Locale> locale) { - using Signature = jni::String(); - auto static method = javaClass.GetMethod<Signature>(env, "getCountry"); +jni::Local<jni::String> Locale::getCountry(jni::JNIEnv& env, const jni::Object<Locale>& locale) { + static auto& javaClass = jni::Class<Locale>::Singleton(env); + static auto method = javaClass.GetMethod<jni::String ()>(env, "getCountry"); return locale.Call(env, method); } -jni::Object<Locale> Locale::getDefault(jni::JNIEnv& env) { - using Signature = jni::Object<Locale>(); - auto method = javaClass.GetStaticMethod<Signature>(env, "getDefault"); +jni::Local<jni::Object<Locale>> Locale::getDefault(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<Locale>::Singleton(env); + static auto method = javaClass.GetStaticMethod<jni::Object<Locale> ()>(env, "getDefault"); return javaClass.Call(env, method); } -jni::Object<Locale> Locale::New(jni::JNIEnv& env, jni::String language) { +jni::Local<jni::Object<Locale>> Locale::New(jni::JNIEnv& env, const jni::String& language) { + static auto& javaClass = jni::Class<Locale>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::String>(env); return javaClass.New(env, constructor, language); } -jni::Object<Locale> Locale::New(jni::JNIEnv& env, jni::String language, jni::String region) { +jni::Local<jni::Object<Locale>> Locale::New(jni::JNIEnv& env, const jni::String& language, const jni::String& region) { + static auto& javaClass = jni::Class<Locale>::Singleton(env); static auto constructor = javaClass.GetConstructor<jni::String, jni::String>(env); return javaClass.New(env, constructor, language, region); } -jni::Class<Locale> Locale::javaClass; - } // namespace android namespace style { @@ -101,26 +108,25 @@ public: { LanguageTag languageTag = locale_ ? LanguageTag::fromBCP47(*locale_) : LanguageTag(); if (!languageTag.language) { - locale = android::Locale::getDefault(*env).NewGlobalRef(*env); + locale = jni::NewGlobal(*env, + android::Locale::getDefault(*env)); } else if (!languageTag.region) { - locale = android::Locale::New(*env, - jni::Make<jni::String>(*env, *(languageTag.language))) - .NewGlobalRef(*env); + locale = jni::NewGlobal(*env, + android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language))); } else { - locale = android::Locale::New(*env, - jni::Make<jni::String>(*env, *(languageTag.language)), - jni::Make<jni::String>(*env, *(languageTag.region))) - .NewGlobalRef(*env); + locale = jni::NewGlobal(*env, + android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language), + jni::Make<jni::String>(*env, *languageTag.region))); } - collator = android::Collator::getInstance(*env, *locale).NewGlobalRef(*env);; + collator = jni::NewGlobal(*env, android::Collator::getInstance(*env, locale)); if (!diacriticSensitive && !caseSensitive) { - android::Collator::setStrength(*env, *collator, 0 /*PRIMARY*/); + android::Collator::setStrength(*env, collator, 0 /*PRIMARY*/); } else if (diacriticSensitive && !caseSensitive) { - android::Collator::setStrength(*env, *collator, 1 /*SECONDARY*/); + android::Collator::setStrength(*env, collator, 1 /*SECONDARY*/); } else if (caseSensitive) { // If we're case-sensitive and diacritic-sensitive, we use a case-sensitive collator // and a fallback implementation of diacritic-insensitivity. - android::Collator::setStrength(*env, *collator, 2 /*TERTIARY*/); + android::Collator::setStrength(*env, collator, 2 /*TERTIARY*/); } } @@ -138,28 +144,21 @@ public: // Because of the difference in locale-awareness, this means turning on case-sensitivity // can _potentially_ change compare results for strings that don't actually have any case // differences. - jni::String jlhs = jni::Make<jni::String>(*env, useUnaccent ? + jni::Local<jni::String> jlhs = jni::Make<jni::String>(*env, useUnaccent ? platform::unaccent(lhs) : lhs); - jni::String jrhs = jni::Make<jni::String>(*env, useUnaccent ? + jni::Local<jni::String> jrhs = jni::Make<jni::String>(*env, useUnaccent ? platform::unaccent(rhs) : rhs); - jni::jint result = android::Collator::compare(*env, *collator, jlhs, jrhs);; - - jni::DeleteLocalRef(*env, jlhs); - jni::DeleteLocalRef(*env, jrhs); + jni::jint result = android::Collator::compare(*env, collator, jlhs, jrhs); return result; } std::string resolvedLocale() const { - jni::String jLanguage = android::Locale::getLanguage(*env, *locale); - std::string language = jni::Make<std::string>(*env, jLanguage); - jni::DeleteLocalRef(*env, jLanguage); - jni::String jRegion = android::Locale::getCountry(*env, *locale); - std::string region = jni::Make<std::string>(*env, jRegion); - jni::DeleteLocalRef(*env, jRegion); + std::string language = jni::Make<std::string>(*env, android::Locale::getLanguage(*env, locale)); + std::string region = jni::Make<std::string>(*env, android::Locale::getCountry(*env, locale)); optional<std::string> resultLanguage; if (!language.empty()) resultLanguage = language; @@ -168,13 +167,14 @@ public: return LanguageTag(resultLanguage, {}, resultRegion).toBCP47(); } + private: bool caseSensitive; bool diacriticSensitive; android::UniqueEnv env; - jni::UniqueObject<android::Collator> collator; - jni::UniqueObject<android::Locale> locale; + jni::Global<jni::Object<android::Collator>> collator; + jni::Global<jni::Object<android::Locale>> locale; }; diff --git a/platform/android/src/text/collator_jni.hpp b/platform/android/src/text/collator_jni.hpp index 96c381b1c..dd3f84566 100644 --- a/platform/android/src/text/collator_jni.hpp +++ b/platform/android/src/text/collator_jni.hpp @@ -24,33 +24,40 @@ public: static jni::Object<Locale> forLanguageTag(jni::JNIEnv&, jni::String); static jni::String toLanguageTag(jni::JNIEnv&, jni::Object<Locale>); */ - static jni::Object<Locale> getDefault(jni::JNIEnv&); - static jni::String getLanguage(jni::JNIEnv&, jni::Object<Locale>); - static jni::String getCountry(jni::JNIEnv&, jni::Object<Locale>); + static jni::Local<jni::Object<Locale>> getDefault(jni::JNIEnv&); + static jni::Local<jni::String> getLanguage(jni::JNIEnv&, const jni::Object<Locale>&); + static jni::Local<jni::String> getCountry(jni::JNIEnv&, const jni::Object<Locale>&); - static jni::Object<Locale> New(jni::JNIEnv&, jni::String); - static jni::Object<Locale> New(jni::JNIEnv&, jni::String, jni::String); + static jni::Local<jni::Object<Locale>> New(jni::JNIEnv&, const jni::String&); + static jni::Local<jni::Object<Locale>> New(jni::JNIEnv&, const jni::String&, const jni::String&); - static jni::Class<Locale> javaClass; static void registerNative(jni::JNIEnv&); - }; class Collator { public: static constexpr auto Name() { return "java/text/Collator"; }; - static jni::Object<Collator> getInstance(jni::JNIEnv&, jni::Object<Locale>); + static jni::Local<jni::Object<Collator>> getInstance(jni::JNIEnv&, const jni::Object<Locale>&); - static void setStrength(jni::JNIEnv&, jni::Object<Collator>, jni::jint); + static void setStrength(jni::JNIEnv&, const jni::Object<Collator>&, jni::jint); - static jni::jint compare(jni::JNIEnv&, jni::Object<Collator>, jni::String, jni::String); + static jni::jint compare(jni::JNIEnv&, const jni::Object<Collator>&, const jni::String&, const jni::String&); - static jni::Class<Collator> javaClass; static void registerNative(jni::JNIEnv&); +}; + + +class StringUtils { +public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/utils/StringUtils"; }; + + static jni::Local<jni::String> unaccent(jni::JNIEnv&, const jni::String&); + + static void registerNative(jni::JNIEnv&); }; } // namespace android diff --git a/platform/android/src/text/local_glyph_rasterizer.cpp b/platform/android/src/text/local_glyph_rasterizer.cpp index 3dc1eb275..8892ee3f3 100644 --- a/platform/android/src/text/local_glyph_rasterizer.cpp +++ b/platform/android/src/text/local_glyph_rasterizer.cpp @@ -36,37 +36,30 @@ namespace android { LocalGlyphRasterizer::LocalGlyphRasterizer() { UniqueEnv env { AttachEnv() }; + static auto& javaClass = jni::Class<LocalGlyphRasterizer>::Singleton(*env); static auto constructor = javaClass.GetConstructor(*env); - javaObject = javaClass.New(*env, constructor).NewGlobalRef(*env); + javaObject = jni::NewGlobal(*env, javaClass.New(*env, constructor)); } PremultipliedImage LocalGlyphRasterizer::drawGlyphBitmap(const std::string& fontFamily, const bool bold, const GlyphID glyphID) { UniqueEnv env { AttachEnv() }; - using Signature = jni::Object<Bitmap>(jni::String, jni::jboolean, jni::jchar); - static auto method = javaClass.GetMethod<Signature>(*env, "drawGlyphBitmap"); + static auto& javaClass = jni::Class<LocalGlyphRasterizer>::Singleton(*env); + static auto drawGlyphBitmap = javaClass.GetMethod<jni::Object<Bitmap> (jni::String, jni::jboolean, jni::jchar)>(*env, "drawGlyphBitmap"); - jni::String jniFontFamily = jni::Make<jni::String>(*env, fontFamily); - - auto javaBitmap = javaObject->Call(*env, - method, - jniFontFamily, - static_cast<jni::jboolean>(bold), - static_cast<jni::jchar>(glyphID)); - jni::DeleteLocalRef(*env, jniFontFamily); - - PremultipliedImage result = Bitmap::GetImage(*env, javaBitmap); - jni::DeleteLocalRef(*env, javaBitmap); - return result; + return Bitmap::GetImage(*env, + javaObject.Call(*env, + drawGlyphBitmap, + jni::Make<jni::String>(*env, fontFamily), + static_cast<jni::jboolean>(bold), + static_cast<jni::jchar>(glyphID))); } void LocalGlyphRasterizer::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class<LocalGlyphRasterizer>::Find(env).NewGlobalRef(env).release(); + jni::Class<LocalGlyphRasterizer>::Singleton(env); } -jni::Class<LocalGlyphRasterizer> LocalGlyphRasterizer::javaClass; - } // namespace android class LocalGlyphRasterizer::Impl { diff --git a/platform/android/src/text/local_glyph_rasterizer_jni.hpp b/platform/android/src/text/local_glyph_rasterizer_jni.hpp index 1c83ea5f5..e80e84833 100644 --- a/platform/android/src/text/local_glyph_rasterizer_jni.hpp +++ b/platform/android/src/text/local_glyph_rasterizer_jni.hpp @@ -19,8 +19,6 @@ class LocalGlyphRasterizer { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/text/LocalGlyphRasterizer"; }; - static jni::Class<LocalGlyphRasterizer> javaClass; - static void registerNative(jni::JNIEnv&); LocalGlyphRasterizer(); @@ -28,7 +26,7 @@ public: PremultipliedImage drawGlyphBitmap(const std::string& fontFamily, const bool bold, const char16_t glyphID); private: - jni::UniqueObject<LocalGlyphRasterizer> javaObject; + jni::Global<jni::Object<LocalGlyphRasterizer>> javaObject; }; } // namespace android diff --git a/platform/android/src/unaccent.cpp b/platform/android/src/unaccent.cpp new file mode 100644 index 000000000..bc2ec354d --- /dev/null +++ b/platform/android/src/unaccent.cpp @@ -0,0 +1,18 @@ +#include <unaccent.hpp> +#include <string> +#include "attach_env.hpp" +#include "text/collator_jni.hpp" +#include <jni/jni.hpp> + +namespace mbgl { +namespace platform { + +std::string unaccent(const std::string& str) { + android::UniqueEnv env = android::AttachEnv(); + jni::Local<jni::String> input = jni::Make<jni::String>(*env, str); + jni::Local<jni::String> unaccented = android::StringUtils::unaccent(*env, input); + return jni::Make<std::string>(*env, unaccented); +} + +} // namespace platform +} // namespace mbgl diff --git a/platform/darwin/scripts/style-spec-overrides-v8.json b/platform/darwin/scripts/style-spec-overrides-v8.json index d47b13cdb..0c787cd96 100644 --- a/platform/darwin/scripts/style-spec-overrides-v8.json +++ b/platform/darwin/scripts/style-spec-overrides-v8.json @@ -39,6 +39,16 @@ } }, "layout_symbol": { + "symbol-z-order": { + "values": { + "viewport-y": { + "doc": "Specify this z order if symbols’ appearance relies on lower features overlapping higher features. For example, symbols with a pin-like appearance would require this z order." + }, + "source": { + "doc": "Specify this z order if the order in which features appear in the source is significant." + } + } + }, "icon-text-fit-padding": { "doc": "Size of the additional area added to dimensions determined by `icon-text-fit`." }, diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index afaea9a74..363f9efee 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -151,6 +151,26 @@ typedef NS_ENUM(NSUInteger, MGLSymbolPlacement) { }; /** + Controls the order in which overlapping symbols in the same layer are rendered + + Values of this type are used in the `MGLSymbolStyleLayer.symbolZOrder` + property. + */ +typedef NS_ENUM(NSUInteger, MGLSymbolZOrder) { + /** + Specify this z order if symbols’ appearance relies on lower features + overlapping higher features. For example, symbols with a pin-like + appearance would require this z order. + */ + MGLSymbolZOrderViewportY, + /** + Specify this z order if the order in which features appear in the source is + significant. + */ + MGLSymbolZOrderSource, +}; + +/** Part of the text placed closest to the anchor. Values of this type are used in the `MGLSymbolStyleLayer.textAnchor` @@ -1005,6 +1025,32 @@ MGL_EXPORT @property (nonatomic, null_resettable) NSExpression *symbolSpacing; /** + Controls the order in which overlapping symbols in the same layer are rendered + + The default value of this property is an expression that evaluates to + `viewport-y`. Set this property to `nil` to reset it to the default value. + + You can set this property to an expression containing any of the following: + + * Constant `MGLSymbolZOrder` values + * Any of the following constant string values: + * `viewport-y`: Specify this z order if symbols’ appearance relies on lower + features overlapping higher features. For example, symbols with a pin-like + appearance would require this z order. + * `source`: Specify this z order if the order in which features appear in the + source is significant. + * Predefined functions, including mathematical and string operators + * Conditional expressions + * Variable assignments and references to assigned variables + * Step functions applied to the `$zoomLevel` variable + + This property does not support applying interpolation functions to the + `$zoomLevel` variable or applying interpolation or step functions to feature + attributes. + */ +@property (nonatomic, null_resettable) NSExpression *symbolZOrder; + +/** Value to use for a text label. Within a constant string value, a feature attribute name enclosed in curly @@ -2141,6 +2187,19 @@ MGL_EXPORT @property (readonly) MGLSymbolPlacement MGLSymbolPlacementValue; /** + Creates a new value object containing the given `MGLSymbolZOrder` enumeration. + + @param symbolZOrder The value for the new object. + @return A new value object that contains the enumeration value. + */ ++ (instancetype)valueWithMGLSymbolZOrder:(MGLSymbolZOrder)symbolZOrder; + +/** + The `MGLSymbolZOrder` enumeration representation of the value. + */ +@property (readonly) MGLSymbolZOrder MGLSymbolZOrderValue; + +/** Creates a new value object containing the given `MGLTextAnchor` enumeration. @param textAnchor The value for the new object. diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm index ad023a1a0..4c0fcfe53 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.mm +++ b/platform/darwin/src/MGLSymbolStyleLayer.mm @@ -50,6 +50,11 @@ namespace mbgl { { MGLSymbolPlacementLineCenter, "line-center" }, }); + MBGL_DEFINE_ENUM(MGLSymbolZOrder, { + { MGLSymbolZOrderViewportY, "viewport-y" }, + { MGLSymbolZOrderSource, "source" }, + }); + MBGL_DEFINE_ENUM(MGLTextAnchor, { { MGLTextAnchorCenter, "center" }, { MGLTextAnchorLeft, "left" }, @@ -573,6 +578,23 @@ namespace mbgl { return MGLStyleValueTransformer<float, NSNumber *>().toExpression(propertyValue); } +- (void)setSymbolZOrder:(NSExpression *)symbolZOrder { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer<mbgl::style::SymbolZOrderType, NSValue *, mbgl::style::SymbolZOrderType, MGLSymbolZOrder>().toPropertyValue<mbgl::style::PropertyValue<mbgl::style::SymbolZOrderType>>(symbolZOrder, false); + self.rawLayer->setSymbolZOrder(mbglValue); +} + +- (NSExpression *)symbolZOrder { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getSymbolZOrder(); + if (propertyValue.isUndefined()) { + propertyValue = self.rawLayer->getDefaultSymbolZOrder(); + } + return MGLStyleValueTransformer<mbgl::style::SymbolZOrderType, NSValue *, mbgl::style::SymbolZOrderType, MGLSymbolZOrder>().toExpression(propertyValue); +} + - (void)setText:(NSExpression *)text { MGLAssertStyleLayerIsValid(); @@ -1440,6 +1462,16 @@ namespace mbgl { return symbolPlacement; } ++ (NSValue *)valueWithMGLSymbolZOrder:(MGLSymbolZOrder)symbolZOrder { + return [NSValue value:&symbolZOrder withObjCType:@encode(MGLSymbolZOrder)]; +} + +- (MGLSymbolZOrder)MGLSymbolZOrderValue { + MGLSymbolZOrder symbolZOrder; + [self getValue:&symbolZOrder]; + return symbolZOrder; +} + + (NSValue *)valueWithMGLTextAnchor:(MGLTextAnchor)textAnchor { return [NSValue value:&textAnchor withObjCType:@encode(MGLTextAnchor)]; } diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm index 5c108a1ac..865de6893 100644 --- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm +++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm @@ -1044,6 +1044,50 @@ XCTAssertThrowsSpecificNamed(layer.symbolSpacing = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes."); } + // symbol-z-order + { + XCTAssertTrue(rawLayer->getSymbolZOrder().isUndefined(), + @"symbol-z-order should be unset initially."); + NSExpression *defaultExpression = layer.symbolZOrder; + + NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'source'"]; + layer.symbolZOrder = constantExpression; + mbgl::style::PropertyValue<mbgl::style::SymbolZOrderType> propertyValue = { mbgl::style::SymbolZOrderType::Source }; + XCTAssertEqual(rawLayer->getSymbolZOrder(), propertyValue, + @"Setting symbolZOrder to a constant value expression should update symbol-z-order."); + XCTAssertEqualObjects(layer.symbolZOrder, constantExpression, + @"symbolZOrder should round-trip constant value expressions."); + + constantExpression = [NSExpression expressionWithFormat:@"'source'"]; + NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}]; + layer.symbolZOrder = functionExpression; + + { + using namespace mbgl::style::expression::dsl; + propertyValue = mbgl::style::PropertyExpression<mbgl::style::SymbolZOrderType>( + step(zoom(), literal("source"), 18.0, literal("source")) + ); + } + + XCTAssertEqual(rawLayer->getSymbolZOrder(), propertyValue, + @"Setting symbolZOrder to a camera expression should update symbol-z-order."); + XCTAssertEqualObjects(layer.symbolZOrder, functionExpression, + @"symbolZOrder should round-trip camera expressions."); + + + layer.symbolZOrder = nil; + XCTAssertTrue(rawLayer->getSymbolZOrder().isUndefined(), + @"Unsetting symbolZOrder should return symbol-z-order to the default value."); + XCTAssertEqualObjects(layer.symbolZOrder, defaultExpression, + @"symbolZOrder should return the default value after being unset."); + + functionExpression = [NSExpression expressionForKeyPath:@"bogus"]; + XCTAssertThrowsSpecificNamed(layer.symbolZOrder = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes."); + functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}]; + functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}]; + XCTAssertThrowsSpecificNamed(layer.symbolZOrder = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes."); + } + // text-field { XCTAssertTrue(rawLayer->getTextField().isUndefined(), @@ -2829,6 +2873,7 @@ [self testPropertyName:@"symbol-avoids-edges" isBoolean:YES]; [self testPropertyName:@"symbol-placement" isBoolean:NO]; [self testPropertyName:@"symbol-spacing" isBoolean:NO]; + [self testPropertyName:@"symbol-z-order" isBoolean:NO]; [self testPropertyName:@"text" isBoolean:NO]; [self testPropertyName:@"text-allows-overlap" isBoolean:YES]; [self testPropertyName:@"text-anchor" isBoolean:NO]; @@ -2884,6 +2929,8 @@ XCTAssertEqual([NSValue valueWithMGLSymbolPlacement:MGLSymbolPlacementPoint].MGLSymbolPlacementValue, MGLSymbolPlacementPoint); XCTAssertEqual([NSValue valueWithMGLSymbolPlacement:MGLSymbolPlacementLine].MGLSymbolPlacementValue, MGLSymbolPlacementLine); XCTAssertEqual([NSValue valueWithMGLSymbolPlacement:MGLSymbolPlacementLineCenter].MGLSymbolPlacementValue, MGLSymbolPlacementLineCenter); + XCTAssertEqual([NSValue valueWithMGLSymbolZOrder:MGLSymbolZOrderViewportY].MGLSymbolZOrderValue, MGLSymbolZOrderViewportY); + XCTAssertEqual([NSValue valueWithMGLSymbolZOrder:MGLSymbolZOrderSource].MGLSymbolZOrderValue, MGLSymbolZOrderSource); XCTAssertEqual([NSValue valueWithMGLTextAnchor:MGLTextAnchorCenter].MGLTextAnchorValue, MGLTextAnchorCenter); XCTAssertEqual([NSValue valueWithMGLTextAnchor:MGLTextAnchorLeft].MGLTextAnchorValue, MGLTextAnchorLeft); XCTAssertEqual([NSValue valueWithMGLTextAnchor:MGLTextAnchorRight].MGLTextAnchorValue, MGLTextAnchorRight); diff --git a/platform/default/codecvt/codecvt b/platform/default/codecvt/codecvt new file mode 100644 index 000000000..8d21e8234 --- /dev/null +++ b/platform/default/codecvt/codecvt @@ -0,0 +1,30 @@ +#pragma once + +// This is a minimal polyfill that'll only work exactly for how we use codecvt + +#include <string> +#include <boost/locale/encoding_utf.hpp> + +namespace std { + +template <typename Codecvt, typename Elem = wchar_t> +class wstring_convert { +public: + static_assert(std::is_same<Elem, typename Codecvt::Elem>::value, "type mismatch"); + + inline std::basic_string<Elem> from_bytes(const string& str) { + return boost::locale::conv::utf_to_utf<Elem>(str); + } + + inline string to_bytes(const std::basic_string<Elem>& str) { + return boost::locale::conv::utf_to_utf<char>(str); + } +}; + +template <typename E> +class codecvt_utf8_utf16 { +public: + using Elem = E; +}; + +} // namespace std diff --git a/platform/default/utf.cpp b/platform/default/utf.cpp index 8fc44a9ed..8bc8ea731 100644 --- a/platform/default/utf.cpp +++ b/platform/default/utf.cpp @@ -1,25 +1,13 @@ #include <mbgl/util/utf.hpp> -#include <memory> #include <locale> - -// GCC 4.9 compatibility -#if !defined(__GNUC__) || __GNUC__ >= 5 #include <codecvt> -#else -#include <boost/locale/encoding_utf.hpp> -#endif namespace mbgl { namespace util { -std::u16string utf8_to_utf16::convert(std::string const& utf8) { -#if !defined(__GNUC__) || __GNUC__ >= 5 - std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter; - return converter.from_bytes(utf8); -#else - return boost::locale::conv::utf_to_utf<char16_t>(utf8.c_str(), utf8.c_str() + utf8.size()); -#endif +std::u16string utf8_to_utf16::convert(const std::string& utf8) { + return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().from_bytes(utf8); } } // namespace util diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index e7c061aff..409ff19cb 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -2,6 +2,9 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started. +## master +* Added an `MGLSymbolStyleLayer.symbolZOrder` property for forcing point features in a symbol layer to be layered in the same order that they are specified in the layer’s associated source. [#12783](https://github.com/mapbox/mapbox-gl-native/pull/12783) + ## 4.4.0 ### Styles and rendering @@ -26,9 +29,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Fixed inconsistencies in exception naming. ([#12583](https://github.com/mapbox/mapbox-gl-native/issues/12583)) * Fixed an issue where `-[MGLMapView convertCoordinateBounds:toRectToView:]` would return an empty CGRect if the bounds crossed the antimeridian. ([#12758](https://github.com/mapbox/mapbox-gl-native/pull/12758)) * Fixed bug where the completion block passed to `-[MGLMapSnapshotter startWithQueue:completionHandler:]` was not being called in all code paths. ([#12355](https://github.com/mapbox/mapbox-gl-native/pull/12355)) -* Fixed a sporadic crash with location updates. ([#12584](https://github.com/mapbox/mapbox-gl-native/pull/12584)) -* Fixed a crash that occurred during power state changes. ([#12584](https://github.com/mapbox/mapbox-gl-native/pull/12584)) -* Fixed a crash related to telemetry upload. ([#12584](https://github.com/mapbox/mapbox-gl-native/pull/12584)) +* Fixed several crashes related to telemetry collection. ([#12825](https://github.com/mapbox/mapbox-gl-native/pull/12825)) ## 4.3.0 - August 15, 2018 diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index 259c1191b..02652b549 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -271,6 +271,16 @@ CLLocationCoordinate2D randomWorldCoordinate() { [self presentViewController:alertController animated:YES completion:nil]; } + + // Add fall-through single tap gesture recognizer. This will be called when + // the map view's tap recognizers fail. + UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; + for (UIGestureRecognizer *gesture in self.mapView.gestureRecognizers) { + if ([gesture isKindOfClass:[UITapGestureRecognizer class]]) { + [singleTap requireGestureRecognizerToFail:gesture]; + } + } + [self.mapView addGestureRecognizer:singleTap]; } - (void)saveState:(__unused NSNotification *)notification @@ -1830,6 +1840,14 @@ CLLocationCoordinate2D randomWorldCoordinate() { #pragma mark - User Actions +- (void)handleSingleTap:(UITapGestureRecognizer *)singleTap { + [self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES]; + + // This is how you'd get the coordinate for the point where the user tapped: + // CGPoint tapPoint = [singleTap locationInView:self.mapView]; + // CLLocationCoordinate2D tapCoordinate = [self.mapView convertPoint:tapPoint toCoordinateFromView:nil]; +} + - (IBAction)handleLongPress:(UILongPressGestureRecognizer *)longPress { if (longPress.state == UIGestureRecognizerStateBegan) diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml index 84ca50ed4..375750943 100644 --- a/platform/ios/jazzy.yml +++ b/platform/ios/jazzy.yml @@ -107,6 +107,7 @@ custom_categories: - MGLOfflinePackProgress - MGLOfflinePackState - MGLTilePyramidOfflineRegion + - MGLShapeOfflineRegion - name: Geometry children: - MGLCoordinateBounds diff --git a/platform/linux/src/headless_backend_egl.cpp b/platform/linux/src/headless_backend_egl.cpp index 089e34498..d72fbbfde 100644 --- a/platform/linux/src/headless_backend_egl.cpp +++ b/platform/linux/src/headless_backend_egl.cpp @@ -1,5 +1,6 @@ #include <mbgl/gl/headless_backend.hpp> +#include <mbgl/util/string.hpp> #include <mbgl/util/logging.hpp> #include <EGL/egl.h> @@ -98,7 +99,7 @@ public: eglSurface = eglCreatePbufferSurface(eglDisplay->display, eglDisplay->config, surfAttribs); if (eglSurface == EGL_NO_SURFACE) { - throw std::runtime_error("Could not create surface: " + std::to_string(eglGetError())); + throw std::runtime_error("Could not create surface: " + util::toString(eglGetError())); } } diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 2fb601bf6..fe042bd56 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -2,6 +2,9 @@ ## master +### Styles and rendering +* Add `symbol-z-order` symbol layout property to style spec [#12783](https://github.com/mapbox/mapbox-gl-native/pull/12783) + ### Other changes * Fixed bug where completion block passed to `-[MGLMapSnapshotter startWithQueue:completionHandler:]` was not being called in all code paths. ([#12355](https://github.com/mapbox/mapbox-gl-native/pull/12355)) diff --git a/platform/macos/INSTALL.md b/platform/macos/INSTALL.md index f0fb0278b..265039c7b 100644 --- a/platform/macos/INSTALL.md +++ b/platform/macos/INSTALL.md @@ -4,7 +4,7 @@ This document explains how to build a development version of the Mapbox Maps SDK ### Requirements -The Mapbox Maps SDK for macOS requires the macOS 10.10.0 SDK (or above) and Xcode 8.0 (or above). To use this SDK with Xcode 7.3.1, download and use a symbols build from the [releases](https://github.com/mapbox/mapbox-gl-native/releases) page. +The Mapbox Maps SDK for macOS requires the macOS 10.11.0 SDK (or above) and Xcode 9.0 (or above). To use this SDK with Xcode 7.3.1, download and use a symbols build from the [releases](https://github.com/mapbox/mapbox-gl-native/releases) page. Before building, follow these steps to install prerequisites: diff --git a/platform/macos/jazzy.yml b/platform/macos/jazzy.yml index 5f1a21454..b5ff4714a 100644 --- a/platform/macos/jazzy.yml +++ b/platform/macos/jazzy.yml @@ -92,6 +92,7 @@ custom_categories: - MGLOfflinePackProgress - MGLOfflinePackState - MGLTilePyramidOfflineRegion + - MGLShapeOfflineRegion - name: Geometry children: - MGLCoordinateBounds diff --git a/platform/node/CHANGELOG.md b/platform/node/CHANGELOG.md index db33ab52d..5b44d5be1 100644 --- a/platform/node/CHANGELOG.md +++ b/platform/node/CHANGELOG.md @@ -1,4 +1,5 @@ # master +- Add `symbol-z-order` symbol layout property to style spec [#12783](https://github.com/mapbox/mapbox-gl-native/pull/12783) - Don't default-show text/icons that depend on the placement of a paired icon/text [#12483](https://github.com/mapbox/mapbox-gl-native/issues/12483) - Fix symbol querying for annotations near tile boundaries at high zoom. ([#12472](https://github.com/mapbox/mapbox-gl-native/issues/12472)) - The `Map` constructor now accepts a `mode` option which can be either `"static"` (default) or `"tile"`. It must be set to `"tile"` when rendering individual tiles in order for the symbols to match across tiles. diff --git a/scripts/standalone.cmake b/scripts/standalone.cmake new file mode 100644 index 000000000..b8bcbfa03 --- /dev/null +++ b/scripts/standalone.cmake @@ -0,0 +1,18 @@ +include(cmake/mason.cmake) + +# include once for every platform to get all dependency defines +set(MBGL_PLATFORM "android") +include(cmake/mason-dependencies.cmake) +set(MBGL_PLATFORM "ios") +include(cmake/mason-dependencies.cmake) + +get_cmake_property(_VARS VARIABLES) +foreach (_VAR ${_VARS}) + if (_VAR MATCHES "^MASON_PACKAGE_.+_NAME$") + set(_PACKAGE "${${_VAR}}") + if (MASON_PACKAGE_${_PACKAGE}_HEADER_ONLY) + file(RELATIVE_PATH _PREFIX "${CMAKE_CURRENT_LIST_DIR}/.." "${MASON_PACKAGE_${_PACKAGE}_PREFIX}") + message("${_PACKAGE} ${_PREFIX} ${MASON_PACKAGE_${_PACKAGE}_VERSION}") + endif() + endif() +endforeach() diff --git a/scripts/standalone.sh b/scripts/standalone.sh new file mode 100755 index 000000000..80b9ac693 --- /dev/null +++ b/scripts/standalone.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +set -e +set -o pipefail + +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +function usage { + echo "Usage: $0 <args> [target]" + echo "" + echo " -c, --clean-target Removes all files in the target directory instead of overwriting them" + echo " -s, --skip [name] Skips vendoring the given dependency" + exit 1 +} + +CLEAN_TARGET=false + +ARGS=() +while [[ $# -gt 0 ]] ; do case "$1" in + -c|--clean-target) CLEAN_TARGET=true ; shift ;; + -s|--skip) shift ; DEP="$1" ; shift ; declare SKIP_$DEP=true ;; + *) ARGS+=("$1") ; shift ;; +esac ; done +set -- "${ARGS[@]}" + +if [ -z "$1" ]; then usage ; fi +TARGET="$1" + +if [ "$CLEAN_TARGET" = true ] ; then + echo ">> Cleaning target directory..." + rm -rf "$TARGET" +fi + +echo ">> Creating target directory..." +mkdir -p "$TARGET" +TARGET=$(cd "`pwd`/$TARGET"; pwd) + +echo ">> Creating file lists..." +cat cmake/core-files.txt cmake/filesource-files.txt > "$TARGET/files.txt" +mkdir -p "$TARGET/platform/android" +cat platform/android/*-files.txt > "$TARGET/platform/android/files.txt" + +echo ">> Copying source files..." +rsync -rR $(git ls-files \ + "include" \ + "src" \ + "platform/default" \ + "platform/android/mbgl" \ + "platform/android/src" \ + "platform/linux/src" \ + "platform/android/MapboxGLAndroidSDK/src/main" \ +) "$TARGET" + +echo ">> Copying vendored files..." +rsync -rR $(git ls-files \ + "vendor/expected" \ + "vendor/icu" \ + "vendor/nunicode" \ + "vendor/sqlite" \ +) "$TARGET" + +echo ">> Copying Mason dependencies..." +cmake -P scripts/standalone.cmake 2>&1 | while read DEPENDENCY ; do + DEPENDENCY=($DEPENDENCY) + if [ "[Mason]" = "${DEPENDENCY[0]}" ]; then + echo "${DEPENDENCY[@]}" + continue + fi + SKIP=SKIP_${DEPENDENCY[0]} + if [ "${!SKIP:-false}" = true ]; then continue ; fi + DESTINATION="$TARGET/vendor/${DEPENDENCY[0]}" + mkdir -p "$DESTINATION" + echo " - ${DEPENDENCY[0]}" + cp -r "${DEPENDENCY[1]}/" "$DESTINATION" + rm "$DESTINATION/mason.ini" + (cd "${DEPENDENCY[1]}" && find include -type f -name "*.hpp" -o -name "*.h") > "$DESTINATION/files.txt" + echo "${DEPENDENCY[2]}" > "$DESTINATION/version.txt" +done diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 344a76bbe..74abd74f0 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -401,10 +401,11 @@ std::vector<float> CalculateTileDistances(const GeometryCoordinates& line, const } void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIndex>&, std::unordered_map<std::string, std::shared_ptr<Bucket>>& buckets, const bool firstLoad, const bool showCollisionBoxes) { - const bool mayOverlap = layout.get<TextAllowOverlap>() || layout.get<IconAllowOverlap>() || - layout.get<TextIgnorePlacement>() || layout.get<IconIgnorePlacement>(); + const bool zOrderByViewport = layout.get<SymbolZOrder>() == SymbolZOrderType::ViewportY; + const bool sortFeaturesByY = zOrderByViewport && (layout.get<TextAllowOverlap>() || layout.get<IconAllowOverlap>() || + layout.get<TextIgnorePlacement>() || layout.get<IconIgnorePlacement>()); - auto bucket = std::make_shared<SymbolBucket>(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, mayOverlap, bucketLeaderID, std::move(symbolInstances)); + auto bucket = std::make_shared<SymbolBucket>(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(symbolInstances)); for (SymbolInstance &symbolInstance : bucket->symbolInstances) { diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index c17729948..ddac5c5c8 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -402,7 +402,7 @@ CameraOptions cameraForLatLngs(const std::vector<LatLng>& latLngs, const Transfo scaleY -= (padding.top() + padding.bottom()) / height; minScale = util::min(scaleX, scaleY); } - double zoom = transform.getZoom() + ::log2(minScale); + double zoom = transform.getZoom() + util::log2(minScale); zoom = util::clamp(zoom, transform.getState().getMinZoom(), transform.getState().getMaxZoom()); // Calculate the center point of a virtual bounds that is extended in all directions by padding. diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 948954570..9ff68a1a6 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -270,7 +270,7 @@ double TransformState::zoomScale(double zoom) const { } double TransformState::scaleZoom(double s) const { - return ::log2(s); + return util::log2(s); } ScreenCoordinate TransformState::latLngToScreenCoordinate(const LatLng& latLng) const { diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp index d4577e787..f9ae5588d 100644 --- a/src/mbgl/renderer/sources/render_image_source.cpp +++ b/src/mbgl/renderer/sources/render_image_source.cpp @@ -139,7 +139,7 @@ void RenderImageSource::update(Immutable<style::Source::Impl> baseImpl_, auto dx = nePoint.x - swPoint.x; auto dy = nePoint.y - swPoint.y; auto dMax = std::max(dx, dy); - double zoom = std::max(0.0, std::floor(-::log2(dMax))); + double zoom = std::max(0.0, std::floor(-util::log2(dMax))); // Only enable if the long side of the image is > 2 pixels. Resulting in a // display of at least 2 x 1 px image diff --git a/src/mbgl/style/conversion/constant.cpp b/src/mbgl/style/conversion/constant.cpp index de4ab2226..bdc637172 100644 --- a/src/mbgl/style/conversion/constant.cpp +++ b/src/mbgl/style/conversion/constant.cpp @@ -59,6 +59,7 @@ template optional<LineJoinType> Converter<LineJoinType>::operator()(const Conver template optional<RasterResamplingType> Converter<RasterResamplingType>::operator()(const Convertible&, Error&) const; template optional<SymbolAnchorType> Converter<SymbolAnchorType>::operator()(const Convertible&, Error&) const; template optional<SymbolPlacementType> Converter<SymbolPlacementType>::operator()(const Convertible&, Error&) const; +template optional<SymbolZOrderType> Converter<SymbolZOrderType>::operator()(const Convertible&, Error&) const; template optional<TextJustifyType> Converter<TextJustifyType>::operator()(const Convertible&, Error&) const; template optional<TextTransformType> Converter<TextTransformType>::operator()(const Convertible&, Error&) const; template optional<TranslateAnchorType> Converter<TranslateAnchorType>::operator()(const Convertible&, Error&) const; diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp index 6aadaad3b..2ce2f4eaf 100644 --- a/src/mbgl/style/conversion/function.cpp +++ b/src/mbgl/style/conversion/function.cpp @@ -131,6 +131,8 @@ template optional<PropertyExpression<SymbolAnchorType>> convertFunctionToExpression<SymbolAnchorType>(const Convertible&, Error&, bool); template optional<PropertyExpression<SymbolPlacementType>> convertFunctionToExpression<SymbolPlacementType>(const Convertible&, Error&, bool); +template optional<PropertyExpression<SymbolZOrderType>> + convertFunctionToExpression<SymbolZOrderType>(const Convertible&, Error&, bool); template optional<PropertyExpression<TextJustifyType>> convertFunctionToExpression<TextJustifyType>(const Convertible&, Error&, bool); template optional<PropertyExpression<TextTransformType>> diff --git a/src/mbgl/style/conversion/property_value.cpp b/src/mbgl/style/conversion/property_value.cpp index 8a93c2476..3b79ecc0d 100644 --- a/src/mbgl/style/conversion/property_value.cpp +++ b/src/mbgl/style/conversion/property_value.cpp @@ -74,6 +74,7 @@ template optional<PropertyValue<Position>> Converter<PropertyValue<Position>>::o template optional<PropertyValue<RasterResamplingType>> Converter<PropertyValue<RasterResamplingType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional<PropertyValue<SymbolAnchorType>> Converter<PropertyValue<SymbolAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional<PropertyValue<SymbolPlacementType>> Converter<PropertyValue<SymbolPlacementType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; +template optional<PropertyValue<SymbolZOrderType>> Converter<PropertyValue<SymbolZOrderType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional<PropertyValue<TextJustifyType>> Converter<PropertyValue<TextJustifyType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional<PropertyValue<TextTransformType>> Converter<PropertyValue<TextTransformType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional<PropertyValue<TranslateAnchorType>> Converter<PropertyValue<TranslateAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp index 2e823ff43..6e87167d5 100644 --- a/src/mbgl/style/expression/compound_expression.cpp +++ b/src/mbgl/style/expression/compound_expression.cpp @@ -467,7 +467,7 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali define("sqrt", [](double x) -> Result<double> { return sqrt(x); }); define("log10", [](double x) -> Result<double> { return log10(x); }); define("ln", [](double x) -> Result<double> { return log(x); }); - define("log2", [](double x) -> Result<double> { return log2(x); }); + define("log2", [](double x) -> Result<double> { return util::log2(x); }); define("sin", [](double x) -> Result<double> { return sin(x); }); define("cos", [](double x) -> Result<double> { return cos(x); }); define("tan", [](double x) -> Result<double> { return tan(x); }); diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp index ddf1ff0ca..f089c918c 100644 --- a/src/mbgl/style/expression/value.cpp +++ b/src/mbgl/style/expression/value.cpp @@ -297,6 +297,9 @@ template struct ValueConverter<LineJoinType>; template type::Type valueTypeToExpressionType<SymbolPlacementType>(); template struct ValueConverter<SymbolPlacementType>; + +template type::Type valueTypeToExpressionType<SymbolZOrderType>(); +template struct ValueConverter<SymbolZOrderType>; template type::Type valueTypeToExpressionType<SymbolAnchorType>(); template struct ValueConverter<SymbolAnchorType>; diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp index 4ea138a7f..c116d5b7e 100644 --- a/src/mbgl/style/layers/symbol_layer.cpp +++ b/src/mbgl/style/layers/symbol_layer.cpp @@ -149,6 +149,22 @@ void SymbolLayer::setSymbolAvoidEdges(PropertyValue<bool> value) { baseImpl = std::move(impl_); observer->onLayerChanged(*this); } +PropertyValue<SymbolZOrderType> SymbolLayer::getDefaultSymbolZOrder() { + return SymbolZOrder::defaultValue(); +} + +PropertyValue<SymbolZOrderType> SymbolLayer::getSymbolZOrder() const { + return impl().layout.get<SymbolZOrder>(); +} + +void SymbolLayer::setSymbolZOrder(PropertyValue<SymbolZOrderType> value) { + if (value == getSymbolZOrder()) + return; + auto impl_ = mutableImpl(); + impl_->layout.get<SymbolZOrder>() = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} PropertyValue<bool> SymbolLayer::getDefaultIconAllowOverlap() { return IconAllowOverlap::defaultValue(); } @@ -1440,6 +1456,7 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co SymbolPlacement, SymbolSpacing, SymbolAvoidEdges, + SymbolZOrder, IconAllowOverlap, IconIgnorePlacement, IconOptional, @@ -1496,6 +1513,12 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co } break; + case util::hashFNV1a("symbol-z-order"): + if (name == "symbol-z-order") { + property = Property::SymbolZOrder; + } + break; + case util::hashFNV1a("icon-allow-overlap"): if (name == "icon-allow-overlap") { property = Property::IconAllowOverlap; @@ -1801,6 +1824,18 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co } + if (property == Property::SymbolZOrder) { + Error error; + optional<PropertyValue<SymbolZOrderType>> typedValue = convert<PropertyValue<SymbolZOrderType>>(value, error, false, false); + if (!typedValue) { + return error; + } + + setSymbolZOrder(*typedValue); + return nullopt; + + } + if (property == Property::IconRotationAlignment || property == Property::IconPitchAlignment || property == Property::TextPitchAlignment || property == Property::TextRotationAlignment) { Error error; optional<PropertyValue<AlignmentType>> typedValue = convert<PropertyValue<AlignmentType>>(value, error, false, false); diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp index e70ac28d5..10d059e78 100644 --- a/src/mbgl/style/layers/symbol_layer_properties.hpp +++ b/src/mbgl/style/layers/symbol_layer_properties.hpp @@ -27,6 +27,11 @@ struct SymbolAvoidEdges : LayoutProperty<bool> { static bool defaultValue() { return false; } }; +struct SymbolZOrder : LayoutProperty<SymbolZOrderType> { + static constexpr const char * key = "symbol-z-order"; + static SymbolZOrderType defaultValue() { return SymbolZOrderType::ViewportY; } +}; + struct IconAllowOverlap : LayoutProperty<bool> { static constexpr const char * key = "icon-allow-overlap"; static bool defaultValue() { return false; } @@ -252,6 +257,7 @@ class SymbolLayoutProperties : public Properties< SymbolPlacement, SymbolSpacing, SymbolAvoidEdges, + SymbolZOrder, IconAllowOverlap, IconIgnorePlacement, IconOptional, diff --git a/src/mbgl/style/types.cpp b/src/mbgl/style/types.cpp index 46de0173d..51174cf15 100644 --- a/src/mbgl/style/types.cpp +++ b/src/mbgl/style/types.cpp @@ -76,6 +76,11 @@ MBGL_DEFINE_ENUM(SymbolAnchorType, { { SymbolAnchorType::BottomLeft, "bottom-left" }, { SymbolAnchorType::BottomRight, "bottom-right" } }); + +MBGL_DEFINE_ENUM(SymbolZOrderType, { + { SymbolZOrderType::ViewportY, "viewport-y" }, + { SymbolZOrderType::Source, "source" } +}); MBGL_DEFINE_ENUM(TextJustifyType, { { TextJustifyType::Center, "center" }, diff --git a/src/mbgl/text/collision_feature.cpp b/src/mbgl/text/collision_feature.cpp index ac4dbff2a..ee7322e69 100644 --- a/src/mbgl/text/collision_feature.cpp +++ b/src/mbgl/text/collision_feature.cpp @@ -52,7 +52,7 @@ void CollisionFeature::bboxifyLabel(const GeometryCoordinates& line, GeometryCoo // symbol spacing will put labels very close together in a pitched map. // To reduce the cost of adding extra collision circles, we slowly increase // them for overscaled tiles. - const float overscalingPaddingFactor = 1 + .4 * ::log2(static_cast<double>(overscaling)); + const float overscalingPaddingFactor = 1 + .4 * util::log2(static_cast<double>(overscaling)); const int nPitchPaddingBoxes = std::floor(nBoxes * overscalingPaddingFactor / 2); // offset the center of the first box by half a box so that the edge of the diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index 0747133bd..48c58a962 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -117,6 +117,25 @@ void Placement::placeLayerBucket( avoidEdges = collisionIndex.projectTileBoundaries(posMatrix); } + const bool textAllowOverlap = bucket.layout.get<style::TextAllowOverlap>(); + const bool iconAllowOverlap = bucket.layout.get<style::IconAllowOverlap>(); + // This logic is similar to the "defaultOpacityState" logic below in updateBucketOpacities + // If we know a symbol is always supposed to show, force it to be marked visible even if + // it wasn't placed into the collision index (because some or all of it was outside the range + // of the collision grid). + // There is a subtle edge case here we're accepting: + // Symbol A has text-allow-overlap: true, icon-allow-overlap: true, icon-optional: false + // A's icon is outside the grid, so doesn't get placed + // A's text would be inside grid, but doesn't get placed because of icon-optional: false + // We still show A because of the allow-overlap settings. + // Symbol B has allow-overlap: false, and gets placed where A's text would be + // On panning in, there is a short period when Symbol B and Symbol A will overlap + // This is the reverse of our normal policy of "fade in on pan", but should look like any other + // collision and hopefully not be too noticeable. + // See https://github.com/mapbox/mapbox-gl-native/issues/12683 + const bool alwaysShowText = textAllowOverlap && (iconAllowOverlap || !bucket.hasIconData() || bucket.layout.get<style::IconOptional>()); + const bool alwaysShowIcon = iconAllowOverlap && (textAllowOverlap || !bucket.hasTextData() || bucket.layout.get<style::TextOptional>()); + for (auto& symbolInstance : bucket.symbolInstances) { if (seenCrossTileIDs.count(symbolInstance.crossTileID) == 0) { @@ -187,7 +206,7 @@ void Placement::placeLayerBucket( placements.erase(symbolInstance.crossTileID); } - placements.emplace(symbolInstance.crossTileID, JointPlacement(placeText, placeIcon, offscreen || bucket.justReloaded)); + placements.emplace(symbolInstance.crossTileID, JointPlacement(placeText || alwaysShowText, placeIcon || alwaysShowIcon, offscreen || bucket.justReloaded)); seenCrossTileIDs.insert(symbolInstance.crossTileID); } } diff --git a/src/mbgl/util/dtoa.hpp b/src/mbgl/util/dtoa.hpp index 4cb81a94b..e6b1659aa 100644 --- a/src/mbgl/util/dtoa.hpp +++ b/src/mbgl/util/dtoa.hpp @@ -1,11 +1,16 @@ #pragma once #include <string> +#include <cstdlib> namespace mbgl { namespace util { std::string dtoa(double value); +inline double stod(const std::string& str) { + return ::strtod(str.c_str(), nullptr); +} + } // end namespace util } // end namespace mbgl diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp index f58d1270b..7979c550a 100644 --- a/src/mbgl/util/tile_cover.cpp +++ b/src/mbgl/util/tile_cover.cpp @@ -131,7 +131,7 @@ std::vector<UnwrappedTileID> tileCover(const Point<double>& tl, } // namespace int32_t coveringZoomLevel(double zoom, style::SourceType type, uint16_t size) { - zoom += ::log2(util::tileSize / size); + zoom += util::log2(util::tileSize / size); if (type == style::SourceType::Raster || type == style::SourceType::Video) { return ::round(zoom); } else { diff --git a/test/map/transform.test.cpp b/test/map/transform.test.cpp index 11c2c1cc6..44b5f4936 100644 --- a/test/map/transform.test.cpp +++ b/test/map/transform.test.cpp @@ -3,6 +3,8 @@ #include <mbgl/map/transform.hpp> #include <mbgl/util/geo.hpp> +#include <cmath> + using namespace mbgl; TEST(Transform, InvalidZoom) { @@ -15,7 +17,7 @@ TEST(Transform, InvalidZoom) { transform.setZoom(1); ASSERT_DOUBLE_EQ(1, transform.getZoom()); - const double invalid = std::nan(""); + const double invalid = NAN; transform.setZoom(invalid); @@ -67,7 +69,7 @@ TEST(Transform, InvalidBearing) { ASSERT_DOUBLE_EQ(1, transform.getZoom()); ASSERT_DOUBLE_EQ(2, transform.getAngle()); - const double invalid = std::nan(""); + const double invalid = NAN; transform.setAngle(invalid); ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude()); diff --git a/test/storage/http_file_source.test.cpp b/test/storage/http_file_source.test.cpp index 006b7a0fb..42b4174e6 100644 --- a/test/storage/http_file_source.test.cpp +++ b/test/storage/http_file_source.test.cpp @@ -2,6 +2,7 @@ #include <mbgl/storage/http_file_source.hpp> #include <mbgl/util/exception.hpp> #include <mbgl/util/chrono.hpp> +#include <mbgl/util/string.hpp> #include <mbgl/util/run_loop.hpp> using namespace mbgl; @@ -177,12 +178,12 @@ TEST(HTTPFileSource, TEST_REQUIRES_SERVER(Load)) { std::function<void(int)> req = [&](int i) { const auto current = number++; reqs[i] = fs.request({ Resource::Unknown, - std::string("http://127.0.0.1:3000/load/") + std::to_string(current) }, + std::string("http://127.0.0.1:3000/load/") + util::toString(current) }, [&, i, current](Response res) { reqs[i].reset(); EXPECT_EQ(nullptr, res.error); ASSERT_TRUE(res.data.get()); - EXPECT_EQ(std::string("Request ") + std::to_string(current), *res.data); + EXPECT_EQ(std::string("Request ") + util::toString(current), *res.data); EXPECT_FALSE(bool(res.expires)); EXPECT_FALSE(res.mustRevalidate); EXPECT_FALSE(bool(res.modified)); diff --git a/test/storage/online_file_source.test.cpp b/test/storage/online_file_source.test.cpp index 70bfe3ac9..b5a7c139d 100644 --- a/test/storage/online_file_source.test.cpp +++ b/test/storage/online_file_source.test.cpp @@ -4,6 +4,7 @@ #include <mbgl/util/chrono.hpp> #include <mbgl/util/run_loop.hpp> #include <mbgl/util/timer.hpp> +#include <mbgl/util/string.hpp> #include <mbgl/util/constants.hpp> #include <gtest/gtest.h> @@ -240,12 +241,12 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(Load)) { std::function<void(int)> req = [&](int i) { const auto current = number++; reqs[i] = fs.request({ Resource::Unknown, - std::string("http://127.0.0.1:3000/load/") + std::to_string(current) }, + std::string("http://127.0.0.1:3000/load/") + util::toString(current) }, [&, i, current](Response res) { reqs[i].reset(); EXPECT_EQ(nullptr, res.error); ASSERT_TRUE(res.data.get()); - EXPECT_EQ(std::string("Request ") + std::to_string(current), *res.data); + EXPECT_EQ(std::string("Request ") + util::toString(current), *res.data); EXPECT_FALSE(bool(res.expires)); EXPECT_FALSE(res.mustRevalidate); EXPECT_FALSE(bool(res.modified)); diff --git a/test/util/dtoa.test.cpp b/test/util/dtoa.test.cpp index 8d2fba187..ca13a51c4 100644 --- a/test/util/dtoa.test.cpp +++ b/test/util/dtoa.test.cpp @@ -8,17 +8,17 @@ using namespace mbgl; TEST(Dtoa, Precision) { - EXPECT_EQ(M_E, std::stod(util::dtoa(M_E))); - EXPECT_EQ(M_LOG2E, std::stod(util::dtoa(M_LOG2E))); - EXPECT_EQ(M_LOG10E, std::stod(util::dtoa(M_LOG10E))); - EXPECT_EQ(M_LN2, std::stod(util::dtoa(M_LN2))); - EXPECT_EQ(M_LN10, std::stod(util::dtoa(M_LN10))); - EXPECT_EQ(M_PI, std::stod(util::dtoa(M_PI))); - EXPECT_EQ(M_PI_2, std::stod(util::dtoa(M_PI_2))); - EXPECT_EQ(M_PI_4, std::stod(util::dtoa(M_PI_4))); - EXPECT_EQ(M_1_PI, std::stod(util::dtoa(M_1_PI))); - EXPECT_EQ(M_2_PI, std::stod(util::dtoa(M_2_PI))); - EXPECT_EQ(M_2_SQRTPI, std::stod(util::dtoa(M_2_SQRTPI))); - EXPECT_EQ(M_SQRT2, std::stod(util::dtoa(M_SQRT2))); - EXPECT_EQ(M_SQRT1_2, std::stod(util::dtoa(M_SQRT1_2))); + EXPECT_EQ(M_E, util::stod(util::dtoa(M_E))); + EXPECT_EQ(M_LOG2E, util::stod(util::dtoa(M_LOG2E))); + EXPECT_EQ(M_LOG10E, util::stod(util::dtoa(M_LOG10E))); + EXPECT_EQ(M_LN2, util::stod(util::dtoa(M_LN2))); + EXPECT_EQ(M_LN10, util::stod(util::dtoa(M_LN10))); + EXPECT_EQ(M_PI, util::stod(util::dtoa(M_PI))); + EXPECT_EQ(M_PI_2, util::stod(util::dtoa(M_PI_2))); + EXPECT_EQ(M_PI_4, util::stod(util::dtoa(M_PI_4))); + EXPECT_EQ(M_1_PI, util::stod(util::dtoa(M_1_PI))); + EXPECT_EQ(M_2_PI, util::stod(util::dtoa(M_2_PI))); + EXPECT_EQ(M_2_SQRTPI, util::stod(util::dtoa(M_2_SQRTPI))); + EXPECT_EQ(M_SQRT2, util::stod(util::dtoa(M_SQRT2))); + EXPECT_EQ(M_SQRT1_2, util::stod(util::dtoa(M_SQRT1_2))); } |