summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilhelm Berg <wb@BergWerk-GIS.at>2018-09-12 15:07:57 +0200
committerWilhelm Berg <wb@BergWerk-GIS.at>2018-09-12 15:07:57 +0200
commit98b34cb0dbf5c50d7f319724c93021418140b15f (patch)
tree11cd51f86b5c672dda6bfe087f40f77df1553971
parentee17d79f9420eb859303d977955454dacc470db6 (diff)
parent079ba0209ed383c15123902f0810e658c2b0abf4 (diff)
downloadqtlocation-mapboxgl-upstream/bwg-vs2017.tar.gz
Merge remote-tracking branch 'origin' into bwg-vs2017upstream/bwg-vs2017
# Conflicts: # cmake/mason-dependencies.cmake
-rw-r--r--CMakeLists.txt2
-rw-r--r--Makefile3
-rw-r--r--README.md2
-rw-r--r--circle.yml81
-rw-r--r--cmake/codecvt.cmake19
-rw-r--r--cmake/core.cmake2
-rw-r--r--cmake/mason-dependencies.cmake8
-rw-r--r--cmake/mason.cmake4
-rw-r--r--cmake/sqlite.cmake1
-rw-r--r--include/mbgl/math/log2.hpp11
-rw-r--r--include/mbgl/style/expression/interpolator.hpp8
-rw-r--r--include/mbgl/style/layers/symbol_layer.hpp4
-rw-r--r--include/mbgl/style/types.hpp5
-rw-r--r--platform/android/CHANGELOG.md5
-rw-r--r--platform/android/MapboxGLAndroidSDK/build.gradle16
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraCompassBearingAnimator.java24
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraGpsBearingAnimator.java23
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CameraLatLngAnimator.java25
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CompassEngine.java65
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/CompassListener.java33
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LatLngEvaluator.java19
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerAccuracyAnimator.java24
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerBitmapProvider.java33
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerCompassBearingAnimator.java24
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerFeatureProvider.java26
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerGpsBearingAnimator.java23
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerLatLngAnimator.java25
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LayerSourceProvider.java107
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinator.java373
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java266
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java1000
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentCompassEngine.java267
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java60
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentOptions.java1610
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java398
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxAnimator.java92
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxCameraAnimatorAdapter.java38
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxFloatAnimator.java17
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/MapboxLatLngAnimator.java19
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnCameraMoveInvalidateListener.java7
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnCameraTrackingChangedListener.java21
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationClickListener.java14
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationLongClickListener.java14
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/OnLocationStaleListener.java17
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/StaleStateManager.java80
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/TiltAnimator.java27
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java102
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/ZoomAnimator.java28
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/modes/CameraMode.java66
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/modes/RenderMode.java45
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/package-info.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java28
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java48
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java60
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java21
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java20
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java14
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/StringUtils.java27
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml41
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_bearing_icon.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon_shadow.xml19
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon_stale.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_puck_icon.xml17
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_stroke_icon.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml47
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml41
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/CompassEngineTest.java64
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinatorTest.kt284
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java400
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentOptionsTest.java68
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java466
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/UtilsTest.java28
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java15
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/build.gradle4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt1182
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt404
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/LocationComponentAction.kt34
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/MapboxTestingUtils.kt113
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/OnMapFragmentReadyIdlingResource.kt39
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/OnMapReadyIdlingResource.java63
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/utils/StyleChangeIdlingResource.kt46
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/MapboxMapAction.java3
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java19
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/string/UppperLowerCaseTest.java50
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java14
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/debug/AndroidManifest.xml18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/debug/assets/heavy_style.json81857
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleActivity.java66
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleFragmentActivity.java36
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/debug/res/layout/activity_single.xml13
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml59
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QuerySourceFeaturesActivity.java39
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationFragmentActivity.kt172
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationMapChangeActivity.java132
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationModesActivity.java416
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/ManualLocationUpdatesActivity.java191
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/Utils.java59
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestActivity.java3
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterReuseActivity.java14
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_arrow.xml11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_icon.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_puck_icon.xml23
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_fragment.xml24
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_map_change.xml30
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_mode.xml78
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_manual_update.xml43
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_query_source_features.xml24
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_location_mode.xml27
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml4
-rw-r--r--platform/android/config.cmake5
-rw-r--r--platform/android/core-files.txt11
-rw-r--r--platform/android/gradle/dependencies.gradle94
-rw-r--r--platform/android/scripts/exclude-activity-gen.json3
-rwxr-xr-xplatform/android/scripts/generate-style-code.js4
-rw-r--r--platform/android/scripts/run-render-test.py2
-rw-r--r--platform/android/src/annotation/marker.cpp26
-rw-r--r--platform/android/src/annotation/marker.hpp6
-rw-r--r--platform/android/src/annotation/multi_point.hpp12
-rw-r--r--platform/android/src/annotation/polygon.cpp59
-rw-r--r--platform/android/src/annotation/polygon.hpp23
-rw-r--r--platform/android/src/annotation/polyline.cpp44
-rw-r--r--platform/android/src/annotation/polyline.hpp21
-rw-r--r--platform/android/src/asset_manager_file_source.cpp6
-rw-r--r--platform/android/src/asset_manager_file_source.hpp4
-rw-r--r--platform/android/src/bitmap.cpp107
-rw-r--r--platform/android/src/bitmap.hpp30
-rw-r--r--platform/android/src/bitmap_factory.cpp18
-rw-r--r--platform/android/src/bitmap_factory.hpp11
-rw-r--r--platform/android/src/connectivity_listener.cpp6
-rw-r--r--platform/android/src/connectivity_listener.hpp2
-rw-r--r--platform/android/src/conversion/collection.cpp16
-rw-r--r--platform/android/src/conversion/collection.hpp3
-rw-r--r--platform/android/src/conversion/constant.cpp58
-rw-r--r--platform/android/src/conversion/constant.hpp57
-rw-r--r--platform/android/src/file_source.cpp58
-rw-r--r--platform/android/src/file_source.hpp20
-rw-r--r--platform/android/src/geojson/conversion/feature.cpp191
-rw-r--r--platform/android/src/geojson/conversion/feature.hpp33
-rw-r--r--platform/android/src/geojson/feature.cpp87
-rw-r--r--platform/android/src/geojson/feature.hpp22
-rw-r--r--platform/android/src/geojson/feature_collection.cpp19
-rw-r--r--platform/android/src/geojson/feature_collection.hpp9
-rw-r--r--platform/android/src/geojson/geometry.cpp61
-rw-r--r--platform/android/src/geojson/geometry.hpp11
-rw-r--r--platform/android/src/geojson/geometry_collection.cpp36
-rw-r--r--platform/android/src/geojson/geometry_collection.hpp10
-rw-r--r--platform/android/src/geojson/line_string.cpp33
-rw-r--r--platform/android/src/geojson/line_string.hpp14
-rw-r--r--platform/android/src/geojson/multi_line_string.cpp33
-rw-r--r--platform/android/src/geojson/multi_line_string.hpp14
-rw-r--r--platform/android/src/geojson/multi_point.cpp26
-rw-r--r--platform/android/src/geojson/multi_point.hpp12
-rw-r--r--platform/android/src/geojson/multi_polygon.cpp42
-rw-r--r--platform/android/src/geojson/multi_polygon.hpp12
-rw-r--r--platform/android/src/geojson/point.cpp54
-rw-r--r--platform/android/src/geojson/point.hpp19
-rw-r--r--platform/android/src/geojson/polygon.cpp27
-rw-r--r--platform/android/src/geojson/polygon.hpp14
-rw-r--r--platform/android/src/geojson/util.hpp26
-rw-r--r--platform/android/src/geometry/lat_lng.cpp22
-rw-r--r--platform/android/src/geometry/lat_lng.hpp8
-rw-r--r--platform/android/src/geometry/lat_lng_bounds.cpp24
-rw-r--r--platform/android/src/geometry/lat_lng_bounds.hpp7
-rw-r--r--platform/android/src/geometry/lat_lng_quad.cpp24
-rw-r--r--platform/android/src/geometry/lat_lng_quad.hpp7
-rw-r--r--platform/android/src/geometry/projected_meters.cpp13
-rw-r--r--platform/android/src/geometry/projected_meters.hpp7
-rw-r--r--platform/android/src/graphics/pointf.cpp20
-rw-r--r--platform/android/src/graphics/pointf.hpp7
-rw-r--r--platform/android/src/graphics/rectf.cpp26
-rw-r--r--platform/android/src/graphics/rectf.hpp11
-rw-r--r--platform/android/src/gson/json_array.cpp29
-rw-r--r--platform/android/src/gson/json_array.hpp13
-rw-r--r--platform/android/src/gson/json_element.cpp132
-rw-r--r--platform/android/src/gson/json_element.hpp21
-rw-r--r--platform/android/src/gson/json_object.cpp56
-rw-r--r--platform/android/src/gson/json_object.hpp13
-rw-r--r--platform/android/src/gson/json_primitive.cpp135
-rw-r--r--platform/android/src/gson/json_primitive.hpp26
-rw-r--r--platform/android/src/http_file_source.cpp44
-rw-r--r--platform/android/src/image.cpp8
-rw-r--r--platform/android/src/java/lang.cpp76
-rw-r--r--platform/android/src/java/lang.hpp67
-rw-r--r--platform/android/src/java/util.cpp17
-rw-r--r--platform/android/src/java/util.hpp59
-rwxr-xr-xplatform/android/src/jni.cpp7
-rw-r--r--platform/android/src/jni/collection.hpp26
-rw-r--r--platform/android/src/jni/generic_global_ref_deleter.hpp51
-rw-r--r--platform/android/src/jni/local_object.hpp33
-rw-r--r--platform/android/src/logger.cpp9
-rw-r--r--platform/android/src/logger.hpp3
-rw-r--r--platform/android/src/map/camera_position.cpp28
-rw-r--r--platform/android/src/map/camera_position.hpp9
-rw-r--r--platform/android/src/map/image.cpp29
-rw-r--r--platform/android/src/map/image.hpp7
-rw-r--r--platform/android/src/map_renderer.cpp34
-rw-r--r--platform/android/src/map_renderer.hpp16
-rw-r--r--platform/android/src/map_renderer_runnable.cpp11
-rw-r--r--platform/android/src/map_renderer_runnable.hpp6
-rwxr-xr-xplatform/android/src/native_map_view.cpp182
-rwxr-xr-xplatform/android/src/native_map_view.hpp106
-rw-r--r--platform/android/src/offline/offline_manager.cpp108
-rw-r--r--platform/android/src/offline/offline_manager.hpp34
-rw-r--r--platform/android/src/offline/offline_region.cpp203
-rw-r--r--platform/android/src/offline/offline_region.hpp46
-rw-r--r--platform/android/src/offline/offline_region_definition.cpp108
-rw-r--r--platform/android/src/offline/offline_region_definition.hpp24
-rw-r--r--platform/android/src/offline/offline_region_error.cpp21
-rw-r--r--platform/android/src/offline/offline_region_error.hpp4
-rw-r--r--platform/android/src/offline/offline_region_status.cpp7
-rw-r--r--platform/android/src/offline/offline_region_status.hpp4
-rw-r--r--platform/android/src/snapshotter/map_snapshot.cpp17
-rw-r--r--platform/android/src/snapshotter/map_snapshot.hpp8
-rw-r--r--platform/android/src/snapshotter/map_snapshotter.cpp39
-rw-r--r--platform/android/src/snapshotter/map_snapshotter.hpp27
-rw-r--r--platform/android/src/string_util.cpp25
-rw-r--r--platform/android/src/style/conversion/filter.cpp4
-rw-r--r--platform/android/src/style/conversion/filter.hpp2
-rw-r--r--platform/android/src/style/conversion/position.cpp2
-rw-r--r--platform/android/src/style/conversion/position.hpp4
-rw-r--r--platform/android/src/style/conversion/property_expression.hpp4
-rw-r--r--platform/android/src/style/conversion/property_value.hpp22
-rw-r--r--platform/android/src/style/conversion/transition_options.cpp2
-rw-r--r--platform/android/src/style/conversion/transition_options.hpp4
-rw-r--r--platform/android/src/style/layers/background_layer.cpp44
-rw-r--r--platform/android/src/style/layers/background_layer.hpp20
-rw-r--r--platform/android/src/style/layers/circle_layer.cpp104
-rw-r--r--platform/android/src/style/layers/circle_layer.hpp46
-rw-r--r--platform/android/src/style/layers/custom_layer.cpp17
-rw-r--r--platform/android/src/style/layers/custom_layer.hpp11
-rw-r--r--platform/android/src/style/layers/fill_extrusion_layer.cpp76
-rw-r--r--platform/android/src/style/layers/fill_extrusion_layer.hpp34
-rw-r--r--platform/android/src/style/layers/fill_layer.cpp72
-rw-r--r--platform/android/src/style/layers/fill_layer.hpp32
-rw-r--r--platform/android/src/style/layers/heatmap_layer.cpp54
-rw-r--r--platform/android/src/style/layers/heatmap_layer.hpp24
-rw-r--r--platform/android/src/style/layers/hillshade_layer.cpp63
-rw-r--r--platform/android/src/style/layers/hillshade_layer.hpp28
-rw-r--r--platform/android/src/style/layers/layer.cpp28
-rw-r--r--platform/android/src/style/layers/layer.cpp.ejs35
-rw-r--r--platform/android/src/style/layers/layer.hpp22
-rw-r--r--platform/android/src/style/layers/layer.hpp.ejs14
-rw-r--r--platform/android/src/style/layers/layers.cpp8
-rw-r--r--platform/android/src/style/layers/layers.hpp4
-rw-r--r--platform/android/src/style/layers/line_layer.cpp128
-rw-r--r--platform/android/src/style/layers/line_layer.hpp56
-rw-r--r--platform/android/src/style/layers/raster_layer.cpp81
-rw-r--r--platform/android/src/style/layers/raster_layer.hpp36
-rw-r--r--platform/android/src/style/layers/symbol_layer.cpp321
-rw-r--r--platform/android/src/style/layers/symbol_layer.hpp134
-rw-r--r--platform/android/src/style/layers/unknown_layer.cpp13
-rw-r--r--platform/android/src/style/layers/unknown_layer.hpp6
-rw-r--r--platform/android/src/style/light.cpp45
-rw-r--r--platform/android/src/style/light.cpp.ejs123
-rw-r--r--platform/android/src/style/light.hpp26
-rw-r--r--platform/android/src/style/light.hpp.ejs59
-rw-r--r--platform/android/src/style/position.cpp27
-rw-r--r--platform/android/src/style/position.hpp13
-rw-r--r--platform/android/src/style/sources/custom_geometry_source.cpp53
-rw-r--r--platform/android/src/style/sources/custom_geometry_source.hpp25
-rw-r--r--platform/android/src/style/sources/geojson_source.cpp62
-rw-r--r--platform/android/src/style/sources/geojson_source.hpp36
-rw-r--r--platform/android/src/style/sources/image_source.cpp27
-rw-r--r--platform/android/src/style/sources/image_source.hpp16
-rw-r--r--platform/android/src/style/sources/raster_dem_source.cpp21
-rw-r--r--platform/android/src/style/sources/raster_dem_source.hpp12
-rw-r--r--platform/android/src/style/sources/raster_source.cpp21
-rw-r--r--platform/android/src/style/sources/raster_source.hpp12
-rw-r--r--platform/android/src/style/sources/source.cpp28
-rw-r--r--platform/android/src/style/sources/source.hpp16
-rw-r--r--platform/android/src/style/sources/unknown_source.cpp13
-rw-r--r--platform/android/src/style/sources/unknown_source.hpp6
-rw-r--r--platform/android/src/style/sources/vector_source.cpp34
-rw-r--r--platform/android/src/style/sources/vector_source.hpp18
-rw-r--r--platform/android/src/style/transition_options.cpp13
-rw-r--r--platform/android/src/style/transition_options.hpp7
-rw-r--r--platform/android/src/style/value.cpp37
-rw-r--r--platform/android/src/style/value.hpp5
-rw-r--r--platform/android/src/test/main.jni.cpp4
-rw-r--r--platform/android/src/text/collator.cpp110
-rw-r--r--platform/android/src/text/collator_jni.hpp29
-rw-r--r--platform/android/src/text/local_glyph_rasterizer.cpp29
-rw-r--r--platform/android/src/text/local_glyph_rasterizer_jni.hpp4
-rw-r--r--platform/android/src/unaccent.cpp18
-rw-r--r--platform/darwin/scripts/style-spec-overrides-v8.json10
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.h59
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.mm32
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.mm47
-rw-r--r--platform/default/codecvt/codecvt30
-rw-r--r--platform/default/utf.cpp16
-rw-r--r--platform/ios/CHANGELOG.md7
-rw-r--r--platform/ios/app/MBXViewController.m18
-rw-r--r--platform/ios/jazzy.yml1
-rw-r--r--platform/linux/src/headless_backend_egl.cpp3
-rw-r--r--platform/macos/CHANGELOG.md3
-rw-r--r--platform/macos/INSTALL.md2
-rw-r--r--platform/macos/jazzy.yml1
-rw-r--r--platform/node/CHANGELOG.md1
-rw-r--r--scripts/standalone.cmake18
-rwxr-xr-xscripts/standalone.sh78
-rw-r--r--src/mbgl/layout/symbol_layout.cpp7
-rw-r--r--src/mbgl/map/map.cpp2
-rw-r--r--src/mbgl/map/transform_state.cpp2
-rw-r--r--src/mbgl/renderer/sources/render_image_source.cpp2
-rw-r--r--src/mbgl/style/conversion/constant.cpp1
-rw-r--r--src/mbgl/style/conversion/function.cpp2
-rw-r--r--src/mbgl/style/conversion/property_value.cpp1
-rw-r--r--src/mbgl/style/expression/compound_expression.cpp2
-rw-r--r--src/mbgl/style/expression/value.cpp3
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp35
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp6
-rw-r--r--src/mbgl/style/types.cpp5
-rw-r--r--src/mbgl/text/collision_feature.cpp2
-rw-r--r--src/mbgl/text/placement.cpp21
-rw-r--r--src/mbgl/util/dtoa.hpp5
-rw-r--r--src/mbgl/util/tile_cover.cpp2
-rw-r--r--test/map/transform.test.cpp6
-rw-r--r--test/storage/http_file_source.test.cpp5
-rw-r--r--test/storage/online_file_source.test.cpp5
-rw-r--r--test/util/dtoa.test.cpp26
332 files changed, 94929 insertions, 3963 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bb315916b4..b37a69a83e 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()
diff --git a/Makefile b/Makefile
index 627eec9354..20bf8cfa4e 100644
--- a/Makefile
+++ b/Makefile
@@ -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.
diff --git a/README.md b/README.md
index 0d6e731103..1844c06b1c 100644
--- a/README.md
+++ b/README.md
@@ -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 c03b52e12f..190578b1dc 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 0000000000..8228a6df6b
--- /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 32e77f5d55..1b29b4fb08 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 c953981fd8..3c6a535fc8 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 76d02b95b5..c0795d962c 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 03841ea9b9..b099210c85 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 3136ac22b4..4f5fde60d1 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 f37fb2c9cd..62b48c1752 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 fa0b0c4e4e..aabda0d794 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 805cff118c..ed875733c7 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 13162c0b48..1db3140b6f 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 e796c35cee..f91df8a8a4 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 0000000000..ea1817ab5e
--- /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 0000000000..f46cf805ff
--- /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 0000000000..533abfc335
--- /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 0000000000..3691bdc0ea
--- /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 0000000000..3e5eb7f258
--- /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 0000000000..fa966641fd
--- /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 0000000000..e893f0fee9
--- /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 0000000000..6c9f063c18
--- /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 0000000000..e75eaca2b5
--- /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 0000000000..0be38dc4db
--- /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 0000000000..75cea13750
--- /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 0000000000..f4dc2861cf
--- /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 0000000000..d6198a7da8
--- /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 0000000000..b8baa0d497
--- /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 0000000000..501bb95f8e
--- /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 0000000000..01ef314bf4
--- /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 0000000000..b53d909de3
--- /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 0000000000..40aae5bb6f
--- /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 0000000000..584d214f6e
--- /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 0000000000..da3144eea1
--- /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 0000000000..a72bf08a86
--- /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 0000000000..89d27a38fa
--- /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 0000000000..4a6d8c3b73
--- /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 0000000000..b2f1b61a2d
--- /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 0000000000..6594e543ff
--- /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 0000000000..1ea80d26aa
--- /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 0000000000..fdd2aeb811
--- /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 0000000000..0c34614f3e
--- /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 0000000000..6bbe7f34b3
--- /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 0000000000..c8f6ed58b9
--- /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 0000000000..8ff0f97a70
--- /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 0000000000..ff0a9ce193
--- /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 0000000000..323b51fa88
--- /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 0000000000..51806a33cd
--- /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 0000000000..3d20313dfe
--- /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 0000000000..c871a16ebe
--- /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 6fcc2c199a..73495f78e7 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 08369bb566..c1392be731 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 2322d8211b..bdeeeb0926 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 ba3619567d..1c87b9004b 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 c619d0141a..670548f12e 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 3c4924bb6f..1d45f34bd3 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 0000000000..8a0be63de9
--- /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 1c3653479a..b6f6abeba2 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 0000000000..51bb1161aa
--- /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 0000000000..42f7d35aa9
--- /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 0000000000..05e30364d7
--- /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 0000000000..ecfb85b2e8
--- /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 0000000000..4f13268419
--- /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 0000000000..b4213a7e83
--- /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 053da80ade..b279252c41 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 19007f503f..565d1c99ca 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 00fc05cf6d..d2428d8d8f 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 0000000000..122b76ba3f
--- /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 0000000000..bc64379263
--- /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 0000000000..2c94642610
--- /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 0000000000..616e86bd78
--- /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 0000000000..4c25fa840d
--- /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 0000000000..cb6dcd8fe5
--- /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 0000000000..bf5ee40f4a
--- /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 054d9da8af..61105d89b4 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 cf0a8ed66e..dee713ffcb 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 0000000000..aa3e2eea6f
--- /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 0000000000..41a349b993
--- /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 0000000000..75fae82cf2
--- /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 0000000000..7d362a6f76
--- /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 0000000000..4d02a4d2bf
--- /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 0000000000..9adb30ee32
--- /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 0000000000..0f37498a29
--- /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 5e8f3ed365..926212afc8 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 5480aa7a1c..3682440aeb 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 0000000000..f5b4586a86
--- /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 8cf452a6cf..98c9c27fc2 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 0000000000..489ec3f407
--- /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 0000000000..238ed7d9f2
--- /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 0000000000..5daea88ba0
--- /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 0000000000..823b80af10
--- /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 0000000000..f7e3d1f8ec
--- /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 e23b1d64f3..a0594d8b83 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 fbf439448f..28a89f4b42 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 29c0ae0fca..67fe05eaa6 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 e069a7fd08..4ee8354981 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 79069a26f7..3a52a22f6e 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 0000000000..035ad67e12
--- /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 0000000000..e53604fdd4
--- /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 0000000000..86feb00dec
--- /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 0000000000..2651137273
--- /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 0000000000..41c308c696
--- /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 01c0477610..13d0ad4240 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 e3c5254805..7bbaed192f 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 302fa1ff77..1191b47c11 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 3a11a7e020..61b4eaad1b 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 0000000000..65c3b4aae3
--- /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 0000000000..37f1d4de09
--- /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 0000000000..31d93f1ed4
--- /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 0000000000..16f058f322
--- /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 0000000000..3c1436a1a8
--- /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 0000000000..54171a073d
--- /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 0000000000..e23d876e3a
--- /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 0000000000..3aac74a1e2
--- /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 1c439a5ecc..27c77cf004 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 0000000000..302ab33bc2
--- /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 aafeb1cd9c..a4403a34f7 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 6c68edc4d2..cb9c2043dc 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 777d8a5f56..a0525171a5 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 ddf3518863..f094a67b39 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 d6be05095b..cc44c2585c 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 eca7529c0b..2e32355dcf 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 86571bb05a..af9b7e00b8 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 e4418bdc53..2a1fbec496 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 0825ef1c26..4a35b2d6a6 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 1a7289a116..940ae7a3df 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 a1fe436dbd..899f87a74f 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 b11a225245..b38a25b4fb 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 e1152dfd60..20f1b3eaf2 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 fbd849432a..f22cffb100 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 a98b2822cf..bc21878ef3 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 3723dc1871..d6161e856e 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 bcc616a5f7..6178e98cfc 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 aa65e3ff48..b9150deef9 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 dcad95664a..4ec5b4c30e 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 0d3670b666..eb7c676b12 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 c4e41db1e0..9d96405c26 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 7d9b068b20..170bd52ea5 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 b0e7198260..f73b7a2906 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 5b1c0a86e4..9c13f1f749 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 b0d655d027..a09507c0f7 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 27b614e8cd..954a161baf 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 bb8941c984..322ebb62e0 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 16e8b32943..804d5fd146 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 0e665cf56a..c6dafe1174 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 2a6cac3b02..d9b8e12dc4 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 e4295e1b84..572ac647b7 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 3cb6d37b17..0000000000
--- 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 031449cd23..0000000000
--- 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 d8a4e829e2..f0ed097842 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 ab59d783e5..fdf5d977ba 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 18a41d48fa..f90d5226b7 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 259ffab370..66e92eacad 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 5635b5a0f5..2356af780a 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 a1bb886683..4bf55c858b 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 770cb9a5d6..cca909126d 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 9ed9953b0d..9f02ac848d 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 a5f1a468ce..ae1345c958 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 98dc414642..906d809fa8 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 4a6ea37dd1..1aaf53c01f 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 934a0cb6b5..65ce43bd1f 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 6f62541209..d530ef721f 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 cfe80cd34c..a3ca49b731 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 cc872d4955..3c5c3ec338 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 b4657af09d..fd7b08016d 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 8a9656ea14..2000447c0f 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 627bd1b649..b5d71ecae1 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 96058b63b3..4437d134a8 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 f3c23b4d7b..8e1761feda 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 5e6d90a953..59154516fa 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 0bf6ea7add..5d8313cb2a 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 b2f12c8dcd..30b7db1ef3 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 827ee52e95..d76ff5b365 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 1c853e4b67..d51026711d 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 2b36139e18..1a1e49048b 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 8f8c9abeef..f6560b57ba 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 f3d9d1b0ef..e079de0062 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 9b70967b5d..baad1efc81 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 3f854da2ea..2fc762d6e9 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 e3ef24dd65..899468b8e3 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 1b375dad18..8f418da037 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 0f3a7756d5..ba611f2262 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 e8852d77e9..8ffa658b76 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 c9ae98692f..24d5d3d291 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 5eaaf531f4..7c9a34c03c 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 d850caa526..e3b8a0268d 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 61b55f8b9e..10d244ee48 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 4bc61e51a2..b8916f8ae1 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 4e171c4845..79d6b07617 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 c418e0ebe8..36f138d902 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 fc7ffbec8c..e1b3493f0f 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 0456381578..31515ff16f 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 3c95737169..0000000000
--- 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 981e3b14b7..0000000000
--- 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 89c4c77794..b3aebb36cc 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 c6b07acac5..9b0c01459e 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 872d8bc89a..e323dc83b3 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 5f94ec29ce..0000000000
--- 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 7239e361a7..0000000000
--- 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 00fc4a1933..0000000000
--- 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 0ade914604..f5d78cc83c 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 d4805fccd8..7481ecb265 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 01ffc6530b..3caf4ea2f3 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 4eee8be758..7579f9fed1 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 ce89e22d7a..a91cc938ed 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 1513e13ee7..7549bc646a 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 ba6fdc63b0..13790c4544 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 97d2db4a91..d60447e0ec 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 4dc6611c40..77c3aa301d 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 46fb028d26..21c4369b69 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 8c76332b39..25605e09e4 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 e577670323..969833a25b 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 e96ed7e4d2..b27af8bdae 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 9ae2714ca2..21ca5ca9c1 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 5ed37eda73..1cd73a7c76 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 c05383a91a..49fa0c8ff8 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 a856672902..23e5b7466b 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 a9dfb54634..827fac0a80 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 b0a19f934f..199bbafa6b 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 61efaca67e..151e05ab19 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 d0bbae124f..5dd9f20a7f 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 b29a653655..9ef48ec357 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 42c1c16ca1..1650f72dc7 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 f168be85b4..6b82d02835 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 a93404dbfb..e2e01f4e38 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 7b72452c45..e20acf4f1f 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 0000000000..f02155caff
--- /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 4eac0cf82b..d15e2747ac 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 df482de8f3..920d336a1a 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 9b3925914e..e3c334afd2 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 2ef4bf4395..90409d527d 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 08429960cb..4e26b11f96 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 8150285c85..317705a286 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 313333ad17..66ddc74145 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 6630456d37..06c042922e 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 a8f013b230..c806e8471f 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 95555a2d78..78cd5659fd 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 4c7f69e956..9ec48d7b18 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 9d323e92bb..0ff34094e1 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 61e74a9cf5..f6f3bb249c 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 7eb649d923..950fcef9c1 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 492e1729b9..cf53e774a5 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 11a74bc8ef..abc30b5845 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 f4cddc8858..555f8eb3cd 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 a773cf785b..ea96320570 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 b3d90faab7..b72b372929 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 9e8908b062..2976e6c482 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 d98e3ee074..5cd6162575 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 4b68251775..9ca0e33cfd 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 48e09674e8..5726873f40 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 b08f0ec4dc..875bc88bc0 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 41022bf74a..cee1b5a64e 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 837049b4c3..5ceab0dcfa 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 5df689b45d..232e92a7c7 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 75863a324a..c9a6ba2e66 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 f143ecc236..376e4aafc0 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 9eef1349cb..01be481958 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 53086951e4..5a3579bc37 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 d1c1b45234..40cc47634e 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 d44744a6cf..f1c77c61a9 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 417e5e143f..9887fd8fb7 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 8ffda82bfc..5c770012bd 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 67992ea007..692e2f5db4 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 71f1cb076e..d8ed4d9d96 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 17f0bba09d..0000000000
--- 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 2c314067be..97767c4f76 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 18f961b9e0..0000000000
--- 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 0bbcefcbcd..20a0c47dff 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 4aafa853db..eb4f5ac674 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 e9a530f75b..057f5c99ba 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 801f81b089..52e4027dd8 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 9d6ca704eb..d0ad5fb699 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 24ea3c73f8..20e8b6873b 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 278564485d..b42e0e5a51 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 6021a03dc3..6c359bf0ee 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 75e0159d7c..f60526a9b7 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 56924c1f8d..0b31c4ecd3 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 33223a5b69..535f899c99 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 a1da22f40d..08648f79aa 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 d2e2426c0b..e13f55aff1 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 6b906eb9c0..93b706425a 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 4b5510c1db..b5285a5f9f 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 414d420c61..f042e2042c 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 9a9548d283..e46fc1a94e 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 16049f5c77..4cb46c6c62 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 c70aa5fe2e..b908c37089 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 3e6b0bc488..0bac43fa16 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 70bdea6677..f916909687 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 2057b93454..b3e665e57b 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 f96dd6aa5e..1cd0d26d2c 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 37af0a1c5b..381851eff2 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 96c381b1c1..dd3f845662 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 3dc1eb275a..8892ee3f37 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 1c83ea5f58..e80e848338 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 0000000000..bc2ec354d6
--- /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 d47b13cdb2..0c787cd96e 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 afaea9a74f..363f9efee7 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 ad023a1a03..4c0fcfe539 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 5c108a1ac3..865de68933 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 0000000000..8d21e82348
--- /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 8fc44a9ed3..8bc8ea7314 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 e7c061aff1..409ff19cb5 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 259c1191bc..02652b5490 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 84ca50ed48..3757509430 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 089e344987..d72fbbfdea 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 2fb601bf6f..fe042bd56b 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 f0fb0278be..265039c7b5 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 5f1a214541..b5ff4714ae 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 db33ab52db..5b44d5be1f 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 0000000000..b8bcbfa03f
--- /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 0000000000..80b9ac6931
--- /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 344a76bbe9..74abd74f01 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 c177299485..ddac5c5c8f 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 948954570f..9ff68a1a60 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 d4577e787a..f9ae5588d1 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 de4ab22269..bdc6371722 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 6aadaad3b3..2ce2f4eafd 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 8a93c24767..3b79ecc0db 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 2e823ff43d..6e87167d5a 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 ddf1ff0ca4..f089c918cd 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 4ea138a7f5..c116d5b7e9 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 e70ac28d59..10d059e787 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 46de0173de..51174cf152 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 ac4dbff2af..ee7322e692 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 0747133bd2..48c58a962e 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 4cb81a94be..e6b1659aa2 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 f58d1270bd..7979c550a9 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 11c2c1cc6b..44b5f49366 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 006b7a0fb3..42b4174e69 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 70bfe3ac95..b5a7c139d3 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 8d2fba1877..ca13a51c40 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)));
}